【文章标题】: 用OD学习LoadPE内存转存方法
【文章作者】: lijingli
【作者邮箱】: lijingli168@126.com
【作者QQ号】: 35928252
【使用工具】: OD
【操作平台】: Xp+Sp2
【作者声明】: 没什么技术,只是觉得应该回报一下论坛,虽然一点技术含量都没有。
从开始不懂汇编,到现在从事的工作,真的在看雪学了不少东西,虽然我还是很无知,
但是努力去学习,去追求,也许又一天我会进步很多。
谢谢坛主和大家的无私奉献,我真的希望能回报论坛,尽我小小的绵薄之力。
最近又把PE结构看了一遍,觉得以前看的总是记忆的不是很深刻,于是想编一个PE查看器
又无从下手,就想看看LordPE是用的什么方法。我用OD跟的。
内存转存最后还是要保存到硬盘上的,所以我BP CreateFileA ,
然后可以往上面分析应该就可以找到LordPE的内存转存方法了。
随便选择一个来转存,OD中断在 CreateFileA,如下:
幸运的是我看见了这个文件的路径,我猛然想起以前在论坛的书里看见过,
LordPE是直接读取磁盘上文件的PE头的。但是当时并没有真正的理解。
现在断在了这里,我才明白了LordPE内存转存的方法了(运气占了很大的成分。。

然后CTRL+F9返回。
往上分析,就看见了,LordPE通过:
代码:
00402C2C |. E8 4B560100 call <jmp.&procs.GetProcessPath> 00402C31 |. EB 17 jmp short 00402C4A 00402C33 |> 8B4C24 18 mov ecx, dword ptr [esp+18] 00402C37 |. 8B5424 30 mov edx, dword ptr [esp+30] 00402C3B |. 8D8424 B40100>lea eax, dword ptr [esp+1B4] 00402C42 |. 50 push eax 00402C43 |. 51 push ecx 00402C44 |. 52 push edx 00402C45 |. E8 3E560100 call <jmp.&procs.GetModulePath>
获取执行文件所在的路径,然后通过CreateFileA来打开磁盘上的文件,
然后通过ReadFile读取文件的DOS和PE头,并比较PE的标志:
代码:
|> push 0 ; /pOverlapped = NULL |> push ecx ; |pBytesRead |> lea edx,dword ptr [esp+1C] ; | |> push 40 ; |BytesToRead = 40 (64.) |> push edx ; |Buffer |> push esi ; |hFile |> call edi ; \ReadFile |> test eax, eax |> je 00406CFE |> cmp word ptr [esp+14], 5A4D ;比较MZ |> je short 00406C8C ]
代码:
|. 6A 00 push 0 |. 51 push ecx |. 8D5424 5C lea edx, dword ptr [esp+5C] |. 68 F8000000 push 0F8 |. 52 push edx |. 56 push esi |. FFD7 call edi ; ReadFile |. 85C0 test eax, eax |. 74 48 je short 00406CFE |. 817C24 54 50450000 cmp dword ptr [esp+54], 4550 ; 比较PE标志 |. 75 3E jnz short 00406CFE
然后读取磁盘文件映像的前面的0x1000:
代码:
0012F9A0 00406CF5 /CALL 到 ReadFile 来自 LordPE.00406CF3 0012F9A4 00000150 |hFile = 00000150 (window) 0012F9A8 011A0020 |Buffer = 011A0020 0012F9AC 00001000 |BytesToRead = 1000 (4096.) 0012F9B0 0012F9C8 |pBytesRead = 0012F9C8 0012F9B4 00000000 \pOverlapped = NULL
然后通过ImageNtHeader获取内存中映像的指针。
代码:
call dword ptr [<&IMAGEHLP.ImageNtHea>; IMAGEHLP.ImageNtHeader xor edx, edx ;测试获取的PE指针是否为0 cmp eax, edx je short 0041640D xor ecx, ecx mov cx, word ptr [eax+14] ;PE可选头的大小 lea ecx, dword ptr [ecx+eax+18] ;代码段的起始RVA mov dword ptr [ebp-4], edx mov dword ptr [ebp-1C], edx xor esi, esi mov si, word ptr [eax+6] ;块的数目 cmp edx, esi jnb short 004163D5 ;是否小于0 mov esi, dword ptr [ecx+C] ;该块的RVA mov dword ptr [ecx+14], esi ;该块的RVA移到PointToRawData(在文件中的偏移) mov esi, dword ptr [ecx+8] ;[ecx+8]该块的真实长度 mov dword ptr [ecx+10], esi ;[ecx+10]对齐后的长度,即修正文件对齐后的长度 add ecx, 28 ;转到下一块 mov dword ptr [ebp-20], ecx inc edx jmp short 004163B3 mov dword ptr [ebp-4], -1 mov ecx, 1000 mov dword ptr [eax+3C], ecx ;修正转存文件的文件对齐为0x1000 mov dword ptr [eax+54], ecx ;修正部首+块表的大小为0x1000
之后把DOS,PE头和内存中的块表和块的内容连接起来,写到磁盘上。
就完成了LordPe对内存文件的转存。
写完之后才发现,真的是一点技术含量都么有。
哎,希望能给大家一点启发吧。

第一次发表帖子,有不对的地方大家原谅吧。
