zoukankan      html  css  js  c++  java
  • 通过反汇编分析非循环单链表

    分析的程序采用C语言实现链表的创建及遍历链表中的代码编译成的程序。IDA分析的······有点高射炮打蚊子的感觉,呵呵
    因为程序用C写的,所以函数采用_cdcall的调用约定,参数从右到左进栈。(这应该都知道·····)

    新手上路 与新手一起学习。请大牛不吝指教 

     
    ;编译系统:windows XP

    ;编译环境:VC++ 6.0 

    ; 编译类型:DeBug版 

    ;-------主函数-------

    ;主函数初始化

    .text:0040103055                 push    ebp
    .text:00401031 8B EC             mov     ebp, esp
    .text:00401033 83 EC 44          sub     esp, 44h
    .text:00401036 53                push    ebx
    .text:00401037 56                push    esi
    .text:00401038 57                push    edi
    .text:00401039 8D 7D BC          lea     edi, [ebp+var_44]
    .text:0040103C B9 11 00 00 00    mov     ecx, 11h
    .text:00401041 B8 CC CC CC CC    mov     eax, 0CCCCCCCCh
    .text:00401046 F3 AB             rep stosd
    ;---------------------------------------------------------
    .text:00401048 C7 45 FC 00 00 00+mov     [ebp+var_4], 0           ;pHead = NULL,C语言中的NULL,在汇编里填0
    .text:0040104F E8 BB FF FF FF    call    j_?CreateList@@YAPAUnode@@XZ ;调用 CreateList(void)函数
    .text:00401054 89 45 FC          mov     [ebp+var_4], eax        ;函数返回值给pHead
    .text:00401057 8B 45 FC          mov     eax, [ebp+var_4]        ;把pHead的值给寄存器EAX
    .text:0040105A 50                push    eax                ;把EAX进栈,作为TraverseList(node *)函数的参数
    .text:0040105B E8 A5 FF FF FF    call    j_?TraverseList@@YAXPAUnode@@@Z ; 调用TraverseList(node *)函数
    .text:00401060 83 C4 04          add     esp, 4                ;为了堆栈平衡,esp加4
    .text:00401063 33 C0             xor     eax, eax            ;return 0
    ;-------函数结束处理--------
    .text:00401065 5F                pop     edi
    .text:00401066 5E                pop     esi
    .text:00401067 5B                pop     ebx
    .text:00401068 83 C4 44          add     esp, 44h
    .text:0040106B 3B EC             cmp     ebp, esp
    .text:0040106D E8 AE 01 00 00    call    __chkesp
    .text:00401072 8B E5             mov     esp, ebp
    .text:00401074 5D                pop     ebp
    .text:00401075 C3                retn

    ;-------CreateList函数-------

    ;CreateList函数初始化
    .text:00401090 55                push    ebp
    .text:00401091 8B EC             mov     ebp, esp
    .text:00401093 83 EC 58          sub     esp, 58h
    .text:00401096 53                push    ebx
    .text:00401097 56                push    esi
    .text:00401098 57                push    edi
    .text:00401099 8D 7D A8          lea     edi, [ebp+var_58]
    .text:0040109C B9 16 00 00 00    mov     ecx, 16h
    .text:004010A1 B8 CC CC CC CC    mov     eax, 0CCCCCCCCh
    .text:004010A6 F3 AB             rep stosd
    ;---------------------------------------------------------
    .text:004010A8 6A 08             push    8                     ; sizeof(Node)的计算结果,进栈作为malloc函数的参数
    .text:004010AA E8 91 02 00 00    call    _malloc         ;调用malloc函数
    .text:004010AF 83 C4 04          add     esp, 4             ;为了堆栈平衡
    .text:004010B2 89 45 F0          mov     [ebp+var_10], eax     ;把malloc函数的返回值给pHead,注意此pHead不是主函数中的那个,这是局部变量
    .text:004010B5 8B 45 F0          mov     eax, [ebp+var_10]     ;把pHead放到寄存器EAX
    .text:004010B8 89 45 EC          mov     [ebp+var_14], eax     ;寄存器EAX中的值传给pTail
    .text:004010BB 8B 4D EC          mov     ecx, [ebp+var_14]     ;把pTail放到寄存器ECX
    .text:004010BE C7 41 04 00 00 00+mov     dword ptr [ecx+4], 0  ;pTail->pNext=NULL,
    .text:004010C5 68 3C 50 42 00    push    offset Format         ; 字符串"请输入节点个数:"进栈,作为printf的参数
    .text:004010CA E8 F1 01 00 00    call    _printf         ;调用printf函数
    .text:004010CF 83 C4 04          add     esp, 4             ;堆栈平衡
    .text:004010D2 8D 55 F8          lea     edx, [ebp+var_8]     ;取变量len的地址给寄存器EDX
    .text:004010D5 52                push    edx             ;将寄存器EDX进栈,即把变量len的地址进栈,作为函数Scnaf的参数
    .text:004010D6 68 38 50 42 00    push    offset aD             ;把转换说明符 "%d" 进栈,作为函数scanf的参数
    .text:004010DB E8 80 01 00 00    call    _scanf             ;调用scanf函数
    .text:004010E0 83 C4 08          add     esp, 8             ;保持堆栈平衡

    ;------下面是 for 循环-------

    .text:004010E3 C7 45 FC 00 00 00+mov     [ebp+var_4], 0     ;变量 i ,初始化为0
    .text:004010EA EB 09             jmp     short loc_4010F5     ;跳转到004010F5
    .text:004010EC 8B 45 FC          mov     eax, [ebp+var_4]     ;把变量i放到寄存器EAX中
    .text:004010EF 83 C0 01          add     eax, 1             ; EAX = EAX + 1
    .text:004010F2 89 45 FC          mov     [ebp+var_4], eax     ;把寄存器EAX的值给i
    .text:004010F5 8B 4D FC          mov     ecx, [ebp+var_4]     ;把变量i放到ECX中
    .text:004010F8 3B 4D F8          cmp     ecx, [ebp+var_8]     ;比较 i 和 len
    .text:004010FB 7D 55             jge     short loc_401152     ;大于等于时,跳到00401152
    .text:004010FD 8B 55 FC          mov     edx, [ebp+var_4]     ;把变量 i 放到EDX中
    .text:00401100 83 C2 01          add     edx, 1             ;EDX = EDX + 1
    .text:00401103 52                push    edx             ;EDX进栈,即把变量 i 进栈,作为函数printf的参数
    .text:00401104 68 1C 50 42 00    push    offset aDUG           ; 字符串"第 %d 个节点的数值:"进栈,作为函数printf的参数
    .text:00401109 E8 B2 01 00 00    call    _printf         ;调用printf函数
    .text:0040110E 83 C4 08          add     esp, 8             ;保持堆栈平衡
    .text:00401111 8D 45 F4          lea     eax, [ebp+var_C]     ;取变量val的地址给寄存器EAX
    .text:00401114 50                push    eax             ;将val的地址进栈,作为函数scanf的参数
    .text:00401115 68 38 50 42 00    push    offset aD             ;将转换说明符 "%d"进栈,作为函数scanf的参数
    .text:0040111A E8 41 01 00 00    call    _scanf             ;调用scanf函数
    .text:0040111F 83 C4 08          add     esp, 8             ;保持堆栈平衡
    .text:00401122 6A 08             push    8                     ; sizeof(Node)的计算结果进栈,作为malloc函数的参数
    .text:00401124 E8 17 02 00 00    call    _malloc         ;调用malloc函数
    .text:00401129 83 C4 04          add     esp, 4             ;保持堆栈平衡
    .text:0040112C 89 45 E8          mov     [ebp+var_18], eax     ;将寄存器EAX的值(即malloc函数的返回值)给变量pNew
    .text:0040112F 8B 4D E8          mov     ecx, [ebp+var_18]     ;将pNew放到寄存器ECX
    .text:00401132 8B 55 F4          mov     edx, [ebp+var_C]     ;将变量val放到寄存器EDX
    .text:00401135 89 11             mov     [ecx], edx         ;将变量val的值给pNew->member
    .text:00401137 8B 45 EC          mov     eax, [ebp+var_14]     ;把pTail放到寄存器EAX
    .text:0040113A 8B 4D E8          mov     ecx, [ebp+var_18]     ;把pNew放到寄存器ECX
    .text:0040113D 89 48 04          mov     [eax+4], ecx         ;把寄存器ECX的值给pTail->pNext
    .text:00401140 8B 55 E8          mov     edx, [ebp+var_18]     ;把pNew放到寄存器EDX中
    .text:00401143 C7 42 04 00 00 00+mov     dword ptr [edx+4], 0     ;pNew->pNext = NULL
    .text:0040114A 8B 45 E8          mov     eax, [ebp+var_18]     ;把pNew放到寄存器EAX
    .text:0040114D 89 45 EC          mov     [ebp+var_14], eax     ;将EAX的值给pTail,即pTail = pNew 
    .text:00401150 EB 9A             jmp     short loc_4010EC     ;跳到004010EC
    ;-----------------循环结束

    .text:00401152 8B 45 F0          mov     eax, [ebp+var_10]     ;将pHead给寄存器EAX,作为函数返回值

    ;-------CreateList函数的结尾处理--------

    .text:00401155 5F                pop     edi
    .text:00401156 5E                pop     esi
    .text:00401157 5B                pop     ebx
    .text:00401158 83 C4 58          add     esp, 58h
    .text:0040115B 3B EC             cmp     ebp, esp
    .text:0040115D E8 BE 00 00 00    call    __chkesp
    .text:00401162 8B E5             mov     esp, ebp
    .text:00401164 5D                pop     ebp
    .text:00401165 C3                retn

    ;--------TraverseList(node *)函数---------

    ;------TraverseList函数初始化
    .text:004011A0 55                push    ebp
    .text:004011A1 8B EC             mov     ebp, esp
    .text:004011A3 83 EC 44          sub     esp, 44h
    .text:004011A6 53                push    ebx
    .text:004011A7 56                push    esi
    .text:004011A8 57                push    edi
    .text:004011A9 8D 7D BC          lea     edi, [ebp+var_44]
    .text:004011AC B9 11 00 00 00    mov     ecx, 11h
    .text:004011B1 B8 CC CC CC CC    mov     eax, 0CCCCCCCCh
    .text:004011B6 F3 AB             rep stosd
    ;------------------------------------------------------------
    .text:004011B8 8B 45 08          mov     eax, [ebp+arg_0]     ;将pHead放到EAX
    .text:004011BB 8B 48 04          mov     ecx, [eax+4]         ;pHead->pNext放到ECX
    .text:004011BE 89 4D FC          mov     [ebp+var_4], ecx     ;将pHead->pNext赋给p

    ;-------------while循环
    .text:004011C1 83 7D FC 00       cmp     [ebp+var_4], 0     ;p != NULL 
    .text:004011C5 74 1E             jz      short loc_4011E5     ;p = NULL跳到004011E5
    .text:004011C7 8B 55 FC          mov     edx, [ebp+var_4]     ;将p放到寄存器EDX
    .text:004011CA 8B 02             mov     eax, [edx]         ;将p->member放到寄存器EAX
    .text:004011CC 50                push    eax             ;将寄存器EAX进栈,作为函数printf的参数
    .text:004011CD 68 54 50 42 00    push    offset aD_0           ; 将转换说明符"%d ",进栈,作为函数printf的参数
    .text:004011D2 E8 E9 00 00 00    call    _printf         ;调用printf函数
    .text:004011D7 83 C4 08          add     esp, 8             ;保持堆栈平衡
    .text:004011DA 8B 4D FC          mov     ecx, [ebp+var_4]     ;把p放到寄存器ECX中
    .text:004011DD 8B 51 04          mov     edx, [ecx+4]         ;把p->pNext放到EDX中
    .text:004011E0 89 55 FC          mov     [ebp+var_4], edx     ;p = p->pNext
    .text:004011E3 EB DC             jmp     short loc_4011C1     ;跳到004011C1,
    .text:004011E5 68 50 50 42 00    push    offset asc_425050     ; 把字符串"\n"进栈,作为printf函数的参数
    .text:004011EA E8 D1 00 00 00    call    _printf         ;调用printf函数
    .text:004011EF 83 C4 04          add     esp, 4             ;堆栈平衡
    ;--------------TraverseList函数结束处理
    .text:004011F2 5F                pop     edi
    .text:004011F3 5E                pop     esi
    .text:004011F4 5B                pop     ebx
    .text:004011F5 83 C4 44          add     esp, 44h
    .text:004011F8 3B EC             cmp     ebp, esp
    .text:004011FA E8 21 00 00 00    call    __chkesp
    .text:004011FF 8B E5             mov     esp, ebp
    .text:00401201 5D                pop     ebp
    .text:00401202 C3                retn

     

    通过反汇编我发现函数的返回值,都是通过EAX寄存器传递的。

    还有就是操作一个结构体的成员,都是先把结构体的地址放进寄存器,再通过寄存器相对寻址方式操作结构体的成员

     举个例子就是: struct node{

    int age;

    int num; 

    }pNode 

    假如上述结构体在反汇编中用[ebp+arg_0]表示,那么要操作第一个成员是

    mov eax,[ebp+aeg_0]

    mov [eax],18

    这样这个结构的成员member的值为18,如果第二句是mov [eax+4h],20 这样结构体的第二个成员的值就会变成20. 

    欢迎大神们批评指点········ 

  • 相关阅读:
    erlang遍历目录
    C/C++ makefile自动生成工具(comake2,autotools,linux),希望能为开源做点微薄的贡献!
    shell 文件操作
    互联网分享知识(一)
    分页查询,你真的懂吗?
    awk神器
    Unicode编码解码在线转换工具
    awk 留底
    软件开发真的这么简单吗?
    php性能优化
  • 原文地址:https://www.cnblogs.com/scrat/p/2640852.html
Copyright © 2011-2022 走看看