We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在 Bomb Lab 中我们需要通过 GDB 工具来对代码进行分析,来决定正确的输入,以此避免调用到 explode_bomb 函数
explode_bomb
调试的关键指令
b <func_name>
b explode_bomb
b *addr
b *0x00005555555567b6
i b
delete <NO>
info registers
p *($rsi)
p *(0x7fffffffe610)
p *(int *)($rsi)
p $ebx
info registers rcx
0x00005555555567a7 <+0>: endbr64 0x00005555555567ab <+4>: sub $0x8,%rsp 0x00005555555567af <+8>: lea 0x59ea(%rip),%rsi # 0x55555555c1a0 <sval> 0x00005555555567b6 <+15>: call 0x555555557035 <strings_not_equal> 0x00005555555567bb <+20>: test %al,%al 0x00005555555567bd <+22>: jne 0x5555555567c4 <phase_1+29> 0x00005555555567bf <+24>: add $0x8,%rsp 0x00005555555567c3 <+28>: ret **0x00005555555567c4 <+29>: call 0x5555555572d9 <explode_bomb>** 0x00005555555567c9 <+34>: jmp 0x5555555567bf <phase_1+24>
很单纯的一题
%al
test %al, %al
%al & %al == 0
jne
~ZF
解法
b *0x00005555555567bb
x/s 0x55555555c1a0
x/s $rsi
0x00005555555567cb <+0>: endbr64 0x00005555555567cf <+4>: push %rbx 0x00005555555567d0 <+5>: sub $0x40,%rsp 0x00005555555567d4 <+9>: mov %fs:0x28,%rax 0x00005555555567dd <+18>: mov %rax,0x38(%rsp) 0x00005555555567e2 <+23>: xor %eax,%eax 0x00005555555567e4 <+25>: mov %rsp,%rsi 0x00005555555567e7 <+28>: call 0x55555555731b <read_six_numbers> 0x00005555555567ec <+33>: cmpq $0x2,(%rsp) 0x00005555555567f1 <+38>: jne **0x5555555567fa <phase_2+47>** 0x00005555555567f3 <+40>: mov $0x1,%ebx 0x00005555555567f8 <+45>: jmp 0x555555556805 <phase_2+58> **0x00005555555567fa <+47>: call 0x5555555572d9 <explode_bomb>** 0x00005555555567ff <+52>: jmp 0x5555555567f3 <phase_2+40> 0x0000555555556801 <+54>: add $0x1,%rbx 0x0000555555556805 <+58>: cmp $0x5,%rbx 0x0000555555556809 <+62>: ja 0x555555556820 <phase_2+85> 0x000055555555680b <+64>: mov -0x8(%rsp,%rbx,8),%rax 0x0000555555556810 <+69>: add %rax,%rax 0x0000555555556813 <+72>: cmp %rax,(%rsp,%rbx,8) 0x0000555555556817 <+76>: je 0x555555556801 <phase_2+54> **0x0000555555556819 <+78>: call 0x5555555572d9 <explode_bomb>** 0x000055555555681e <+83>: jmp 0x555555556801 <phase_2+54> 0x0000555555556820 <+85>: mov 0x38(%rsp),%rax 0x0000555555556825 <+90>: sub %fs:0x28,%rax 0x000055555555682e <+99>: jne 0x555555556836 <phase_2+107> 0x0000555555556830 <+101>: add $0x40,%rsp 0x0000555555556834 <+105>: pop %rbx 0x0000555555556835 <+106>: ret 0x0000555555556836 <+107>: call 0x555555556370 <__stack_chk_fail@plt>
cmpq $0x2,(%rsp)
p $rbx
ja
-0x8(%rsp,%rbx,8)
%rax += %rax
通过上面的逻辑,我们差不多可以写出伪代码了
if (input[0] != 2) bomb() for (int i = 1; i <= 5; i++) { if (input[i - 1] + input[i - 1] != input[i]) bomb() }
最终的结果就是 2 4 8 16 32 64
2 4 8 16 32 64
0x000055555555683b <+0>: endbr64 0x000055555555683f <+4>: sub $0x28,%rsp 0x0000555555556843 <+8>: mov %fs:0x28,%rax 0x000055555555684c <+17>: mov %rax,0x18(%rsp) 0x0000555555556851 <+22>: xor %eax,%eax 0x0000555555556853 <+24>: lea 0x7(%rsp),%rcx 0x0000555555556858 <+29>: lea 0x8(%rsp),%rdx 0x000055555555685d <+34>: lea 0x10(%rsp),%r8 0x0000555555556862 <+39>: lea 0x28e3(%rip),%rsi # 0x55555555914c 0x0000555555556869 <+46>: call 0x555555556430 <__isoc99_sscanf@plt> 0x000055555555686e <+51>: cmp $0x2,%eax 0x0000555555556871 <+54>: jle 0x555555556897 <phase_3+92> 0x0000555555556873 <+56>: mov 0x8(%rsp),%rax 0x0000555555556878 <+61>: sub $0x6,%rax 0x000055555555687c <+65>: cmp $0x7,%rax 0x0000555555556880 <+69>: ja 0x55555555698b <phase_3+336> 0x0000555555556886 <+75>: lea 0x28d3(%rip),%rdx # 0x555555559160 0x000055555555688d <+82>: movslq (%rdx,%rax,4),%rax 0x0000555555556891 <+86>: add %rdx,%rax 0x0000555555556894 <+89>: notrack jmp *%rax **0x0000555555556897 <+92>: call 0x5555555572d9 <explode_bomb>** 0x000055555555689c <+97>: jmp 0x555555556873 <phase_3+56> 0x000055555555689e <+99>: cmpq $0x67,0x10(%rsp) 0x00005555555568a4 <+105>: jne 0x5555555568b0 <phase_3+117> 0x00005555555568a6 <+107>: mov $0x62,%eax 0x00005555555568ab <+112>: jmp 0x555555556995 <phase_3+346> 0x00005555555568b0 <+117>: call 0x5555555572d9 <explode_bomb> 0x00005555555568b5 <+122>: mov $0x62,%eax 0x00005555555568ba <+127>: jmp 0x555555556995 <phase_3+346> 0x00005555555568bf <+132>: cmpq $0x53,0x10(%rsp) 0x00005555555568c5 <+138>: jne 0x5555555568d1 <phase_3+150> 0x00005555555568c7 <+140>: mov $0x7a,%eax 0x00005555555568cc <+145>: jmp 0x555555556995 <phase_3+346> 0x00005555555568d1 <+150>: call 0x5555555572d9 <explode_bomb> 0x00005555555568d6 <+155>: mov $0x7a,%eax 0x00005555555568db <+160>: jmp 0x555555556995 <phase_3+346> 0x00005555555568e0 <+165>: cmpq $0x73,0x10(%rsp) 0x00005555555568e6 <+171>: jne 0x5555555568f2 <phase_3+183> 0x00005555555568e8 <+173>: mov $0x77,%eax 0x00005555555568ed <+178>: jmp 0x555555556995 <phase_3+346> 0x00005555555568f2 <+183>: call 0x5555555572d9 <explode_bomb> 0x00005555555568f7 <+188>: mov $0x77,%eax 0x00005555555568fc <+193>: jmp 0x555555556995 <phase_3+346> 0x0000555555556901 <+198>: cmpq $0x64,0x10(%rsp) 0x0000555555556907 <+204>: jne 0x555555556913 <phase_3+216> 0x0000555555556909 <+206>: mov $0x70,%eax 0x000055555555690e <+211>: jmp 0x555555556995 <phase_3+346> 0x0000555555556913 <+216>: call 0x5555555572d9 <explode_bomb> 0x0000555555556918 <+221>: mov $0x70,%eax 0x000055555555691d <+226>: jmp 0x555555556995 <phase_3+346> 0x000055555555691f <+228>: cmpq $0x3b,0x10(%rsp) 0x0000555555556925 <+234>: jne 0x55555555692e <phase_3+243> 0x0000555555556927 <+236>: mov $0x66,%eax 0x000055555555692c <+241>: jmp 0x555555556995 <phase_3+346> 0x000055555555692e <+243>: call 0x5555555572d9 <explode_bomb> 0x0000555555556933 <+248>: mov $0x66,%eax 0x0000555555556938 <+253>: jmp 0x555555556995 <phase_3+346> 0x000055555555693a <+255>: cmpq $0x31,0x10(%rsp) 0x0000555555556940 <+261>: jne 0x555555556949 <phase_3+270> 0x0000555555556942 <+263>: mov $0x6f,%eax 0x0000555555556947 <+268>: jmp 0x555555556995 <phase_3+346> 0x0000555555556949 <+270>: call 0x5555555572d9 <explode_bomb> 0x000055555555694e <+275>: mov $0x6f,%eax 0x0000555555556953 <+280>: jmp 0x555555556995 <phase_3+346> 0x0000555555556955 <+282>: cmpq $0x3c,0x10(%rsp) 0x000055555555695b <+288>: jne 0x555555556964 <phase_3+297> 0x000055555555695d <+290>: mov $0x6a,%eax 0x0000555555556962 <+295>: jmp 0x555555556995 <phase_3+346> 0x0000555555556964 <+297>: call 0x5555555572d9 <explode_bomb> 0x0000555555556969 <+302>: mov $0x6a,%eax 0x000055555555696e <+307>: jmp 0x555555556995 <phase_3+346> 0x0000555555556970 <+309>: cmpq $0x50,0x10(%rsp) 0x0000555555556976 <+315>: jne 0x55555555697f <phase_3+324> 0x0000555555556978 <+317>: mov $0x66,%eax 0x000055555555697d <+322>: jmp 0x555555556995 <phase_3+346> 0x000055555555697f <+324>: call 0x5555555572d9 <explode_bomb> 0x0000555555556984 <+329>: mov $0x66,%eax 0x0000555555556989 <+334>: jmp 0x555555556995 <phase_3+346> **0x000055555555698b <+336>: call 0x5555555572d9 <explode_bomb>** 0x0000555555556990 <+341>: mov $0x64,%eax 0x0000555555556995 <+346>: cmp %al,0x7(%rsp) 0x0000555555556999 <+350>: jne 0x5555555569b0 <phase_3+373> 0x000055555555699b <+352>: mov 0x18(%rsp),%rax 0x00005555555569a0 <+357>: sub %fs:0x28,%rax 0x00005555555569a9 <+366>: jne 0x5555555569b7 <phase_3+380> 0x00005555555569ab <+368>: add $0x28,%rsp 0x00005555555569af <+372>: ret 0x00005555555569b0 <+373>: call 0x5555555572d9 <explode_bomb> 0x00005555555569b5 <+378>: jmp 0x55555555699b <phase_3+352> 0x00005555555569b7 <+380>: call 0x555555556370 <__stack_chk_fail@plt>
x/s 0x55555555914c
"%ld %c %ld”
b *0x0000555555556878
p $rax
b *0x000055555555688d
p/a $rdx
p/a $rax
0x0000555555556955
0x0000555555556955 <+282>: cmpq $0x3c,0x10(%rsp)
mov $0x6a, %eax
答案是 12 j 60
12 j 60
0x00005555555569ff <+0>: endbr64 0x0000555555556a03 <+4>: sub $0x28,%rsp 0x0000555555556a07 <+8>: mov %fs:0x28,%rax 0x0000555555556a10 <+17>: mov %rax,0x18(%rsp) 0x0000555555556a15 <+22>: xor %eax,%eax 0x0000555555556a17 <+24>: lea 0x10(%rsp),%rcx 0x0000555555556a1c <+29>: lea 0x8(%rsp),%rdx 0x0000555555556a21 <+34>: lea 0x2c30(%rip),%rsi # 0x555555559658 0x0000555555556a28 <+41>: call 0x555555556430 <__isoc99_sscanf@plt> 0x0000555555556a2d <+46>: cmp $0x2,%eax 0x0000555555556a30 <+49>: jne 0x555555556a42 <phase_4+67> 0x0000555555556a32 <+51>: mov 0x8(%rsp),%rax 0x0000555555556a37 <+56>: test %rax,%rax 0x0000555555556a3a <+59>: js 0x555555556a42 <phase_4+67> 0x0000555555556a3c <+61>: cmp $0xe,%rax 0x0000555555556a40 <+65>: jle 0x555555556a47 <phase_4+72> 0x0000555555556a42 <+67>: call 0x5555555572d9 <explode_bomb> 0x0000555555556a47 <+72>: mov $0xe,%edx 0x0000555555556a4c <+77>: mov $0x0,%esi 0x0000555555556a51 <+82>: mov 0x8(%rsp),%rdi 0x0000555555556a56 <+87>: call 0x5555555569bc <func4> 0x0000555555556a5b <+92>: cmp $0x25,%rax 0x0000555555556a5f <+96>: jne 0x555555556a69 <phase_4+106> 0x0000555555556a61 <+98>: cmpq $0x25,0x10(%rsp) 0x0000555555556a67 <+104>: je 0x555555556a6e <phase_4+111> 0x0000555555556a69 <+106>: call 0x5555555572d9 <explode_bomb> 0x0000555555556a6e <+111>: mov 0x18(%rsp),%rax 0x0000555555556a73 <+116>: sub %fs:0x28,%rax 0x0000555555556a7c <+125>: jne 0x555555556a83 <phase_4+132> 0x0000555555556a7e <+127>: add $0x28,%rsp 0x0000555555556a82 <+131>: ret 0x0000555555556a83 <+132>: call 0x555555556370 <__stack_chk_fail@plt>
# func4 0x00005555555569bc <+0>: endbr64 0x00005555555569c0 <+4>: push %rbx 0x00005555555569c1 <+5>: mov %rdx,%rax 0x00005555555569c4 <+8>: sub %rsi,%rax 0x00005555555569c7 <+11>: mov %rax,%rbx 0x00005555555569ca <+14>: shr $0x3f,%rbx 0x00005555555569ce <+18>: add %rax,%rbx 0x00005555555569d1 <+21>: sar %rbx 0x00005555555569d4 <+24>: add %rsi,%rbx 0x00005555555569d7 <+27>: cmp %rdi,%rbx 0x00005555555569da <+30>: jg 0x5555555569e3 <func4+39> 0x00005555555569dc <+32>: jl 0x5555555569f1 <func4+53> 0x00005555555569de <+34>: mov %rbx,%rax 0x00005555555569e1 <+37>: pop %rbx 0x00005555555569e2 <+38>: ret 0x00005555555569e3 <+39>: lea -0x1(%rbx),%rdx 0x00005555555569e7 <+43>: call 0x5555555569bc <func4> 0x00005555555569ec <+48>: add %rax,%rbx 0x00005555555569ef <+51>: jmp 0x5555555569de <func4+34> 0x00005555555569f1 <+53>: lea 0x1(%rbx),%rsi 0x00005555555569f5 <+57>: call 0x5555555569bc <func4> 0x00005555555569fa <+62>: add %rax,%rbx 0x00005555555569fd <+65>: jmp 0x5555555569de <func4+34>
最终结果就是 10 37
10 37
0x0000555555556a88 <+0>: endbr64 0x0000555555556a8c <+4>: push %rbx 0x0000555555556a8d <+5>: mov %rdi,%rbx 0x0000555555556a90 <+8>: call 0x55555555701c <string_length> 0x0000555555556a95 <+13>: cmp $0x6,%rax 0x0000555555556a99 <+17>: jne 0x555555556aa7 <phase_5+31> 0x0000555555556a9b <+19>: mov $0x0,%edx 0x0000555555556aa0 <+24>: mov $0x0,%eax 0x0000555555556aa5 <+29>: jmp 0x555555556ac8 <phase_5+64> 0x0000555555556aa7 <+31>: call 0x5555555572d9 <explode_bomb> 0x0000555555556aac <+36>: jmp 0x555555556a9b <phase_5+19> 0x0000555555556aae <+38>: shl $0x4,%rdx 0x0000555555556ab2 <+42>: movzbl (%rbx,%rax,1),%ecx 0x0000555555556ab6 <+46>: and $0xf,%ecx 0x0000555555556ab9 <+49>: lea 0x26c0(%rip),%rsi # 0x555555559180 <array.0> 0x0000555555556ac0 <+56>: add (%rsi,%rcx,8),%rdx 0x0000555555556ac4 <+60>: add $0x1,%rax 0x0000555555556ac8 <+64>: cmp $0x5,%rax 0x0000555555556acc <+68>: jle 0x555555556aae <phase_5+38> 0x0000555555556ace <+70>: cmp $0x198b91,%rdx 0x0000555555556ad5 <+77>: jne 0x555555556ad9 <phase_5+81> 0x0000555555556ad7 <+79>: pop %rbx 0x0000555555556ad8 <+80>: ret 0x0000555555556ad9 <+81>: call 0x5555555572d9 <explode_bomb> 0x0000555555556ade <+86>: jmp 0x555555556ad7 <phase_5+79>
+13 对比输入的长度和 0x6 —— 因此我们输入的长度为 6
然后我们会跳到 38 ~ 68 行的循环中
display $rdx display $rcx ,我们可以发现通过 +42行,%rcx 会依次变成 string 每一个字符的 ASCII (例如我的 string[0] == ‘c’,那么 %rcx 就会变成 99)
display $rdx
display $rcx
在 +49 行执行 x/128x 0x555555559180 可以打印出数组内容
x/128x 0x555555559180
0x555555559180 <array.0>: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x555555559188 <array.0+8>: 0x0a 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x555555559190 <array.0+16>: 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x555555559198 <array.0+24>: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591a0 <array.0+32>: 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591a8 <array.0+40>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591b0 <array.0+48>: 0x09 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591b8 <array.0+56>: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591c0 <array.0+64>: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591c8 <array.0+72>: 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591d0 <array.0+80>: 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591d8 <array.0+88>: 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591e0 <array.0+96>: 0x0b 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591e8 <array.0+104>: 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591f0 <array.0+112>: 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x5555555591f8 <array.0+120>: 0x0d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
我的第一个输入如果是 c,那么就会在 +42 变成 99,然后在 +46 变成 0x3,对应到数组里的 0x01,然后给累加到 rdx 上
经过了六次循环,我们得到了一个最终的 %rdx 的值,在 +70 行我们对比这个值和 0x198b91
因此这道题目实际上的目的就是我们输入一个 string,其中的每一个字符都会对应到一个数字,然后我们希望最终的数字组合起来的到 0x198b61
答案是 cfmlfc
cfmlfc
太长了,分几段来观察汇编代码
0x0000555555556ae0 <+0>: endbr64 0x0000555555556ae4 <+4>: push %r12 0x0000555555556ae6 <+6>: push %rbp 0x0000555555556ae7 <+7>: push %rbx 0x0000555555556ae8 <+8>: sub $0x70,%rsp 0x0000555555556aec <+12>: mov %fs:0x28,%rax 0x0000555555556af5 <+21>: mov %rax,0x68(%rsp) 0x0000555555556afa <+26>: xor %eax,%eax 0x0000555555556afc <+28>: mov %rsp,%rsi 0x0000555555556aff <+31>: call 0x55555555731b <read_six_numbers> 0x0000555555556b04 <+36>: mov $0x0,%ebp 0x0000555555556b09 <+41>: jmp 0x555555556b30 <phase_6+80> // 一定会跳到 +80 0x0000555555556b0b <+43>: call 0x5555555572d9 <explode_bomb>
这一段感觉也没有啥太多内容,关键就是让我们知道我们需要 read_six_numbers
然后就跳到了 +80
// 要求所有的数字都不相等 0x0000555555556b10 <+48>: jmp 0x555555556b44 <phase_6+100> 0x0000555555556b12 <+50>: add $0x1,%rbx 0x0000555555556b16 <+54>: cmp $0x5,%rbx 0x0000555555556b1a <+58>: jg 0x555555556b2d <phase_6+77> // rbx > 0x5 会跳到77 0x0000555555556b1c <+60>: mov (%rsp,%rbx,8),%rax // (%rsp,%rbx,8) 其实就是依次读取 arr[0], arr[1], arr[2]... 0x0000555555556b20 <+64>: cmp %rax,(%rsp,%rbp,8) 0x0000555555556b24 <+68>: jne 0x555555556b12 <phase_6+50> // 要求 not equal,不然会爆炸 0x0000555555556b26 <+70>: call 0x5555555572d9 <explode_bomb> // 要求所有的数字都 1 ~ 6 0x0000555555556b2b <+75>: jmp 0x555555556b12 <phase_6+50> // 走不到这里 0x0000555555556b2d <+77>: mov %r12,%rbp 0x0000555555556b30 <+80>: cmp $0x5,%rbp 0x0000555555556b34 <+84>: jg 0x555555556b4d <phase_6+109> // 如果 rbp > 5, 会跳到 109 0x0000555555556b36 <+86>: mov (%rsp,%rbp,8),%rax // (%rsp,%rbp,8) 这里给到的是 arr[i] 0x0000555555556b3a <+90>: sub $0x1,%rax 0x0000555555556b3e <+94>: cmp $0x5,%rax 0x0000555555556b42 <+98>: ja 0x555555556b0b <phase_6+43> // 如果 rax > 5,就会爆炸 0x0000555555556b44 <+100>: lea 0x1(%rbp),%r12 // 0x0000555555556b48 <+104>: mov %r12,%rbx // rbx = r12 0x0000555555556b4b <+107>: jmp 0x555555556b16 <phase_6+54> 0x0000555555556b4d <+109>: mov $0x0,%eax 0x0000555555556b52 <+114>: jmp 0x555555556b65 <phase_6+133>
0x0000555555556b54 <+116>: mov $0x7,%edx 0x0000555555556b59 <+121>: sub (%rsp,%rax,8),%rdx 0x0000555555556b5d <+125>: mov %rdx,(%rsp,%rax,8) 0x0000555555556b61 <+129>: add $0x1,%rax 0x0000555555556b65 <+133>: cmp $0x5,%rax 0x0000555555556b69 <+137>: jle 0x555555556b54 <phase_6+116>
sub S,D → D = D - S
0x0000555555556b6b <+139>: mov $0x0,%ecx 0x0000555555556b70 <+144>: jmp 0x555555556b89 <phase_6+169> 0x0000555555556b72 <+146>: mov 0x10(%rdx),%rdx // 这里相当于不断的读取链表的下一个节点 0x0000555555556b76 <+150>: add $0x1,%rax 0x0000555555556b7a <+154>: cmp %rax,(%rsp,%rcx,8) 0x0000555555556b7e <+158>: jg 0x555555556b72 <phase_6+146> // 0x0000555555556b80 <+160>: mov %rdx,0x30(%rsp,%rcx,8) 0x0000555555556b85 <+165>: add $0x1,%rcx 0x0000555555556b89 <+169>: cmp $0x5,%rcx # 这里是一个好的断点,我们在这里读取 x/8xb $rdx 0x0000555555556b8d <+173>: jg 0x555555556b9d <phase_6+189> 0x0000555555556b8f <+175>: mov $0x1,%eax 0x0000555555556b94 <+180>: lea 0x6755(%rip),%rdx # 0x55555555d2f0 <node1> # 这里是一个链表的头节点,将地址丢到 rdx 中 0x0000555555556b9b <+187>: jmp 0x555555556b7a <phase_6+154>
0x30(%rsp,%rcx,8)
0x0000555555556b9d <+189>: mov 0x30(%rsp),%rbx # 断点 0x0000555555556ba2 <+194>: mov %rbx,%rcx 0x0000555555556ba5 <+197>: mov $0x1,%eax 0x0000555555556baa <+202>: jmp 0x555555556bbc <phase_6+220> 0x0000555555556bac <+204>: mov 0x30(%rsp,%rax,8),%rdx 0x0000555555556bb1 <+209>: mov %rdx,0x10(%rcx) 0x0000555555556bb5 <+213>: add $0x1,%rax 0x0000555555556bb9 <+217>: mov %rdx,%rcx 0x0000555555556bbc <+220>: cmp $0x5,%rax 0x0000555555556bc0 <+224>: jle 0x555555556bac <phase_6+204>
这一段看起来是一个数组的重排
0x0000555555556bc2 <+226>: movq $0x0,0x10(%rcx) 0x0000555555556bca <+234>: mov $0x0,%ebp 0x0000555555556bcf <+239>: jmp 0x555555556bd9 <phase_6+249> 0x0000555555556bd1 <+241>: mov 0x10(%rbx),%rbx 0x0000555555556bd5 <+245>: add $0x1,%rbp // rbp += 1 0x0000555555556bd9 <+249>: cmp $0x4,%rbp 0x0000555555556bdd <+253>: jg 0x555555556bf2 <phase_6+274> // 跳到 274 的话就肯定安全了 0x0000555555556bdf <+255>: mov 0x10(%rbx),%rax 0x0000555555556be3 <+259>: mov (%rax),%rax 0x0000555555556be6 <+262>: cmp %rax,(%rbx) 0x0000555555556be9 <+265>: jge 0x555555556bd1 <phase_6+241> // 要求 rax 的值 >= rbx 的值 0x0000555555556beb <+267>: call 0x5555555572d9 <explode_bomb>
因此这一题的逻辑是,我们 input 的每一个数字最终都会对应到一个特定的链表的值
然后我们希望这个特定的值可以满足降序
最终答案是 5 4 1 6 3 2
5 4 1 6 3 2
The text was updated successfully, but these errors were encountered:
No branches or pull requests
CMU 15213 Bomb Lab
在 Bomb Lab 中我们需要通过 GDB 工具来对代码进行分析,来决定正确的输入,以此避免调用到
explode_bomb
函数调试的关键指令
b <func_name>
: 在对应的 func_name 处打上断点,例如b explode_bomb
b *addr
: 在对应的 address 处打上断点,打上断点后该 addr 那一行的代码未执行,例如b *0x00005555555567b6
i b
: 展示目前打上的所有断点delete <NO>
: 删除某一个指定断点info registers
: 展示所有的 register infop *($rsi)
p *(0x7fffffffe610)
p *(int *)($rsi)
p $ebx
info registers rcx
Phase_1
很单纯的一题
%al
会存储 0x1%al
会存储 0x0test %al, %al
当%al & %al == 0
的时候,会设置 ZFjne
的判断条件是~ZF
即不相等 / 非零解法
b *0x00005555555567bb
打上断点一x/s 0x55555555c1a0
或者x/s $rsi
显示内存中的 stringPhase_2
cmpq $0x2,(%rsp)
,我们会执行 (%rsp) - $0x2,如果两者相同,就会 set ZF = 1,当 ZF = 1 的时候,+38 行的jne
就不会被满足,就躲开了第一个炸弹p $rbx
就可以看出来 $rbx 里面存储的是 0x1 (+40 行操作导致的结果)ja
,因此我们会继续执行-0x8(%rsp,%rbx,8)
,计算的逻辑是 -0x8 + %rsp + 8 * %rbx%rax += %rax
通过上面的逻辑,我们差不多可以写出伪代码了
最终的结果就是
2 4 8 16 32 64
Phase_3
x/s 0x55555555914c
会得到"%ld %c %ld”
,这预示了我们的入参的形式b *0x0000555555556878
打上 +61 行的断点,执行到这一行后p $rax
,显示的就是我们的 input[0]b *0x000055555555688d
打上 +82 行的断点p/a $rdx
显示 0x555555559160,p/a $rax
显示 0x6,stepi 追踪这几行的变化,可以得到 $rax 最终变成0x0000555555556955
0x0000555555556955 <+282>: cmpq $0x3c,0x10(%rsp)
它要对比 $0x3c 和我们输入的第三个参数 —— 因此 input[2] = 60mov $0x6a, %eax
, 给 eax 寄存器写入了值答案是
12 j 60
Phase_4
最终结果就是
10 37
Phase_5
+13 对比输入的长度和 0x6 —— 因此我们输入的长度为 6
然后我们会跳到 38 ~ 68 行的循环中
display $rdx
display $rcx
,我们可以发现通过 +42行,%rcx 会依次变成 string 每一个字符的 ASCII (例如我的 string[0] == ‘c’,那么 %rcx 就会变成 99)在 +49 行执行
x/128x 0x555555559180
可以打印出数组内容我的第一个输入如果是 c,那么就会在 +42 变成 99,然后在 +46 变成 0x3,对应到数组里的 0x01,然后给累加到 rdx 上
经过了六次循环,我们得到了一个最终的 %rdx 的值,在 +70 行我们对比这个值和 0x198b91
因此这道题目实际上的目的就是我们输入一个 string,其中的每一个字符都会对应到一个数字,然后我们希望最终的数字组合起来的到 0x198b61
答案是
cfmlfc
Phase_6
太长了,分几段来观察汇编代码
这一段感觉也没有啥太多内容,关键就是让我们知道我们需要 read_six_numbers
然后就跳到了 +80
sub S,D → D = D - S
0x30(%rsp,%rcx,8)
中(看起来是一个数组的结构这一段看起来是一个数组的重排
因此这一题的逻辑是,我们 input 的每一个数字最终都会对应到一个特定的链表的值
然后我们希望这个特定的值可以满足降序
最终答案是
5 4 1 6 3 2
The text was updated successfully, but these errors were encountered: