L2 bomblab
Resources
r2 usage is a bit of a pain, but it's a great tool for debugging.
Q & A:
- c - Display value found at given address gdb - Stack Overflow
- c++ - What's the difference between nexti and stepi in gdb? - Stack Overflow
- x86 Assembly/GNU assembly syntax - Wikibooks, open books for an open world
- bit manipulation - The difference between logical shift right, arithmetic shift right, and rotate right - Stack Overflow
Takeaways
x86 Assembly/GNU assembly syntax - Wikibooks, open books for an open world
- b = byte (8 bit).
- s = single (32-bit floating point).
- w = word (16 bit).
- l = long (32 bit integer or 64-bit floating point).
- q = quad (64 bit).
- t = ten bytes (80-bit floating point).
GDB
Check out CSAPP textbook Chapter 3.10.3 Figure 3.39 for more details.
gdb <program>
r # Run your program (give command-line arguments here)
info bre
info reg
ni # stay in the main
si # step into the function
break <function/address>
x/<x/s/d> # shows you the contents of a memory address e.g. x/2g 0x400
p/<format> # shows you the value stored in a named variable e.g. p/x ($rsp+8)
list
cont
Introduction - The Official Radare2 Book
Basic Commands - The Official Radare2 Book
r2 <program>
aaa # disassemble all
afl # List all functions
pdf @ main~phase # print disassemble function (pdf)
s sym.phase_5 # seek to the address of phase_5
pdf
v # into visual mode
c # toggle the cursor on/off
Phase 1
Similar to activity 3 in recitation03-bomblab
break phase_1
disas
Dump of assembler code for function phase_1:
=> 0x0000000000400ee0 <+0>: sub $0x8,%rsp
0x0000000000400ee4 <+4>: mov $0x402400,%esi
0x0000000000400ee9 <+9>: callq 0x401338 <strings_not_equal>
0x0000000000400eee <+14>: test %eax,%eax
0x0000000000400ef0 <+16>: je 0x400ef7 <phase_1+23>
0x0000000000400ef2 <+18>: callq 0x40143a <explode_bomb>
0x0000000000400ef7 <+23>: add $0x8,%rsp
0x0000000000400efb <+27>: retq
End of assembler dump.
After disassembling, we can see that for callq strings_not_equal, it is using %esi as its argument.
(gdb) x/s 0x402400
0x402400: "Border relations with Canada have never been better."
Phase 2
It starts from <phase_2+18> and loops between <phase_2+27> and <phase_2+52>. The key is <+14>: cmpl $0x1,(%rsp) and <+30>: add %eax,%eax.
Phase 3
0x0000000000400f51 <+14>: mov $0x4025cf,%esi
(gdb) x/s 0x4025cf
0x4025cf: "%d %d"
The input format is two decimal numbers separated by a space.
<+9>: lea 0x8(%rsp),%rdx`
<+39>: cmpl $0x7,0x8(%rsp)
<+44>: ja 0x400fad <phase_3+106>
4 bytes of the first number is compared to 0x7, pay attention to operand order for cmp, which is different in linux and windows.
(gdb) x/2wd $rsp+0x8
0x7fffffffe548: 7 321
exam test inputs: 7 321
<+50>: jmpq *0x402470(,%rax,8)
(gdb) x 0x402470 + 32
0x402490: 0x00400f91
go to dereferenced content in address 0x00400f91
0x0000000000400f91 <+78>: mov $0x185,%eax
0x0000000000400f96 <+83>: jmp 0x400fbe <phase_3+123>
0x0000000000400fbe <+123>: cmp 0xc(%rsp),%eax
0x0000000000400fc2 <+127>: je 0x400fc9 <phase_3+134>
(gdb) p $rsp
$72 = (void *) 0x7fffffffe540
(gdb) x/d 0x7fffffffe540+0xc
0x7fffffffe54c: 123
(gdb) p/d 0x185
$73 = 389
Phase 4
Look over phase_4 function and we can find:
0x000000000040101a <+14>: mov $0x4025cf,%esi
(gdb) x/s 0x4025cf
0x4025cf: "%d %d"
0x0000000000401051 <+69>: cmpl $0x0,0xc(%rsp)
0x0000000000401056 <+74>: je 0x40105d <phase_4+81>
0x0000000000401058 <+76>: callq 0x40143a <explode_bomb>
(gdb) x/wd $rsp+0x8
0x7fffffffe548: 10
(gdb) x/wd $rsp+0xc
0x7fffffffe54c: 123
second number should be 0, here I tested with 10 123.
0x000000000040102e <+34>: cmpl $0xe,0x8(%rsp)
0x0000000000401033 <+39>: jbe 0x40103a <phase_4+46>
(gdb) x/d $rsp+0x8
0x7fffffffe548: 10
the first number should be less than or equal to 0xe=14
0x0000000000401048 <+60>: callq 0x400fce <func4>
0x000000000040104d <+65>: test %eax,%eax
0x000000000040104f <+67>: jne 0x401058 <phase_4+76>
0x0000000000401051 <+69>: cmpl $0x0,0xc(%rsp)
0x0000000000401056 <+74>: je 0x40105d <phase_4+81>
0x0000000000401058 <+76>: callq 0x40143a <explode_bomb>
the second number should be 0
func4 is called and the result is compared to 0x0, if it is not 0x0, it will call explode_bomb. Then we disassemble func4
0x0000000000400fe2 <+20>: cmp %edi,%ecx
0x0000000000400fe4 <+22>: jle 0x400ff2 <func4+36>
0x0000000000400ff2 <+36>: mov $0x0,%eax
0x0000000000400ff7 <+41>: cmp %edi,%ecx
0x0000000000400ff9 <+43>: jge 0x401007 <func4+57>
to let func4 return 0x0, the code at <+36>, we can find that the input x must be 7 <= x <= 7. So the first argument is 7.
Phase 5
CMU Bomb Lab with Radare2 — Phase 5 | by Mark Higgins | Medium
I recommend using Radare2, although it has a steep learning curve - Migration from ida, GDB or WinDBG - The Official Radare2 Book
Phase 6
Really tricky that idk if it's worth the effort to defuse it.
<+93> all numbers should be unique
<+121> for each number x, we replace it with 7-x
<+183> copy values into a new stack based on input (six numbers)
<+257> values in the stack (linked list) should be sorted
The key is to understand the linked list structure:
0x0000000000401183 <+143>: mov $0x6032d0,%edx
(gdb) x/24wd 0x6032d0
0x6032d0 <node1>: 332 1 6304480 0
0x6032e0 <node2>: 168 2 6304496 0
0x6032f0 <node3>: 924 3 6304512 0
0x603300 <node4>: 691 4 6304528 0
0x603310 <node5>: 477 5 6304544 0
0x603320 <node6>: 443 6 0 0
Then all we need to do is to sort the values in the nodes, in this case, 332 168 924 691 477 443 to 924 691 477 443 332 168.
So, the node order is 3 4 5 6 1 2 and we replace each number x with 7-x: 4 3 2 1 6 5.