发表于 2015-8-20 11:07

申请会员ID: freeGod【未报到,账号已删除】

1、申 请 I D:FreeGod
2、个人邮箱:netfreegod3@126.com
3、原创技术文章: qq反汇编日志


标 题: 【原创】qq反汇编日志1
作 者: freeGod
时 间: 2006-06-15,18:20:36
链 接: http://bbs.pediy.com/showthread.php?t=27458

2006年6月15日 9:30
oo,前两天的反汇编记录下来的东西都丢了(昨天重做系统时,忘了),不过还好,丢的东西大部分都是我的曲折错误分析
现在从新开始:(为写远程暴力破解qq密码程序而反汇编qq)
反汇编工具:OllyICE
现在开始:
用OllyICE加载qq.exe,qq登录对话框出现,随便输入密码:123,运行,一个错误对话框出现,
错误
输入密码与上次成功登录得密码不一致,
是否到服务器验证?

好,打开OllyICE的模块窗口,然后找到user32模块,打开右键菜单选中查看名称,OllyICE的名称窗口出现了,这里的函数都是
User32模块中的,好,找到MessageBoxA,打开右键菜单选中反汇编窗口中跟随,这样就到了MessageBoxA函数的入口点,按f2键设下
端点,设好后点刚才qq跳出来的错误对话框上的否,qq用户登录又出现了,再输入123
OllyICE在我们刚才设置的MessageBoxA函数的入口点停了下来,察看堆栈窗口

0012FC2C   60B5C8E7/CALL 到 MessageBoxA 来自 MFC42.60B5C8E1

说明调用是MFC42库中的60b5c8e1处的指令的前一条指令调用了MessageBoxA,在CALL 到 MessageBoxA 来自 MFC42.60B5C8E1上
右键,打开右键菜单,选中反汇编窗口跟随,就到mfc42地址空间的60b5c8e7指令位置(不同的电脑,可能值不一样),上一条指令
就是调用MessageBoxA函数的,如下所示

60B5C8DC|.FF7424 10   push    dword ptr                ; |Text
60B5C8E0|.51            push    ecx                              ; |hOwner
60B5C8E1|.FF15 D0B5B960 call    [<&USER32.MessageBoxA>]          ; \MessageBoxA
60B5C8E7|.5E            pop   esi
60B5C8E8|.C2 0C00       retn    0C

在 60b5c8e7 pop esi上设置端点,然后点运行,刚才的那个错误对话框又出现了,点否,好,现在程序停在了我们刚才设置端点的位
置605c8e7处,现在在MFC42地址空间中,不管它,我们想到的位置是qq空间,按两下f8键,到了 00415c35 cmp eax,6 指令处,看一
下OllyICE的标题栏 OllyICE - QQ.exe -
好了这就是我们的目的地。

反汇编就从这里开始,第一个分析的函数就是:包含 指令地址00415c35 的函数
第一步:找出 包含指令地址 00415c35 的 函数入口点
      向上滚动反汇编窗口,找到00415b55 地址
00415B52\.C2 0400       retn    4
00415B55/$B8 5CD24C00   mov   eax, 004CD25C
00415B5A|.E8 41A10500   call    0046FCA0
00415B5F|.83EC 48       sub   esp, 48

OllyICE 分析出这个是函数的入口点,因为上面紧跟的是retn指令,不过一般的函数入口处:应该是
pushebp
movebp,esp
才对,如果是罗函数的话,经过优化编译的话就不是这个样子了,我们先在反汇编的是qq,qq的软件工程师水平应该是可以
的,有可能经过特殊处理,

004CD25C=004CD25C
eax=0012FCBC
本地调用来自 00414FE8, 00416FEE
这个交叉引用说明,的确是函数的入口点

这样函数入口点就确定了:004b5b55
第二步:确定函数结束地址,按OllyICE 的提示 结束地址应为:00415c9b retn 14,一个函数有可能有多个出口
      我们来做进一步的鉴定,看看从004b5b55 到 00415c9b 之间的指令有无交叉引用到 00415c9b 以后的指令
答:没有,因此 00415c9b 即为函数的结束地址,至此我们确定了函数的入口点和结束地址
004b5b55--00415c9b
现在我们开始还原 函数 qq004b55 的源代码

第三步:确定参数个数和参数类型
找到调用 004b5b55 函数 指令 :00414fe8 ------------------------------------
                                                                                  |
00414FD6|.C645 FC 05    mov   byte ptr , 5                           |
00414FDA|.E8 A1A60500   call    <jmp.&MFC42.#535_CString::CString>            |
00414FDF|.FF75 EC       push    dword ptr                             |
00414FE2|.8BCB          mov   ecx, ebx                                    |
00414FE4|.C645 FC 05    mov   byte ptr , 5                           |
00414FE8|.E8 680B0000   call    00415B55      ---------------------------------                  
00414FED|.FFD6          call    esi

