跳转至

BombLab

前置知识

  1. objdump -d bomb8 > bomb8.asm生成反汇编代码 >objdump生成的汇编地址并非最后的内存虚拟地址,而是一个相对地址。 objdump生成的绝对地址有问题,但是各个指令之间的相对位置不会出现改变,可以认为在可执行程序加载到内存的时候,操作系统帮我们完成一次地址移动,绝对地址改变,但是指令之间的相对地址关系不变。

  2. gdb bomb8使用gdb调试可执行文件

    • r run 运行程序直到断点
    • c continue 继续执行
    • q quit 退出
    • si 单指令执行
    • b break 设置断电,b n 在第n行,b func 在func()入口设置断点,b *地址值在地址值处设置断点
    • i b info break 显示断电设置情况
    • i r info registers 显示寄存器的内容
    • delete n 删除第n个断点
    • disable/enable n 暂停/开启第n个断电
    • delete breakpoints 删除所有断点
    • layout regs 显示寄存器和反汇编窗口
    • layout asm 显示反汇编窗口
    • x/FMT ADDRESS
      • ADDRESS is an expression for the memory address to examine.
      • FMT is a repeat count followed by a format letter and a size letter.
    • until + 行号

解题过程

phase_1

b phase_1 test %eax,%eax jne 1604 说明strings_not_equal函数结束后,eax存的值是0 草稿纸-605.jpg 从函数名上猜测是判断2个字符串是否想到 通过i r rbx rdi 发现rbx rdi存的是input string image.png 发现 rsi 存的是这个字符串的地址 根据strings_not_equal,可以得出input string应该和rsi一致 所以第一问答案为You can Russia from land here in Alaska.

phase_2

image.png 说明的作用是读取6个数字,中间用空格隔开

image.png 可以发现rsp寄存器存的地址是:输入的6个数字

image.png 说明第一个数字要大于0 草稿纸-606.jpg 发现 644-658 之间有个循环 等价于 for(ebx = 1; ebx != 6; ebx++) rbp=rsp存的是输入的6个数字 通过add $0x4 %rbp$遍历输入的6个数字 再判断x[i] + ebxx[i+1]的大小关系 如果不等 就爆炸 所以对输入的要求:每2个数字之间的差值从1增加到5 所以第一问答案为 12 4 7 11 16

phase_3

image.png 说明输入2个数字,中间以空格隔开 草稿纸-607.jpg cmpl $0x7, (%rsp)确保x1 <= 7

image.png 这3行代码会跳到由x1决定的地址 当x1 == 6时,会跳到70b,令eax = 0x11a即282 由6d8行代码可知 x2必须等于eax=282 所以第三问答案 6 282

phase_4

image.png 说明输入4个数字,中间以空格隔开 草稿纸-608.jpg 根据7c1行代码可知 x2必须等于31 根据7bc行代码可知 eax必须等于31 说明退出func4的时候 eax要设置为31 草稿纸-609.jpg 第一次进入func4的时候 edi指向input,edx为14,esi为0 研究func4代码... 发现eax存的值每一次递归中的ebx的值的和 func4会根据edi(即x1)和ebx的大小关系 进入不同的递归 本质时不断找[esi,edx]的中点ebx 再累加 image.png 画个图很容易就出来了 除了对x1 x2有限制,x3 x4任取 所以第4问答案 13 31 1 2

phase_5

image.png 说明输入2个数字,中间以空格隔开

image.png 怀疑rsi存的地址是一个数组的开头 然后edx从0到15,说明要遍历数组 现在就是不清楚mov (%rsi,%rax,4),%eax 对应的eax是多少 ecx是每一次eax的值的和 草稿纸-611.jpg 核心是选定一个初始的x1,进入数组,根据数组中对应x1位置的值 跳到值对应的位置,跳来跳去,最后跳到值为15的位置结束循环,有点指针的感觉 image.png 倒推很容易算出来x1=5 x2=120,但是发现bomb 直接 i r ecx 发现值为115 所以最后的答案是5 115

phase_6

image.png read_six_numbers直接猜输入6个数字,中间以空格隔开 草稿纸-615.jpg 8f4行以前的代码是通过2个循环,确保输入的6个数字都不相等 同时8e6行代码确保每个数字都要≤6 尝试输入小于0的数字 发现bomb,说明input是1 2 3 4 5 6的排列 903行代码通过i b rdx发现5个node image.png 每个node由3部分组成:一个值,第几个node,下一个node的地址。像是链表 image.png 所以根据node5的第3部分发现node6的地址是0x555555559110 image.png

8d8d05e24e6f6934b7b2f22fc0e07df5.jpg

929-95b之间的代码本质上是把6个node按照输入的6个数组 按顺序排在 rsp+0x20 的位置,rsp存的是input的位置

最后一块代码本质上是要求排好序的6个node的第一部分是按照递增的顺序排序 所以对输入的数字有要求 发现node1< node2 < node3 < node6 < node4 < node5 所以最后的答案是 1 2 3 6 4 5

通过截图

image.png image.png 还是挺好玩的,没有参考任何答案

10.30

竟然还有secret_phase

ctrl+f查找secret_phase 发现入口在phase_defused 查找phase_defused 发现每个phase结束后都会进入这个函数 研究phase_defused的代码,发现 0x3921(%rip) 即 0x5555555596F0 不等于6的时候会直接ret,怀疑这个地址存的是输入的次数,所以在phase_6的时候跳到下面的逻辑 image.png

发现rsi要求输入2个数字和一个字符串 rdi存的是第4题的答案

把第4题的答案改为13 31 inputstring image.png image.png 发现rdi和rsi应该相等,前者是输入的字符串,后者是DrEvil 修改答案 重新r answer.txt image.png 成功进入到secret_phase image.png 发现在strtol@plt炸了 image.png 看不懂源代码,由strtol联想到c语言中的函数strtol:用于将字符串转换为长整数 怀疑输入的字符串应该是数字 输入12345 image.png 发现eax存的值就是12345 但是下面有个判断,如果eax-1>0x3e8 直接炸

image.png 发现输入的值不能超过1000 image.png

开始研究fun7 草稿纸-617.jpg

image.png

所以最后的答案就是7

通过截图 7个phase

image.png