c语言异或 反汇编,[原创]qq反汇编日志(1,2,3,4)

1

2006-6-17 20:09

识别函数中的参数和局部变量

经过上面的分析我们已经知道在qq00405b55函数中参数和局部变量都是用ebp寄存器来表示的,现在我们来找出函数中的参数,和局部变量

首先:我们把函数中使用ebp寄存器寻找的变量找出来,删除重复的并按从低地址到高地址排序,得到如下结果:

ebp-54h

ebp-14h

ebp-10h

ebp-ch

ebp-4h

ebp+8h

ebp+ch

ebp+10h

ebp+18h

我们知道堆栈参数是:从ebp+8开始向高地址方向的,局部变量是从ebp-d开始向低地址方向的

现在给他们分组:

堆栈参数有:ebp+8h,ebp+ch,ebp+10h,ebp+18h,堆栈参数名我们规定从低地址开始编号_arg1,_arg2,_arg3,....,所以就有 :

ebp+8h = _arg1

ebp+ch = _arg2

ebp+10h = _arg3

ebp+18h = _arg4 少了一个 怎么没有ebp+14h 呢,_arg3 占了8个字节的地盘???先不管它,呆会分析参数类型的时候在看

局部变量有:ebp-10h,ebp-14h,ebp-54h,局部变量我们规定从高地址开始编号@var1,@var2,@var3,.....所以有:

ebp-10h = @var1        因为局部变量是从ebp-d开始的所以可知这个局部变量的大小为(10h-d)+1 4 byte

ebp-14h = @var2 同理:这个紧挨着@var1 可知他也为(14h-11h)+1 4 byte

ebp-54h = @var3 这是最后一个变量,它的大小为:(54h-15h)+1 = 40h byte

还有几个孤儿,没有组的,他们是ebp-ch,和ebp-4h,日至1中已经知道他们分别是seh指针和seh的附加数据

第二步:我们将参数名、局部变量名替换到反汇编代码中去,还有跳转地址我们也用相应的标号替换掉就得到了

mov     eax, 004CD25C

call    0046FCA0

sub     esp, 48

push    ebx

push    esi

xor     ebx, ebx

mov     [ebp-4], ebx

mov     @var1, ebx

mov     eax, [ecx+84]

lea     edx, @var1

push    edx

push    004E7460

mov     ecx, [eax]

push    eax

mov     byte ptr [ebp-4], 1

call    [ecx+1C]

test    eax, eax

jnz     lable1                ;short 00415B9F

mov     eax, @var1

lea     edx, @var2

push    edx

push    004E8940

mov     ecx, [eax]

push    eax

call    [ecx+14]

test    eax, eax

je      lable2                ;short 00415BAD

lable1:

mov     eax, _arg3

mov     dword ptr [eax], 2

jmp     lable3                ;00415C72

lable2:

mov     eax, _arg2

push    edi

mov     edx, @var1

push    1

mov     ecx, [eax-8]

pop     esi

mov     edi, [edx]

push    esi

push    eax

push    ecx

push    ebx

push    dword ptr _arg1

push    edx

call    [edi+1C]

test    eax, eax

pop     edi

je      lable4                ;00415C6D

cmp     _arg4, esi

je      lable5                ;short 00415BDF

mov     eax, _arg3

mov     [eax], ebx

jmp     lable3                ;00415C72

lable5:

lea     ecx, _arg4

call   

lea     ecx, _arg1

mov     byte ptr [ebp-4], 2

call   