00414FE2|.8BCB          mov   ecx, ebx --- ecx 应该是个寄存器参数,要不这条指令就是个垃圾指令
函数004b5b55 可能有一个寄存器参数,说可能,是因为编译器生成的垃圾指令到处可见,要对ecx进一步鉴定,要
分析004b5b55 函数的代码
00415B55/$B8 5CD24C00   mov   eax, 004CD25C
00415B5A|.E8 41A10500   call    0046FCA0
00415B5F|.83EC 48       sub   esp, 48
00415B62|.53            push    ebx
00415B63|.56            push    esi
00415B64|.33DB          xor   ebx, ebx
00415B66|.895D FC       mov   , ebx
00415B69|.895D F0       mov   , ebx
00415B6C|.8B81 84000000 mov   eax,
在函数的开始处,调用了一个函数 0046fca0,察看一下它的代码,看看和ecx有染没有
0046FCA0/$6A FF         push    -1
0046FCA2|.50            push    eax
0046FCA3|.64:A1 0000000>mov   eax, fs:
0046FCA9|.50            push    eax
0046FCAA|.8B4424 0C   mov   eax,
0046FCAE|.64:8925 00000>mov   fs:, esp
0046FCB5|.896C24 0C   mov   , ebp
0046FCB9|.8D6C24 0C   lea   ebp,
0046FCBD|.50            push    eax
0046FCBE\.C3            retn
哈哈,这个函数挺简练的,和ecx无关,这就好,再看看00415b6c地址 以上的指令都与ecx无关,而在00415b6c处引用了
ecx,因此断定ecx就是一个寄存器参数,不错,good
下面来看一下004b5b55 函数 有多少个堆栈参数
从函数结束地址 00415C9B\.C2 1400       retn    14
可知 堆栈参数个数为 14h / 4 = 5
到此我们确定了参数的个数:一个寄存器参数 + 5 个堆栈参数 = 6(说明函数采用的是fastcall调用方式)
给他们编号分别为:arg1,arg2,arg3,arg4,arg5,arg6

下面我们来确定参数类型
在指令中识别参数
函数004b5b55 每有标准的函数头 即 push ebp ; mov ebp,esp,如果是采用优化编译的话,参数应该用esp寄存器来寻址
可在函数过程中只在分配局部变量时,用了一次esp
00415B5F|.83EC 48       sub   esp, 48
其他的地方都没有,令人奇怪的是到处都是用ebp寄存器寻址的,对了,函数入口点,调用了一个函数:0046fca0
看看它都实现了什么功能

0046FCA0/$6A FF         push    -1
执行指令后堆栈数据
相对esp的地址    数据
esp      -1
esp+4      ret addr
0046FCA2|.50            push    eax
执行指令后堆栈数据
相对esp的地址    数据
esp      eax (通过寄存器eax传递过来的参数进栈)
esp+4      -1
esp+8      ret addr
0046FCA3|.64:A1 0000000>mov   eax, fs:    ;eax 指向 seh (结构化异常处理)
0046FCA9|.50            push    eax
执行指令后堆栈数据
相对esp的地址    数据
esp      eax (seh 指针)
esp+4      eax (通过寄存器eax传递过来的参数进栈)
esp+8      -1
esp+c      ret addr
0046FCAA|.8B4424 0C   mov   eax, ;把ret addr 传递给eax
执行指令后堆栈数据
相对esp的地址    数据
esp      eax (seh 指针)
esp+4      eax (通过寄存器eax传递过来的参数进栈)
esp+8      -1
esp+c      ret addr
0046FCAE|.64:8925 00000>mov   fs:, esp    ;此时esp指向一个 EXCEPTION_REGISTRATION 结构
            ;表明同过寄存器eax传递给函数的是异常回调函数地址
            ;-1 则是seh 的附加数据
执行指令后堆栈数据
相对esp的地址    数据
esp      eax (seh 指针)<-------------------------------fs:
esp+4      eax (通过寄存器eax传递过来的参数进栈)
esp+8      -1
esp+c      ret addr

0046FCB5|.896C24 0C   mov   , ebp;保存ebp 到 原来 ret addr 所占堆栈位置
执行指令后堆栈数据
相对esp的地址    数据
esp      eax (seh 指针)<-------------------------------fs:
esp+4      eax (通过寄存器eax传递过来的参数进栈)
esp+8      -1
esp+c      ebp----- 注意发生变化了

0046FCB9|.8D6C24 0C   lea   ebp, ;ebp指向 保存ebp的位置(也即原来 ret addr 的位置)
执行指令后堆栈数据
相对esp的地址    数据
esp      eax (seh 指针)<-------------------------------fs:
esp+4      eax (通过寄存器eax传递过来的参数进栈)
esp+8      -1
esp+c      ebp----- 注意发生变化了<------------------------ ebp
0046FCBD|.50            push    eax
执行指令后堆栈数据
相对ebp的地址    相对esp的地址    数据
ebp-10      esp      eax(函数的返回地址)
ebp-c      esp+4      eax (seh 指针)<-------------------------------fs:
ebp-8      esp+8      eax (通过寄存器eax传递过来的参数进栈)
ebp-4      esp+c      -1
ebp      esp+10      ebp----- 注意发生变化了<------------------------ ebp
0046FCBE\.C3            retn
执行指令后堆栈数据
相对ebp的地址    相对esp的地址    数据
ebp-c      esp      eax (seh 指针)<-------------------------------fs:
ebp-8      esp+4      eax (通过寄存器eax传递过来的参数进栈)
ebp-4      esp+8      -1
ebp      esp+c      ebp----- 注意发生变化了<------------------------ ebp

因为 函数0046fca0没有堆栈参数,所以 ebp+4 指向的是它的父函数即 004b5b55 结束时要返回的地址

相对ebp的地址    相对esp的地址    数据
ebp-c      esp      eax (seh 指针)<-------------------------------fs:
ebp-8      esp+4      eax (通过寄存器eax传递过来的参数进栈)
ebp-4      esp+8      -1
ebp      esp+c      ebp----- 注意发生变化了<------------------------ ebp
ebp +4      esp+10      004b5b55函数 结束时要返回的地址

综上所述:0046fca0 实现的功能为:《1》注册异常回调函数
         《2》实现了和 pushebp
               movebp,esp
          查不多的功能,调用0046fca0函数的函数的第一个堆栈参数地址为 ebp +8
          这和push ebp ;move ebp,esp 是一样的,但是局部变量的寻址就不一样了
          调用0046fca0 函数的函数局部变量是从ebp-d 开始的,而不是从ebp-4开始的
          搞定……^_^
现在我们就可以很轻松的识别出参数了,开始吧
识别参数类型
首先我用32位汇编语言来实现00415b55,我给他起个名字叫 _lastStep 吧,我把寄存器传参也改成堆栈方式

_LastStepproc_arg1,_arg2,_arg3,_arg4,_arg5,_arg6
    moveax,004cd25c
    call0046fca0
    subesp,48h
    pushebx
    pushesi
    xorebx,ebx
    mov,ebx; 是seh附加数据的地址,原来值为-1,现在要把它置零了
    mov@dwVar1,ebx
    movecx,_arg1
    moveax,;可知_arg1 是一个指针
    leaedx,@dwVar1
    pushedx
    push004e7460
    movecx,
    pusheax
    movbyte ptr,1; 是seh附加数据的地址
    call    ;表明_arg1 是一个函数指针的指针的指针
    testeax,eax
    jnzlable1
    moveax,@dwVar1
    leaedx,@dwVar2
    pushedx
    push004e8940    ;ascii "ewh.db"
    movecx,
    pusheax
    call
    testeax,eax
    jelabel2
lable1:
    moveax,_arg4    ;可知_arg4 是一个int*
    movdword ptr,2
    jmplable3
lable2:
    moveax,_arg3
    pushedi
    movedx,@dwVar1
    push1
    movecx,
    popesi
    movedi,
    pushesi
    pusheax
    pushecx
    pushebx
    pushdword ptr _arg2
    pushedx
    call
    testeax,eax
    popedi
    jelable4
    cmp_arg6,esi
    jelable5
    moveax,_arg4
    mov,ebx;可知_arg4是个指针
    jmplable3
lable5:
    leaecx,_arg6
    callCString::CString
    leaecx,_arg2
    movbyte ptr ,2
    callCString::CString
    movesi,BasicCtrDll.BasicLoadStr
    leaeax,_arg6
    push281
    pusheax
    movbyte prt,3
    callesi
    leaeax,_arg2
    push28d
    pusheax
    callesi
    addesp,10
    leaecx,;ebp-54 指向一个结构
    callCWNd::CWnd
    push114
    leaecx,
    pushdword ptr _arg2
    movbyte prt,4
    pushdword ptr _arg6
    callCWnd::MessageBoxA
    cmpeax,6
    moveax,_arg4
    jnzLable6
    movdword prt,2
    jmplable7
lable6:
    mov,ebx
lable7:
    leaecx,
    movbyte ptr,3
    callCWnd::~Cwnd
    leaecx,_arg2
    movbyte ptr,2
    callCString::~CString
    leaecx,_arg6
    movbyte ptr,1
    callCString::~Cstring
    jmplable3
lable4:
    moveax,_arg4
    mov,esi
lable3:
    moveax,@dwVar1
    mov,bl
    cmpeax,ebx
    jelable8
    movecx,
    pusheax
    call
lable8:
    ordwword ptr,0ffffffffh
    leaecx,_arg3
    callCString::~CString
    movecx,; pre seh handler 指针
    popesi
    popebx
    movfs:,ecx
    leave
    retn14
_LastSetpenp

今天就到这里,明天继续
2006-6-15 13:20







Hmily 发表于 2015-8-20 16:21

请在看雪论坛给hmilywen发一条短消息我确认下是否是本人。

发表于 2015-8-21 08:35

已经发送了短消息

Hmily 发表于 2015-8-21 16:30

ID:FreeGod
邮箱:netfreegod3@126.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。

Hmily 发表于 2015-9-2 10:38

一周内在未报道,删除账号。
页: [1]
查看完整版本: 申请会员ID: freeGod【未报到,账号已删除】