资讯

展开

Datalab实验_Bomblab

作者:快盘下载 人气:

Datalab实验_Bomblab

文章目录

Datalab实验_Bomblab1.phase_1;字符串比较;2.phase_2;循环;3.phase_3;条件/分支;含switch语句;4.phase_4;递归调用和栈;5.phase_5;指针;6.phase_6;链表/指针/结构;bomblab 隐藏关卡

1.phase_1;字符串比较;

思路;首先在gdb中输入disassemble phase_1:
   0x08048ae0 <;0>:     push   %ebp// 入栈
   0x08048ae1 <;1>:     mov    %esp,%ebp// 形成帧底 
   0x08048ae3 <;3>:     sub    $0x18,%esp// esp - 24 生成栈帧
   0x08048ae6 <;6>:     movl   $0x804a128,0x4(%esp)// 将立即数存放在 esp;4 的位置
   0x08048aee <;14>:    mov    0x8(%ebp),%eax
   0x08048af1 <;17>:    mov    %eax,(%esp)// 准备入口参数
   0x08048af4 <;20>:    call   0x8048f22 er// 调用函数 
   0x08048af9 <;25>:    test   %eax,%eax// 设置标志位 eax与自己按位相与 判断是否等于0
   0x08048afb <;27>:    je     0x8048b02 <phase_1;34>// 根据标志位判断是否跳转 若ZF == 0 则跳过引爆炸弹的程序
   0x08048afd <;29>:    call   0x8049145 <explode_bomb>// 炸弹引爆
   0x08048b02 <;34>:    leave// 退栈
   0x08048b03 <;35>:    ret// 返回地址

画出调用函数strings_not_equal之前phase_1内部的栈帧情况;

;--------------------------;
|         其他              |(底部)
;--------------------------;
|        输入的参数          |通过eax转移到%ebp ; 0x8的地方
;--------------------------;
|       返回值(%eax)        |
;--------------------------;
|                          |<———— ebp
;--------------------------;
|        ... ...           |
;--------------------------;
|       $0x804a128         |
;--------------------------;
|       %ebp ; 0x8         |<———— esp
;--------------------------;

而函数strings_not_equal的功能是判断两个参数是是否相等;所以只需要输入$0x804a128中对应的内容即可
Datalab实验_Bomblab

2.phase_2;循环;

思路;
首先调出phase_2的反汇编;
   0x08048b04 <;0>:     push   %ebp
   0x08048b05 <;1>:     mov    %esp,%ebp
   0x08048b07 <;3>:     push   %esi
   0x08048b08 <;4>:     push   %ebx // esi和ebx为调用者保存寄存器;因为后面的循环用到了者两个寄存器;因此在这里需要压栈保存
   0x08048b09 <;5>:     sub    $0x30,%esp///esp-48 生成栈帧
   0x08048b0c <;8>:     lea    -0x20(%ebp),%eax// 加载有效地址 
   0x08048b0f <;11>:    mov    %eax,0x4(%esp)
   0x08048b13 <;15>:    mov    0x8(%ebp),%eax
   0x08048b16 <;18>:    mov    %eax,(%esp)// 准备入口参数
   0x08048b19 <;21>:    call   0x8049187 <read_six_numbers>// 调用函数读入6个数字
   0x08048b1e <;26>:    cmpl   $0x1,-0x20(%ebp)// 比较立即数0x1与ebp - 32的值   第一个数存放在ebp - 32的位置 应该是0x1
   0x08048b22 <;30>:    je     0x8048b42 <phase_2;62>// 如果上述比较结果相等;ZF==1;跳转
   0x08048b24 <;32>:    call   0x8049145 <explode_bomb>// 引爆炸弹
   0x08048b29 <;37>:    jmp    0x8048b42 <phase_2;62>// 无条件转移
   0x08048b2b <;39>:    mov    -0x4(%ebx),%eax
   0x08048b2e <;42>:    add    %eax,%eax
   0x08048b30 <;44>:    cmp    %eax,(%ebx)
   0x08048b32 <;46>:    je     0x8048b39 <phase_2;53>//  如果上述比较结果相等;ZF==1;跳转
   0x08048b34 <;48>:    call   0x8049145 <explode_bomb>// 引爆炸弹
   0x08048b39 <;53>:    add    $0x4,%ebx
   0x08048b3c <;56>:    cmp    %esi,%ebx// 比较esi与ebx寄存器的值
   0x08048b3e <;58>:    jne    0x8048b2b <phase_2;39>// 如果上述比较结果不相等;ZF==0;跳转
   0x08048b40 <;60>:    jmp    0x8048b4a <phase_2;70>// 无条件转移
   0x08048b42 <;62>:    lea    -0x1c(%ebp),%ebx// 赋ebx寄存器的初值
   0x08048b45 <;65>:    lea    -0x8(%ebp),%esi// 赋esi寄存器的初值
   0x08048b48 <;68>:    jmp    0x8048b2b <phase_2;39>// 无条件转移
   0x08048b4a <;70>:    add    $0x30,%esp
   0x08048b4d <;73>:    pop    %ebx
   0x08048b4e <;74>:    pop    %esi
   0x08048b4f <;75>:    pop    %ebp
   0x08048b50 <;76>:    ret

将读入的6个数字设为数组num[6]中的数;则在调用函数read_six_numbers后的栈帧为;

      ;--------------------------;
ebp   |                          |
      ;--------------------------;                                      
ebp-4 |                          |
      ;--------------------------;
ebp-8 |                          |
      ;--------------------------;
ebp-12|num[6]                    |<———— esi的初值
      ;--------------------------;
ebp-16|num[5]                    |
      ;--------------------------;
ebp-20|num[4]                    |
      ;--------------------------;
ebp-20|num[3]                    |
      ;--------------------------;
ebp-24|num[2]                    |
      ;--------------------------;
ebp-28|num[1]                    |<———— ebx 初值
      ;--------------------------;
ebp-32|num[0]                 	 |<———— eax 初值
      ;--------------------------;
      |         ... ..           |
      ;--------------------------;
esp   |                          |
      ;--------------------------;

调用函数后

	0x08048b1e <;26>:    cmpl   $0x1,-0x20(%ebp)// 比较立即数0x1与ebp - 32的值   第一个数存放在ebp - 32的位置 应该是0x1
	0x08048b22 <;30>:    je     0x8048b42 <phase_2;62>// 如果上述比较结果相等;ZF==1;跳转

判断出num[0] = 0x1

   0x08048b42 <;62>:    lea    -0x1c(%ebp),%ebx// 赋ebx寄存器的初值
   0x08048b45 <;65>:    lea    -0x8(%ebp),%esi// 赋esi寄存器的初值

