基本知识介绍:
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

不常发帖,排版排的好烂,将就着看吧,今天才发现排版这么累。。。

  • 标 题:答复
  • 作 者:backer
  • 时 间:2008-11-15 14:57

里面对虚拟地址的分配描叙有误。
每个进程可以使用4G的线性地址空间,但nimda说的“线程都分配了一个4G的虚拟内存”是错误的。首先是线性地址空间不表示就会分配内存,也就是说地址为00400000的模块,不见得前面就有3fffffff的内存被分配,简单地说,就是虚拟内存空间和线性地址空间不是一个概念,具体请查阅保护模式课程中的笔记。
还有就是描叙为每个线程都有4G虚拟内存,这个就更错了,线性地址和进程的对应关系在KPROCESS里面描叙,也就是说某进程不管多少个线程,其地址空间是各个线程共用的,并不是各个线程独立。
最后,4G的线性地址空间里面其实也有水分,一般高2G的地址作为系统使用了(>=80000000),/3GB以后,高1G的空间作为系统使用(>=C0000000)。


由此产生的不便,望大家原谅。