基本知识介绍:
PE文件在运行时会将文件拉伸后按照PE格式映射到内存中,而每个进程都分配了一个4G的虚拟内存(高2G是所有应用程序共享的系统内存区域,低2G为每个应用程序独享),这样可以通过ReadProcessMemory 、WriteProcessMemory这两个API读取进程中被拉伸的PE文件镜像,并将其按照PE格式保存起来,这样就可以把程序dump下来了。
这次分析的不是OD的dump,而是OD中的“保存到可执行文件“的功能,即内存补丁。
下面具体分析:
OD是基于消息处理的,文件的内存补丁也不例外,这里有两种情况:
1. 将选择部分的代码替换原可执行文件的代码,并另存为一个可执行文件;
2. 将所有改动部分的代码替换原可执行文件中的代码,并另存为一个可执行文件。
经过分析,这两种情况的代码处理有一些不同,这里给出两种情况的处理步骤:
第一种情况:
1. 将选择部分的RVA转换成文件偏移,并检查是否在合理范围内;
2. 将调试程序的路径广播出去,检查是否广播成功;
3. 创建内存dump窗口,将整个程序加载到内存中;
4. 发送检查消息,检查新建窗口是否更新成功;
5. 读取选择部分的代码,存放到一块申请的内存空间,检查是否申请成功和读取成功;
6. 检查选择部分里面的代码是否被修改过,修改的部分是否包含重定位表区,都给出相应的错误提示;
7. 最后如果都成功的话,将选择部分中修改的机器码都用反汇编方式显示在dump窗口中。
第二种情况:
1. 将内存中代码段的内容都复制到一块申请的空间中,并检错;
2. 对代码段的内容与程序原文件做逐行汇编代码比较,如果出现不同则逐个机器码比较,若出现三次相同后退出逐个机器码比较,继续逐行比较;
3. 将所有不同的地方找出来后,会有提示对话框是否全部复制,然后创建dump窗口,将整个程序我呢舰映射到内存中;
4. 下面的过程和第一种情况的4~7类似。
1)第一种情况:
将选择部分的首地址RVA转换成文件偏移:
00424B37 . C785 28D8FFFF>mov dword ptr [ebp-27D8], 9011
00424B41 . 8B15 2DDA4C00 mov edx, dword ptr [4CDA2D]
00424B47 . 52 push edx
00424B48 . 56 push esi
00424B49 . E8 0A940300 call _Findfileoffset
00424B4E . 83C4 08 add esp, 8
将首地址文件偏移保存到两个局部变量中:
00424B51 . 8985 30D8FFFF mov dword ptr [ebp-27D0], eax
00424B57 . 8985 2CD8FFFF mov dword ptr [ebp-27D4], eax
将选择部分的尾地址RVA转换成文件偏移:
00424B5D . 8B15 31DA4C00 mov edx, dword ptr [4CDA31]
00424B63 . 4A dec edx
00424B64 . 52 push edx
00424B65 . 56 push esi
00424B66 . E8 ED930300 call _Findfileoffset
00424B6B . 83C4 08 add esp, 8
将尾地址文件偏移保存到一个局部变量中,如果转换失败,则跳过设置局部变量为1的代码:
00424B6E . 8985 34D8FFFF mov dword ptr [ebp-27CC], eax
00424B74 . 83BD 34D8FFFF>cmp dword ptr [ebp-27CC], 0
;检查转换是否失败
00424B7B . 74 06 je short 00424B83 ;转换失败则跳过下行代码
00424B7D . FF85 34D8FFFF inc dword ptr [ebp-27CC] ;
计算首尾的RVA间隔以及文件偏移间隔是否相同,如果不同则报错并结束:
00424B83 > 8B8D 34D8FFFF mov ecx, dword ptr [ebp-27CC]
00424B89 . A1 31DA4C00 mov eax, dword ptr [4CDA31]
;eax = RVA_range
00424B8E . 2B05 2DDA4C00 sub eax, dword ptr [4CDA2D]
00424B94 . 2B8D 30D8FFFF sub ecx, dword ptr [ebp-27D0] ; ecx = file_range
00424B9A . 3BC8 cmp ecx, eax
00424B9C . 74 12 je short 00424BB0
00424B9E . 68 11494B00 push 004B4911
00424BA3 . E8 74F40200 call _Error
00424BA8 . 59 pop ecx
00424BA9 . 33C0 xor eax, eax ;返回0
;跳转到结束处将调试程序路径广播到每个子窗体中,并检查是否广播成功:
00424BAB . E9 87120000 jmp 00425E37
00424BB0 > 33D2 xor edx, edx
00424BB2 . 8995 38D8FFFF mov dword ptr [ebp-27C8], edx
00424BB8 . 8D4E 50 lea ecx, dword ptr [esi+50]
00424BBB . 51 push ecx
00424BBC . 8D85 28D8FFFF lea eax, dword ptr [ebp-27D8]
00424BC2 . 50 push eax
00424BC3 . 68 72040000 push 472 ; |Arg1 = 00000472
00424BC8 . E8 A7580300 call _Broadcast
00424BCD . 83C4 0C add esp, 0C
00424BD0 . 3D 34120000 cmp eax, 1234 ;检查返回值
;文件映射失败则跳转到检查标识处
00424BD5 . 74 40 je short 00424C17
创建dump窗口,该函数下面会具体分析:
00424BD7 . 6A 00 push 0 ; /Arg6 = 00000000
00424BD9 . 68 11900000 push 9011 ; |Arg5 = 00009011
00424BDE . 8B95 2CD8FFFF mov edx, dword ptr [ebp-27D4]
00424BE4 . 52 push edx ; |Arg4
00424BE5 . 6A 00 push 0 ; |Arg3 = 00000000
00424BE7 . 6A 00 push 0 ; |Arg2 = 00000000
00424BE9 . 8D4E 50 lea ecx, dword ptr [esi+50]
00424BEC . 51 push ecx ; |Arg1
00424BED . E8 62E50200 call _Createdumpwindow
00424BF2 . 83C4 18 add esp, 18
发送消息,检查调试程序是否正确加载到内存中:
00424BF5 . 8985 74FFFFFF mov dword ptr [ebp-8C], eax
00424BFB . 8D46 50 lea eax, dword ptr [esi+50]
00424BFE . 50 push eax ; /lParam
00424BFF . 8D95 28D8FFFF lea edx, dword ptr [ebp-27D8]
00424C05 . 52 push edx ; |wParam
00424C06 . 68 72040000 push 472 ; |Message = MSG(472)
00424C0B . 8B8D 74FFFFFF mov ecx, dword ptr [ebp-8C] ; |
00424C11 . 51 push ecx ; |hWnd
00424C12 . E8 59A90800 call <jmp.&USER32.SendMessageA>
检查是否加载成功,失败则跳转到错误处理:
00424C17 > 83BD 38D8FFFF>cmp dword ptr [ebp-27C8], 0
00424C1E . 74 0E je short 00424C2E ;失败则跳转到错误处理
00424C20 . 8B85 34D8FFFF mov eax, dword ptr [ebp-27CC]
00424C26 . 3B85 3CD8FFFF cmp eax, dword ptr [ebp-27C4]
00424C2C . 76 12 jbe short 00424C40
这里为加载程序失败处理处,弹出错误窗口,并退出:
00424C2E > 68 11494B00 push 004B4911 ; /Arg1 = 004B4911
00424C33 . E8 E4F30200 call _Error ; \_Error
00424C38 . 59 pop ecx
00424C39 . 33C0 xor eax, eax ;返回0
00424C3B . E9 F7110000 jmp 00425E37 ;跳转到最后恢复现场
经过上面的错误检查,创建一块内存用于存放选择的部分的代码,并检查是否申请成功:
00424C40 > 8B15 31DA4C00 mov edx, dword ptr [4CDA31] ;选择的首地址
00424C46 . 2B15 2DDA4C00 sub edx, dword ptr [4CDA2D] ;选择的尾地址
00424C4C . 8955 AC mov dword ptr [ebp-54], edx ;得到选择的代码长度
00424C4F . 8B4D AC mov ecx, dword ptr [ebp-54]
00424C52 . 51 push ecx ; /MemSize
00424C53 . 6A 00 push 0 ; |Flags = GMEM_FIXED
00424C55 . E8 96A40800 call <jmp.&KERNEL32.GlobalAlloc> ; \GlobalAlloc
00424C5A . 8945 84 mov dword ptr [ebp-7C], eax
00424C5D . 837D 84 00 cmp dword ptr [ebp-7C], 0 ;检查是否申请内存成功
00424C61 . 75 18 jnz short 00424C7B ;成功则跳过错误处理
00424C63 . 8B45 AC mov eax, dword ptr [ebp-54]
00424C66 . 50 push eax ; /Arg2
00424C67 . 68 3A494B00 push 004B493A ; |Arg1 = 004B493A
00424C6C . E8 ABF30200 call _Error ; \_Error
00424C71 . 83C4 08 add esp, 8
00424C74 . 33C0 xor eax, eax ;返回0
00424C76 . E9 BC110000 jmp 00425E37 ;跳转到最后恢复现场
然后从内存中读取选择部分的代码放入刚申请的内存空间中,并检查读取是否成功:
00424C7B > 6A 01 push 1 ; /Arg4 = 00000001
00424C7D . 8B0D 2DDA4C00 mov ecx, dword ptr [4CDA2D] ; |Ollydbg.0040052A
00424C83 . 8B55 AC mov edx, dword ptr [ebp-54] ; |
00424C86 . 52 push edx ; |Arg3
00424C87 . 51 push ecx ; |Arg2 => 0040052A
00424C88 . 8B45 84 mov eax, dword ptr [ebp-7C] ; |
00424C8B . 50 push eax ; |Arg1
00424C8C . E8 7BC60300 call _Readmemory ; \_Readmemory
00424C91 . 83C4 10 add esp, 10
00424C94 . 3B45 AC cmp eax, dword ptr [ebp-54] ;检查读取到的数目
00424C97 . 0F85 5A030000 jnz 00424FF7 ;如果读取不完整,则释放内存并退出
检查选择部分的代码是否在主模块中,并检查是否有修改的代码,如果有则返回一个结构体数组,里面包括修改处的首地址及长度,否则返回0值:
00424C9D . 33D2 xor edx, edx
00424C9F . 8B0D 2DDA4C00 mov ecx, dword ptr [4CDA2D] ;选择的首地址
00424CA5 . 8955 D4 mov dword ptr [ebp-2C], edx
00424CA8 . 51 push ecx ; /Arg2 => 0040052A
00424CA9 . 56 push esi ; |Arg1
00424CAA . E8 D1910300 call _Findfixup ; \_Findfixup
00424CAF . 83C4 08 add esp, 8
00424CB2 . 8BF8 mov edi, eax
00424CB4 . 85FF test edi, edi ;检查得到的是否是0值
00424CB6 . 0F84 07030000 je 00424FC3 ;为0值不用进一步检查
00424CBC . E9 D9010000 jmp 00424E9A ;得到地址后进一步检查其位置
下面开始检查选择部分代码是否包含被修改过的代码,如果有,则将修改过的代码复制到为dump创建的程序代码空间中的相应位置:
00424CC1 > 837F 04 04 cmp dword ptr [edi+4], 4
00424CC5 . 74 0C je short 00424CD3
00424CC7 . C745 D4 01000>mov dword ptr [ebp-2C], 1
00424CCE . E9 C4010000 jmp 00424E97
这部分用于检查选择部分代码的首地址之前是不是有被修改过的代码,如果有就有两步操作,分别是将修改过的代码复制到两个程序代码空间的相应位置(一个为RVA一个为文件偏移):
00424CD3 > 8B07 mov eax, dword ptr [edi]
00424CD5 . 3B05 2DDA4C00 cmp eax, dword ptr [4CDA2D] ;choose_addr_begin
00424CDB . 0F83 9F000000 jnb 00424D80
00424CE1 . 33D2 xor edx, edx
00424CE3 . 8B0D 2DDA4C00 mov ecx, dword ptr [4CDA2D] ;choose_addr_begin
00424CE9 . 8955 C4 mov dword ptr [ebp-3C], edx
00424CEC . B8 04000000 mov eax, 4
00424CF1 . 2B0F sub ecx, dword ptr [edi]
00424CF3 . 2BC1 sub eax, ecx
00424CF5 . 8D4D C4 lea ecx, dword ptr [ebp-3C]
00424CF8 . 50 push eax
00424CF9 . 030D 2DDA4C00 add ecx, dword ptr [4CDA2D] ;choose_addr_begin
00424CFF . 8B55 84 mov edx, dword ptr [ebp-7C]
00424D02 . 52 push edx
00424D03 . 2B0F sub ecx, dword ptr [edi]
00424D05 . 51 push ecx
00424D06 . E8 25E80700 call 004A3530 ;memcpy
00424D0B . 33C0 xor eax, eax
00424D0D . 8B15 2DDA4C00 mov edx, dword ptr [4CDA2D] ;choose_addr_begin
00424D13 . 8945 9C mov dword ptr [ebp-64], eax
00424D16 . 83C4 0C add esp, 0C
00424D19 . 2B17 sub edx, dword ptr [edi]
00424D1B . B9 04000000 mov ecx, 4
00424D20 . 2BCA sub ecx, edx
00424D22 . 8D55 9C lea edx, dword ptr [ebp-64]
00424D25 . 51 push ecx
00424D26 . 0315 2DDA4C00 add edx, dword ptr [4CDA2D] ; choose_addr_begin
00424D2C . 8B85 38D8FFFF mov eax, dword ptr [ebp-27C8]
00424D32 . 0385 30D8FFFF add eax, dword ptr [ebp-27D0]
00424D38 . 50 push eax
00424D39 . 2B17 sub edx, dword ptr [edi]
00424D3B . 52 push edx
00424D3C . E8 EFE70700 call 004A3530 ;memcpy
00424D41 . 8B0D 2DDA4C00 mov ecx, dword ptr [4CDA2D] ; choose_addr_begin
00424D47 . 83C8 FF or eax, FFFFFFFF
00424D4A . 2B0F sub ecx, dword ptr [edi]
00424D4C . 83C4 0C add esp, 0C
00424D4F . C1E1 03 shl ecx, 3
00424D52 . D3E0 shl eax, cl
00424D54 . 8945 98 mov dword ptr [ebp-68], eax
00424D57 . 8B55 C4 mov edx, dword ptr [ebp-3C]
00424D5A . 8B4D 9C mov ecx, dword ptr [ebp-64]
00424D5D . 2B8E 60010000 sub ecx, dword ptr [esi+160]
00424D63 . 2B16 sub edx, dword ptr [esi]
00424D65 . 33D1 xor edx, ecx
00424D67 . 2355 98 and edx, dword ptr [ebp-68]
00424D6A . 8955 C4 mov dword ptr [ebp-3C], edx
00424D6D . 837D C4 00 cmp dword ptr [ebp-3C], 0
00424D71 . 0F84 20010000 je 00424E97
00424D77 . 834D D4 02 or dword ptr [ebp-2C], 2
00424D7B . E9 17010000 jmp 00424E97
这部分用于检查选择部分代码的尾地址之后是不是有被修改过的代码,如果有就有两步操作,分别是将修改过的代码复制到两个程序代码空间的相应位置(一个为RVA一个为文件偏移):
00424D80 > 8B07 mov eax, dword ptr [edi]
00424D82 . 83C0 04 add eax, 4
00424D85 . 3B05 31DA4C00 cmp eax, dword ptr [4CDA31] ; choose_addr_end
00424D8B . 0F86 8E000000 jbe 00424E1F
00424D91 . 33D2 xor edx, edx
00424D93 . 8955 C4 mov dword ptr [ebp-3C], edx
00424D96 . 8B0D 31DA4C00 mov ecx, dword ptr [4CDA31] ; choose_addr_end
00424D9C . 2B0F sub ecx, dword ptr [edi]
00424D9E . 51 push ecx ; /Arg3
00424D9F . 8B07 mov eax, dword ptr [edi] ; |
00424DA1 . 0345 84 add eax, dword ptr [ebp-7C] ; |
00424DA4 . 2B05 2DDA4C00 sub eax, dword ptr [4CDA2D] ; | choose_addr_size
00424DAA . 50 push eax ; |Arg2
00424DAB . 8D55 C4 lea edx, dword ptr [ebp-3C] ; |
00424DAE . 52 push edx ; |Arg1
00424DAF . E8 7CE70700 call 004A3530 ; memcpy
00424DB4 . 83C4 0C add esp, 0C
00424DB7 . 33C9 xor ecx, ecx
00424DB9 . 894D 9C mov dword ptr [ebp-64], ecx
00424DBC . A1 31DA4C00 mov eax, dword ptr [4CDA31]
00424DC1 . 2B07 sub eax, dword ptr [edi]
00424DC3 . 50 push eax
00424DC4 . 8B95 38D8FFFF mov edx, dword ptr [ebp-27C8]
00424DCA . 0395 30D8FFFF add edx, dword ptr [ebp-27D0]
00424DD0 . 0317 add edx, dword ptr [edi]
00424DD2 . 2B15 2DDA4C00 sub edx, dword ptr [4CDA2D] ; choose_addr_size
00424DD8 . 52 push edx
00424DD9 . 8D4D 9C lea ecx, dword ptr [ebp-64]
00424DDC . 51 push ecx
00424DDD . E8 4EE70700 call 004A3530 ;memcpy
00424DE2 . B9 04000000 mov ecx, 4
00424DE7 . 83C8 FF or eax, FFFFFFFF
00424DEA . 2B0D 31DA4C00 sub ecx, dword ptr [4CDA31] ; choose_addr_end
00424DF0 . 83C4 0C add esp, 0C
00424DF3 . 030F add ecx, dword ptr [edi]
00424DF5 . C1E1 03 shl ecx, 3
00424DF8 . D3E8 shr eax, cl
00424DFA . 8945 98 mov dword ptr [ebp-68], eax
00424DFD . 8B45 9C mov eax, dword ptr [ebp-64]
00424E00 . 8B55 C4 mov edx, dword ptr [ebp-3C]
00424E03 . 2B16 sub edx, dword ptr [esi]
00424E05 . 2B86 60010000 sub eax, dword ptr [esi+160]
00424E0B . 33D0 xor edx, eax
00424E0D . 2355 98 and edx, dword ptr [ebp-68]
00424E10 . 8955 C4 mov dword ptr [ebp-3C], edx
00424E13 . 837D C4 00 cmp dword ptr [ebp-3C], 0
00424E17 . 74 7E je short 00424E97
00424E19 . 834D D4 02 or dword ptr [ebp-2C], 2
00424E1D . EB 78 jmp short 00424E97
这部分用于检查选择部分代码的首地址与尾地址之间是不是有被修改过的代码,如果有就有两步操作,分别是将修改过的代码复制到两个程序代码空间的相应位置(一个为RVA一个为文件偏移):
00424E1F > 6A 04 push 4 ; /Arg3 = 00000004
00424E21 . 8B17 mov edx, dword ptr [edi] ; |
00424E23 . 0355 84 add edx, dword ptr [ebp-7C] ; |
00424E26 . 2B15 2DDA4C00 sub edx, dword ptr [4CDA2D] ; | choose_addr_size
00424E2C . 52 push edx ; |Arg2
00424E2D . 8D4D C4 lea ecx, dword ptr [ebp-3C] ; |
00424E30 . 51 push ecx ; |Arg1
00424E31 . E8 FAE60700 call 004A3530 ; \memcpy
00424E36 . 83C4 0C add esp, 0C
00424E39 . 6A 04 push 4
00424E3B . 8B85 38D8FFFF mov eax, dword ptr [ebp-27C8]
00424E41 . 0385 30D8FFFF add eax, dword ptr [ebp-27D0]
00424E47 . 0307 add eax, dword ptr [edi]
00424E49 . 2B05 2DDA4C00 sub eax, dword ptr [4CDA2D] ;choose_addr_begin
00424E4F . 50 push eax
00424E50 . 8D55 9C lea edx, dword ptr [ebp-64]
00424E53 . 52 push edx
00424E54 . E8 D7E60700 call 004A3530 ;memcpy
00424E59 . 8B4D C4 mov ecx, dword ptr [ebp-3C]
00424E5C . 8B45 9C mov eax, dword ptr [ebp-64]
00424E5F . 2B86 60010000 sub eax, dword ptr [esi+160]
00424E65 . 2B0E sub ecx, dword ptr [esi]
00424E67 . 83C4 0C add esp, 0C
00424E6A . 3BC8 cmp ecx, eax
00424E6C . 74 29 je short 00424E97
00424E6E . 8B16 mov edx, dword ptr [esi]
00424E70 . 8D4D C4 lea ecx, dword ptr [ebp-3C]
00424E73 . 2B96 60010000 sub edx, dword ptr [esi+160]
00424E79 . 2955 C4 sub dword ptr [ebp-3C], edx
00424E7C . 6A 04 push 4 ; /Arg3 = 00000004
00424E7E . 51 push ecx ; |Arg2
00424E7F . 8B07 mov eax, dword ptr [edi] ; |
00424E81 . 0345 84 add eax, dword ptr [ebp-7C] ; |
00424E84 . 2B05 2DDA4C00 sub eax, dword ptr [4CDA2D] ; | choose_addr_begin
00424E8A . 50 push eax ; |Arg1
00424E8B . E8 A0E60700 call 004A3530 ; \memcpy
00424E90 . 83C4 0C add esp, 0C
00424E93 . 834D D4 01 or dword ptr [ebp-2C], 1
修改点结构体自加,指向下个修改点信息:
00424E97 > 83C7 08 add edi, 8
首先检查选择部分的代码是否为0,如果是则跳过代码检查:
00424E9A > 833F 00 cmp dword ptr [edi], 0
00424E9D . 74 0E je short 00424EAD ;跳过代码检查
检查模块中修改过部分的是否已经超出选择部分,如果没有超出继续copy下个修改处:
00424E9F . 8B17 mov edx, dword ptr [edi]
00424EA1 . 3B15 31DA4C00 cmp edx, dword ptr [4CDA31]
00424EA7 .^ 0F82 14FEFFFF jb 00424CC1 ;没超出则继续copy
检查选择部分是否在重定位表区域,并检查重定位表区是否被修改,根据修改地址的不同弹出不同的错误提示窗口,并要求确认对重定位表的更新:
……
……
这里为copy更改的代码到为dump准备的程序内存映射的相应位置,并发送广播消息:
00424FC3 > 837D D4 00 cmp dword ptr [ebp-2C], 0
00424FC7 . 75 2E jnz short 00424FF7
00424FC9 . 8B55 AC mov edx, dword ptr [ebp-54]
00424FCC . 52 push edx ; /Arg3
00424FCD . 8B4D 84 mov ecx, dword ptr [ebp-7C] ; |
00424FD0 . 51 push ecx ; |Arg2
00424FD1 . 8B85 38D8FFFF mov eax, dword ptr [ebp-27C8] ; |
00424FD7 . 0385 30D8FFFF add eax, dword ptr [ebp-27D0] ; |
00424FDD . 50 push eax ; |Arg1
00424FDE . E8 4DE50700 call 004A3530 ; \memcpy
00424FE3 . 83C4 0C add esp, 0C
00424FE6 . 6A 00 push 0 ; /Arg3 = 00000000
00424FE8 . 6A 00 push 0 ; |Arg2 = 00000000
00424FEA . 68 74040000 push 474 ; |Arg1 = 00000474
00424FEF . E8 80540300 call _Broadcast ; \_Broadcast
00424FF4 . 83C4 0C add esp, 0C
下面是读取失败的处理部分,主要释放已经申请的内存空间,并跳转到整个消息处理函数的后面:
00424FF7 > 8B55 84 mov edx, dword ptr [ebp-7C]
00424FFA . 52 push edx ; /hMem
00424FFB . E8 F6A00800 call <jmp.&KERNEL32.GlobalFree> ; \GlobalFree
2)第二种情况:
首先为代码段申请一块内存空间,并检查是否申请成功,如果失败则报错:
00425022 . 8B55 AC mov edx, dword ptr [ebp-54]
00425025 . 52 push edx ; /MemSize
00425026 . 6A 00 push 0 ; |Flags = GMEM_FIXED
00425028 . E8 C3A00800 call <jmp.&KERNEL32.GlobalAlloc> ; \GlobalAlloc
0042502D . 8945 84 mov dword ptr [ebp-7C], eax
00425030 . 837D 84 00 cmp dword ptr [ebp-7C], 0
00425034 . 75 18 jnz short 0042504E
00425036 . 8B4D AC mov ecx, dword ptr [ebp-54]
00425039 . 51 push ecx ; /Arg2
0042503A . 68 3A494B00 push 004B493A ; |Arg1 = 004B493A
0042503F . E8 D8EF0200 call _Error ; \_Error
00425044 . 83C4 08 add esp, 8
00425047 . 33C0 xor eax, eax
00425049 . E9 E90D0000 jmp 00425E37 ;跳转到结束处
然后将代码段中的所有内容都copy到申请到的内存中,并检查是否完全读取,若没有完全读取,则释放申请的内存,并退出:
0042504E > 6A 01 push 1 ; /Arg4 = 00000001
00425050 . 8B55 AC mov edx, dword ptr [ebp-54] ; |
00425053 . 52 push edx ; |Arg3
00425054 . 8B4D B0 mov ecx, dword ptr [ebp-50] ; |
00425057 . 51 push ecx ; |Arg2
00425058 . 8B45 84 mov eax, dword ptr [ebp-7C] ; |
0042505B . 50 push eax ; |Arg1
0042505C . E8 ABC20300 call _Readmemory ; \_Readmemory
00425061 . 83C4 10 add esp, 10
00425064 . 3B45 AC cmp eax, dword ptr [ebp-54] ;检查是否完全读取
00425067 . 74 10 je short 00425079
00425069 . 8B55 84 mov edx, dword ptr [ebp-7C]
0042506C . 52 push edx ; /hMem
0042506D . E8 84A00800 call <jmp.&KERNEL32.GlobalFree> ; \GlobalFree
00425072 . 33C0 xor eax, eax
00425074 . E9 BE0D0000 jmp 00425E37 ;跳转到结束处
下面是一个大的循环体,用于将代码段的内容反汇编,并检查是否有代码被修改;并将程序文件内存映射到一块申请的内存空间中,根据被修改过的代码修改对应的文件内存中的位置,并用一个dump窗口显示出来:
初始化一些用于循环的变量:
00425079 > 33D2 xor edx, edx
0042507B . 33C9 xor ecx, ecx
0042507D . 8955 F4 mov dword ptr [ebp-C], edx
00425080 . 894D E0 mov dword ptr [ebp-20], ecx
00425083 . 8B45 B0 mov eax, dword ptr [ebp-50]
00425086 . 8945 B8 mov dword ptr [ebp-48], eax
00425089 . E9 5E040000 jmp 004254EC
将代码段的机器码转换成一行汇编码:
0042508E > 8B55 B8 mov edx, dword ptr [ebp-48]
00425091 . 8955 BC mov dword ptr [ebp-44], edx
00425094 . 6A 01 push 1 ; /Arg6 = 00000001
00425096 . 6A 01 push 1 ; |Arg5 = 00000001
00425098 . 8B4D BC mov ecx, dword ptr [ebp-44] ; |
0042509B . 51 push ecx ; |Arg4
0042509C . 8B45 AC mov eax, dword ptr [ebp-54] ; |
0042509F . 50 push eax ; |Arg3
004250A0 . 8B55 B0 mov edx, dword ptr [ebp-50] ; |
004250A3 . 52 push edx ; |Arg2
004250A4 . 8B4D 84 mov ecx, dword ptr [ebp-7C] ; |
004250A7 . 51 push ecx ; |Arg1
004250A8 . E8 5F9A0500 call _Disassembleforward ; \_Disassembleforward
004250AD . 83C4 18 add esp, 18
比较代码段中的一行机器码是否与原程序相同,如果相同则比较下一行机器码:
004250B0 . 8945 B8 mov dword ptr [ebp-48], eax
004250B3 . 8B45 B8 mov eax, dword ptr [ebp-48]
004250B6 . 2B45 BC sub eax, dword ptr [ebp-44]
004250B9 . 50 push eax ; /Arg3
004250BA . 8B15 4DDA4C00 mov edx, dword ptr [4CDA4D] ; |
004250C0 . 0355 BC add edx, dword ptr [ebp-44] ; |
004250C3 . 2B55 B0 sub edx, dword ptr [ebp-50] ; |
004250C6 . 52 push edx ; |Arg2
004250C7 . 8B4D 84 mov ecx, dword ptr [ebp-7C] ; |
004250CA . 034D BC add ecx, dword ptr [ebp-44] ; |
004250CD . 2B4D B0 sub ecx, dword ptr [ebp-50] ; |
004250D0 . 51 push ecx ; |Arg1
004250D1 . E8 FEE60700 call 004A37D4 ; \memcmp
004250D6 . 83C4 0C add esp, 0C
004250D9 . 85C0 test eax, eax
004250DB . 0F84 0B040000 je 004254EC ;相同则跳转到下面检查是否比较完毕
如果不同则将不同的那行反汇编代码地址记录到一个局部变量中:
004250E1 . 8B45 B8 mov eax, dword ptr [ebp-48]
004250E4 . 8945 B4 mov dword ptr [ebp-4C], eax ;将不同的地址记录下来
004250E7 . 8BF8 mov edi, eax
004250E9 . 33C0 xor eax, eax
004250EB . 8945 F8 mov dword ptr [ebp-8], eax
004250EE . EB 56 jmp short 00425146 ;跳转到逐个比较处
机器码转换成汇编代码:
004250F0 > 6A 01 push 1 ; /Arg6 = 00000001
004250F2 . 6A 01 push 1 ; |Arg5 = 00000001
004250F4 . 57 push edi ; |Arg4
004250F5 . 8B55 AC mov edx, dword ptr [ebp-54] ; |
004250F8 . 52 push edx ; |Arg3
004250F9 . 8B4D B0 mov ecx, dword ptr [ebp-50] ; |
004250FC . 51 push ecx ; |Arg2
004250FD . 8B45 84 mov eax, dword ptr [ebp-7C] ; |
00425100 . 50 push eax ; |Arg1
00425101 . E8 069A0500 call _Disassembleforward ; \_Disassembleforward
00425106 . 8945 B4 mov dword ptr [ebp-4C], eax
00425109 . 83C4 18 add esp, 18
0042510C . 8B55 B4 mov edx, dword ptr [ebp-4C]
0042510F . 8B0D 4DDA4C00 mov ecx, dword ptr [4CDA4D]
00425115 . 2BD7 sub edx, edi
00425117 . 03CF add ecx, edi
00425119 . 52 push edx ; /Arg3
0042511A . 2B4D B0 sub ecx, dword ptr [ebp-50] ; |
0042511D . 51 push ecx ; |Arg2
0042511E . 8B45 84 mov eax, dword ptr [ebp-7C] ; |
00425121 . 03C7 add eax, edi ; |
00425123 . 2B45 B0 sub eax, dword ptr [ebp-50] ; |
00425126 . 50 push eax ; |Arg1
00425127 . E8 A8E60700 call 004A37D4 ; \Ollydbg.004A37D4
0042512C . 83C4 0C add esp, 0C
0042512F . 85C0 test eax, eax ;查看比较结果
00425131 . 75 05 jnz short 00425138 ;不同则跳过
记录相同的次数,如果有3次相同,则不再逐个机器码比较,继续一句一句往下比较:
00425133 . FF45 F8 inc dword ptr [ebp-8]
00425136 . EB 0B jmp short 00425143 ;跳过计数清零代码
00425138 > 33D2 xor edx, edx
0042513A . 8955 F8 mov dword ptr [ebp-8], edx
0042513D . 8B4D B4 mov ecx, dword ptr [ebp-4C]
00425140 . 894D B8 mov dword ptr [ebp-48], ecx
00425143 > 8B7D B4 mov edi, dword ptr [ebp-4C]
这里为出现不同代码处理处,从出现不同代码的地址开始,逐个机器码往下比较,直到有相同为止:
00425146 > 837D F8 02 cmp dword ptr [ebp-8], 2
0042514A . 7F 0B jg short 00425157
0042514C . 8B45 B0 mov eax, dword ptr [ebp-50]
0042514F . 0345 AC add eax, dword ptr [ebp-54]
00425152 . 3B45 B4 cmp eax, dword ptr [ebp-4C]
00425155 .^ 77 99 ja short 004250F0
将不同部分的机器码转换成汇编代码,并保存到为创建dump窗口准备的内存中:
00425157 > FF45 F4 inc dword ptr [ebp-C]
0042515A . 68 05800000 push 8005 ; /Arg3 = 00008005
0042515F . 8B55 B8 mov edx, dword ptr [ebp-48] ; |
00425162 . 2B55 BC sub edx, dword ptr [ebp-44] ; |
00425165 . 52 push edx ; |Arg2
00425166 . 8B4D BC mov ecx, dword ptr [ebp-44] ; |
00425169 . 51 push ecx ; |Arg1
0042516A . E8 358D0000 call _Setdisasm ; \_Setdisasm
0042516F . 83C4 0C add esp, 0C
00425172 . 8D45 EC lea eax, dword ptr [ebp-14]
00425175 . 50 push eax ; /Arg4
00425176 . 8D55 F0 lea edx, dword ptr [ebp-10] ; |
00425179 . 52 push edx ; |Arg3
0042517A . 6A 03 push 3 ; |Arg2 = 00000003
0042517C . 68 A8D64C00 push 004CD6A8 ; |Arg1 = 004CD6A8
00425181 . E8 12240200 call 00447598 ; \Ollydbg.00447598
00425186 . 83C4 10 add esp, 10
将不同部分的机器码的首、尾地址转换成文件偏移:
00425189 . C785 28D8FFFF>mov dword ptr [ebp-27D8], 9011
00425193 . 8B4D BC mov ecx, dword ptr [ebp-44] ;转换首地址
00425196 . 51 push ecx ; /Arg2
00425197 . 56 push esi ; |Arg1
00425198 . E8 BB8D0300 call _Findfileoffset ; \_Findfileoffset
0042519D . 8985 30D8FFFF mov dword ptr [ebp-27D0], eax
004251A3 . 8985 2CD8FFFF mov dword ptr [ebp-27D4], eax
004251A9 . 83C4 08 add esp, 8
004251AC . 8B55 B8 mov edx, dword ptr [ebp-48] ;转换尾地址
004251AF . 4A dec edx
004251B0 . 52 push edx ; /Arg2
004251B1 . 56 push esi ; |Arg1
004251B2 . E8 A18D0300 call _Findfileoffset ; \_Findfileoffset
004251B7 . 83C4 08 add esp, 8
004251BA . 8985 34D8FFFF mov dword ptr [ebp-27CC], eax
004251C0 . 83BD 34D8FFFF>cmp dword ptr [ebp-27CC], 0
004251C7 . 74 06 je short 004251CF
004251C9 . FF85 34D8FFFF inc dword ptr [ebp-27CC]
检查首、尾地址是否转换成功,若失败则弹出错误窗口,然后继续跳转到下面检查是否已经反汇编所有的代码段机器码:
004251CF > 8B4D B8 mov ecx, dword ptr [ebp-48]
004251D2 . 8B85 34D8FFFF mov eax, dword ptr [ebp-27CC]
004251D8 . 2B85 30D8FFFF sub eax, dword ptr [ebp-27D0]
004251DE . 2B4D BC sub ecx, dword ptr [ebp-44]
004251E1 . 3BC8 cmp ecx, eax
004251E3 . 74 24 je short 00425209
004251E5 . 8B55 EC mov edx, dword ptr [ebp-14]
004251E8 . A1 E1D84C00 mov eax, dword ptr [4CD8E1]
004251ED . 52 push edx ; /Arg5
004251EE . 8B4D F0 mov ecx, dword ptr [ebp-10] ; |
004251F1 . 51 push ecx ; |Arg4
004251F2 . 68 80000000 push 80 ; |Arg3 = 00000080
004251F7 . 50 push eax ; |Arg2 => 00000002
004251F8 . 68 11494B00 push 004B4911 ; |Arg1 = 004B4911
004251FD . E8 BA120200 call 004464BC ; \DialogBoxParam
00425202 . 83C4 14 add esp, 14
00425205 . 8BF8 mov edi, eax
00425207 . EB 2D jmp short 00425236 ;跳转到条件比较处
00425209 > 837D E0 00 cmp dword ptr [ebp-20], 0
0042520D . 74 07 je short 00425216
0042520F . BF 01000000 mov edi, 1 ;设置继续比较的标识
00425214 . EB 20 jmp short 00425236 ;跳转到条件比较处
弹出窗口,显示提示信息(确定要复制选择部分到可执行文件吗?):
00425216 > 8B45 EC mov eax, dword ptr [ebp-14]
00425219 . 8B0D E1D84C00 mov ecx, dword ptr [4CD8E1]
0042521F . 50 push eax ; /Arg5
00425220 . 8B55 F0 mov edx, dword ptr [ebp-10] ; |
00425223 . 52 push edx ; |Arg4
00425224 . 6A 00 push 0 ; |Arg3 = 00000000
00425226 . 51 push ecx ; |Arg2 => 00000002
00425227 . 68 8C4B4B00 push 004B4B8C ; |Arg1 = 004B4B8C
0042522C . E8 8B120200 call 004464BC ; \DialogBoxParam
00425231 . 83C4 14 add esp, 14
00425234 . 8BF8 mov edi, eax
检查选择的按钮,根据选择确定是继续检查还是退出dump:
00425236 > 85FF test edi, edi ;检查选择的是什么
00425238 . 0F8C BD020000 jl 004254FB ;这里为跳转到退出
0042523E . 85FF test edi, edi
00425240 . 0F84 A6020000 je 004254EC ;这里为跳转到反汇编下条指令
00425246 . 83FF 02 cmp edi, 2
00425249 . 75 07 jnz short 00425252
0042524B . C745 E0 01000>mov dword ptr [ebp-20], 1
下面为发送一个自定义消息,用于检查所有子窗体,若已经创建dump窗体则跳过创建部分:
00425252 > 33C0 xor eax, eax
00425254 . 8985 38D8FFFF mov dword ptr [ebp-27C8], eax
0042525A . 8D56 50 lea edx, dword ptr [esi+50]
0042525D . 52 push edx ; /Arg3
0042525E . 8D8D 28D8FFFF lea ecx, dword ptr [ebp-27D8] ; |
00425264 . 51 push ecx ; |Arg2
00425265 . 68 72040000 push 472 ; |Arg1 = 00000472
0042526A . E8 05520300 call _Broadcast ; \_Broadcast
0042526F . 83C4 0C add esp, 0C
00425272 . 3D 34120000 cmp eax, 1234 ;检查消息返回的结果
00425277 . 74 40 je short 004252B9 ;若有创建就不再重复创建
创建dump显示信息子窗体,并发送消息表明窗口已经创建:
00425279 . 6A 00 push 0 ; /Arg6 = 00000000
0042527B . 68 11900000 push 9011 ; |Arg5 = 00009011
00425280 . 8B85 2CD8FFFF mov eax, dword ptr [ebp-27D4] ; |
00425286 . 50 push eax ; |Arg4
00425287 . 6A 00 push 0 ; |Arg3 = 00000000
00425289 . 6A 00 push 0 ; |Arg2 = 00000000
0042528B . 8D56 50 lea edx, dword ptr [esi+50] ; |
0042528E . 52 push edx ; |Arg1
0042528F . E8 C0DE0200 call _Createdumpwindow ; \_Createdumpwindow
00425294 . 83C4 18 add esp, 18
00425297 . 8985 74FFFFFF mov dword ptr [ebp-8C], eax
0042529D . 8D4E 50 lea ecx, dword ptr [esi+50]
004252A0 . 51 push ecx ; /lParam
004252A1 . 8D85 28D8FFFF lea eax, dword ptr [ebp-27D8] ; |
004252A7 . 50 push eax ; |wParam
004252A8 . 68 72040000 push 472 ; |Message = MSG(472)
004252AD . 8B95 74FFFFFF mov edx, dword ptr [ebp-8C] ; |
004252B3 . 52 push edx ; |hWnd
004252B4 . E8 B7A20800 call <jmp.&USER32.SendMessageA> ; \SendMessageA
检查程序文件映射是否创建,若没有创建则显示提示信息,并且检查下一行汇编指令:
004252B9 > 83BD 38D8FFFF>cmp dword ptr [ebp-27C8], 0
004252C0 . 74 0E je short 004252D0
004252C2 . 8B8D 34D8FFFF mov ecx, dword ptr [ebp-27CC]
004252C8 . 3B8D 3CD8FFFF cmp ecx, dword ptr [ebp-27C4]
004252CE . 76 30 jbe short 00425300
004252D0 > 8B45 EC mov eax, dword ptr [ebp-14]
004252D3 . 8B0D E1D84C00 mov ecx, dword ptr [4CD8E1]
004252D9 . 50 push eax ; /Arg5
004252DA . 8B55 F0 mov edx, dword ptr [ebp-10] ; |
004252DD . 52 push edx ; |Arg4
004252DE . 68 80000000 push 80 ; |Arg3 = 00000080
004252E3 . 51 push ecx ; |Arg2 => 00000002
004252E4 . 68 11494B00 push 004B4911 ; |Arg1 = 004B4911
004252E9 . E8 CE110200 call 004464BC ; \Ollydbg.004464BC
004252EE . 83C4 14 add esp, 14
004252F1 . 8BF8 mov edi, eax
004252F3 . 85FF test edi, edi
004252F5 . 0F8C 00020000 jl 004254FB
004252FB . E9 EC010000 jmp 004254EC
这部分通过findfixup函数得到代码段中哪些位置的代码是被修改过的:
00425300 > 33C0 xor eax, eax
00425302 . 8945 D4 mov dword ptr [ebp-2C], eax
00425305 . 8B55 BC mov edx, dword ptr [ebp-44]
00425308 . 52 push edx ; /Arg2
00425309 . 56 push esi ; |Arg1
0042530A . E8 718B0300 call _Findfixup ; \_Findfixup
0042530F . 83C4 08 add esp, 8
00425312 . 8BF8 mov edi, eax
00425314 . 85FF test edi, edi
00425316 . 0F84 A4010000 je 004254C0
0042531C . E9 A6000000 jmp 004253C7
通过上面函数返回的结构体,即一个指向每个被修改地址的指针和大小,将每个修改的代码一一覆盖调试程序的文件映射:
00425321 > 837F 04 04 cmp dword ptr [edi+4], 4
00425325 . 74 0C je short 00425333
00425327 . C745 D4 01000>mov dword ptr [ebp-2C], 1
0042532E . E9 91000000 jmp 004253C4
00425333 > 8B07 mov eax, dword ptr [edi]
00425335 . 3B45 B0 cmp eax, dword ptr [ebp-50]
00425338 . 72 0F jb short 00425349
0042533A . 8B17 mov edx, dword ptr [edi]
0042533C . 8B4D B0 mov ecx, dword ptr [ebp-50]
0042533F . 034D AC add ecx, dword ptr [ebp-54]
00425342 . 0357 04 add edx, dword ptr [edi+4]
00425345 . 3BD1 cmp edx, ecx
00425347 . 76 09 jbe short 00425352
00425349 > C745 D4 01000>mov dword ptr [ebp-2C], 1
00425350 . EB 72 jmp short 004253C4
00425352 > 6A 04 push 4 ; /Arg3 = 00000004
00425354 . 8B07 mov eax, dword ptr [edi] ; |
00425356 . 2B45 B0 sub eax, dword ptr [ebp-50] ; |
00425359 . 0345 84 add eax, dword ptr [ebp-7C] ; |
0042535C . 50 push eax ; |Arg2
0042535D . 8D55 C4 lea edx, dword ptr [ebp-3C] ; |
00425360 . 52 push edx ; |Arg1
00425361 . E8 CAE10700 call 004A3530 ; \memcpy
00425366 . 83C4 0C add esp, 0C
00425369 . 6A 04 push 4
0042536B . 8B8D 38D8FFFF mov ecx, dword ptr [ebp-27C8]
00425371 . 038D 30D8FFFF add ecx, dword ptr [ebp-27D0]
00425377 . 030F add ecx, dword ptr [edi]
00425379 . 2B4D BC sub ecx, dword ptr [ebp-44]
0042537C . 51 push ecx
0042537D . 8D45 9C lea eax, dword ptr [ebp-64]
00425380 . 50 push eax
00425381 . E8 AAE10700 call 004A3530 ;memcpy
00425386 . 8B55 C4 mov edx, dword ptr [ebp-3C]
00425389 . 8B4D 9C mov ecx, dword ptr [ebp-64]
0042538C . 2B8E 60010000 sub ecx, dword ptr [esi+160]
00425392 . 2B16 sub edx, dword ptr [esi]
00425394 . 83C4 0C add esp, 0C
00425397 . 3BD1 cmp edx, ecx
00425399 . 74 29 je short 004253C4
0042539B . 8B06 mov eax, dword ptr [esi]
0042539D . 8D55 C4 lea edx, dword ptr [ebp-3C]
004253A0 . 2B86 60010000 sub eax, dword ptr [esi+160]
004253A6 . 2945 C4 sub dword ptr [ebp-3C], eax
004253A9 . 6A 04 push 4 ; /Arg3 = 00000004
004253AB . 52 push edx ; |Arg2
004253AC . 8B0F mov ecx, dword ptr [edi] ; |
004253AE . 034D 84 add ecx, dword ptr [ebp-7C] ; |
004253B1 . 2B4D B0 sub ecx, dword ptr [ebp-50] ; |
004253B4 . 51 push ecx ; |Arg1
004253B5 . E8 76E10700 call 004A3530 ; \memcpy
004253BA . C745 D4 01000>mov dword ptr [ebp-2C], 1
004253C1 . 83C4 0C add esp, 0C
004253C4 > 83C7 08 add edi, 8
这部分代码用于检查是否更改了重定位表,并给出相应的提示信息:
……
……
到这里已经得到文件映射中需要修改的代码的首地址以及字节数,用修改后的代码覆盖文件映射中的代码即可:
004254C6 . 8B55 B8 mov edx, dword ptr [ebp-48]
004254C9 . 2B55 BC sub edx, dword ptr [ebp-44]
004254CC . 52 push edx ; /Arg3
004254CD . 8B4D 84 mov ecx, dword ptr [ebp-7C] ; |
004254D0 . 034D BC add ecx, dword ptr [ebp-44] ; |
004254D3 . 2B4D B0 sub ecx, dword ptr [ebp-50] ; |
004254D6 . 51 push ecx ; |Arg2
004254D7 . 8B85 38D8FFFF mov eax, dword ptr [ebp-27C8] ; |
004254DD . 0385 30D8FFFF add eax, dword ptr [ebp-27D0] ; |
004254E3 . 50 push eax ; |Arg1
004254E4 . E8 47E00700 call 004A3530 ; \memcpy
004254E9 . 83C4 0C add esp, 0C
检查是否已经反汇编完毕,没有则继续反汇编:
004254EC > 8B55 B0 mov edx, dword ptr [ebp-50]
004254EF . 0355 AC add edx, dword ptr [ebp-54]
004254F2 . 3B55 B8 cmp edx, dword ptr [ebp-48]
004254F5 .^ 0F87 93FBFFFF ja 0042508E
最后分析OD的导出函数Createdumpwindow,该函数用于读取调试程序到内存,下面给出机器代码并分析:
注册窗口类,用于创建一个存放需要保存文件的窗口:
00453154 >/$ 55 push ebp
00453155 |. 8BEC mov ebp, esp
00453157 |. 81C4 E8FDFFFF add esp, -218
0045315D |. 33C0 xor eax, eax
0045315F |. 53 push ebx
00453160 |. 56 push esi
00453161 |. 57 push edi
00453162 |. 8B7D 10 mov edi, dword ptr [ebp+10]
00453165 |. 8B75 0C mov esi, dword ptr [ebp+C]
00453168 |. 8945 EC mov dword ptr [ebp-14], eax
0045316B |. 85FF test edi, edi
0045316D |. 75 09 jnz short 00453178
0045316F |. C745 F8 4AB24>mov dword ptr [ebp-8], 004BB24A ; ASCII "ADUMPFILE"
00453176 |. EB 07 jmp short 0045317F
00453178 |> C745 F8 54B24>mov dword ptr [ebp-8], 004BB254 ; ASCII "ADUMP"
0045317F |> 68 18E64400 push 0044E618 ; /Arg3 = 0044E618
00453184 |. 68 5AB24B00 push 004BB25A ; |Arg2 = 004BB25A ASCII "ICO_DUMP"
00453189 |. 8B55 F8 mov edx, dword ptr [ebp-8] ; |
0045318C |. 52 push edx ; |Arg1
0045318D |. E8 AA0F0000 call _Registerotclass ; \_Registerotclass
00453192 |. 83C4 0C add esp, 0C
00453195 |. 85C0 test eax, eax ;查看是否注册成功
00453197 |. 74 07 je short 004531A0 ;注册成功跳转到下面,否则返回0并退出
00453199 |. 33C0 xor eax, eax ;返回0
0045319B |. E9 6F030000 jmp 0045350F ;跳转到结束处
申请一个空间用于存放dump文件相关信息:
004531A0 |> 68 CD030000 push 3CD ; /MemSize = 3CD (973.)
004531A5 |. 6A 40 push 40 ; |Flags = GPTR
004531A7 |. E8 44BF0500 call <jmp.&KERNEL32.GlobalAlloc> ; \GlobalAlloc
下面是对申请空间的错误处理:
004531AC |. 8BD8 mov ebx, eax
004531AE |. 85DB test ebx, ebx ;申请空间是否成功
004531B0 |. 0F84 2D030000 je 004534E3 ;失败则跳转到最后处理部分
004531B6 |. 85FF test edi, edi
004531B8 |. 0F85 45010000 jnz 00453303
004531BE |. 837D 08 00 cmp dword ptr [ebp+8], 0 ;文件名是否存在
004531C2 |. 0F84 1B030000 je 004534E3 ;不存在则跳转到最后处理部分
004531C8 |. 8B45 08 mov eax, dword ptr [ebp+8]
004531CB |. 8038 00 cmp byte ptr [eax], 0 ;文件内容是否为空
004531CE |. 0F84 0F030000 je 004534E3 ;为空则跳转到最后处理部分
如果都成功则打开要读取的文件:
004531D4 |. 68 ECA44B00 push 004BA4EC ; /Arg2 = 004BA4EC ASCII "rb"
004531D9 |. 8B55 08 mov edx, dword ptr [ebp+8] ; |
004531DC |. 52 push edx ; |Arg1
004531DD |. E8 92210500 call 004A5374 ;fopen
004531E2 |. 83C4 08 add esp, 8
检查是否打开成功,如果失败则报错,并跳转到最后处理部分:
004531E5 |. 8945 EC mov dword ptr [ebp-14], eax
004531E8 |. 837D EC 00 cmp dword ptr [ebp-14], 0 ;检查是否打开文件
004531EC |. 75 16 jnz short 00453204 ;如果打开则跳过报错部分
004531EE |. 8B4D 08 mov ecx, dword ptr [ebp+8]
004531F1 |. 51 push ecx ; /Arg2
004531F2 |. 68 63B24B00 push 004BB263 ; |Arg1 = 004BB263
004531F7 |. E8 200E0000 call _Error ; \_Error
004531FC |. 83C4 08 add esp, 8
004531FF |. E9 DF020000 jmp 004534E3 ;跳转到最后处理部分
通过fseek移动到文件末尾,然后用ftell得到文件总大小:
00453204 |> 6A 02 push 2 ; /Arg3 = 00000002
00453206 |. 6A 00 push 0 ; |Arg2 = 00000000
00453208 |. 8B45 EC mov eax, dword ptr [ebp-14] ; |
0045320B |. 33F6 xor esi, esi ; |
0045320D |. 50 push eax ; |Arg1
0045320E |. E8 4D240500 call 004A5660 ; \fseek
00453213 |. 83C4 0C add esp, 0C
00453216 |. 8B55 EC mov edx, dword ptr [ebp-14]
00453219 |. 52 push edx ; /Arg1
0045321A |. E8 A5240500 call 004A56C4 ; \ftell
然后再将文件指针移动到文件开始处:
0045321F |. 59 pop ecx
00453220 |. 8BF8 mov edi, eax
00453222 |. 6A 00 push 0 ; /Arg3 = 00000000
00453224 |. 6A 00 push 0 ; |Arg2 = 00000000
00453226 |. 8B45 EC mov eax, dword ptr [ebp-14] ; |
00453229 |. 50 push eax ; |Arg1
0045322A |. E8 31240500 call 004A5660 ; \fseek
这里根据上面得到的文件大小申请一个空间用于存放文件:
0045322F |. 83C4 0C add esp, 0C
00453232 |. 57 push edi ; /MemSize
00453233 |. 6A 00 push 0 ; |Flags = GMEM_FIXED
00453235 |. E8 B6BE0500 call <jmp.&KERNEL32.GlobalAlloc> ; \GlobalAlloc
检查是否申请到空间,如果申请到,则跳过报错部分,否则跳转到最后处理部分:
0045323A |. 8983 A1030000 mov dword ptr [ebx+3A1], eax
00453240 |. 83BB A1030000>cmp dword ptr [ebx+3A1], 0 ;检查是否申请到空间
00453247 |. 75 17 jnz short 00453260 ;申请到则跳过报错部分
00453249 |. 8B55 08 mov edx, dword ptr [ebp+8]
0045324C |. 52 push edx ; /Arg3
0045324D |. 57 push edi ; |Arg2
0045324E |. 68 86B24B00 push 004BB286 ; |Arg1 = 004BB286
00453253 |. E8 C40D0000 call _Error ; \_Error
00453258 |. 83C4 0C add esp, 0C
0045325B |. E9 83020000 jmp 004534E3 ;跳转到最后处理部分
读取文件,将所有文件的内容都copy到刚才申请的内存中:
00453260 |> 8B4D EC mov ecx, dword ptr [ebp-14]
00453263 |. 51 push ecx ; /Arg4
00453264 |. 57 push edi ; |Arg3
00453265 |. 6A 01 push 1 ; |Arg2 = 00000001
00453267 |. 8B83 A1030000 mov eax, dword ptr [ebx+3A1] ; |
0045326D |. 50 push eax ; |Arg1
0045326E |. E8 5D230500 call 004A55D0 ; \fread
00453273 |. 83C4 10 add esp, 10
00453276 |. 3BF8 cmp edi, eax ;检查是否读取失败
00453278 |. 0F85 65020000 jnz 004534E3 ;失败则跳转到最后处理部分
读取完毕后关闭文件:
0045327E |. 8B55 EC mov edx, dword ptr [ebp-14]
00453281 |. 52 push edx ; /Arg1
00453282 |. E8 511C0500 call 004A4ED8 ; \Ollydbg.004A4ED8
中间部分只是保存文件信息和设置窗口属性,就不再详细分析了:
……
……
这里为申请空间不成功的处理处,主要用于释放两个申请的空间(一个是存放文件信息的空间、一个是存放文件内容的空间,释放之前都进行了判断):
004534E3 |> 85DB test ebx, ebx
004534E5 |. 74 16 je short 004534FD
004534E7 |. 8B83 A1030000 mov eax, dword ptr [ebx+3A1]
004534ED |. 85C0 test eax, eax
004534EF |. 74 06 je short 004534F7
004534F1 |. 50 push eax ; /hMem
004534F2 |. E8 FFBB0500 call <jmp.&KERNEL32.GlobalFree> ; \GlobalFree
004534F7 |> 53 push ebx ; /hMem
004534F8 |. E8 F9BB0500 call <jmp.&KERNEL32.GlobalFree> ; \GlobalFree
检查文件是否打开,打开则关闭文件,否则就跳过关闭部分:
004534FD |> 837D EC 00 cmp dword ptr [ebp-14], 0 ;检查是否打开文件
00453501 |. 74 0A je short 0045350D ;如果没打开就跳过
00453503 |. 8B55 EC mov edx, dword ptr [ebp-14]
00453506 |. 52 push edx
00453507 |. E8 CC190500 call 004A4ED8 ;fclose 关闭文件
0045350C |. 59 pop ecx
恢复现场,返回0:
0045350D |> 33C0 xor eax, eax
0045350F |> 5F pop edi
00453510 |. 5E pop esi
00453511 |. 5B pop ebx
00453512 |. 8BE5 mov esp, ebp
00453514 |. 5D pop ebp
00453515 \. C3 retn
不常发帖,排版排的好烂,将就着看吧,今天才发现排版这么累。。。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!