将ebx与esi赋初值(esi的地址相当于num[6];为了确保只取了6个数;防止溢出)

   0x08048b2b <;39>:    mov    -0x4(%ebx),%eax
   0x08048b2e <;42>:    add    %eax,%eax
   0x08048b30 <;44>:    cmp    %eax,(%ebx)
   0x08048b32 <;46>:    je     0x8048b39 <phase_2;53>//  如果上述比较结果相等;ZF==1;跳转
   0x08048b34 <;48>:    call   0x8049145 <explode_bomb>// 引爆炸弹
   0x08048b39 <;53>:    add    $0x4,%ebx
   0x08048b3c <;56>:    cmp    %esi,%ebx// 比较esi与ebx寄存器的值
   0x08048b3e <;58>:    jne    0x8048b2b <phase_2;39>// 如果上述比较结果不相等;ZF==0;跳转

当第一次循环的时候ebx=num[1],eax=num[0],为了满足46行的条件判断je 0x8048b39 <phase_2;53>必须有num[1] = 2num[0],然后ebx;4直到ebx == esi结束;所以6个数后一个是前一个的2倍;即;

for(int i = 0; i < 5; i;;)
    num[i ; 1] = num[i] * 2;// num[0] == 1

最终结果是;

1 2 4 8 16 32

3.phase_3;条件/分支;含switch语句;

思路;
调出phase_3的反汇编;
   0x08048b51 <;0>:     push   %ebp
   0x08048b52 <;1>:     mov    %esp,%ebp
   0x08048b54 <;3>:     sub    $0x28,%esp
   0x08048b57 <;6>:     lea    -0x10(%ebp),%eax
   0x08048b5a <;9>:     mov    %eax,0xc(%esp)
   0x08048b5e <;13>:    lea    -0xc(%ebp),%eax
   0x08048b61 <;16>:    mov    %eax,0x8(%esp)
   0x08048b65 <;20>:    movl   $0x804a3d1,0x4(%esp)
   0x08048b6d <;28>:    mov    0x8(%ebp),%eax
   0x08048b70 <;31>:    mov    %eax,(%esp)
   0x08048b73 <;34>:    call   0x80487d0 <__isoc99_sscanf;plt>
   0x08048b78 <;39>:    cmp    $0x1,%eax
   0x08048b7b <;42>:    jg     0x8048b82 <phase_3;49>
   0x08048b7d <;44>:    call   0x8049145 <explode_bomb>
   0x08048b82 <;49>:    cmpl   $0x7,-0xc(%ebp)
   0x08048b86 <;53>:    ja     0x8048bc3 <phase_3;114> 
   0x08048b88 <;55>:    mov    -0xc(%ebp),%eax
   0x08048b8b <;58>:    jmp    *0x804a1a0(,%eax,4)
   0x08048b92 <;65>:    mov    $0x164,%eax
   0x08048b97 <;70>:    jmp    0x8048bd4 <phase_3;131>
   0x08048b99 <;72>:    mov    $0x2a2,%eax
   0x08048b9e <;77>:    jmp    0x8048bd4 <phase_3;131>
   0x08048ba0 <;79>:    mov    $0x255,%eax
   0x08048ba5 <;84>:    jmp    0x8048bd4 <phase_3;131>
   0x08048ba7 <;86>:    mov    $0x77,%eax
   0x08048bac <;91>:    jmp    0x8048bd4 <phase_3;131>
   0x08048bae <;93>:    mov    $0x30e,%eax
   0x08048bb3 <;98>:    jmp    0x8048bd4 <phase_3;131>
   0x08048bb5 <;100>:   mov    $0x271,%eax
   0x08048bba <;105>:   jmp    0x8048bd4 <phase_3;131>
   0x08048bbc <;107>:   mov    $0x389,%eax
   0x08048bc1 <;112>:   jmp    0x8048bd4 <phase_3;131>
   0x08048bc3 <;114>:   call   0x8049145 <explode_bomb>
   0x08048bc8 <;119>:   mov    $0x0,%eax
   0x08048bcd <;124>:   jmp    0x8048bd4 <phase_3;131>
   0x08048bcf <;126>:   mov    $0xa4,%eax
   0x08048bd4 <;131>:   cmp    -0x10(%ebp),%eax
   0x08048bd7 <;134>:   je     0x8048bde <phase_3;141>
   0x08048bd9 <;136>:   call   0x8049145 <explode_bomb>
   0x08048bde <;141>:   leave
   0x08048bdf <;142>:   ret

在第20行有命令;movl $0x804a3d1,0x4(%esp),将一个立即数送入到esp寄存器中;所以查看立即数代表的值;
说明需要输入两个int型的字符num_1,num_2的分别存放在esp;0x8和esp;0xc处

   0x08048b78 <;39>:    cmp    $0x1,%eax
   0x08048b82 <;49>:    cmpl   $0x7,-0xc(%ebp)
   0x08048b86 <;53>:    ja     0x8048bc3 <phase_3;114> 

说明输入数的个数为2个;而且需要小于等于0x7才行

   0x08048b88 <;55>:    mov    -0xc(%ebp),%eax
   0x08048b8b <;58>:    jmp    *0x804a1a0(,%eax,4)

这段代码是将esp-0xc的值存放到eax中;然后跳转到eax*4 ; *0x804a1a0的地址处;所以我查看了0x804a1a0的内容;
Datalab实验_Bomblab
跳转对应地址的代码为;

   0x08048b97 <;70>:    jmp    0x8048bd4 <phase_3;131>
   0x08048b99 <;72>:    mov    $0x2a2,%eax
   0x08048b9e <;77>:    jmp    0x8048bd4 <phase_3;131>
   0x08048ba0 <;79>:    mov    $0x255,%eax
   0x08048ba5 <;84>:    jmp    0x8048bd4 <phase_3;131>
   0x08048ba7 <;86>:    mov    $0x77,%eax
   0x08048bac <;91>:    jmp    0x8048bd4 <phase_3;131>
   0x08048bae <;93>:    mov    $0x30e,%eax
   0x08048bb3 <;98>:    jmp    0x8048bd4 <phase_3;131>
   0x08048bb5 <;100>:   mov    $0x271,%eax
   0x08048bba <;105>:   jmp    0x8048bd4 <phase_3;131>
   0x08048bbc <;107>:   mov    $0x389,%eax
   0x08048bc1 <;112>:   jmp    0x8048bd4 <phase_3;131>
   0x08048bc3 <;114>:   call   0x8049145 <explode_bomb>
   0x08048bc8 <;119>:   mov    $0x0,%eax
   0x08048bcd <;124>:   jmp    0x8048bd4 <phase_3;131>
   0x08048bcf <;126>:   mov    $0xa4,%eax

