CSAPP实验-bomblab超详解

gdb调试知识

gdb bomb:使用gdb调试可执行文件bomb

break 函数名/行号:打断点

r(run):运行至断点

c(continue):继续执行到下一个断点

q(quit):退出gdb

si:单指令执行

n(next):单步跟踪程序,遇到调用函数不会进入函数内部

s(step):单步调试,遇到调用函数会进入函数内部

until:运行程序直到退出循环体

layout asm:显示反汇编窗口

layout regs:显示反汇编和寄存器窗口

disassemble:查看当前执行指令的汇编代码

i r 寄存器名:显示当前寄存器值

x/[count][format] [address]:打印指定格式指定数量的内存值

phase_1 

反汇编代码:

   0x00005555555555e7 <+0>:     endbr64 
   0x00005555555555eb <+4>:     sub    $0x8,%rsp
   0x00005555555555ef <+8>:     lea    0x1b56(%rip),%rsi        # 0x55555555714c
   0x00005555555555f6 <+15>:    call   0x555555555af3 <strings_not_equal>
   0x00005555555555fb <+20>:    test   %eax,%eax
   0x00005555555555fd <+22>:    jne    0x555555555604 <phase_1+29>
   0x00005555555555ff <+24>:    add    $0x8,%rsp
   0x0000555555555603 <+28>:    ret
   0x0000555555555604 <+29>:    call   0x555555555c07 <explode_bomb>
   0x0000555555555609 <+34>:    jmp    0x5555555555ff <phase_1+24>

<+0>指令前缀,目的是增强安全性

<+4>减少栈指针的八个字节,分配空间

前两行基本是固定的,对拆弹没什么作用。

<+8>lea这个指令在实际应用中是用来计算地址,而非访问内存。这里是将%rip内的地址加上0x1b56的偏移量加载到%rsi中,i r rip查看此处rip的值为0x5555555555e7,加上偏移量刚好等于注释中的0x55555555714c。

<+15>这里调用函数,看名字就能知道这是一个判断字符串是否相等的函数,我们先接着往下看。

<+20>这里是将eax的值自身按位与,eax是返回值,也就是判断<+15>处调用的函数的返回值是否为零。

<+22>:如果上一行返回值不等于0,则跳转到<phase_1+29>处,即爆炸。

<+24>:如果<+20>处返回值等于0,则增加栈指针八个字节,释放分配的空间。

<+28>:从函数返回,结束phase_1。

也就是说我们本题输入应为一个字符串,存在%rdi(第一个参数)中,与%rsi(第二个参数)内地址对应的字符串相等。

x/s 0x55555555714c查看内容得到"Public speaking is very easy."即为答案。

phase_2

反汇编代码:

   0x000055555555560b <+0>:     endbr64
   0x000055555555560f <+4>:     push   %rbp
   0x0000555555555610 <+5>:     push   %rbx
   0x0000555555555611 <+6>:     sub    $0x28,%rsp
   0x0000555555555615 <+10>:    mov    %fs:0x28,%rax
   0x000055555555561e <+19>:    mov    %rax,0x18(%rsp)
   0x0000555555555623 <+24>:    xor    %eax,%eax
   0x0000555555555625 <+26>:    mov    %rsp,%rsi
   0x0000555555555628 <+29>:    call   0x555555555c33 <read_six_numbers>
   0x000055555555562d <+34>:    cmpl   $0x0,(%rsp)
   0x0000555555555631 <+38>:    js     0x55555555563d <phase_2+50>
   0x0000555555555633 <+40>:    mov    %rsp,%rbp
   0x0000555555555636 <+43>:    mov    $0x1,%ebx
   0x000055555555563b <+48>:    jmp    0x555555555650 <phase_2+69>
   0x000055555555563d <+50>:    call   0x555555555c07 <explode_bomb>
   0x0000555555555642 <+55>:    jmp    0x555555555633 <phase_2+40>
   0x0000555555555644 <+57>:    add    $0x1,%ebx
   0x0000555555555647 <+60>:    add    $0x4,%rbp
   0x000055555555564b <+64>:    cmp    $0x6,%ebx
   0x000055555555564e <+67>:    je     0x555555555661 <phase_2+86>
   0x0000555555555650 <+69>:    mov    %ebx,%eax
   0x0000555555555652 <+71>:    add    0x0(%rbp),%eax
   0x0000555555555655 <+74>:    cmp    %eax,0x4(%rbp)
   0x0000555555555658 <+77>:    je     0x555555555644 <phase_2+57>
   0x000055555555565a <+79>:    call   0x555555555c07 <explode_bomb>
   0x000055555555565f <+84>:    jmp    0x555555555644 <phase_2+57>
   0x0000555555555661 <+86>:    mov    0x18(%rsp),%rax
   0x0000555555555666 <+91>:    sub    %fs:0x28,%rax
   0x000055555555566f <+100>:   jne    0x555555555678 <phase_2+109>
   0x0000555555555671 <+102>:   add    $0x28,%rsp
   0x0000555555555675 <+106>:   pop    %rbx
   0x0000555555555676 <+107>:   pop    %rbp
   0x0000555555555677 <+108>:   ret
   0x0000555555555678 <+109>:   call   0x555555555250 <__stack_chk_fail@plt>

有了上边的经验,我们后边直接看关键点,调用了函数<read_six_numbers>可以推知我们本题需要输入六个数字,设为x1-x6。

<+34>:比较栈指针指向的内存中的数与0的大小,即判断正负,若为负数,跳转到<phase_2+50>爆炸。

此时栈指针指向的内存的数即x1。

然后将栈指针的值赋给%rbp,将立即数1赋给%ebx。

无条件跳转至<phase_2+69>,将%ebx的值(也就是1)赋给%eax,将%rbp指向的内存的值(即x1)加到%eax中,比较%rbp的值+0x4的偏移量所指向的内存的值(即x2)与%eax的值(1+x1)的大小。如果相等则跳转<phase_2+57>,不相等则爆炸。

所以有x2=x1+1。

跳转到<+57>:将%ebx的值加1,将%rbp的值加4,此时%rbp指向的内存的数变为x2。再判断6和%ebx的大小,不相等则继续进行<+69>的操作:将%ebx的值(此时为2)赋给%eax,将%rbp指向的内存的值(x2)加到%eax中,比较%rbp的值+0x4的偏移量所指向的内存的值(即x3)与%eax的值(2+x2)的大小。如果相等则跳转<phase_2+57>,不相等则爆炸。

即x3=x2+2。

只有当%ebx=6时才跳出这个循环,那么%ebx在这里我们可以理解为数字的索引n,必须保证Xn=X(n-1)+n-1。

又因为输入的数必须不能为负,我们设x1=1,则答案为1 2 4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值