mov     esi, [;  BasicCtr.BasicLoadStr

lea     eax, _arg4

push    281

push    eax

mov     byte ptr [ebp-4], 3

call    esi                              ;  

lea     eax, _arg1

push    28D

push    eax

call    esi

add     esp, 10

lea     ecx, @var3

call   

push    114

lea     ecx, @var3

push    dword ptr _arg1

mov     byte ptr [ebp-4], 4

push    dword ptr _arg4

call   

cmp     eax, 6

mov     eax, _arg3

jnz     label6                                ;short 00415C45

mov     dword ptr [eax], 2               ;  [eax]可能保存的是某个标志,2代表本地登陆失败,到服务器上去验证去

jmp     lable7                                ;short 00415C47

lable6:

mov     [eax], ebx

lable7:

lea     ecx, @var3

mov     byte ptr [ebp-4], 3              ;  [12fcac]

call   

lea     ecx, _arg1

mov     byte ptr [ebp-4], 2

call   

lea     ecx, _arg4

mov     byte ptr [ebp-4], 1

call   

jmp     lable3                                ;short 00415C72

lable4:

mov     eax, _arg3

mov     [eax], esi

lable3:

mov     eax, _arg3

mov     [ebp-4], bl

cmp     eax, ebx

je      lable8                                ;short 00415C82

mov     ecx, [eax]

push    eax

call    [ecx+8]

lable8:

or      dword ptr [ebp-4], FFFFFFFF

lea     ecx, _arg2

call   

mov     ecx, [ebp-C]                     ;  seh 指针

pop     esi

pop     ebx

mov     fs:[0], ecx

leave

retn    14                               ;  父函数传递了5个参数

靠,终于整完了

下一步:去掉编译器自己添加的或与函数功能无关的,异常处理东东

删掉

mov     eax, 004CD25C

call    0046FCA0

注册异常处理函数,打开堆栈页面

sub     esp, 48                ;分配局部变量空间

删掉

mov     ecx, [ebp-C]                     ;  seh 指针

删掉

mov     fs:[0], ecx

leave

retn    14

将注册的异常处理函数删除掉,堆栈平衡

剩下的就是裸函数了

push    ebx

push    esi

xor     ebx, ebx

mov     [ebp-4], ebx

mov     @var1, ebx

mov     eax, [ecx+84]

lea     edx, @var1

push    edx

push    004E7460

mov     ecx, [eax]

push    eax

mov     byte ptr [ebp-4], 1

call    [ecx+1C]

test    eax, eax

jnz     lable1

mov     eax, @var1

lea     edx, @var2

push    edx

push    004E8940

mov     ecx, [eax]

push    eax

call    [ecx+14]

test    eax, eax

je      lable2

lable1:

mov     eax, _arg3

mov     dword ptr [eax], 2

jmp     lable3

lable2:

mov     eax, _arg2

push    edi

mov     edx, @var1

push    1

mov     ecx, [eax-8]

pop     esi

mov     edi, [edx]

push    esi

push    eax

push    ecx

push    ebx

push    dword ptr _arg1

push    edx

call    [edi+1C]

test    eax, eax

pop     edi

je      lable4

cmp     _arg4, esi

je      lable5

mov     eax, _arg3

mov     [eax], ebx

jmp     lable3

lable5:

lea     ecx, _arg4

call   

lea     ecx, _arg1

mov     byte ptr [ebp-4], 2

call   

mov     esi, [;  BasicCtr.BasicLoadStr

lea     eax, _arg4

push    281

push    eax

mov     byte ptr [ebp-4], 3

call    esi                              ;  

lea     eax, _arg1

push    28D

push    eax

call    esi

add     esp, 10

lea     ecx, @var3

call   

push    114

lea     ecx, @var3

push    dword ptr _arg1

mov     byte ptr [ebp-4], 4

push    dword ptr _arg4

call   

cmp     eax, 6

mov     eax, _arg3

jnz     label6

mov     dword ptr [eax], 2

jmp     lable7

lable6:

mov     [eax], ebx

lable7:

lea     ecx, @var3

mov     byte ptr [ebp-4], 3

call   

lea     ecx, _arg1

mov     byte ptr [ebp-4], 2

call   

lea     ecx, _arg4

mov     byte ptr [ebp-4], 1

call   

jmp     lable3

lable4:

mov     eax, _arg3

mov     [eax], esi

lable3:

mov     eax, _arg3

mov     [ebp-4], bl

cmp     eax, ebx

je      lable8

mov     ecx, [eax]

push    eax

call    [ecx+8]

lable8:

or      dword ptr [ebp-4], FFFFFFFF

lea     ecx, _arg2

call   

pop     esi

pop     ebx

让函数光着身子不好,现在给它穿上衣服吧

我先给它穿上win32asm 这套衣服,以后再给她穿c++这套衣服,给这个过程起个名字:叫 _TempName 吧,现在还不知道她是做什么用的,知道了,再换

寄存器参数我用 _regArg1,_regArg2,...表示

_TempName        Proc        _regArg1,_arg1,_arg2,_arg3,_arg?,_arg4        (因为不知道倒数第二个为什么没有在函数中引用过,所以先用?表示)

push    ebx

push    esi

xor     ebx, ebx

mov     [ebp-4], ebx

mov     @var1, ebx

mov     eax, [ecx+84]

lea     edx, @var1

push    edx

push    004E7460

mov     ecx, [eax]

push    eax

mov     byte ptr [ebp-4], 1

call    [ecx+1C]

test    eax, eax

jnz     lable1

mov     eax, @var1

lea     edx, @var2

push    edx

push    004E8940

mov     ecx, [eax]

push    eax

call    [ecx+14]

test    eax, eax

je      lable2

lable1:

mov     eax, _arg3

mov     dword ptr [eax], 2

jmp     lable3

lable2:

mov     eax, _arg2

push    edi

mov     edx, @var1

push    1

mov     ecx, [eax-8]

pop     esi

mov     edi, [edx]

push    esi

push    eax

push    ecx

push    ebx

push    dword ptr _arg1

push    edx

call    [edi+1C]

test    eax, eax

pop     edi

je      lable4

cmp     _arg4, esi

je      lable5

mov     eax, _arg3

mov     [eax], ebx

jmp     lable3

lable5:

lea     ecx, _arg4

call   

lea     ecx, _arg1

mov     byte ptr [ebp-4], 2

call   

mov     esi, [;  BasicCtr.BasicLoadStr

lea     eax, _arg4

push    281

push    eax

mov     byte ptr [ebp-4], 3

call    esi                              ;  

lea     eax, _arg1

push    28D

push    eax

call    esi

add     esp, 10

lea     ecx, @var3

call   

push    114

lea     ecx, @var3

push    dword ptr _arg1

mov     byte ptr [ebp-4], 4

push    dword ptr _arg4

call   

cmp     eax, 6

mov     eax, _arg3

jnz     label6

mov     dword ptr [eax], 2

jmp     lable7

lable6:

mov     [eax], ebx

lable7:

lea     ecx, @var3

mov     byte ptr [ebp-4], 3

call   

lea     ecx, _arg1

mov     byte ptr [ebp-4], 2

call   

lea     ecx, _arg4

mov     byte ptr [ebp-4], 1

call   

jmp     lable3

lable4:

mov     eax, _arg3

mov     [eax], esi

lable3:

mov     eax, _arg3

mov     [ebp-4], bl

cmp     eax, ebx

je      lable8

mov     ecx, [eax]

push    eax

call    [ecx+8]

lable8:

or      dword ptr [ebp-4], FFFFFFFF

lea     ecx, _arg2

call   

pop     esi

pop     ebx

ret

_TempName        endp

下一步分析qq00415b55 调用的函数

第一个        call    [ecx+1C] oo 是个间接调用指令,那来动态跟踪以下调用的是什么?00410ee2

00410EE2   .  B8 CCC84C00   mov     eax, 004CC8CC

00410EE7   .  E8 B4ED0500   call    0046FCA0

00410EEC   .  51            push    ecx

00410EED   .  51            push    ecx

00410EEE   .  8B45 08       mov     eax, [ebp+8]

00410EF1   .  56            push    esi

00410EF2   .  8D4D EC       lea     ecx, [ebp-14]

00410EF5   .  FF70 D8       push    dword ptr [eax-28]

00410EF8   .  8D70 BC       lea     esi, [eax-44]

00410EFB   .  E8 94E80500   call   

00410F00   .  FF75 10       push    dword ptr [ebp+10]               ; /Arg2

00410F03   .  8365 FC 00    and     dword ptr [ebp-4], 0             ; |

00410F07   .  8BCE          mov     ecx, esi                         ; |

00410F09   .  FF75 0C       push    dword ptr [ebp+C]                ; |Arg1

00410F0C   .  E8 71040000   call    00411382                         ; \QQ.00411382

00410F11   .  8B4D F0       mov     ecx, [ebp-10]

00410F14   .  8B55 EC       mov     edx, [ebp-14]

00410F17   .  834D FC FF    or      dword ptr [ebp-4], FFFFFFFF

00410F1B   .  5E            pop     esi

00410F1C   .  8951 04       mov     [ecx+4], edx

00410F1F   .  8B4D F4       mov     ecx, [ebp-C]

00410F22   .  64:890D 00000>mov     fs:[0], ecx

00410F29   .  C9            leave

00410F2A   .  C2 0C00       retn    0C

分析过程和 分析qq00415b55 一样

经分析可知 函数没有寄存器参数,c/4=3个堆栈参数,这里要注意的是

00410EEC   .  51            push    ecx

00410EED   .  51            push    ecx

这两条指令是分配局部变量空间的,因为函数中有两个局部变量,这是编译器快速分配局部变量而使得花招

00410ee2 的函数原型为:

00410ee2        proto        _arg1,_arg2,_arg3

下一个qq00415b55调用的函数是 call [ecx+14] = 0044c62b

0044C62B   .  B8 84424D00   mov     eax, 004D4284

0044C630   .  E8 6B360200   call    0046FCA0

0044C635   .  51            push    ecx

0044C636   .  51            push    ecx

0044C637   .  8B45 08       mov     eax, [ebp+8]

0044C63A   .  56            push    esi

0044C63B   .  8D4D EC       lea     ecx, [ebp-14]

0044C63E   .  FF70 FC       push    dword ptr [eax-4]

0044C641   .  8D70 E0       lea     esi, [eax-20]

0044C644   .  E8 4B310200   call   

0044C649   .  FF75 10       push    dword ptr [ebp+10]

0044C64C   .  8B06          mov     eax, [esi]

0044C64E   .  8365 FC 00    and     dword ptr [ebp-4], 0

0044C652   .  FF75 0C       push    dword ptr [ebp+C]

0044C655   .  56            push    esi

0044C656   .  FF50 64       call    [eax+64]

0044C659   .  8B4D F0       mov     ecx, [ebp-10]

0044C65C   .  8B55 EC       mov     edx, [ebp-14]

0044C65F   .  834D FC FF    or      dword ptr [ebp-4], FFFFFFFF

0044C663   .  5E            pop     esi

0044C664   .  8951 04       mov     [ecx+4], edx

0044C667   .  8B4D F4       mov     ecx, [ebp-C]

0044C66A   .  64:890D 00000>mov     fs:[0], ecx

0044C671   .  C9            leave

0044C672   .  C2 0C00       retn    0C

看起来好像和上个函数长得很像

函数原型为:

0044c62b        proto        _arg1,_arg2,_arg3

next function: 0044c6c5

函数原型为:

0044c6c5        proto        _arg1,_arg2,_arg3,_arg4,_arg5,_arg6

下一个函数是 BasicCtr.BasicLoadStr

60092057 >/$  55            push    ebp

60092058  |.  8BEC          mov     ebp, esp

6009205A  |.  56            push    esi

6009205B  |.  57            push    edi

6009205C  |.  E8 5FCD0000   call   

60092061  |.  8B70 0C       mov     esi, [eax+C]

60092064  |.  8B3D BC8B0B60 mov     edi, [600B8BBC]                                                 ;  BasicCtr.60090000

6009206A  |.  E8 51CD0000   call   

6009206F  |.  FF75 0C       push    dword ptr [ebp+C]

60092072  |.  8B4D 08       mov     ecx, [ebp+8]

60092075  |.  8978 0C       mov     [eax+C], edi

60092078  |.  E8 91CD0000   call   

6009207D  |.  E8 3ECD0000   call   

60092082  |.  8970 0C       mov     [eax+C], esi

60092085  |.  5F            pop     edi

60092086  |.  5E            pop     esi

60092087  |.  5D            pop     ebp

60092088  \.  C3            retn

可算见到一个正常函数,函数有两个堆栈参数参数,没有寄存器参数,这个函数调用方式属于_cdel方式,平很堆栈交给了

qq00415b55,qq00415b55调用完这个函数后并没有做平衡堆栈,而是在第二次调用完这个函数后一起做了堆栈平衡,这可能是

优化编译的结果,这样节省一条指令

我们从basicCtr.BasicLoadStr中也可以找出参数,[ebp+8],[ebp+c]这两个

在qq00415b55中平衡堆栈代码

00415C06  |.  FFD6          call    esi                                                             ;  BasicCtr.BasicLoadStr;

00415C08  |.  8D45 08       lea     eax, [ebp+8]                                                    ;  _arg2

00415C0B  |.  68 8D020000   push    28D

00415C10  |.  50            push    eax

00415C11  |.  FFD6          call    esi

00415C13  |.  83C4 10       add     esp, 10 ---------------------平衡了两次调用,一个函数的参数个数=10h/2/4=2个

所以这个函数的原型应为:

BasicCtr.BasicLoadStr        proto        _arg1,_arg2

下一个,也是qq00415b55调用qq自定义函数中的最后一个 0044cf97 函数只有一个堆栈参数,没有寄存器参数,函数原型为:

0044cf97        proc        _arg1

经过上面的分析,qq00415b55 的win32asm 源代码应为:

BasicCtr.BasicLoadStr        proto        _arg1,_arg2

0044cf97        proto        _arg1

_TempName        Proc        _regArg1,_arg1,_arg2,_arg3,_arg?,_arg4        (因为不知道倒数第二个为什么没有在函数中引用过,所以先用?表示)

local        @dwVar1,@dwVar2

local        @wnd:CWnd        (这个以后再解释)

push    ebx

push    esi

xor     ebx, ebx

mov     [ebp-4], ebx

mov     @var1, ebx

mov     eax, [ecx+84]

mov     ecx, [eax]

mov     byte ptr [ebp-4], 1

invoke        [ecx+1c],eax,004e7460,addr @var1        (这里不管 addr 会覆盖掉 eax的值)

test    eax, eax

jnz     lable1

mov     eax, @var1

mov     ecx, [eax]

invoke        [ecx+14],eax,004e8940,addr @var2(这里不管 addr 会覆盖掉 eax的值)

test    eax, eax

je      lable2

lable1:

mov     eax, _arg3

mov     dword ptr [eax], 2

jmp     lable3

lable2:

mov     eax, _arg2

push    edi

mov     edx, @var1

push    1

mov     ecx, [eax-8]

pop     esi

mov     edi, [edx]

invoke        [edi+1c],edx,_arg1,ebx,ecx,eax,esi

test    eax, eax

pop     edi

je      lable4

cmp     _arg4, esi

je      lable5

mov     eax, _arg3

mov     [eax], ebx

jmp     lable3

lable5:

invoke  CString::CString,_arg4

mov     byte ptr [ebp-4], 2

invoke  CString::CString>,_arg1

mov     byte ptr [ebp-4], 3

invoke        BasicCtrlDll.BasicLoadStr,addr _arg4,281h

invoke        BasicCtrlDll.BasicLoadStr,addr _arg1,28dh

invoke        CWnd::CWnd,addr @wnd

mov     byte ptr [ebp-4], 4

invoke        CWnd::MessageBox,addr @wnd,_arg4,_arg1,MB_YESNO or MB_DEFBUTTON2 or MB_ICONHAND (114h)        ;这个就是登录失败的时候的标题和信息

cmp     eax, 6

mov     eax, _arg3

jnz     label6

mov     dword ptr [eax], 2

jmp     lable7

lable6:

mov     [eax], ebx

lable7:

mov     byte ptr [ebp-4], 3

invoke        CWnd::~CWnd,addr @wnd

mov     byte ptr [ebp-4], 2

invoke  CString::~CString,addr _arg1

mov     byte ptr [ebp-4], 1

invoke        CString::~CString,_arg4

jmp     lable3

lable4:

mov     eax, _arg3

mov     [eax], esi

lable3:

mov     eax, _arg3

mov     [ebp-4], bl

cmp     eax, ebx

je      lable8

mov     ecx, [eax]

invoke        [ecx+8],eax

lable8:

or      dword ptr [ebp-4], FFFFFFFF

invoke  CString::~CString,_arg2

pop     esi

pop     ebx

ret

_TempName        endp

有点累了,今天就到这里了,明天继续.......

2006-06-17 20:00

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值