所以这也是一个switch语句;参数就是eax里的值;整理下可以得到;

num_1    	num_2          eax     jmp      
0           0x164 = 356    0       0x08048b92
1           0xa4 = 164     1       0x08048bcf 
2           0x2a2 = 674    2       0x08048b99
3           0x255 = 597    3       0x08048ba0
4           0x77 = 119     4       0x08048ba7
5           0x30e = 782    5       0x08048bae
6           0x271 = 625    6       0x08048bb5
7           0x389 = 905    7       0x08048bbc

switch语句为 ;

switch(num_1)
{
    case 0:
        if(num_2 != 356)	Boom();
        break;
	... ...  
}

4.phase_4;递归调用和栈;

思路;
调出phase_4的反汇编;
   0x08048c42 <;0>:     push   %ebp
   0x08048c43 <;1>:     mov    %esp,%ebp
   0x08048c45 <;3>:     sub    $0x28,%esp
   0x08048c48 <;6>:     lea    -0x10(%ebp),%eax
   0x08048c4b <;9>:     mov    %eax,0xc(%esp)// 将ebp-16处的地址赋给esp;12 num_2
   0x08048c4f <;13>:    lea    -0xc(%ebp),%eax
   0x08048c52 <;16>:    mov    %eax,0x8(%esp)// 将ebp-12处的地址赋给esp;8 num_1
   0x08048c56 <;20>:    movl   $0x804a3d1,0x4(%esp)
   0x08048c5e <;28>:    mov    0x8(%ebp),%eax
   0x08048c61 <;31>:    mov    %eax,(%esp)
   0x08048c64 <;34>:    call   0x80487d0 <__isoc99_sscanf;plt>
   0x08048c69 <;39>:    cmp    $0x2,%eax
   0x08048c6c <;42>:    jne    0x8048c74 <phase_4;50>// eax != 0x2
   0x08048c6e <;44>:    cmpl   $0xe,-0xc(%ebp)//比较ebp-12处的值与0xe(14)的大小 
   0x08048c72 <;48>:    jbe    0x8048c79 <phase_4;55>
   0x08048c74 <;50>:    call   0x8049145 <explode_bomb>
   0x08048c79 <;55>:    movl   $0xe,0x8(%esp)// 0xe(14)赋值给esp;8
   0x08048c81 <;63>:    movl   $0x0,0x4(%esp)// 0x0赋值给esp;4
   0x08048c89 <;71>:    mov    -0xc(%ebp),%eax// eax = num_1
   0x08048c8c <;74>:    mov    %eax,(%esp)// 准备参数
   0x08048c8f <;77>:    call   0x8048be0 <func4>// 调用递归函数
   0x08048c94 <;82>:    cmp    $0x4,%eax// eax为函数func4的返回值
   0x08048c97 <;85>:    jne    0x8048c9f <phase_4;93>// eax要等于0x4;否则引爆炸弹
   0x08048c99 <;87>:    cmpl   $0x4,-0x10(%ebp)
   0x08048c9d <;91>:    je     0x8048ca4 <phase_4;98>// -0x10(%ebp) == 0x4
   0x08048c9f <;93>:    call   0x8049145 <explode_bomb>
   0x08048ca4 <;98>:    leave
   0x08048ca5 <;99>:    ret

先查询第20行命令movl $0x804a3d1,0x4(%esp)中立即数;
Datalab实验_Bomblab

   0x08048c69 <;39>:    cmp    $0x2,%eax
   0x08048c6c <;42>:    jne    0x8048c74 <phase_4;50>// eax != 0x2

所以我需要输入两个int型的数num_1; num_2

   0x08048c6e <;44>:    cmpl   $0xe,-0xc(%ebp)//比较ebp-12处的值与0xe(14)的大小 
   0x08048c72 <;48>:    jbe    0x8048c79 <phase_4;55>
   0x08048c99 <;87>:    cmpl   $0x4,-0x10(%ebp)
   0x08048c9d <;91>:    je     0x8048ca4 <phase_4;98>// -0x10(%ebp) == 0x4

这段代码确定了输入的第一个参数num_1需要小于14;第二个参数num_2为0x4

   0x08048c79 <;55>:    movl   $0xe,0x8(%esp)// 0xe(14)赋值给esp;8
   0x08048c81 <;63>:    movl   $0x0,0x4(%esp)// 0x0赋值给esp;4
   0x08048c89 <;71>:    mov    -0xc(%ebp),%eax// eax = num_1
   0x08048c8c <;74>:    mov    %eax,(%esp)// 准备参数
   0x08048c8f <;77>:    call   0x8048be0 <func4>// 调用递归函数
   0x08048c94 <;82>:    cmp    $0x4,%eax// eax为函数func4的返回值
   0x08048c97 <;85>:    jne    0x8048c9f <phase_4;93>// eax要等于0x4;否则引爆炸弹

