失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > c语言异或 反汇编 [原创]qq反汇编日志(1 2 3 4)

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

时间:2020-12-28 02:41:21

相关推荐

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

1

-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:

invokeCString::CString,_arg4

mov byte ptr [ebp-4], 2

invokeCString::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

invokeCString::~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

invokeCString::~CString,_arg2

pop esi

pop ebx

ret

_TempName endp

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

-06-17 20:00

如果觉得《c语言异或 反汇编 [原创]qq反汇编日志(1 2 3 4)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。