用OD跟踪金山游侠的部分代码并用汇编还原其功能

这是偶无聊的时候跟踪金山游侠的部分代码,并用汇编根据其程序流程写出了完整的代码,就当练练手吧!

0041EC32  /.  55            push    ebp                                        ;后面要用EBP读堆栈找外部参数所以就要先保存EBP
0041EC33  |.  8BEC          mov     ebp, esp                                   ;用EBP读堆栈,以为ESP在不断变化
0041EC35  |.  51            push    ecx
0041EC36  |.  56            push    esi
0041EC37  |.  57            push    edi                                        ;以上为保存3个寄存器的值
0041EC38  |.  FF71 20       push    dword ptr [ecx+20]                         ; /打开的进程ID,第三个参数
0041EC3B  |.  6A 00         push    0                                          ; |句柄是否可以被继承,0为不继承,第二个参数
0041EC3D  |.  6A 10         push    10                                         ; |打开进程权限,这里是读权限,第一个参数
0041EC3F  |.  FF15 78F34500 call    dword ptr [<&KERNEL32.OpenProcess>]        ; /打开进程函数,要使用就得先打开
0041EC45  |.  8BF0          mov     esi, eax                                   ;  把EAX中的返回句柄保存到ESI中
0041EC47  |.  85F6          test    esi, esi                                   ;  测试ESI,就是看函数是否执行成功
0041EC49  |.  74 35         je      short 0041EC80                             ;  不成功的话跳到子程序末尾
0041EC4B  |.  8B7D 10       mov     edi, dword ptr [ebp+10]                    ;  把外部第3个参数保存到EDI
0041EC4E  |.  8D45 FC       lea     eax, dword ptr [ebp-4]                     ;  PUSH ECX时在内存中的值
0041EC51  |.  50            push    eax                                        ; /返回实际读取数,第五个参数
0041EC52  |.  57            push    edi                                        ; |要读写的字节数[EBP+10]中的值,第四个参数
0041EC53  |.  FF75 0C       push    dword ptr [ebp+C]                          ; |接收读取数值的缓冲区,第三个参数
0041EC56  |.  8365 FC 00    and     dword ptr [ebp-4], 0                       ; |把返回实际读取数缓冲区初始为0
0041EC5A  |.  FF75 08       push    dword ptr [ebp+8]                          ; |起始地址,第二个参数
0041EC5D  |.  56            push    esi                                        ; |句柄,第一个参数
0041EC5E  |.  FF15 74F34500 call    dword ptr [<&KERNEL32.ReadProcessMemory>]  ; /读进程内存
0041EC64  |.  85C0          test    eax, eax                                   ;  测试函数返回值
0041EC66  |.  74 11         je      short 0041EC79                             ;  不成功的话跳到子程序末尾
0041EC68  |.  397D FC       cmp     dword ptr [ebp-4], edi                     ;  比较设定读取长度和返回长度是否一样
0041EC6B  |.  75 0C         jnz     short 0041EC79                             ;  不一样的话跳到子程序末尾
0041EC6D  |.  56            push    esi                                        ; /进程ID,第一个参数
0041EC6E  |.  FF15 A0F34500 call    dword ptr [<&KERNEL32.CloseHandle>]        ; /结束进程
0041EC74  |.  6A 01         push    1                                          ;把1压入堆栈
0041EC76  |.  58            pop     eax                                        ;把刚才的1弹到EAX
0041EC77  |.  EB 09         jmp     short 0041EC82                             ;无条件跳
0041EC79  |>  56            push    esi                                        ; /进程ID,第一个参数
0041EC7A  |.  FF15 A0F34500 call    dword ptr [<&KERNEL32.CloseHandle>]        ; /结束进程
0041EC80  |>  33C0          xor     eax, eax                                   ;EAX清O
0041EC82  |>  5F            pop     edi
0041EC83  |.  5E            pop     esi                                        ;把先前保存的EDI和ESI还原
0041EC84  |.  C9            leave
0041EC85  /.  C2 0C00       retn    0C                                         ;返回并清理堆栈中12个字节

 

以下是用汇编写的代码,为了大家能看懂我没大量使用汇编指令,我使用高级语言的结构描述
_myReadProcessMemory    proc   uses edi esi lpBaseAddress,lpBuffer,dwSize ;
                       local  @lpNumberOfByteRead                         ;局部变量,保存返回读取的实际字数

                       invoke  OpenProcess,PROCESS_VM_READ,NULL,          ;以读的方式打开进程,最后一个参数是进程句柄我没写,因为我不知道push dword ptr [ecx+20]是怎么得到进程句柄的,谁能告诉我?
                       mov     esi, eax                                   ;把EAX中的返回句柄保存到ESI中
                       .if  esi == 1                                      ;判断函数是否执行成功
                            mov  edi,dwSize                               ;把dwSize参数保存到EDI
                            lea  eax,@lpNumberOfByteRead                  ;把@lpNumberOfByteRead地址装到EAX里
                            invoke  ReadProcessMemory,esi,lpBaseAddress,lpBuffer,dwSize,eax  ;读内存
                            .if eax == 1                                  ;判断函数是否执行成功
                               .if @lpNumberOfByteRead == edi             ;比较设定读取长度和返回长度是否一样
                                       invoke  CloseHandle,esi            ;结束进程
                                       push 1                             ;把1压入堆栈
                                       pop  eax                           ;把刚才的1弹到EAX做为返回值,因为程序返回时默认把返回值压到EAX中
                                       jmp  _end                          ;条到结尾
                               .endif
                            .endif
                            invoke  CloseHandle,esi                       ;结束进程
                        .endif
                        xor eax,eax                                       ;EAX清O,因为程序返回时默认把返回值压到EAX中,返回0说明没执行成功
_end:
                        ret                                               ;返回
_myReadProcessMemory    endp

 

BY:晓斌
QQ:6750333
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值