调用递归函数func4;传入的参数依次为; num_1; 0; 14;而且需要在调用函数后eax的值等于4;所以函数的返回值应为4;所以我需要查看func4函数;

   0x8048be0 <func4>:   push   %ebp
   0x8048be1 <func4;1>: mov    %esp,%ebp
   0x8048be3 <func4;3>: push   %esi
   0x8048be4 <func4;4>: push   %ebx// ebx和esi是被调用保存寄存器
   0x8048be5 <func4;5>: sub    $0x10,%esp// 开栈
   0x8048be8 <func4;8>: mov    0x8(%ebp),%edx// ebp;8 赋值给 edx edx = 14 保存参数f_1
   0x8048beb <func4;11>:        mov    0xc(%ebp),%eax// 保存f_2 
   0x8048bee <func4;14>:        mov    0x10(%ebp),%ebx// 保存f_3
   0x8048bf1 <func4;17>:        mov    %ebx,%ecx// ecx寄存器其到一个展示保存结果的作用
   0x8048bf3 <func4;19>:        sub    %eax,%ecx// ecx -= eax 
   0x8048bf5 <func4;21>:        mov    %ecx,%esi
   0x8048bf7 <func4;23>:        shr    $0x1f,%esi// 逻辑右移31位 esi = ecx >> 31
   0x8048bfa <func4;26>:        add    %esi,%ecx// 
   0x8048bfc <func4;28>:        sar    %ecx//算数右移 没有参数默认移动一位 
   0x8048bfe <func4;30>:        add    %eax,%ecx// ecx ;= eax
   0x8048c00 <func4;32>:        cmp    %edx,%ecx
   0x8048c02 <func4;34>:        jle    0x8048c1b <func4;59>// 如果edx >= ecx
   0x8048c04 <func4;36>:        sub    $0x1,%ecx// ecx -= 0x1
   0x8048c07 <func4;39>:        mov    %ecx,0x8(%esp)
   0x8048c0b <func4;43>:        mov    %eax,0x4(%esp)
   0x8048c0f <func4;47>:        mov    %edx,(%esp)
   0x8048c12 <func4;50>:        call   0x8048be0 <func4>// 递归调用自身
   0x8048c17 <func4;55>:        add    %eax,%eax// eax *= 2;
   0x8048c19 <func4;57>:        jmp    0x8048c3b <func4;91>
   0x8048c1b <func4;59>:        mov    $0x0,%eax// eax = 0
   0x8048c20 <func4;64>:        cmp    %edx,%ecx
   0x8048c22 <func4;66>:        jge    0x8048c3b <func4;91>
   0x8048c24 <func4;68>:        mov    %ebx,0x8(%esp)
   0x8048c28 <func4;72>:        add    $0x1,%ecx
   0x8048c2b <func4;75>:        mov    %ecx,0x4(%esp)
   0x8048c2f <func4;79>:        mov    %edx,(%esp)
   0x8048c32 <func4;82>:        call   0x8048be0 <func4>
   0x8048c37 <func4;87>:        lea    0x1(%eax,%eax,1),%eax// eax = eax ; eax * 1 ; 1
   0x8048c3b <func4;91>:        add    $0x10,%esp//增加栈
   0x8048c3e <func4;94>:        pop    %ebx
   0x8048c3f <func4;95>:        pop    %esi
   0x8048c40 <func4;96>:        pop    %ebp
   0x8048c41 <func4;97>:        ret

设传入func4的参数为f_1,f_2,f_3, 则;

   0x8048bf1 <func4;17>:        mov    %ebx,%ecx// ecx寄存器其到一个展示保存结果的作用
   0x8048bf3 <func4;19>:        sub    %eax,%ecx// ecx -= eax 
   0x8048bf5 <func4;21>:        mov    %ecx,%esi
   0x8048bf7 <func4;23>:        shr    $0x1f,%esi// 逻辑右移31位 esi = ecx >> 31
   0x8048bfa <func4;26>:        add    %esi,%ecx// 
   0x8048bfc <func4;28>:        sar    %ecx//算数右移 没有参数默认移动一位 
   0x8048bfe <func4;30>:        add    %eax,%ecx// ecx ;= eax

上面的代码的作用是计算((((f_3 - f_2) >> 31) ; (f_3 - f_2))>> 1) ; f_2的结果保存在寄存器ecx;temp)中;下面是在不同的情况下不同的操作;

​ (1) 当edx>=ecx(f_1 >= temp)的情况下时;令eax=0;判断edx与ecx的值是否相等;相等直接返回eax的值,不能则递归调用自己;即;(eax = f_2, edx = f_1, ecx = temp)

   0x8048c00 <func4;32>:        cmp    %edx,%ecx
   0x8048c02 <func4;34>:        jle    0x8048c1b <func4;59>// 如果edx >= ecx
   0x8048c1b <func4;59>:        mov    $0x0,%eax// eax = 0
   /* edx == ecx */
   0x8048c20 <func4;64>:        cmp    %edx,%ecx
   0x8048c22 <func4;66>:        jge    0x8048c3b <func4;91>
   0x8048c24 <func4;68>:        mov    %ebx,0x8(%esp)
   0x8048c28 <func4;72>:        add    $0x1,%ecx
   /*  edx > ecx */
   0x8048c2b <func4;75>:        mov    %ecx,0x4(%esp)
   0x8048c2f <func4;79>:        mov    %edx,(%esp)
   0x8048c32 <func4;82>:        call   0x8048be0 <func4>
   0x8048c37 <func4;87>:        lea    0x1(%eax,%eax,1),%eax// eax = eax ; eax * 1 ; 1

用C语言表示为;

   f_2 = 0;      
   if(temp == f_1)
       return f_2;
   else
   {
       temp ;;;
       return (func4(f_1, temp, f_3) * 2 ; 1);
   }

(2) 当edx>=ecx时;ecx的值减1;在调用自身;

   0x8048c04 <func4;36>:        sub    $0x1,%ecx// ecx -= 0x1
   0x8048c07 <func4;39>:        mov    %ecx,0x8(%esp)
   0x8048c0b <func4;43>:        mov    %eax,0x4(%esp)
   0x8048c0f <func4;47>:        mov    %edx,(%esp)
   0x8048c12 <func4;50>:        call   0x8048be0 <func4>// 递归调用自身
   0x8048c17 <func4;55>:        add    %eax,%eax// eax *= 2;

用C语言表示为;

    temp --;
    return (func4(f_1, f_2, temp) * 2);

综上;func4的函数用C语言表示为;

int func4(int f_1, int f_2, int f_3)
{/*           %edx     %eax     %ebx*/
    int temp = f_3;

    temp = ((((f_3 - f_2) >> 31) ; (f_3 - f_2))>> 1) ; f_2;
    if(temp <= f_1)
    {
        f_2 = 0;      
        if(temp == f_1)
            return f_2;
        else
        {
            temp ;;;
            return (func4(f_1, temp, f_3) * 2 ; 1);
        }
    }
    else
    {
        temp --;
        return (func4(f_1, f_2, temp) * 2);
    }   
}

为了求出第一个输入参数num_1的值;我写了一个程序运行求结果

int func4(int f_1, int f_2, int f_3)
{
    int temp = f_3;

    temp = ((((f_3 - f_2) >> 31) ; (f_3 - f_2))>> 1) ; f_2;
    if(temp <= f_1)
    {
        f_2 = 0;      
        if(temp == f_1)
            return f_2;
        else
        {
            temp ;;;
            return (func4(f_1, temp, f_3) * 2 ; 1);
        }
    }
    else
    {
        temp --;
        return (func4(f_1, f_2, temp) * 2);
    }   
}

int main()
{
    int i = 0, r = 0;

    for(i = 0; i < 14; i;;)
    {
        r = func4(i, 0, 14);
        if(r == 0x4)
            printf(%d
;,i);
    }
    return 0;
}

最终的结果是;2 4

5.phase_5;指针;

思路;
调出phase_5的反汇编;
   0x08048ca6 <;0>:     push   %ebp
   0x08048ca7 <;1>:     mov    %esp,%ebp
   0x08048ca9 <;3>:     push   %ebx
   0x08048caa <;4>:     sub    $0x14,%esp
   0x08048cad <;7>:     mov    0x8(%ebp),%ebx
   0x08048cb0 <;10>:    mov    %ebx,(%esp)
   0x08048cb3 <;13>:    call   0x8048f00 <string_length>
   0x08048cb8 <;18>:    cmp    $0x6,%eax
   0x08048cbb <;21>:    je     0x8048cc2 <phase_5;28>
   0x08048cbd <;23>:    call   0x8049145 <explode_bomb>
   0x08048cc2 <;28>:    mov    $0x0,%edx
   0x08048cc7 <;33>:    mov    $0x0,%eax
   0x08048ccc <;38>:    movzbl (%ebx,%eax,1),%ecx
   0x08048cd0 <;42>:    and    $0xf,%ecx
   0x08048cd3 <;45>:    add    0x804a1c0(,%ecx,4),%edx
   0x08048cda <;52>:    add    $0x1,%eax
   0x08048cdd <;55>:    cmp    $0x6,%eax
   0x08048ce0 <;58>:    jne    0x8048ccc <phase_5;38>
   0x08048ce2 <;60>:    cmp    $0x32,%edx
   0x08048ce5 <;63>:    je     0x8048cec <phase_5;70>
   0x08048ce7 <;65>:    call   0x8049145 <explode_bomb>
   0x08048cec <;70>:    add    $0x14,%esp
   0x08048cef <;73>:    pop    %ebx
   0x08048cf0 <;74>:    pop    %ebp
   0x08048cf1 <;75>:    ret

在调用完string_length函数后让eax与6比较可得知需要输入6个字符;为了了解程序运行的过程;我在0x08048ccc<;38>处设置断点;运行程序后输入123456:
Datalab实验_Bomblab
查看ecx寄存器的值;
Datalab实验_Bomblab
当ecx的值为0x31是继续往下执行;

   0x08048cd0 <;42>:    and    $0xf,%ecx
   0x08048cd3 <;45>:    add    0x804a1c0(,%ecx,4),%edx
   0x08048cda <;52>:    add    $0x1,%eax  

把ecx的值与0xf相与在把地址ecx * 4 ; 0x804a1c0的值赋值给edx寄存器;所以需要查看立即数0x804a1c0里的值;
Datalab实验_Bomblab
整理后可得;

and    $0xf,%ecx        0x804a1c0(,%ecx,4)
        0               0x2 = 2
        1               0xa = 10
        2               0x6 = 6
        3               0x1 = 1
        4               0xc = 12
        5               0x1 = 1
        6               0x9 = 9
        7               0x3 = 3
        8               0x4 = 4
        9               0x7 = 7
        10              0xe = 14
        11              0x5 = 5
        12              0xb = 11
        13              0x8 = 8
        14              0xf = 15
        15              0xd = 13

所以下面这个代码段是一个循环;一次取出我输入的字符存放到ecx中并与 0x相与;然后求出ecx*4;0x804a1c0对应的值;累加后存放到edx中

   0x08048ccc <;38>:    movzbl (%ebx,%eax,1),%ecx
   0x08048cd0 <;42>:    and    $0xf,%ecx
   0x08048cd3 <;45>:    add    0x804a1c0(,%ecx,4),%edx
   0x08048cda <;52>:    add    $0x1,%eax
   0x08048cdd <;55>:    cmp    $0x6,%eax
   0x08048ce0 <;58>:    jne    0x8048ccc <phase_5;38>

当eax的值为6是代表已经运行了6次;此时跳出循环继续往下执行;

   0x08048ce2 <;60>:    cmp    $0x32,%edx
   0x08048ce5 <;63>:    je     0x8048cec <phase_5;70>
   0x08048ce7 <;65>:    call   0x8049145 <explode_bomb>

把累加后的edx的值与0x32(50)比较;如果相等则不引爆炸弹。
所以整个phase_5首先依次取出输入的值;不同的值对应不同的数字;循环6次取出所有输入后把累加的结果与50比较;如果相等就不引爆炸弹。
为了简单;取50 = 8 ; 8 ; 8 ; 8 ; 8 ; 10
在循环中若要edx=8;则and $0xf,%ecx的值应该是0xD(13), 同理edx=10对应0x1
查找ASCII码表可知;
最低位为0xD的字符为;‘-’ ‘=’ ‘M’ ‘]’ ‘m’ ‘}’
最低位为0x1的字符为: ‘!’ ‘1’ ‘A’ ‘Q’ ‘a’ ‘q’
所以只要在0xD中任取5个字符;0x1中任取1个字符组成输入的密码即可;即输入MMMMMA

6.phase_6;链表/指针/结构;

思路;
调出phase_6的反汇编;(把输入的数记做num[0…5])
   0x08048cf2 <;0>:     push   %ebp
   0x08048cf3 <;1>:     mov    %esp,%ebp
   0x08048cf5 <;3>:     push   %esi
   0x08048cf6 <;4>:     push   %ebx
   0x08048cf7 <;5>:     sub    $0x40,%esp
   0x08048cfa <;8>:     lea    -0x20(%ebp),%eax
   0x08048cfd <;11>:    mov    %eax,0x4(%esp)
   0x08048d01 <;15>:    mov    0x8(%ebp),%eax
   0x08048d04 <;18>:    mov    %eax,(%esp)
   0x08048d07 <;21>:    call   0x8049187 <read_six_numbers>
   0x08048d0c <;26>:    mov    $0x0,%esi// eis初始化

/*判断输入的数应该在1-6之间 而且各不相等*/
   0x08048d11 <;31>:    mov    -0x20(%ebp,%esi,4),%eax
   0x08048d15 <;35>:    sub    $0x1,%eax
   0x08048d18 <;38>:    cmp    $0x5,%eax
   0x08048d1b <;41>:    jbe    0x8048d22 <phase_6;48>//如果eax减为负数时会大于0x5 这时会引爆
   0x08048d1d <;43>:    call   0x8049145 <explode_bomb>
   0x08048d22 <;48>:    add    $0x1,%esi// 计数 esi ;;
   0x08048d25 <;51>:    cmp    $0x6,%esi
   0x08048d28 <;54>:    jne    0x8048d31 <phase_6;63>// 不足6次
   0x08048d2a <;56>:    mov    $0x0,%ebx// 如果完成了6次
   0x08048d2f <;61>:    jmp    0x8048d69 <phase_6;119>
   0x08048d31 <;63>:    mov    %esi,%ebx// ebx = esi
   0x08048d33 <;65>:    mov    -0x20(%ebp,%ebx,4),%eax
   0x08048d37 <;69>:    cmp    %eax,-0x24(%ebp,%esi,4)
   0x08048d3b <;73>:    jne    0x8048d42 <phase_6;80>// 如果num[ebx] 等于 num[esi - 1] 引爆
   0x08048d3d <;75>:    call   0x8049145 <explode_bomb>
   0x08048d42 <;80>:    add    $0x1,%ebx// 计数 ebx ;;
   0x08048d45 <;83>:    cmp    $0x5,%ebx
   0x08048d48 <;86>:    jle    0x8048d33 <phase_6;65>// ebx <= 0x5
   0x08048d4a <;88>:    jmp    0x8048d11 <phase_6;31>// 

