BombLab
前置知识
-
objdump -d bomb8 > bomb8.asm生成反汇编代码 >objdump生成的汇编地址并非最后的内存虚拟地址,而是一个相对地址。 objdump生成的绝对地址有问题,但是各个指令之间的相对位置不会出现改变,可以认为在可执行程序加载到内存的时候,操作系统帮我们完成一次地址移动,绝对地址改变,但是指令之间的相对地址关系不变。 -
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
从函数名上猜测是判断2个字符串是否想到 通过i r rbx rdi 发现rbx rdi存的是input string
发现 rsi 存的是这个字符串的地址 根据strings_not_equal,可以得出input string应该和rsi一致 所以第一问答案为You can Russia from land here in Alaska.
phase_2
说明第一个数字要大于0
发现 644-658 之间有个循环 等价于 for(ebx = 1; ebx != 6; ebx++) rbp=rsp存的是输入的6个数字 通过add $0x4 %rbp$遍历输入的6个数字 再判断x[i] + ebx 和 x[i+1]的大小关系 如果不等 就爆炸 所以对输入的要求:每2个数字之间的差值从1增加到5 所以第一问答案为 12 4 7 11 16
phase_3
说明输入2个数字,中间以空格隔开
cmpl $0x7, (%rsp)确保x1 <= 7
这3行代码会跳到由x1决定的地址 当x1 == 6时,会跳到70b,令eax = 0x11a即282 由6d8行代码可知 x2必须等于eax=282 所以第三问答案 6 282
phase_4
说明输入4个数字,中间以空格隔开
根据7c1行代码可知 x2必须等于31 根据7bc行代码可知 eax必须等于31 说明退出func4的时候 eax要设置为31
第一次进入func4的时候 edi指向input,edx为14,esi为0 研究func4代码... 发现eax存的值每一次递归中的ebx的值的和 func4会根据edi(即x1)和ebx的大小关系 进入不同的递归 本质时不断找[esi,edx]的中点ebx 再累加
画个图很容易就出来了 除了对x1 x2有限制,x3 x4任取 所以第4问答案 13 31 1 2
phase_5
怀疑rsi存的地址是一个数组的开头 然后edx从0到15,说明要遍历数组 现在就是不清楚mov (%rsi,%rax,4),%eax 对应的eax是多少 ecx是每一次eax的值的和
核心是选定一个初始的x1,进入数组,根据数组中对应x1位置的值 跳到值对应的位置,跳来跳去,最后跳到值为15的位置结束循环,有点指针的感觉
倒推很容易算出来x1=5 x2=120,但是发现bomb 直接 i r ecx 发现值为115 所以最后的答案是5 115
phase_6
read_six_numbers直接猜输入6个数字,中间以空格隔开
8f4行以前的代码是通过2个循环,确保输入的6个数字都不相等 同时8e6行代码确保每个数字都要≤6 尝试输入小于0的数字 发现bomb,说明input是1 2 3 4 5 6的排列 903行代码通过i b rdx发现5个node
每个node由3部分组成:一个值,第几个node,下一个node的地址。像是链表
所以根据node5的第3部分发现node6的地址是0x555555559110 
929-95b之间的代码本质上是把6个node按照输入的6个数组 按顺序排在 rsp+0x20 的位置,rsp存的是input的位置
最后一块代码本质上是要求排好序的6个node的第一部分是按照递增的顺序排序 所以对输入的数字有要求 发现node1< node2 < node3 < node6 < node4 < node5 所以最后的答案是 1 2 3 6 4 5
通过截图
10.30
竟然还有secret_phase
ctrl+f查找secret_phase 发现入口在phase_defused 查找phase_defused 发现每个phase结束后都会进入这个函数 研究phase_defused的代码,发现 0x3921(%rip) 即 0x5555555596F0 不等于6的时候会直接ret,怀疑这个地址存的是输入的次数,所以在phase_6的时候跳到下面的逻辑 
发现rsi要求输入2个数字和一个字符串 rdi存的是第4题的答案
把第4题的答案改为13 31 inputstring
发现rdi和rsi应该相等,前者是输入的字符串,后者是DrEvil 修改答案 重新r answer.txt
成功进入到secret_phase
发现在strtol@plt炸了
看不懂源代码,由strtol联想到c语言中的函数strtol:用于将字符串转换为长整数 怀疑输入的字符串应该是数字 输入12345
发现eax存的值就是12345 但是下面有个判断,如果eax-1>0x3e8 直接炸
所以最后的答案就是7










