“金山杯2007逆向分析挑战赛”第一阶段第二题

  • 时间:
  • 浏览:2
  • 来源:大发5分快3APP下载_大发5分快3APP官方

  都要先用 VC (我采用 VS5005)创建从前 Windows 窗口任务管理器(它将提供这名 主要样本,但是我有称这名 任务管理器为样本任务管理器),把任务管理器写的尽可能和题目中的任务管理器相似,因此 编译,即首先得到了从前 PE 文件头的原型,再次基础上进行修改,也但是我根据题目给出的 section,适当调整 PE 文件头中的都要修改的字段。

  本题目中所有的 Trunk 的最大地址(RVA)是 0x7124(从 USER32.dll 导入的 DispatchMessageA),可得:

  OriginalFirstTrunkFirstTrunk 指向的这从前指针数组所处 .rdata 的不同位置,其中 FirstTrunk 指向的数组所处 .rdata 的起始位置(稍后都要看一遍这但是我 IAT),OriginalFirstTrunk 指向的数组所处稍微靠后的位置。从前 Trunk 在 PE 文件中的值都指向相同的 IMAGE_IMPORT_BY_NAME (由 Hint 和 函数名称字符串 组成的数据社会形态)。IAT 所在的页面将在加载时被临时设定为可写,绑定但是再恢复为只读。有关这要素的细节请参考我的博客文章:《读取PE文件的导入表》。

  

  首先下载题目的附件,附件中可能有从前文件,分别是 PE 文件的从前 section,都要看一遍从前 section 文件可能按照 0x50000 大小对齐。从前亲们 只都要把这从前文件依次连接在一齐,接在从前正确的 PE 文件头里边就都要了。

  IMAGE_NT_HEADERS.IMAGE_OPTIONAL_HEADER.DataDirectory[2].VirtualAddress = 0x7618;

  觉得应用任务管理器都要通过序号导入函数,并具有极高数率单位,因此 从不会是因为看要能了导入函数的名字,对任务管理器和系统的维护造成障碍。但是我有除非成本太高(相似 MFC 类库的导出函数太少,且面向对象的 C++ 函数名称也很长,但是我有 MFC 类库的函数以 Ordinal 土方法被导入),按名称导入是普遍做法,显然按名称导入,都要线性搜索模块的导出函数表,这就会消耗一定的加载时间成本。为了提高任务管理器加载时数率单位,应用任务管理器都要通过 “但是 Rebase” (将任务管理器都要导入的模块自身建议的 ImageBase 进行精心调整,从而除理在加载时重定向) 和 “但是绑定” 提高任务管理器在客户运行环境的加载数率单位,系统通过时间戳判定绑定信息有无有效,可能时间戳不一致,可能所处重定向,系统则都要再次进行加载时绑定。

  经过以上修改,都要通过 CreateNewPe 函数,生成从前都要执行的 PE 文件了。题目的前半要素要求此时完成。接下来考虑后半要素要求,为任务管理器加进菜单和相关的命令除理函数。

  FA: 0x000077AC: "KERNEL32.dll";  (这里使用的是文件地址 FA,可能说是 RVA)

  (4)从样本任务管理器 pediy02.exe 中插入资源 (.rsrc) section,并选则 DataDirectory[2]: resource Table (资源表)的地址和尺寸。

  

  众所周知,窗口的菜单通常是在注册窗口类时指定的。因此 为了加进菜单,在 IDA 中观察 WinMain 函数的代码:

  IAT.Size = max ( 所有 DLL 的 FirstTrunk 数组元素所在的地址(RVA) ) - IAT.VirtualAddress (RVA) + 8 。

  Code 1.1 将从前 Section 拼接成 PE 文件的 C++ 代码:

  sizeof ( IMAGE_IMPORT_DESCRIPTOR ) = sizeof ( DWORD ) * 5 = 20 Bytes;

  目录:第13篇 论坛活动 \ 金山杯5007逆向分析挑战赛 \ 第一阶段 \ 第二题 \ 题目 \ [第一阶段 第二题]

  BmpFileView 的可执行文件的下载链接(不敢说它是最好的,但作为帮助学习PE文件格式的辅助工具而强烈推荐):

  VA = FA + 50000h;

  DataDirectory[12].VirualAddress = 0x7000; // RVA (Relative to ImageBase )

  1. 将 _text, _rdata, _data 合并成从前 EXE 文件,重建从前 PE 头,这名 关键参数,如 EntryPoint,ImportTable 的 RVA,请另一方分析文件获得。合并成功后,任务管理器即可运行。

  2. 请在第1步获得的EXE文件基础上,增加菜单。具体见图:

  

  http://files.cnblogs.com/hoodlum19500/BmpFileView_V2_Bin.zip

  注:题目来自于以下链接地址:http://www.pediy.com/kssd/

  这里但是我从前 IMAGE_IMPORT_DESCRIPTOR 元素,把该地址减去 3 个 DWORD 值,即得到该元素的起始地址为 0x00007618。可能导入表元素内容非常有特点,很容易就都要判断导入表的两端边界,因此 都要快一点 选则导入表的起始地址(RVA)和 Size 如下:

  对于 PE 文件头的 IMAGE_OPTINAL_HEADER.CheckSum,Windows 看起来完整篇 忽略这名 字段的值,但是我有这名 字段都要我太少 管。

  0x004011EC: WinMain,高级语言编程时的任务管理器入口点。

  (2)选则 DataDirectory[1]: ImportTable (导入表)的地址和尺寸。

  补充说明:在如此经过但是绑定时,OriginalFirstTrunkFirstTrunk 指向的数组内容在加载但是都指向 .rdata 中的这名 长度不固定的 Ascii 编码的字符串,在加载时 FirstTrunk 指向的数组被系统绑定成映射到本任务管理器的 DLL 的实际函数地址(因此 该数组称为 IAT),但是我有那此元素称为 Trunk (是因为分析其身份的可变性,那此元素在加载后其身份所处了变化),可能指向的是数组头部,但是我有称之为 First(IMAGE_IMPORT_DESCRIPTOR.(Original)FirstTrunk 表示某个 DLL 被本模块导入的首个函数的 Trunk 的位置,里边还有更多的函数 Trunk,以 NULL 表征刚结束了了)。OriginalFirstTrunk 在加载后保持不变(但是我有称为 Original),但是我有大慨存储着导入函数名称的一份副本。在模块被加载后,都要通过 OriginalFirstTrunk 数组了解到该模块导入了那此函数(名称),通过 FirstTrunk 数组的内容可了解到导入函数的运行时虚拟地址。导入函数的实际地址是在加载时绑定的(无法在编译时选则),编译器可能为每个 dll 函数调用生成从前很小的函数体,称为 j_XXX, 该函数体负责 jmp 到 FirstTrunk 数组中的元素给出的运行时函数地址,也都要直接调用 IAT 元素内容指向的 VA 地址。

  IMAGE_NT_HEADERS.IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint = 0x1527;

  该工作相对简单容易,先把 EntryPoint 设置为 .text (代码段)的起始地址:0x50000,因此 生成文件后,加载到 IDA 中分析代码段的内容,就都要很容易的找到以下函数的地址(以下地址为 VA,即加进了 ImageBase 后的地址):

  题目分析和解答:

  0x00401527: __tmainCRTStartup,是 PE 文件的实际入口点。

  IMAGE_NT_HEADERS.IMAGE_OPTIONAL_HEADER.DataDirectory[2].Size = sizeof ( IMAGE_IMPORT_DESCRIPTOR ) * 4;

  关于导入表和 IAT 的在内存空间中的位置布局,请参考本文的补充讨论(2)。

  题目描述:

  里边的函数可能是最终版本的函数,它可能完成了以下工作:

  这里都要有点痛 注意的是,.data 的虚拟内存尺寸,都要要比文件尺寸(RawDataSize)更大这名 ,关于这名 点我还暂时要能了给出完整篇 的解释,有待于在将来做进一步研究。可能把 .data 的 VirtualSize 设置为和 RawDataSize 一样大(5000h),则任务管理器无法运行,会弹出从前消息框提示这都是从前有效的 Win32 任务管理器。但是我有这名 步我也是反复尝试有无这名 字段的问題,纠结了半天才发现从前问題卡在这名 地方。

  (1)加进 .rsrc section (菜单资源)

  关于此任务管理器的更多信息,请参见我的博客文章:《[VC6] 图像文件格式数据查看》。

  这名 步也相对比较简单,导入表所处 .rdata 中(所处中部)。在此但是,都要了解导入表的社会形态,导入表是从前由多个 IMAGE_IMPORT_DESCRIPTOR 元素组成的数组,以 NULL 元素(内容完整篇 是 0 )标识结尾(IMAGE_IMPORT_DESCRIPTOR 的数据社会形态定义参见 winnt.h)。每个元素由 5 个 DWORD 组成,其中倒数第八个 DWORD 是 Name 字段(字符串指针),它的值是从前 RVA(即相对于 ImageBase 的偏移),指向了 Dll 名字(ASCII)字符串(该字符串同样所处 .rdata 中)。

  导入表的示意社会形态如下图所示(图中展示的是从前 Thunk 数组并行状况,因此 FirstThunk 也是字符串指针的大多数状况,图中的字符串觉得所处整齐的矩形格子之内,这但是我为了图形外观,应该强调的是那此字符串的长度是不固定的,长度有长有短,但是我有它们在空间中的分布是参差不齐的):

  每个元素的 OriginalFirstTrunk 和 FirstTrunk 是从前指针,指向了从前 并行的指针数组,通常状况下(即如此在链接时但是绑定)这从前数组的内容是相同的(即从前数组的所有元素的值相同),在静态 PE 文件中,都指向相同的长度不固定的函数名称字符串(可能是被导入函数的 Ordinal)。

  (1)选则 AddressOfEntryPoint 的地址。

  有关怎么才能 才能 遍历导入表的更多内容,请参考我的博客文章(在此就不再完整篇 叙述了):《读取PE文件的导入表》。

  己知是从前 PE 格式 EXE 文件,其从前(section)区块的数据文件依次如下:(详见附件)

 

  _text,_rdata,_data

  

  3. 执行菜单 Help / About 弹出如下图所示的 MessageBox 窗口:

  找到附过指向该位置的指针,即在附过的文件内容中搜索 "AC 77 00 00" 片段,都要找到文件地址:

  注意:可能 .data 节在加载到虚拟内存中时被扩大了 50000h,但是我有所处最后的 .rsrc 的文件地址(FA)和虚拟地址(VA)可能偏差 50000h。即:

  在本题求解过程中,我严重依赖于我从前写的从前展示 PE 文件格式的应用任务管理器,此任务管理器最近经过我的调整和改进,它的优点是可能此任务管理器基于扩展 TreeView 控件,因此 帮助快速理解 PE 文件头的社会形态,其效果见以下截图:

  (一)拼接可执行文件:

  0x004059C4: sub_4059C4,基本等价于 MessageBoxA,有点痛 要,称它为 ___crtMessageBoxA

  (3)选则 DataDirectory [12],IAT的地址和大小:

  (3)选则 DataDirectory[12]: Import Address Table (绑定导入函数地址表)的地址和尺寸。

  现在假使 知道,在文件头中把入口地址设置到 __tmainCRTStartup 函数即可,文件头要求的是 RVA,因此 在代码中设置入口点:

  (二)加进菜单 和 除理函数。

  要计算 IAT 的大小,都要遍历导入表,找到导入的所有 Dll 的 FirstTrunk 的最后从前元素的位置,一齐都要考虑到结尾还都要从前 NULL 指针作为刚结束了了标志,但是我有:

  加进资源,同样通过在样本任务管理器中实现。在样本任务管理器中,加进题目要求一样的资源(只保留菜单,删除所有这名 种类资源,从前都要使 .rsrc 最小,仅占用 50000h 大小),因此 都要从样本任务管理器中拷贝 .rsrc 段,追加到亲们 可能得到的 PE 文件的尾部。一齐调整 PE 文件头中的相关字段。

  DataDirectory[12].Size = 0x012C;

  上图表示了 pediy2_new.exe 的实际导入表,共导入了 3 个 DLL,每个导入 DLL 是导入表中的从前元素,在这名 数组中的每个元素大小为 20 Bytes,可能引用了 3 个 DLL,则这名 数组一共为 (3 + 1) * 20 = 500 Bytes (最后有从前 null terminator element)。下面是单个元素 descriptor 大小:

  FA: 0x00007624: AC 77 00 00

  观察题目给出的从前 section 文件,都要给出这从前 section 的基本信息如下:

  IAT 的地址比较简单,它但是我所有 DLL 的 FirstTrunk 字段的最小值,通常但是我 .rdata 的起始位置(那此常量字符串所处 IAT 和 ImportTable 的里边),也但是我 0x7000 (都要看一遍这里是从 Gdi32.dll 的导入的第从前函数 DeleteObject)。

  Code 2.1 由 .text 提供的 WinMain 函数的汇编代码:

  (1)选则入口点地址:

  (2)选则 DataDirectory [1] 导入表的地址和大小:

  其中,.rsrc 是都要在稍后插入的资源 section,将在稍后讲解。

  从前入口点地址就选则好了。

  0x004012D5: WndProc, 当前的窗口过程(稍后可能被子类化)

  明确了以上问題,现在都要把这从前 section 和文件头链接成从前新的 PE 文件了,把样本任务管理器 pediy02.exe 和从前 section 文件装入 同从前目录下,通过从前辅助的 Console 项目(pediy02_helper 项目)来完成那此工作,生成的新的 PE 文件名为 pediy02_new.exe,使用的辅助函数如下(为了简单明了起见,代码中并如此插入繁琐的检测性代码,相似申请的缓冲区大小,可能根据都要,在编码时被静态的选则了):

  当然很显然里边的工作并都是一步到位完成的,下面简要介绍里边的工作是怎么才能 才能 完成的:

  了解了导入表社会形态,就都要快一点 找到导入表的位置了,首先在 .rdata 中查找 DLL 名称字符串,都要找到如下的字符串: