0


CSAPP:BombLab 详细解析

Bomb Lab 来自《深入理解计算机系统》(CSAPP)一书的第三章的配套实验,该实验的目的是通过反汇编可执行程序,来反推出程序执行内容,进而能够正确破解”密码“,解除“炸弹”。

本实验共有6个 phase,对于每个 phase,你需要输入一段字符串,然后让代码中 explode_bomb函数不执行,这样就不会 boom !

准备工作

在拆炸弹之前我们先复习一下第三章的知识

1.关于跳转指令

指令解释jz如果ZF=1,跳转至指定位置jnz如果ZF=0,跳转至制定位置je与jz类似,但通常在一条cmp指令后使用。如果源操作数与目的操作数相等,则跳转jne与jnz类似,但通常在一条cmp指令后使用。如果源操作数与目的操作数不相等,则跳转jgcmp指令做有符号比较之后,如果目的操作数大于原操作数,跳转jgecmp指令做有符号比较之后,如果目的操作数大于或等于原操作数,跳转ja与jg类似,但使用无符号比较jae与jge类似,但使用无符号比较jlcmp指令做有符号比较之后,如果目的操作数小于原操作数,则跳转jlecmp指令做有符号比较之后,如果目的操作数小于或等于原操作数,则跳转jb与jl类似,但使用无符号比较jbe与jle类似,但使用无符号比较jo如果前一条指令置位了溢出标志位(OF=1),则跳转js如果符号标志位被置位(SF=1),则跳转jecxz如果ECX=0,则跳转

2. 关于栈

当某个函数运行时,机器需要分配一定的内存去进行函数内的各种操作,这个过程中分配的那部分栈称为栈帧。下图描述了栈帧的通用结构。

栈帧是一段有界限的内存区间,由最顶端的两个指针界定,寄存器 %ebp 为帧指针(栈底),而寄存器 %esp 为栈指针(也就是说寄存器%ebp保存了所分配内存的最高地址,寄存器%esp保存了所分配内存的最低地址)。

当程序执行时,栈指针(栈顶)可以移动,因此大多数信息的访问都是相对于桢指针的。

** 在函数被调用之前,**调用者会为调用函数做准备,具体来说就是传参。(传参对应的寄存器分别为:第一个参数%rdi,第二个参数%rsi......)

(c 程序使用栈存放局部变量、函数参数和返回地址)

被调用函数运行时,我们在函数里面是要执行各种操作的,所以我们需要给新栈帧分配一定的内存。也就是:

sub $0x10,%esp

(举个例子,具体分配内存大小按照所需空间分配),将%esp低地址移动16个字节。有了这么多的储存空间,才能支持函数里面的各种操作。

被调用函数运行结束时,恢复原来栈顶的状态。

⚠️这里要注意:函数的返回值一般储存在%eax寄存器中

请把下面这张图刻进 DNA

3.关于sscanf

sscanf(char *string, char *format, arg1,arg2, arg3....)

其中是%rdi寄存器作为指向string的头指针

同理,%rsi作为format

arg1, arg2, arg3, arg4分别是由寄存器%rdx, %rcx, %r8, %r9存储

如果上面的知识你已经掌握了,那我们来开始拆炸弹吧!

Bomb Lab

首先拿到代码我们先看 README 文件,好吧,什么都没有,我们继续看其他文件。

发现 bomb.c 文件,但是没有头文件,所以不能进行运行和编译。但可以看出该程序要求从命令行或者文件以“行”为单位读入字符串,每行字符串对应一个phase的输入。如果phase执行完毕,会调用phase_defused 函数表明该 phase 成功搞定。

最后剩一个可执行文件,我们通过gdb调试,反汇编bomb文件,尝试得到该可执行文件的汇编代码。

具体操作如下:

objdump -d bomb > bomb.asm

这样就把反汇编得到的汇编代码存在一个文件 bomb.asm 中,便于查看。

然后通过打 breakpoint 的方法,以及查看寄存器和内存里存的值的情况,结合汇编语句,推算出应该输入的语句。

phase_1

在汇编代码中找到phase_1函数

0000000000400ee0 <phase_1>:
  400ee0:    48 83 ec 08              sub    $0x8,%rsp
  400ee4:    be 00 24 40 00           mov    $0x402400,%esi
  400ee9:    e8 4a 04 00 00           callq  401338 <strings_not_equal>
  400eee:    85 c0                    test   %eax,%eax
  400ef0:    74 05                    je     400ef7 <phase_1+0x17>
  400ef2:    e8 43 05 00 00           callq  40143a <explode_bomb>
  400ef7:    48 83 c4 08              add    $0x8,%rsp
  400efb:    c3                       retq   

阅读代码我们先找到了 explode_bomb,在继续往上看

由于我们不能执行 explode_bomb 函数,所以需要在该函数之前执行跳转指令跳过explode_bomb 函数,那么什么条件可以执行该跳转指令呢?我们在继续往上看

发现 %eax 作为上一个函数的返回值,若 %eax 为0,才可以执行跳转

继续往上推发现了函数 strings_not_equal ,通过阅读代码可以发现这个函数是判断输入的两个字符串是否相等,根据上面我们提到的知识可以知道函数传进去的参数分别在寄存器 %edi 和 %es i中,其中 %edi 是我们输入的字符串

答案出来了,寄存器 %esi 里的值就是本题答案,寄存器 %esi 是被地址在 0x402400 的内容赋值,我们可以通过gdb查看一下该地址内容

先进入bomb(注意此时路径一定要在bomb文件下)

gdb bomb

查看该地址内容

(gdb) x/s 0x402400

出现本题答案

Border relations with Canada have never been better.

测试结果如下:

phase_2 (循环)

还是阅读代码找到 explode_bomb 函数,发现有两个

我们先看一下如何避免第一个引爆函数的执行

好与上题同理,这里需让 %rsp 的值为1,后执行跳转指令 je

目标地址 400f30 处是 lea 指令,功能为加载有效地址

两条指令执行后运行时栈的状态为

设置完栈地址后又执行了跳转指令

  400f17:    8b 43 fc                 mov    -0x4(%rbx),%eax
  400f1a:    01 c0                    add    %eax,%eax
  400f1c:    39 03                    cmp    %eax,(%rbx)
  400f1e:    74 05                    je     400f25 <phase_2+0x29>
  400f20:    e8 15 05 00 00           callq  40143a <explode_bomb>
  400f25:    48 83 c3 04              add    $0x4,%rbx
  400f29:    48 39 eb                 cmp    %rbp,%rbx
  400f2c:    75 e9                    jne    400f17 <phase_2+0x1b>
  400f2e:    eb 0c                    jmp    400f3c <phase_2+0x40>

我们来仔细看一下这几条指令

首先 %eax 为 %rsp 指针指向的位置(值为1),%eax = %eax + %eax(此时值为2)

比较 %eax 与% rbx 指针所指向的值,这里为了不引爆炸弹,所以 %rbx 指针指向的值必须等于 %eax(值为2),那么我们可以知道 %rbx 指针指向的位置的值为 2

下一步将 %rbx + 4(其实也就是%rbx指针向上移动4个字节),比较 %rbp 与 %rbx ,相等则跳到结束语句,不相等则继续执行上几条指令

由此我们可以看出这是几条语句是循环指令,当 %rbp 与 %rbx 的值相等,则结束循环,若不相等则仍然执行上述指令

同理可得整个栈的内容为

由此phase_2的功能大概可以清楚了,首先将字符串解析成6个数字的正数数组,其中第一个整数必须为1,后面的每一个元素都是前一个元素的两倍。

即可得到本题答案

1 2 4 8 16 32

phase_3 (switch-case)

这次我们从上往下开始看

进入 phase_3 之后,首先是通过 sscanf 解析字符串,通过 gdb 调试可看出 sscanf 的 format 是

%d %d 

因此推断输出两个数字

(gdb) x/s 0x4025cf
0x4025cf:    "%d %d"

好下面我们开始找 explode_bomb 函数,发现有四个( 400f6f 行也算进去了)

400f60:    83 f8 01                 cmp    $0x1,%eax
400f63:    7f 05                    jg     400f6a <phase_3+0x27>
400f65:    e8 d0 04 00 00           callq  40143a <explode_bomb>

在找到第一个 explode_bomb 函数后往上看,发现在地址 400f63 处必须跳转

也就等同于输入的第一个值要大于等于 1

下面我们找到第二个函数

  400f6a:    83 7c 24 08 07           cmpl   $0x7,0x8(%rsp)
  400f6f:    77 3c                    ja     400fad <phase_3+0x6a> #bomb

此时 7 必须大于 0x8(%rsp) --就是输入的第一个值,才不会发生爆炸

我们继续往下看

将输入的第一个值存到 %eax 中,然后执行一个间接跳转,地址为内存地址 0x402470(,%rax,8)处的值(这里%rax是我们输入的第一个值)

下面我们用 gdb 调试一下看看内存地址为 0x402470(,%rax,8) 的值

这里我们能看出,当输入值(%rax)为 0 的时候,跳转到 0x400f7c

同理为 1 的时候,跳到 0x400fb9 ...... 可以得出一个跳转表
index01234567address0x400f7c0x400fb90x400f830x400f8a0x400f910x400f980x400f9f0x400fa6%eax207311707256389206682327
为了跳过 400fad 行的炸弹,我们需要完成跳转表跳到 ** 400fbe**

这里为跳过 400fc4 行的 explode_bomb 函数,我们输入的第二个值要对应上面的跳转表

所以答案出来了,可以是以下答案的任意一种

1 311 / 2 707 / 3 256 / 4 389 / 5 206 / 6 682 / 7 327

phase_4 (递归)

这回我们还是从上往下看,发现很多代码与上一个相同

这里的 sscanf 也是输入两个数字,分别在地址0x8(%rsp)、0xc(%rsp) 上

  401029:    83 f8 02                 cmp    $0x2,%eax
  40102c:    75 07                    jne    401035 <phase_4+0x29> #bomb

在 40102c 行我们遇到了第一个炸弹,此时限制条件是输入的第一个值不能为 2

  40102e:    83 7c 24 08 0e           cmpl   $0xe,0x8(%rsp)
  401033:    76 05                    jbe    40103a <phase_4+0x2e>
  401035:    e8 00 04 00 00           callq  40143a <explode_bomb>

在这里的为了跳过这个炸弹,限制条件是0x8(%rsp) --输入的第一个值要小于 14(0xe)

  40103a:    ba 0e 00 00 00           mov    $0xe,%edx
  40103f:    be 00 00 00 00           mov    $0x0,%esi
  401044:    8b 7c 24 08              mov    0x8(%rsp),%edi
  401048:    e8 81 ff ff ff           callq  400fce <func4>

再解决这两个限制条件之后,将 edx、esi、edi 赋值,将参数传进 func4函数

当执行完 func4 函数之后返回的值在寄存器 %eax 中

  40104d:    85 c0                    test   %eax,%eax
  40104f:    75 07                    jne    401058 <phase_4+0x4c>
  401051:    83 7c 24 0c 00           cmpl   $0x0,0xc(%rsp)
  401056:    74 05                    je     40105d <phase_4+0x51>
  401058:    e8 dd 03 00 00           callq  40143a <explode_bomb>

此时为了防止调用 explode_bomb 函数,**返回值 %eax 要为 0 **

并且,0xc(%rsp) --输入的第二个值 也必须为 0

至此我们知道:

  • 解析字符串为两个数字 x、y
  • x 必须小于等于14
  • 调用 fun​​​​​​​c4,x、0、14 分别为其参数
  • func4 返回值必须为0,y 必须为0

那下面看一下 func4 函数

这个函数最初看着可能有点麻烦,需要整理一下

eax = edx
eax = eax - esi
ecx = eax 
ecx = 0
eax = eax + ecx
eax = eax / 2
ecx = esi + eax
if(edi >= ecx)
{
    return
    eax = 0 //正好是我们想要的结果
    edi <= ecx 
}

else
{
    edx = rcx - 1
    func4()
    eax = eax + eax
    return
}

我们将之前对参数带入发现:

    寄存器 %eax 和 %ecx 存了7

    %ecx 寄存器的值与 %edi 里的值比较 (%edi里是我们输入的第一个数)

这里比较的时候有两种情况

发生跳转时

  400ff2:    b8 00 00 00 00           mov    $0x0,%eax
  400ff7:    39 f9                    cmp    %edi,%ecx
  400ff9:    7d 0c                    jge    401007 <func4+0x39>
    此时 %edi 大于等于 7

    地址400ff2处把%eax置为0,正好是我们想要的结果

    比较要求 7 大于等于 %edi,后跳转可以顺利退出

我们发现当 %edi = 7 的时候可以满足这些条件顺利退出(这是一个答案,也就是说第一个输入的值可以为 7 )

不发生跳转时

  400fe6:    8d 51 ff                 lea    -0x1(%rcx),%edx
  400fe9:    e8 e0 ff ff ff           callq  400fce <func4>
  400fee:    01 c0                    add    %eax,%eax
  400ff0:    eb 15                    jmp    401007 <func4+0x39>

这里用到递归,但也不要怕,我们只需要按照上面的指令,对寄存器 %eax 和 %ecx 一顿操作就可以了

至此答案就出来了:我们第一个输入的值可以是 0、1、3、7,第二个输入的值为 0

0 0 / 1 0 / 3 0 / 7 0

phase_5 (循环 字符串 ascii 码)

从上往下看,首先将输入值赋给寄存器 rbx ,第40106a行是金丝雀值,这里不用管,我们可以简单的看成从内存中读取一个数到寄存器 rax 中(忘记的可以回头看看书,这里是为了验证是否发生缓冲区溢出)

  401062:    53                       push   %rbx
  401063:    48 83 ec 20              sub    $0x20,%rsp
  401067:    48 89 fb                 mov    %rdi,%rbx
  40106a:    64 48 8b 04 25 28 00     mov    %fs:0x28,%rax
  401071:    00 00 
  401073:    48 89 44 24 18           mov    %rax,0x18(%rsp)
  401078:    31 c0                    xor    %eax,%eax
  40107a:    e8 9c 02 00 00           callq  40131b <string_length>
  40107f:    83 f8 06                 cmp    $0x6,%eax
  401082:    74 4e                    je     4010d2 <phase_5+0x70>
  401084:    e8 b1 03 00 00           callq  40143a <explode_bomb>

其次将寄存器 eax 清零,调用 string_length 函数(之前我们看过,这里不再赘述,就是比较字符串长度的函数)

此时为了防止炸弹爆炸,我们知道了输入的字符串长度应该为 6

 4010d2:    b8 00 00 00 00           mov    $0x0,%eax
 4010d7:    eb b2                    jmp    40108b <phase_5+0x29>

寄存器 eax 清零,继续执行跳转

  40108b:    0f b6 0c 03              movzbl (%rbx,%rax,1),%ecx
  40108f:    88 0c 24                 mov    %cl,(%rsp)
  401092:    48 8b 14 24              mov    (%rsp),%rdx
  401096:    83 e2 0f                 and    $0xf,%edx
  401099:    0f b6 92 b0 24 40 00     movzbl 0x4024b0(%rdx),%edx
  4010a0:    88 54 04 10              mov    %dl,0x10(%rsp,%rax,1)
  4010a4:    48 83 c0 01              add    $0x1,%rax
  4010a8:    48 83 f8 06              cmp    $0x6,%rax
  4010ac:    75 dd                    jne    40108b <phase_5+0x29>

这里我们将汇编代码做一下调整

for(rax = 0,rax != 6,rax ++)
{
    ecx = rbx + rax
    *(rsp) = cl
    rdx = *(rsp)
    edx = edx & 0xf
    edx = 0x4024b0 + rdx
    rsp + rax + 0x10 = dl
}

取输入字符串的字符,然后逐次将每个字符与 0xf “与”操作,得到的值作为

0x4024b0 

处字符串的下标。

0xf “与运算” 

操作意味着能取到

0x4024b0 

处字符串的范围是 0-15,通过 gdb 查看

0x4024b0 

处字符串:

得到了前16为字符串:

maduiersnfotvbyl

通过 for 循环能够生成一个字符串,该字符串由输入的

每个字符和 0xf “与运算”

得到的值,作为

maduiersnfotvbyl 

的下标,来选择字符

那么生成的字符串是什么呢?我们继续往下看

  4010ae:    c6 44 24 16 00           movb   $0x0,0x16(%rsp)
  4010b3:    be 5e 24 40 00           mov    $0x40245e,%esi
  4010b8:    48 8d 7c 24 10           lea    0x10(%rsp),%rdi
  4010bd:    e8 76 02 00 00           callq  401338 <strings_not_equal>
  4010c2:    85 c0                    test   %eax,%eax
  4010c4:    74 13                    je     4010d9 <phase_5+0x77>
  4010c6:    e8 6f 03 00 00           callq  40143a <explode_bomb>

4010ae 行是字符串的结束符,将生成的字符串与 0x40245e 处的字符串比较,为了防止炸弹爆炸,我们生成的字符串就要和 0x40245e 处的字符串相等,那我们查看一下

所以结果出来了:

1.输入的字符串长度为6

2.输入字符串的每个字符与 0xf “与运算”得到的数值在“

maduiersnfotvbyl

”中寻找字符,最后得到一段字符串

3.循环得到的字符串应该为“flyers”

我们可以发现“flyers”六个字母对应 “

maduiersnfotvbyl

” 的下标分别为 9、15、14、5、6、7

查一下 ascii 表,可以找到六个 & 0xf 分别为 9、15、14、5、6、7 的字符

答案为:

ionefg

phase_6 (链表、循环)

代码看着很长,我们拆成六个模块一点一点看

第一个模块就是调用 read_six_numbers 函数

  4010f4:    41 56                    push   %r14
  4010f6:    41 55                    push   %r13
  4010f8:    41 54                    push   %r12
  4010fa:    55                       push   %rbp
  4010fb:    53                       push   %rbx
  4010fc:    48 83 ec 50              sub    $0x50,%rsp
  401100:    49 89 e5                 mov    %rsp,%r13
  401103:    48 89 e6                 mov    %rsp,%rsi
  401106:    e8 51 03 00 00           callq  40145c <read_six_numbers>
  40110b:    49 89 e6                 mov    %rsp,%r14
  40110e:    41 bc 00 00 00 00        mov    $0x0,%r12d

不停的赋值,然后读入六个数,得到的栈如下图

第二个模块就是一个嵌套循环,利用上图的栈,对输入的数进行一些操作,这里就是看指针的变化

  401114:    4c 89 ed                 mov    %r13,%rbp
  401117:    41 8b 45 00              mov    0x0(%r13),%eax
  40111b:    83 e8 01                 sub    $0x1,%eax
  40111e:    83 f8 05                 cmp    $0x5,%eax
  401121:    76 05                    jbe    401128 <phase_6+0x34>
  401123:    e8 12 03 00 00           callq  40143a <explode_bomb>
  401128:    41 83 c4 01              add    $0x1,%r12d
  40112c:    41 83 fc 06              cmp    $0x6,%r12d
  401130:    74 21                    je     401153 <phase_6+0x5f>
  401132:    44 89 e3                 mov    %r12d,%ebx
  401135:    48 63 c3                 movslq %ebx,%rax
  401138:    8b 04 84                 mov    (%rsp,%rax,4),%eax
  40113b:    39 45 00                 cmp    %eax,0x0(%rbp)
  40113e:    75 05                    jne    401145 <phase_6+0x51>
  401140:    e8 f5 02 00 00           callq  40143a <explode_bomb>
  401145:    83 c3 01                 add    $0x1,%ebx
  401148:    83 fb 05                 cmp    $0x5,%ebx
  40114b:    7e e8                    jle    401135 <phase_6+0x41>
  40114d:    49 83 c5 04              add    $0x4,%r13
  401151:    eb c1                    jmp    401114 <phase_6+0x20>
//双层循环

这里大家可能要回去复习一下几种寻址方式

比如(%r13)表示的是 r13 寄存器指向的值而不是 r13 寄存器的值

好,那我们看一下这个嵌套循环是怎么实现的呢?

40111e 行中 eax 寄存器其实是外层循环,循环六次,每次 r12 寄存器分别指向 num1、num2、num3......

内层循环就是拿 r12 寄存器的值和剩下的五个对比,这里为了跳过炸弹,这里告诉我们六个值都是不一样的且都小于等于6

用 c 代码给大家清楚的看一下

for (int r12 = 0; r12 != 6; r12++) {
    rbp = r13;
    eax = *r13;
    eax -= 1;
    if ((eax > 5)        // 最大为6
        explode_bomb();

    for (ebx = r12+1; ebx <= 5; ebx++) {
        rax = ebx;
        eax = *(rsp+rax*4);
        if (*rbp == eax)    //所有值不能相等
            explode_bomb();
        }

    r13 += 4;
}

第三个模块就是一个循环,让每个栈中的 num 的值修改为 “7 - num”

  401153:    48 8d 74 24 18           lea    0x18(%rsp),%rsi
  401158:    4c 89 f0                 mov    %r14,%rax
  40115b:    b9 07 00 00 00           mov    $0x7,%ecx
  401160:    89 ca                    mov    %ecx,%edx
  401162:    2b 10                    sub    (%rax),%edx
  401164:    89 10                    mov    %edx,(%rax)
  401166:    48 83 c0 04              add    $0x4,%rax
  40116a:    48 39 f0                 cmp    %rsi,%rax
  40116d:    75 f1                    jne    401160 <phase_6+0x6c>
//num = 7 - num

这里还是要注意一个寻址方式的问题哦~

第四个模块是本题组重要的环节,真的很复杂,可以多看几遍

  40116f:    be 00 00 00 00           mov    $0x0,%esi
  401174:    eb 21                    jmp    401197 <phase_6+0xa3>

  401176:    48 8b 52 08              mov    0x8(%rdx),%rdx
  40117a:    83 c0 01                 add    $0x1,%eax
  40117d:    39 c8                    cmp    %ecx,%eax
  40117f:    75 f5                    jne    401176 <phase_6+0x82>
  401181:    eb 05                    jmp    401188 <phase_6+0x94>
  
  401183:    ba d0 32 60 00           mov    $0x6032d0,%edx
  401188:    48 89 54 74 20           mov    %rdx,0x20(%rsp,%rsi,2)
  40118d:    48 83 c6 04              add    $0x4,%rsi
  401191:    48 83 fe 18              cmp    $0x18,%rsi
  401195:    74 14                    je     4011ab <phase_6+0xb7>

  401197:    8b 0c 34                 mov    (%rsp,%rsi,1),%ecx
  40119a:    83 f9 01                 cmp    $0x1,%ecx
  40119d:    7e e4                    jle    401183 <phase_6+0x8f>

  40119f:    b8 01 00 00 00           mov    $0x1,%eax
  4011a4:    ba d0 32 60 00           mov    $0x6032d0,%edx
  4011a9:    eb cb                    jmp    401176 <phase_6+0x82>
//将六个节点的起始地址按照某顺序放到栈上

对栈里的6个数字,先判断他们是否为1

如果为1,就把0x6032d0放在栈里;如果不为1,就循环操作

对这个地址进行计算之后的地址里的值放在寄存器里,可以得到5个地址

分别是 0x6032e0、0x6032f0、 0x603300,、0x603310、0x603320

分别对应值2、3、4、5、6,我们用 gdb 查看对应的值

然后把他们按照某种顺序放在栈的 %rsp + 0x20 到 %rsp + 0x48 处

第五个模块对每个地址里存的值做了操作,其实就是将链表重新连接

  4011ab:    48 8b 5c 24 20           mov    0x20(%rsp),%rbx
  4011b0:    48 8d 44 24 28           lea    0x28(%rsp),%rax
  4011b5:    48 8d 74 24 50           lea    0x50(%rsp),%rsi
  4011ba:    48 89 d9                 mov    %rbx,%rcx
  4011bd:    48 8b 10                 mov    (%rax),%rdx
  4011c0:    48 89 51 08              mov    %rdx,0x8(%rcx)
  4011c4:    48 83 c0 08              add    $0x8,%rax
  4011c8:    48 39 f0                 cmp    %rsi,%rax
  4011cb:    74 05                    je     4011d2 <phase_6+0xde>
  4011cd:    48 89 d1                 mov    %rdx,%rcx
  4011d0:    eb eb                    jmp    4011bd <phase_6+0xc9>

  4011d2:    48 c7 42 08 00 00 00     movq   $0x0,0x8(%rdx)
  4011d9:    00 
//重新连接链表

第六个模块为了防止炸弹爆炸,我们只能将链表降序连接

  4011da:    bd 05 00 00 00           mov    $0x5,%ebp
  4011df:    48 8b 43 08              mov    0x8(%rbx),%rax
  4011e3:    8b 00                    mov    (%rax),%eax
  4011e5:    39 03                    cmp    %eax,(%rbx)
  4011e7:    7d 05                    jge    4011ee <phase_6+0xfa>
  4011e9:    e8 4c 02 00 00           callq  40143a <explode_bomb>
  4011ee:    48 8b 5b 08              mov    0x8(%rbx),%rbx
  4011f2:    83 ed 01                 sub    $0x1,%ebp
  4011f5:    75 e8                    jne    4011df <phase_6+0xeb>

好啦答案就出来啦

链表排序,输入的数字为原链表位置,输入的次序为新链表的位置

又因为第二个循环对array每个数字 7 - array[i],因此输入的数字需要将链表重排成为升序
地址值对应值输入值0x6032d014c160x6032e0a8250x6032f039c340x6033002b3430x6033101dd520x6033201bb61
原链表的从小到大顺序是 5 6 1 2 3 4, 重排后为 4 3 2 1 6 5

即可得到答案

4 3 2 1 6 5

总结

其实这篇博客算是我写的最久的一篇了(可能下一篇会更久),上学期写项目有压力的时候开始写(结果写完更有压力了bushi)一直到所有比赛结束,我才开始收心写这篇博客。

不过也正是因为如此我做了很多遍这个lab,同时让我对汇编、逆向有了更深层次的了解,希望能给你们带来帮助❤️


本文转载自: https://blog.csdn.net/weixin_52259822/article/details/124219469
版权归原作者 prician 所有, 如有侵权,请联系我们删除。

“CSAPP:BombLab 详细解析”的评论:

还没有评论