/*小端方式压栈 如;$0x804c154 压入-0x38(%ebp,%esi,4)*/
   0x08048d4c <;90>:    mov    0x8(%edx),%edx
   0x08048d4f <;93>:    add    $0x1,%eax// eax ;;
   0x08048d52 <;96>:    cmp    %ecx,%eax
   0x08048d54 <;98>:    jne    0x8048d4c <phase_6;90>// 不相等
   0x08048d56 <;100>:   jmp    0x8048d5d <phase_6;107>// 相等则跳转
   0x08048d58 <;102>:   mov    $0x804c154,%edx// *** ecx == 1
   0x08048d5d <;107>:   mov    %edx,-0x38(%ebp,%esi,4)// 压栈
   0x08048d61 <;111>:   add    $0x1,%ebx
   0x08048d64 <;114>:   cmp    $0x6,%ebx
   0x08048d67 <;117>:   je     0x8048d80 <phase_6;142>// 相等
   0x08048d69 <;119>:   mov    %ebx,%esi// ebx = esi
   0x08048d6b <;121>:   mov    -0x20(%ebp,%ebx,4),%ecx// ecx = num[edx]
   0x08048d6f <;125>:   cmp    $0x1,%ecx
   0x08048d72 <;128>:   jle    0x8048d58 <phase_6;102>// ecx <= 1
   0x08048d74 <;130>:   mov    $0x1,%eax
   0x08048d79 <;135>:   mov    $0x804c154,%edx// 
   0x08048d7e <;140>:   jmp    0x8048d4c <phase_6;90>

  /*node5->next = &node4*/ 
   0x08048d80 <;142>:   mov    -0x38(%ebp),%ebx// num[0]
   0x08048d83 <;145>:   lea    -0x34(%ebp),%eax// num[1]
   0x08048d86 <;148>:   lea    -0x20(%ebp),%esi
   0x08048d89 <;151>:   mov    %ebx,%ecx
   0x08048d8b <;153>:   mov    (%eax),%edx
   0x08048d8d <;155>:   mov    %edx,0x8(%ecx)// ecx;8是节点存储的第三个数据
   0x08048d90 <;158>:   add    $0x4,%eax// 下一个地址
   0x08048d93 <;161>:   cmp    %esi,%eax
   0x08048d95 <;163>:   je     0x8048d9b <phase_6;169>
   0x08048d97 <;165>:   mov    %edx,%ecx
   0x08048d99 <;167>:   jmp    0x8048d8b <phase_6;153>


   0x08048d9b <;169>:   movl   $0x0,0x8(%edx)//node6->next = NULL
   0x08048da2 <;176>:   mov    $0x5,%esi
   0x08048da7 <;181>:   mov    0x8(%ebx),%eax
   0x08048daa <;184>:   mov    (%eax),%eax
   0x08048dac <;186>:   cmp    %eax,(%ebx)
   0x08048dae <;188>:   jle    0x8048db5 <phase_6;195>// node1.num <= node1.num
   0x08048db0 <;190>:   call   0x8049145 <explode_bomb>
   0x08048db5 <;195>:   mov    0x8(%ebx),%ebx
   0x08048db8 <;198>:   sub    $0x1,%esi
   0x08048dbb <;201>:   jne    0x8048da7 <phase_6;181>// !=0
   0x08048dbd <;203>:   add    $0x40,%esp
   0x08048dc0 <;206>:   pop    %ebx
   0x08048dc1 <;207>:   pop    %esi
   0x08048dc2 <;208>:   pop    %ebp

分别来看 phase_6的汇编;
;1;检查输入的值是否满足要求;

   0x08048d11 <;31>:    mov    -0x20(%ebp,%esi,4),%eax
   0x08048d15 <;35>:    sub    $0x1,%eax
   0x08048d18 <;38>:    cmp    $0x5,%eax
   0x08048d1b <;41>:    jbe    0x8048d22 <phase_6;48>//如果eax减为负数时会大于0x5 这时会引爆

在这里首先eax–,如果eax的初值小于等于1或大于5;在eax减1后会大于5;所以这里是对输入的值的大小进行判断

   0x08048d25 <;51>:    cmp    $0x6,%esi
   0x08048d28 <;54>:    jne    0x8048d31 <phase_6;63>// 不足6次
   0x08048d31 <;63>:    mov    %esi,%ebx// ebx = esi
   0x08048d33 <;65>:    mov    -0x20(%ebp,%ebx,4),%eax
   0x08048d37 <;69>:    cmp    %eax,-0x24(%ebp,%esi,4)
   0x08048d3b <;73>:    jne    0x8048d42 <phase_6;80>// 如果num[ebx] 等于 num[esi - 1] 

这里是对相邻两个数之间进行判断;确保相邻两数不等

   0x08048d2a <;56>:    mov    $0x0,%ebx// 如果完成了6次
   0x08048d2f <;61>:    jmp    0x8048d69 <phase_6;119>

如果所有的数都已经进行了判断则跳出第一个大循环;继续向下运行
;2;把对应数据压栈保存

   0x08048d6b <;121>:   mov    -0x20(%ebp,%ebx,4),%ecx// ecx = num[edx]
   0x08048d6f <;125>:   cmp    $0x1,%ecx
   0x08048d72 <;128>:   jle    0x8048d58 <phase_6;102>// ecx <= 1
   0x08048d74 <;130>:   mov    $0x1,%eax
   0x08048d79 <;135>:   mov    $0x804c154,%edx// 
   0x08048d7e <;140>:   jmp    0x8048d4c <phase_6;90>
   0x08048d4c <;90>:    mov    0x8(%edx),%edx

将esi的值保存到edx中;如果ecx>= 1则执行下述操作;

   0x08048d4c <;90>:    mov    0x8(%edx),%edx
   0x08048d4f <;93>:    add    $0x1,%eax// eax ;;
   0x08048d52 <;96>:    cmp    %ecx,%eax
   0x08048d54 <;98>:    jne    0x8048d4c <phase_6;90>// 不相等
   0x08048d56 <;100>:   jmp    0x8048d5d <phase_6;107>// 相等则跳转

如果ecx与eax不等则继续循环;相等后就会跳出循环执行;

   0x08048d5d <;107>:   mov    %edx,-0x38(%ebp,%esi,4)// 压栈
   0x08048d61 <;111>:   add    $0x1,%ebx
   0x08048d64 <;114>:   cmp    $0x6,%ebx
   0x08048d67 <;117>:   je     0x8048d80 <phase_6;142>// 相等

即把edx里面对应的值压栈保存到ebp ;esi*4 -0x38中;而edx的初值在第102行

   0x08048d58 <;102>:   mov    $0x804c154,%edx// *** ecx == 1
   0x08048d5d <;107>:   mov    %edx,-0x38(%ebp,%esi,4)// 压栈
   0x08048d61 <;111>:   add    $0x1,%ebx
   0x08048d64 <;114>:   cmp    $0x6,%ebx
   0x08048d67 <;117>:   je     0x8048d80 <phase_6;142>// 相等

当该循环刚开始运行时ecx==1执行上诉操作;所以我需要查看0x804c154:
Datalab实验_Bomblab
整理可得;

0x804c154 <node1>:      0x0000010a      0x00000001      0x0804c160
0x804c160 <node2>:      0x00000303      0x00000002      0x0804c16c
0x804c16c <node3>:      0x0000038e      0x00000003      0x0804c178
0x804c154 <node4>:      0x0000036f      0x00000004      0x0804c184
0x804c178 <node5>:      0x00000054      0x00000005      0x0804c190
0x804c190 <node6>:      0x000002cf      0x00000006      0x00000000
                        // 0x00000000      0x38313631                --->esi

可以看出第二列为节点的编号;
即可设节点结构为;

struct node{
	int num_1;
    int num;// 序号
    int num_2
}

;3;建立节点之间的连接

   0x08048d80 <;142>:   mov    -0x38(%ebp),%ebx// num[0]
   0x08048d83 <;145>:   lea    -0x34(%ebp),%eax// num[1]
   0x08048d86 <;148>:   lea    -0x20(%ebp),%esi
   0x08048d89 <;151>:   mov    %ebx,%ecx
   0x08048d8b <;153>:   mov    (%eax),%edx

赋初值操作;esi的设置是为了防止循环到最后链表指向空

   0x08048d8d <;155>:   mov    %edx,0x8(%ecx)// ecx;8是节点存储的第三个数据
   0x08048d90 <;158>:   add    $0x4,%eax// 下一个地址
   0x08048d93 <;161>:   cmp    %esi,%eax
   0x08048d95 <;163>:   je     0x8048d9b <phase_6;169>
   0x08048d97 <;165>:   mov    %edx,%ecx
   0x08048d99 <;167>:   jmp    0x8048d8b <phase_6;153>

在赋初值和循环过程中eax指向的地址一直是ebx后一个的地址,所以在命令mov %edx,0x8(%ecx)中的操作是把前一个节点的0x8处的地址指向下一个节点;所以ecx;0x8应该是指针next,所以当循环结束后链表的结构是;
node1.next->node2.next->node3.next->node4.next->node5.next->node6
链表的第一行应该是节点的值node.num
(4) 排序

   0x08048dac <;186>:   cmp    %eax,(%ebx)
   0x08048dae <;188>:   jle    0x8048db5 <phase_6;195>// node1.num <= node1.num

表明是升序排序

所以根据节点的值升序排序的节点序列为;5 1 6 2 4 3

bomblab 隐藏关卡

思路;
调出secret_phase的反汇编;
   0x08048e17 <;0>:     push   %ebp
   0x08048e18 <;1>:     mov    %esp,%ebp
   0x08048e1a <;3>:     push   %ebx
   0x08048e1b <;4>:     sub    $0x14,%esp
   0x08048e1e <;7>:     call   0x80491d6 <read_line>
   0x08048e23 <;12>:    movl   $0xa,0x8(%esp)
   0x08048e2b <;20>:    movl   $0x0,0x4(%esp)
   0x08048e33 <;28>:    mov    %eax,(%esp)
   0x08048e36 <;31>:    call   0x8048830 <strtol;plt>// Strtol有三个参数;第一个是要转化的字符串的地址;第二个是结束符标志;0表明是;;;第三个是转化的数的进制;a说明最后是10进制。
   0x08048e3b <;36>:    mov    %eax,%ebx
   0x08048e3d <;38>:    lea    -0x1(%eax),%eax
   0x08048e40 <;41>:    cmp    $0x3e8,%eax
   0x08048e45 <;46>:    jbe    0x8048e4c <secret_phase;53>// eax-1 <= 1000 
   0x08048e47 <;48>:    call   0x8049145 <explode_bomb>
   0x08048e4c <;53>:    mov    %ebx,0x4(%esp)
   0x08048e50 <;57>:    movl   $0x804c0a0,(%esp)
   0x08048e57 <;64>:    call   0x8048dc4 <fun7>
   0x08048e5c <;69>:    cmp    $0x5,%eax// eax 需要等于0x5
   0x08048e5f <;72>:    je     0x8048e66 <secret_phase;79>
   0x08048e61 <;74>:    call   0x8049145 <explode_bomb>
   0x08048e66 <;79>:    movl   $0x804a15c,(%esp)
   0x08048e6d <;86>:    call   0x8048780 <puts;plt>
   0x08048e72 <;91>:    call   0x804930e <phase_defused>
   0x08048e77 <;96>:    add    $0x14,%esp
   0x08048e7a <;99>:    pop    %ebx
   0x08048e7b <;100>:   pop    %ebp
   0x08048e7c <;101>:   ret

首先需要考虑如何在boomlab中调出隐藏关;因此我查看了phase_defused函数的反汇编;(节选)

   0x08049341 <;51>:    movl   $0x804a42b,0x4(%esp)
   0x08049349 <;59>:    movl   $0x804c8f0,(%esp)
   0x08049350 <;66>:    call   0x80487d0 <__isoc99_sscanf;plt>
   0x08049355 <;71>:    cmp    $0x3,%eax
   0x08049358 <;74>:    jne    0x804938e <phase_defused;128>
   0x0804935a <;76>:    movl   $0x804a434,0x4(%esp)

首先在71行把eax与0x3比较;我查看其他的命令发现没通过一关eax就会加1;而当eax与0x3相等时代表我正在通过第4关;而且讲义上说开启隐藏关需要在第 4 关输入特殊字符;所以我查看了0x804a42b0x804a434
Datalab实验_Bomblab
所以隐藏关的开启是在第四关写入2 4 DrEvil

   0x08048e45 <;46>:    jbe    0x8048e4c <secret_phase;53>// eax-1 <= 1000 
   0x08048e47 <;48>:    call   0x8049145 <explode_bomb>
   0x08048e4c <;53>:    mov    %ebx,0x4(%esp)
   0x08048e50 <;57>:    movl   $c,(%esp)
   0x08048e57 <;64>:    call   0x8048dc4 <fun7>// 参数c 和 ebx
   0x08048e5c <;69>:    cmp    $0x5,%eax// eax 需要等于0x5
   0x08048e5f <;72>:    je     0x8048e66 <secret_phase;79>

这里说明了需要输入一个数num,满足num <= 1001, 而且这个数需要传入func7函数里;返回值需要为5

于是查看func7的反汇编;

   0x08048dc4 <;0>:     push   %ebp
   0x08048dc5 <;1>:     mov    %esp,%ebp
   0x08048dc7 <;3>:     push   %ebx
   0x08048dc8 <;4>:     sub    $0x14,%esp
   0x08048dcb <;7>:     mov    0x8(%ebp),%edx// a
   0x08048dce <;10>:    mov    0xc(%ebp),%ecx// b
   0x08048dd1 <;13>:    test   %edx,%edx
   0x08048dd3 <;15>:    je     0x8048e0c <fun7;72>// edx == 0
   0x08048dd5 <;17>:    mov    (%edx),%ebx// ebx = a
   0x08048dd7 <;19>:    cmp    %ecx,%ebx
   0x08048dd9 <;21>:    jle    0x8048dee <fun7;42>// *a <= b
   0x08048ddb <;23>:    mov    %ecx,0x4(%esp)// b
   0x08048ddf <;27>:    mov    0x4(%edx),%eax
   0x08048de2 <;30>:    mov    %eax,(%esp)// a
   0x08048de5 <;33>:    call   0x8048dc4 <fun7>// 递归调用
   0x08048dea <;38>:    add    %eax,%eax// eax *= 2
   0x08048dec <;40>:    jmp    0x8048e11 <fun7;77>// 跳出
   0x08048dee <;42>:    mov    $0x0,%eax
   0x08048df3 <;47>:    cmp    %ecx,%ebx// *a == b
   0x08048df5 <;49>:    je     0x8048e11 <fun7;77>// 跳出 返回值eax = 0
   0x08048df7 <;51>:    mov    %ecx,0x4(%esp)
   0x08048dfb <;55>:    mov    0x8(%edx),%eax
   0x08048dfe <;58>:    mov    %eax,(%esp)
   0x08048e01 <;61>:    call   0x8048dc4 <fun7>
   0x08048e06 <;66>:    lea    0x1(%eax,%eax,1),%eax//eax = eax*2 ; 0x1
   0x08048e0a <;70>:    jmp    0x8048e11 <fun7;77>
   0x08048e0c <;72>:    mov    $0xffffffff,%eax// eax = -1
   0x08048e11 <;77>:    add    $0x14,%esp
   0x08048e14 <;80>:    pop    %ebx
   0x08048e15 <;81>:    pop    %ebp
   0x08048e16 <;82>:    ret

设func7的参数为a,b,则

   0x08048dd1 <;13>:    test   %edx,%edx
   0x08048dd3 <;15>:    je     0x8048e0c <fun7;72>// edx == 0
   0x08048e0c <;72>:    mov    $0xffffffff,%eax// eax = -1
   0x08048e11 <;77>:    add    $0x14,%esp

如果指针a为空则返会-1

   0x08048dd5 <;17>:    mov    (%edx),%ebx// ebx = a
   0x08048dd7 <;19>:    cmp    %ecx,%ebx
   0x08048dd9 <;21>:    jle    0x8048dee <fun7;42>// *a <= b

先判断*a,b的大小关系;如果*a <= b则;

/* *a == b*/
   0x08048dee <;42>:    mov    $0x0,%eax
   0x08048df3 <;47>:    cmp    %ecx,%ebx// *a == b
   0x08048df5 <;49>:    je     0x8048e11 <fun7;77>// 跳出 返回值eax = 0
/* *a < b */
   0x08048df7 <;51>:    mov    %ecx,0x4(%esp)
   0x08048dfb <;55>:    mov    0x8(%edx),%eax
   0x08048dfe <;58>:    mov    %eax,(%esp)// *a ;0x8
   0x08048e01 <;61>:    call   0x8048dc4 <fun7>
   0x08048e06 <;66>:    lea    0x1(%eax,%eax,1),%eax//eax = eax*2 ; 0x1
   0x08048e0a <;70>:    jmp    0x8048e11 <fun7;77>

如果 *a > b,则;

   0x08048ddb <;23>:    mov    %ecx,0x4(%esp)// b
   0x08048ddf <;27>:    mov    0x4(%edx),%eax
   0x08048de2 <;30>:    mov    %eax,(%esp)// *a ; 0x4
   0x08048de5 <;33>:    call   0x8048dc4 <fun7>// 递归调用
   0x08048dea <;38>:    add    %eax,%eax// eax *= 2
   0x08048dec <;40>:    jmp    0x8048e11 <fun7;77>// 跳出

综上,用C语言描述func7函数;

int fun7(int *a, int b)
{
   if(a == NULL)
      return -1;
   else if(*a <= b)
   {
      if(*a == b)
         return 0;
      else
         return (2 * fun7(*a ; 8, b) ; 1);
   }
   else
       return (2 * fun7(*a ; 0x4));
} 

因为返回值为5 ;则有;

5 = 2 * 2 ; 1
2 = 2 * 1
1 = 2 * 0 ; 1
0: a == b
/*********************/
            0
     ;0x4 /    ;0x8
         /     
             1 = 2 * ;0; ; 1
      ;0x4 /    ;0x8
          /     
      2 = 2 * ;1;
    /   
   /     
       5 = 2 * ;2; ; 1     注;;;标注表示上一级func7的返回值

而参数a地址为0x804c0a0,所以最初输入的值应该是0x804c0a0先加0x8的对应的地址;然后该地址再加0X4后对应的地址在加0x8,最后的这个地址对应的值即为所求;
Datalab实验_Bomblab
最终结果为 ;47

加载全部内容

相关教程
猜你喜欢
用户评论
快盘暂不提供评论功能!