Defusing A Binary Bomb With GDB PDF
Defusing A Binary Bomb With GDB PDF
Defusing a binary bomb with gdb
- Part 1
12 Nov 2015
This series of posts will show you how we can defuse a binary bomb. So what's a
binary bomb?
“A "binary bomb" is a Linux executable C program that consists of six
"phases." Each phase expects the student to enter a particular string on
stdin. If the student enters the expected string, then that phase is
"defused." Otherwise the bomb "explodes" by printing "BOOM!!!". The
goal for the students is to defuse as many phases as possible.”
I found this type of bomb in the website for the excellent book “Computer
Systems: A Programmer's Perspective” .
The basic tools necessary to defuse such bomb are gdb and objdump . gdb
is a debugger which we will use to inspect the program as we run it. objdump is
a tool to disassemble object files so we can see the actual instructions that the
computer is executing.
Enough of that, let's start having some fun. After extracting the tarball we are
left with:
$ ls -l
total 36
-rwxr-xr-x 1 carlos carlos 26406 Jun 9 15:41 bomb
-rw-r--r-- 1 carlos carlos 4069 Jun 9 15:41 bomb.c
-rw-rw-r-- 1 carlos carlos 49 Jun 9 15:46 README
You can pass a file as argument to avoid typing every time the correct input for
already defused phases.
Next we need to take a look at the bomb executable which is binary data so we
won't see anything interesting if we open it using $EDITOR . That's why we need
objdump to disassemble this executable.
If we take a look at the first few lines of this new file we see:
0000000000400ac0 <_init>:
400ac0: 48 83 ec 08 sub $0x8,%rsp
400ac4: e8 f3 01 00 00 callq 400cbc <call_gmon_start>
400ac9: 48 83 c4 08 add $0x8,%rsp
400acd: c3 retq
That is what an ELF file looks like when disassembled. Let's look at the main
function then:
0000000000400da0 <main>:
400da0: 53 push %rbx
400da1: 83 ff 01 cmp $0x1,%edi
400da4: 75 10 jne 400db6 <main+0x16>
400da6: 48 8b 05 9b 29 20 00 mov 0x20299b(%rip),%rax
# 603748 <stdin@@GLIBC_2.2.5>
400dad: 48 89 05 b4 29 20 00 mov %rax,0x2029b4(%rip)
# 603768 <infile>
400db4: eb 63 jmp 400e19 <main+0x79>
400db6: 48 89 f3 mov %rsi,%rbx
400db9: 83 ff 02 cmp $0x2,%edi
400dbc: 75 3a jne 400df8 <main+0x58>
400dbe: 48 8b 7e 08 mov 0x8(%rsi),%rdi
400dc2: be b4 22 40 00 mov $0x4022b4,%esi
400dc7: e8 44 fe ff ff callq 400c10 <fopen@plt>
400dcc: 48 89 05 95 29 20 00 mov %rax,0x202995(%rip)
# 603768 <infile>
400dd3: 48 85 c0 test %rax,%rax
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&… 2/7
5/29/2016 Defusing a binary bomb with gdb - Part 1 · carlosgaldino
I didn't paste the entire function since it's big enough and we are not concerned
about the other phases yet.
The first few lines in the main function correspond to the C code that checks
whether or not we passed a file as argument to the program. Skipping those
lines we start to see the fun part:
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&… 3/7
5/29/2016 Defusing a binary bomb with gdb - Part 1 · carlosgaldino
This line says that the function initialize_bomb should be called. The
correspoding line in the C file is the following:
/* Do all sorts of secret stuff that makes the bomb harder to defuse.
*/
initialize_bomb();
00000000004013a2 <initialize_bomb>:
4013a2: 48 83 ec 08 sub $0x8,%rsp
4013a6: be a0 12 40 00 mov $0x4012a0,%esi
4013ab: bf 02 00 00 00 mov $0x2,%edi
4013b0: e8 db f7 ff ff callq 400b90 <signal@plt>
4013b5: 48 83 c4 08 add $0x8,%rsp
4013b9: c3 retq
Inspecting the values don't reveal anything interesting. Let's move on. The next
few lines after initialize_bomb in the main function correspond to the
following lines in the C file:
So they print the messages and read the input. Then it's time to defuse the first
phase.
Again, this calls the function phase_1 located at 0x400ee0 . Let's see what
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&… 4/7
5/29/2016 Defusing a binary bomb with gdb - Part 1 · carlosgaldino
0000000000400ee0 <phase_1>:
400ee0: 48 83 ec 08 sub $0x8,%rsp
400ee4: be 00 24 40 00 mov $0x402400,%esi
400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>
400eee: 85 c0 test %eax,%eax
400ef0: 74 05 je 400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
400ef7: 48 83 c4 08 add $0x8,%rsp
400efb: c3 retq
Notice on 0x400ee4 that the value 0x402400 is copied to the register esi .
The esi register is usually used as the register for the second argument of a
function that will be called later. In our case such function is called right after
the mov instruction. You might then ask: where is the first argument? The first
argument is usually placed in the edi register which in this case will be the
string we provided as input. If you take a look at the main function you will
see:
The return value (stored in rax ) of the read_line function has been placed
in the rdi register ( edi is a 32-bit register and rdi is the equivalent 64-bit
register) and will be used as the first argument for the function that will be
called next which in this case is phase_1 . And that is exactly what the C code is
doing:
Ok, back to the phase_1 function. We now know what the arguments given to
strings_not_equal are and after executing such function there is a test to
check the result:
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&… 5/7
5/29/2016 Defusing a binary bomb with gdb - Part 1 · carlosgaldino
The test instruction will perform a bitwise AND operation between its
operands and set the appropriate flags on register eflags . The je
instruction is a conditional jump instruction that jumps to the specified location
only if the previous comparison set the ZF (Zero Flag) to 1 in the eflags
register.
If the strings are not equal the conditional jump will not be performed and then
the next line will be executed which will explode the bomb. If the strings are
equal we jump to 0x400eef7 and return to main :
Ok, we now know that the first phase requires us to provide a string that we
don't know. How we are going to discover which string is this? We need to start
executing the program. But in this case instead of executing like you usually do
with other programs we will run it with gdb . gdb will help us to inspect the
values and find out what is this mysterious string.
$ gdb bomb
The line above starts gdb with the bomb program attached to it so we can
execute the bomb and inspect the values, set breakpoints, etc. In this case we
have already done most of the work by only examining the assembly code and
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&… 6/7
5/29/2016 Defusing a binary bomb with gdb - Part 1 · carlosgaldino
(gdb) run
Starting program: /home/carlos/Downloads/bomb/bomb
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Then entering the full string we will see that phase 1 was defused:
http://webcache.googleusercontent.com/search?q=cache:NPuQo5CSngAJ:blog.carlosgaldino.com/2015/11/12/defusing-a-binary-bomb-with-gdb-part-1.html+&… 7/7
5/29/2016 Defusing a binary bomb with gdb - Part 2 · carlosgaldino
Defusing a binary bomb with gdb
- Part 2
19 Nov 2015
This post is part of a series where I show how to defuse a binary bomb by
reading assembly code and using gdb . You might want to read the first
part if you haven't yet.
After defusing the first phase we were challenged to defuse the next one:
As we can see (at 0x400e53 ) it puts our input in the rdi register to be used
as the first argument to phase_2 which will be called by the next instruction.
Just like you would imagine that the actual C code is doing:
0000000000400efc <phase_2>:
400efc: 55 push %rbp
400efd: 53 push %rbx
400efe: 48 83 ec 28 sub $0x28,%rsp
400f02: 48 89 e6 mov %rsp,%rsi
400f05: e8 52 05 00 00 callq 40145c <read_six_numbers>
400f0a: 83 3c 24 01 cmpl $0x1,(%rsp)
400f0e: 74 20 je 400f30 <phase_2+0x34>
400f10: e8 25 05 00 00 callq 40143a <explode_bomb>
400f15: eb 19 jmp 400f30 <phase_2+0x34>
400f17: 8b 43 fc mov -0x4(%rbx),%eax
400f1a: 01 c0 add %eax,%eax
400f1c: 39 03 cmp %eax,(%rbx)
400f1e: 74 05 je 400f25 <phase_2+0x29>
400f20: e8 15 05 00 00 callq 40143a <explode_bomb>
400f25: 48 83 c3 04 add $0x4,%rbx
400f29: 48 39 eb cmp %rbp,%rbx
400f2c: 75 e9 jne 400f17 <phase_2+0x1b>
400f2e: eb 0c jmp 400f3c <phase_2+0x40>
400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx
400f35: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp
400f3a: eb db jmp 400f17 <phase_2+0x1b>
400f3c: 48 83 c4 28 add $0x28,%rsp
400f40: 5b pop %rbx
400f41: 5d pop %rbp
400f42: c3 retq
Right off the bat we can see that this phase is expecting us to enter six numbers:
000000000040145c <read_six_numbers>:
40145c: 48 83 ec 18 sub $0x18,%rsp
401460: 48 89 f2 mov %rsi,%rdx
401463: 48 8d 4e 04 lea 0x4(%rsi),%rcx
401467: 48 8d 46 14 lea 0x14(%rsi),%rax
40146b: 48 89 44 24 08 mov %rax,0x8(%rsp)
401470: 48 8d 46 10 lea 0x10(%rsi),%rax
401474: 48 89 04 24 mov %rax,(%rsp)
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&… 2/6
5/29/2016 Defusing a binary bomb with gdb - Part 2 · carlosgaldino
At 0x40148a we see that it calls sscanf which has the following purpose:
#include <stdio.h>
Following the same idea we used on phase 1 we can confirm this function does
exactly what its name suggests. On 0x401480 something is stored at esi to
be used as the second argument for sscanf which as seen above is the
expected format for our input.
Then on gdb we can print the value just like we did on phase_1 :
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&… 3/6
5/29/2016 Defusing a binary bomb with gdb - Part 2 · carlosgaldino
(gdb) p $rsp+0x18
$2 = (void *) 0x7fffffffddd8
(gdb) p $rsp
$3 = (void *) 0x7fffffffddc0
Considering just the low order byte: 0xd8 - 0xc0 = 0x18 . Which is decimal
24 . Each int takes four bytes so the memory structure looks like the image
below which explains why rbp holds the address after the sixth number:
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&… 4/6
5/29/2016 Defusing a binary bomb with gdb - Part 2 · carlosgaldino
On 0x400f17 the previous number is copied into eax then the next
instruction duplicates this value on eax which is then compared with our
second number. If they are equal the function will continue execution at
0x400f25 , otherwise you know what.
On 0x400f25 the pointer goes to the next number. Next it checks if the pointer
passed the last number which means all six numbers were checked. If it didn't it
goes back to 0x400f17 to check the next number and if all numbers were
already checked it will jump to 0x400f3c that will then return to main .
Checking numbers, moving pointers forward, jumping back and forth suggests
that we are dealing with a loop. Assuming p is a pointer to the first number,
the loop in phase_2 might look like the following:
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&… 5/6
5/29/2016 Defusing a binary bomb with gdb - Part 2 · carlosgaldino
if (*x != previous * 2)
explode_bomb();
}
Alright, now we have an idea of what the next five numbers should be. They
have to be the double of the previous number. If we start at 1 the next is 2 ,
the next is 4 and so on. This might ring a bell, doesn't it? Our input must be
the first six powers of 2 :
20 = 1
21 = 2
22 = 4
23 = 8
24 = 16
25 = 32
After entering the six numbers we see that we defused the second phase:
http://webcache.googleusercontent.com/search?q=cache:0AQyhw4TGq4J:blog.carlosgaldino.com/2015/11/19/defusing-a-binary-bomb-with-gdb-part-2.html+&… 6/6
5/29/2016 Defusing a binary bomb with gdb - Part 3 · carlosgaldino
Defusing a binary bomb with gdb
- Part 3
03 Dec 2015
This post is part of a series where I show how to defuse a binary bomb by
reading assembly code and using gdb . You might want to read the
other parts if you haven't yet.
Following the usual process, after defusing the second phase we were
challenged to defuse the third one:
0000000000400f43 <phase_3>:
400f43: 48 83 ec 18 sub $0x18,%rsp
400f47: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
400f4c: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
400f51: be cf 25 40 00 mov $0x4025cf,%esi
400f56: b8 00 00 00 00 mov $0x0,%eax
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/12/03/defusing-a-binary-bomb-with-gdb-part-3.html+&cd… 1/6
5/29/2016 Defusing a binary bomb with gdb - Part 3 · carlosgaldino
On 0x400f51 we see that some value is stored on esi , eax gets initialized
and then sscanf is called.
If you don't remember from the previous phase , sscanf is a function that
scans input according to some format that is given as argument to it. Such
format must be what's stored on esi .
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/12/03/defusing-a-binary-bomb-with-gdb-part-3.html+&cd… 2/6
5/29/2016 Defusing a binary bomb with gdb - Part 3 · carlosgaldino
continue executing the third phase otherwise the bomb will explode.
You might be wondering how sscanf got its first argument which is the string
used as source for scanning the desired values. As explained in previous posts
the first argument to functions is usually placed on register rdi and any
instruction can interact with any register, the same way you would interact with
a global variable in a program. If you look at 0x400e6f in the main function
the string we enter as input for phase_3 is copied to rdi to then be used as
the first argument to sscanf :
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/12/03/defusing-a-binary-bomb-with-gdb-part-3.html+&cd… 3/6
5/29/2016 Defusing a binary bomb with gdb - Part 3 · carlosgaldino
The first instruction above will copy the first integer to eax and then on the
second instruction jump to a location based on this integer. Let's pretend we
entered 0 as our first integer. In that case the program would jump to the
address location stored at 0x402470 . The rule for calculating the address is the
following:
*(%rax * 8 + 0x402470)
That is: multiply the value stored on rax by 8 , add it to 0x402470 and then
read the value stored at the result location. Inspecting the value on 0x402470
we see that's the address of the next line:
(gdb) x 0x402470
0x402470: 0x00400f7c
This stores 0xcf (decimal 207) on eax and then jumps to 0x400fbe that
does the following:
In other words, on 0x400fbe the program will compare our second number to
what was stored on eax , in this imaginary case of entering 0 as our first
number it would then compare if our second number was 207 . If that's the
case it means we defused phase_3 :
0 207
Halfway there!
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/12/03/defusing-a-binary-bomb-with-gdb-part-3.html+&cd… 4/6
5/29/2016 Defusing a binary bomb with gdb - Part 3 · carlosgaldino
So that's it?! Pretty simple, right? But what about all the other instructions
above 400fbe ? What are their purpose?
The command above tells gdb to examine the memory starting at address
0x402470 and display eight blocks ( 8 in the command) of eight bytes ( g in
the command, g as in giant words). The output then shows two values per line
so we can build a table relating the first input number, the address the switch
jumps to and what should be the second input number:
Notes
http://webcache.googleusercontent.com/search?q=cache:T7QwiqsqtVEJ:blog.carlosgaldino.com/2015/12/03/defusing-a-binary-bomb-with-gdb-part-3.html+&cd… 6/6
5/29/2016 Defusing a binary bomb with gdb - Part 4 · carlosgaldino
Defusing a binary bomb with gdb
- Part 4
25 Apr 2016
This post is part of a series where I show how to defuse a binary bomb by
reading assembly code and using gdb . You might want to read the first
part if you haven't yet.
000000000040100c <phase_4>:
40100c: 48 83 ec 18 sub $0x18,%rsp
401010: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
401015: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
40101a: be cf 25 40 00 mov $0x4025cf,%esi
40101f: b8 00 00 00 00 mov $0x0,%eax
401024: e8 c7 fb ff ff callq 400bf0 <__isoc99_sscanf@pl
t>
401029: 83 f8 02 cmp $0x2,%eax
40102c: 75 07 jne 401035 <phase_4+0x29>
40102e: 83 7c 24 08 0e cmpl $0xe,0x8(%rsp)
401033: 76 05 jbe 40103a <phase_4+0x2e>
401035: e8 00 04 00 00 callq 40143a <explode_bomb>
40103a: ba 0e 00 00 00 mov $0xe,%edx
40103f: be 00 00 00 00 mov $0x0,%esi
401044: 8b 7c 24 08 mov 0x8(%rsp),%edi
401048: e8 81 ff ff ff callq 400fce <func4>
40104d: 85 c0 test %eax,%eax
40104f: 75 07 jne 401058 <phase_4+0x4c>
401051: 83 7c 24 0c 00 cmpl $0x0,0xc(%rsp)
401056: 74 05 je 40105d <phase_4+0x51>
401058: e8 dd 03 00 00 callq 40143a <explode_bomb>
40105d: 48 83 c4 18 add $0x18,%rsp
401061: c3 retq
Exactly as happened on phase 3 we can see that this phase is expecting two
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c… 1/7
5/29/2016 Defusing a binary bomb with gdb - Part 4 · carlosgaldino
integers as input. On 0x40101a the same format used before is stored on esi
which is then used by sscanf on 0x401024 .
On 0x401029 we can also confirm that if we enter more than 2 integers the
code will jump to 0x401035 that calls explode_bomb :
So which exact numbers should we enter? It must be a number that is less than
15:
cmpl compares 0xe which is 14 to the first integer 1 we entered for this
phase. Then jbe ("jump below or equal") will skip exploding the bomb if the
value is less than or equal to 14.
After that we can see that some setup is done before calling a new function,
func4 :
edi is usually used as the register to hold the first argument, esi holds the
second and edx holds the third argument. The first argument is the first
number we provided, the second and third are 0 and 14 , respectively.
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c… 2/7
5/29/2016 Defusing a binary bomb with gdb - Part 4 · carlosgaldino
0000000000400fce <func4>:
400fce: 48 83 ec 08 sub $0x8,%rsp
400fd2: 89 d0 mov %edx,%eax
400fd4: 29 f0 sub %esi,%eax
400fd6: 89 c1 mov %eax,%ecx
400fd8: c1 e9 1f shr $0x1f,%ecx
400fdb: 01 c8 add %ecx,%eax
400fdd: d1 f8 sar %eax
400fdf: 8d 0c 30 lea (%rax,%rsi,1),%ecx
400fe2: 39 f9 cmp %edi,%ecx
400fe4: 7e 0c jle 400ff2 <func4+0x24>
400fe6: 8d 51 ff lea -0x1(%rcx),%edx
400fe9: e8 e0 ff ff ff callq 400fce <func4>
400fee: 01 c0 add %eax,%eax
400ff0: eb 15 jmp 401007 <func4+0x39>
400ff2: b8 00 00 00 00 mov $0x0,%eax
400ff7: 39 f9 cmp %edi,%ecx
400ff9: 7d 0c jge 401007 <func4+0x39>
400ffb: 8d 71 01 lea 0x1(%rcx),%esi
400ffe: e8 cb ff ff ff callq 400fce <func4>
401003: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax
401007: 48 83 c4 08 add $0x8,%rsp
40100b: c3 retq
Looking at the first few instructions we can try to write what exactly is
happening with the arguments that were given to this function. The instructions
until 0x400fe2 are actually doing something like the following:
Then it compares y with a (our first input number for this phase) and if y
<= a it will jump to 0x400ff2 . Otherwise it calls func4 again but this time
c will be y - 1 (set at 0x400fe6 ). So on 0x400fe9 we can think of the
invocation as:
func4(a, b, y - 1);
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c… 3/7
5/29/2016 Defusing a binary bomb with gdb - Part 4 · carlosgaldino
After calling it you can see that 0x400fee will double the result from that
"inner" invocation ( eax holds the return value from that execution) and then
jump to 0x401007 which cleanups the stack frame for this invocation. So the
result from this recursive call is actually:
If y >= a the code will continue execution on 0x400ff2 . At that line it sets
the possible result as 0 and then compares the same y with a again. This
time if y >= a it jumps to 0x401007 and returns 0 , that's why eax got
the value 0 by the instruction before that. If y < a then func4 will be
called again but in this case b will be y + 1 (this assignment happens on
0x400ffb ) and the following invocation happens on 0x400ffe :
func4(a, y + 1, c);
After returning from this recursive call the return value is set on 0x401003
using the result from the recursive call so the result is actually:
return 2 * func4(a, y + 1, c) + 1;
With all this context we can now try to guess what exactly is going on with this
function:
if (y <= a) {
if (y >= a) {
return 0;
} else {
return 2 * func4(a, y + 1, c) + 1;
}
} else {
return 2 * func4(a, b, y - 1);
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c… 4/7
5/29/2016 Defusing a binary bomb with gdb - Part 4 · carlosgaldino
}
}
func4(1, 0, 14) {
int x = 14 - 0;
int y = 14 >> 31;
x = 14 + 0;
x = 14 >> 1;
y = 7 + 0;
}
Then we can see that func4 will be called by the else clause of the first
if :
func4(1, 0, 6) {
int x = 6 - 0;
int y = 6 >> 31;
x = 6 + 0;
x = 6 >> 1;
y = 3 + 0;
}
func4(1, 0, 2) {
int x = 2 - 0;
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c… 5/7
5/29/2016 Defusing a binary bomb with gdb - Part 4 · carlosgaldino
Since the last call to func4 returned 0 the final result will also be 0 and
the execution will continue this time on phase_4 at 0x40104d :
This line and the line below test whether or not the result of that func4
invocation returned 0 , if it did our first input is correct and execution
continues at 0x401051 . This instruction then simply checks if our second
input is 0 and if it is the function returns and phase 4 is defused:
1 0
So you got that one. Try this one.
We have something interesting here, remember that there are two checks about
y and a ? The second check uses the jge instruction that checks whether
the value is greater than or equal to (kind of obvious if you think about what
ge might mean in the instruction name). The interesting fact here is that the
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c… 6/7
5/29/2016 Defusing a binary bomb with gdb - Part 4 · carlosgaldino
previous check also tested for equality with jle . So, if y <= a and then you
check whether y >= a there's only one case that would satisfy both conditions
and that is y == a . I'm not sure if the compiler chose jge even though the
code was written as if (y == a) or if the code was actually written as if (y
>= a) .
Another interesting thing about this phase is how the compiler manages the
results of the recursive calls. Since eax is a register the results of each
recursive invocation will be available to the stack frame that invoked it and then
it can simply be returned without saving the result in some other place. Also you
see that after calling func4 again there's nothing managing the local variables
x and y which is why they are also stored in registers instead of being saved
inside each stack frame.
An exercise left to the reader is trying to find the other possible solutions for this
phase including one input that doesn't even call func4 recursively. Also try to
see which numbers are invalid for this phase and the result that func4 returns
when these numbers are used.
Notes
http://webcache.googleusercontent.com/search?q=cache:POrmVxSy8kgJ:blog.carlosgaldino.com/2016/04/25/defusing-a-binary-bomb-with-gdb-part-4.html+&c… 7/7
5/29/2016 Defusing a binary bomb with gdb - Part 5 · carlosgaldino
Defusing a binary bomb with gdb
- Part 5
28 Apr 2016
This post is part of a series where I show how to defuse a binary bomb by
reading assembly code and using gdb . You might want to read the first
part if you haven't yet.
After defusing the fourth phase the program continues to the next phase:
0000000000401062 <phase_5>:
401062: 53 push %rbx
401063: 48 83 ec 20 sub $0x20,%rsp
401067: 48 89 fb mov %rdi,%rbx
40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
401071: 00 00
401073: 48 89 44 24 18 mov %rax,0x18(%rsp)
401078: 31 c0 xor %eax,%eax
40107a: e8 9c 02 00 00 callq 40131b <string_length>
40107f: 83 f8 06 cmp $0x6,%eax
401082: 74 4e je 4010d2 <phase_5+0x70>
401084: e8 b1 03 00 00 callq 40143a <explode_bomb>
401089: eb 47 jmp 4010d2 <phase_5+0x70>
40108b: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx
40108f: 88 0c 24 mov %cl,(%rsp)
401092: 48 8b 14 24 mov (%rsp),%rdx
401096: 83 e2 0f and $0xf,%edx
401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx
4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1)
4010a4: 48 83 c0 01 add $0x1,%rax
4010a8: 48 83 f8 06 cmp $0x6,%rax
4010ac: 75 dd jne 40108b <phase_5+0x29>
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd… 1/5
5/29/2016 Defusing a binary bomb with gdb - Part 5 · carlosgaldino
The first few lines setup the stack for this function and on 0x40106a the stack
protector 1 is setup.
On 0x40108b the first byte from the input string is copied to ecx . Notice that
at the start of this function the input string stored on rdi was copied to rbx
at 0x401067 . The instruction at 0x40108b uses both rbx and rax but
since rax has a value of 0 the data address used as source will be solely the
address stored on rbx . We can confirm it with:
Stepping to next instruction we can also confirm that the byte from the first
character is stored on ecx :
(gdb) i r $ecx
ecx 0x69 105
Then on the next two instructions this byte is copied to rdx and on
0x401096 a bitwise AND is performed against this byte. The value after the
bitwise AND is then used as an offset to copy a value from some location to the
same edx register on 0x401099 . That same 1-byte value is then stored in a
local variable on 0x4010a0 . The next instruction increments rax which is
then checked by the next instruction to see if this process was executed for all
characters from our input. If the process wasn't performed for all characters it
then jumps again to 0x40108b to read the next character and repeat the steps
above.
At the end of this process a local variable will hold a new string that is created
by using our input characters as an offset to a mysterious string.
If the process was executed for all characters it then prepares the arguments for
the next function call, starting at 0x4010ae . This new string we're talking
about will be used as an argument to the strings_not_equal function that
we've seen before in this series. The other string that ours will be compared to is
located at 0x40245e as you can see on 0x4010b3 .
Now that we know the flow for this phase it's time to see which string our input
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd… 3/5
5/29/2016 Defusing a binary bomb with gdb - Part 5 · carlosgaldino
must produce.
Now all that we need is to look at the intermediary string to see which are the
offsets we need to input so that the final string will be flyers .
Looking at the output above we can guess that the actual intermediary string
must be just maduiersnfotvbyl . Looking at the position of each character we
can then check that the correct offsets must be:
letter offset
f 0x9
l 0xf
y 0xe
e 0x5
r 0x6
s 0x7
Considering just the printable characters from the ASCII table we can devise the
following table:
offset possible chars
0x9 )9IYiy
0xf / ? O _ o DEL
0xe .>N^n~
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd… 4/5
5/29/2016 Defusing a binary bomb with gdb - Part 5 · carlosgaldino
0x5 %5EUeu
0x6 &6FVfv
0x7 '7GWgw
Any combination of a single char for each offset will defuse phase_5 .
The sixth and final phase will be covered in the next post .
Notes
1. https://en.wikipedia.org/wiki/Buffer_overflow_protection ↩
http://webcache.googleusercontent.com/search?q=cache:r7Vvh9Ci4SUJ:blog.carlosgaldino.com/2016/04/28/defusing-a-binary-bomb-with-gdb-part-5.html+&cd… 5/5
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
Defusing a binary bomb with gdb
- Part 6
19 May 2016
This post is part of a series where I show how to defuse a binary bomb by
reading assembly code and using gdb . You might want to read the first
part if you haven't yet.
Here we are at the last phase. This is the most interesting phase so far. The code
for phase_6 is the following:
00000000004010f4 <phase_6>:
4010f4: 41 56 push %r14
4010f6: 41 55 push %r13
4010f8: 41 54 push %r12
4010fa: 55 push %rbp
4010fb: 53 push %rbx
4010fc: 48 83 ec 50 sub $0x50,%rsp
401100: 49 89 e5 mov %rsp,%r13
401103: 48 89 e6 mov %rsp,%rsi
401106: e8 51 03 00 00 callq 40145c <read_six_numbers>
40110b: 49 89 e6 mov %rsp,%r14
40110e: 41 bc 00 00 00 00 mov $0x0,%r12d
401114: 4c 89 ed mov %r13,%rbp
401117: 41 8b 45 00 mov 0x0(%r13),%eax
40111b: 83 e8 01 sub $0x1,%eax
40111e: 83 f8 05 cmp $0x5,%eax
401121: 76 05 jbe 401128 <phase_6+0x34>
401123: e8 12 03 00 00 callq 40143a <explode_bomb>
401128: 41 83 c4 01 add $0x1,%r12d
40112c: 41 83 fc 06 cmp $0x6,%r12d
401130: 74 21 je 401153 <phase_6+0x5f>
401132: 44 89 e3 mov %r12d,%ebx
401135: 48 63 c3 movslq %ebx,%rax
401138: 8b 04 84 mov (%rsp,%rax,4),%eax
40113b: 39 45 00 cmp %eax,0x0(%rbp)
40113e: 75 05 jne 401145 <phase_6+0x51>
401140: e8 f5 02 00 00 callq 40143a <explode_bomb>
401145: 83 c3 01 add $0x1,%ebx
401148: 83 fb 05 cmp $0x5,%ebx
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+&… 1/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+&… 2/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
It's longer than the other phases and seems more complicated so we're going to
break it in parts to explain what each part is doing.
The first part we can look at is where the function initializes. It starts by saving
some registers values because they are going to be used as local variables in this
function, then making room for other local variables and then reading the input
that will be used to defuse the phase. At 0x401106 we can see that the input
for this phase must be six numbers:
After reading the six numbers and placing the first one on rsp the code copies
the address pointing to the first one into r14 then it sets up other variables
and finally on 0x40111e it checks whether or not the first number we provided
is less than or equal to 6 . How it did that?
rsi is used to hold the second argument for a function call and prior to calling
read_six_numbers (at 0x401103 ) the address of rsp was copied to rsi
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+&… 3/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
Then on 0x401117 the value stored in the address on r13 , our first number,
is copied to eax and then the code checks if it is less than or equal to 6 .
So now that we understand how the check was made, let's proceed to the next
part:
Remember that on line 0x40110e the register r12d stored the value 0 so
the first three lines are just for checking if the code already went through 6
iterations. Let's continue on 0x401132 where the new value of r12d (which
is 1 for the first iteration) is copied into ebx which then is copied to rax by
sign-extending from double word (4 bytes) to quad word (8 bytes) since ebx is
a 32-bit register while rax is a 64-bit register.
After that the next number we entered is checked against the first one. The
second number is copied to eax by this instruction:
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+&… 4/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
What this line actually does is: multiply by 4 the value on rax ( 1 since it
came from r12d ) and add that value to value stored on rsp (the starting
address of the array holding our input numbers). For the first iteration the
resulting address will be:
(gdb) x $rsp+$rax*0x4
0x7fffffffdd64: 0x00000002
The value stored at this resulting address will then be copied to eax . For the
first iteration it means our second input number.
Then our second value (on eax ) is compared to first one to see if they are not
equal and jumps to the next part:
The first three lines will check if we did this check for all six numbers which
means we cannot input repeated numbers. After that, on 0x40114d , r13 is
changed to hold the address of the second input number by adding 4 bytes
( sizeof(int) ) to the address r13 is currently storing. Then it goes back to
0x401114 to do the same checks against the other numbers we provided.
Let's continue to see which other characteristics these numbers must have.
After doing these initial checks the code will jump to 0x401153 :
The first line of this part simply defines the address that means we iterated over
all six numbers. The first number is stored on the address that rsp holds and
the sixth number will be on $rsp + 0x14 (start address + offset of 5 int ).
r14 also holds the address for the first number so it's going to be copied to
rax on 0x401158 to be used in this iteration. Then on the next two lines both
ecx and edx store the value 7 . After the setup the actual iteration will start
by first subtracting from edx the value stored by the address in rax (our
first number in the first iteration). At 0x401164 the result of this subtraction
will overwrite the value on rax and then on 0x401166 the code will move to
the next int we provided, compare on 0x40116d if we iterated over all six
numbers and jump back to 0x401160 if we did not, otherwise get out of the
loop and continue execution on 0x401197 .
Let's simulate what happens after this loop is executed. Suppose we entered 1
2 3 4 5 6 as our input numbers for this phase. Then after iterating in this loop
our array will have the following new values: 6 5 4 3 2 1 . The loop just
changes the all numbers in the array to be abs(n-7) .
After exiting the loop we continue on 0x401197 which brings us to the next
part in this phase:
Although the first line of this part is at 0x401176 , execution actually starts at
0x401197 . After executing this line ecx will hold the first number from our
array because the value stored on rsi is 0 (from 0x40116f ) and the
instruction on 0x401197 means: copy the value stored by the address of
$rsi*0x1 + $rsp to ecx . This operation clearly means it is part of some
iteration and we can guess that rsi will be updated in the process to go over
the other numbers in the array.
If the current number on ecx is less than or equal to 1 the code will jump to
0x401183 , otherwise it will jump to 0x401176 .
In the last part our array became: 6 5 4 3 2 1 . So the code will jump to
0x401176 . Let's see what happens there.
Notice that before jumping to 0x401176 , the address 0x6032d0 was stored
on edx . Then the value stored after the first 8 bytes of this address will be
copied to rdx on 0x401176 . After this operation, eax will be incremented
and compared with ecx to then conditionally jump to another place in this
part or again to 0x401176 . The initial value of eax in this case is 1 that was
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+&… 7/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
The values on ecx and eax will match only after six iterations: in our
example, ecx starts with 6 and eax with 1 . In this case before jumping
to 0x401188 , rdx will have whatever value is stored in $rdx + 0x48 (six
times adding 0x8 to the initial address and copying the value in the new
address to rdx ).
At this line the address that rdx is holding will be copied to the address that
results from: $rsi*0x2 + $rsp + 0x20 . rsi is the index over the iteration
that is going on:
(gdb) i r rsi
rsi 0x0 0
Now that we know what this iteration is all about let's see what exactly is stored
by the initial address on rdx :
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+&… 8/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
(gdb) x 0x6032d0
0x6032d0 <node1>: 0x0000014c
Huh, node1 , interesting name, right? Let's see what this address plus 8 bytes
holds:
(gdb) x 0x6032d0+0x8
0x6032d8 <node1+8>: 0x006032e0
(gdb) x 0x6032e0
0x6032e0 <node2>: 0x000000a8
Aha! That looks like a linked list. To see the address of node3 :
(gdb) x 0x6032e0+0x8
0x6032e8 <node2+8>: 0x006032f0
(gdb) x *(0x6032e0+0x8)
0x6032f0 <node3>: 0x0000039c
We have a linked list that holds an int value, the node identifier and the
pointer to the next node, something like the following:
struct node {
int x;
int i;
struct node *next;
};
So when the code jumps to 0x401188 , rdx will have the address of the value
stored by node6 since our array is 6 5 4 3 2 1 and it went through
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+&… 9/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
(gdb) i r rdx
rdx 0x603320 6304544
(gdb) x 0x6032d0+0x48
0x603318 <node5+8>: 0x00603320
(gdb) x $rdx
0x603320 <node6>: 0x000001bb
The address rdx holds, which stores the value 0x1bb , will be placed in the
first position of a new array starting at $rsp + 0x20 . Since this code iterates
over all six numbers, after executing this part for all numbers this new array will
actually store the addresses holding the values that the corresponding node
stores, based on our transformed input array.
Explaining: from 0x401176 until 0x401181 the code is looking for the
corresponding node for the current iteration. On 0x401188 the address of
value x that the node holds is then copied to the current iteration index on the
new array. Then the next iteration begins.
Let's see what are the values that each node stores and their addresses. First we
define a command to print the node values and move to the next node:
define plist
set var $n = $arg0
while $n
printf "node%d (%p): value = %#.3x, next=%p\n", *($n+0x4), $n, *$n,
*($n+0x8)
set var $n = *($n+0x8)
end
end
After iterating over the six numbers using our input array which was
transformed into 6 5 4 3 2 1 the new array (starting at $rsp + 0x20 ) will
hold the addresses of x in the following order: node6 node5 node4 node3
node2 node1 .
After creating this new array the code continues execution at 0x4011ab which
is the next part:
At the first line of this part rbx gets the value of the first element of the new
array which is the address of x for node6 . In the next line rax gets the
second element of the new array and in the third line rsi gets an address that
is just past the last element of this new array, most likely to check later if we
iterated over the entire new array.
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+… 11/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
On 0x4011ba , rcx will hold the value of the first element of the new array,
then rdx will get the second value and in the next line, 0x4011c0 , this value
will be copied to $rcx + 0x8 . Let's back it up for a minute and see the values
in both registers after executing the instruction at 0x4011c0 :
$rcx + 0x8 is the address that holds the pointer to the next element of the
list and after executing 0x4011c0 it will point to the value that rdx is
storing:
(gdb) x $rcx+0x8
0x603328 <node6+8>: 0x0000000000603310
After that, on 0x4011c4 the next value from the new array is placed in rax
for the next iteration which is checked against rsi in the next line and the
process repeats. At the end of it the next pointer for each node will be
changed according to the values of the new array. As we've seen above the new
array has the following values:
These values correspond to node6 node5 node4 node3 node2 node1 so after
the iteration above the pointers will be changed to reflect this order. We can
confirm it with our plist command after executing the instruction on
0x4011d2 :
With the initial input of 1 2 3 4 5 6 the code has reversed the list. Note that
I now used the address of node6 as the starting address for plist since that
is the order from the array located at $rsp + 0x20 . Also notice that on
0x4011d2 the next pointer for the last iteration receives the NULL value
and in our case it is node1->next .
Now that the list was changed the execution continues at 0x4011da by storing
the value 5 in ebp . Then the address of value x of the next node is stored
on rax and then in the next line the actual x value is stored on eax (32-bit
register since we're dealing with int ). On 0x4011e5 the value x from the
first node (at rbx ) is compared against the value x of the second and if the
first value is greater than or equal to the second the code jumps to 0x4011ee
that will update the value of rbx to point to the next x value and also update
the value of ebp that is then compared to see if we iterated over the entire list.
So this iteration is checking that the x value of the current node is greater
than or equal to the next x for all nodes in the list. If they are not the bomb
explodes as we can see at 0x4011e9 .
The other part of this function starting at 0x4011f7 cleanups the stack frame
for phase_6 and returns.
Now that we saw everything that this function is doing we know that our input
numbers are used to sort the linked list in descending order.
Don't forget that before being used to reorder the list each input number will
be changed to abs(n-7) .
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+… 13/15
5/29/2016 Defusing a binary bomb with gdb - Part 6 · carlosgaldino
1 0x14c 332
2 0x0a8 168
3 0x39c 924
4 0x2b3 691
5 0x1dd 477
6 0x1bb 443
The values of x for the final list must be in the following order:
924 -> 691 -> 477 -> 443 -> 332 -> 168
node3 -> node4 -> node5 -> node6 -> node1 -> node2
4 3 2 1 6 5
Congratulations! You've defused the bomb!
Or not? There's something odd in the C file. The main function ends like this:
input = read_line();
phase_6(input);
phase_defused();
return 0;
http://webcache.googleusercontent.com/search?q=cache:1K1SsGLv47UJ:blog.carlosgaldino.com/2016/05/19/defusing-a-binary-bomb-with-gdb-part-6.html+… 14/15
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
Defusing a binary bomb with gdb
- Part 7
24 May 2016
This post is part of a series where I show how to defuse a binary bomb by
reading assembly code and using gdb . You might want to read the first
part if you haven't yet.
In the last post the bomb was defused but there was something odd in the C
file. This was the end of the main function:
input = read_line();
phase_6(input);
phase_defused();
return 0;
And I left a hint in the last post about a call to a secret_phase function from
phase_defused .
00000000004015c4 <phase_defused>:
4015c4: 48 83 ec 78 sub $0x78,%rsp
4015c8: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
4015cf: 00 00
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 1/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
The first few lines until 0x4015d8 are for setting the stack protector 1 and then
saving rax before setting it to 0 on 0x4015d6 . Then on 0x4015d8 it
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 2/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
compares if we already went through all the six phases by looking at the number
of input strings. This comparison will only be true after defusing the six phases
so before the last post the code always jumped to 0x40163f that restored the
value of rax and checked the stack protector before returning.
Now that the sixth phase was defused the code will continue on 0x4015e1 . In
the next three lines, registers r8 , rcx and rdx will store addresses to hold
local variables and then on 0x4015f0 and 0x4015f5 , esi and edi receive
two addresses. Let's look at them to see what is in each address:
How could I guess they were strings? Look at the next line:
Both edi and esi are used to hold the first and second arguments,
respectively. Then the only thing that both registers could store were addresses
pointing to strings 2 .
The value 1 0 on edi looks familiar? It should, because that is the answer
for the fourth phase .
sscanf is then used to scan the input of the fourth phase again but with a
different format now, expecting a string after the second value. You can see that
on 0x4015ff if it doesn't see 3 values it jumps to 0x401635 that will print the
following message and return:
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 3/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
Otherwise this function will compare if we entered the correct string to activate
the secret phase. Looking at the instruction on 0x401604 we can see what is
the address of the activation string:
If the input for phase 4 includes DrEvil at the end the code will then call the
secret phase on 0x401630 :
Now we know how to get to the point of calling secret_phase . Let's take a
look at the code for it:
0000000000401242 <secret_phase>:
401242: 53 push %rbx
401243: e8 56 02 00 00 callq 40149e <read_line>
401248: ba 0a 00 00 00 mov $0xa,%edx
40124d: be 00 00 00 00 mov $0x0,%esi
401252: 48 89 c7 mov %rax,%rdi
401255: e8 76 f9 ff ff callq 400bd0 <strtol@plt>
40125a: 48 89 c3 mov %rax,%rbx
40125d: 8d 40 ff lea -0x1(%rax),%eax
401260: 3d e8 03 00 00 cmp $0x3e8,%eax
401265: 76 05 jbe 40126c <secret_phase+0x2a>
401267: e8 ce 01 00 00 callq 40143a <explode_bomb>
40126c: 89 de mov %ebx,%esi
40126e: bf f0 30 60 00 mov $0x6030f0,%edi
401273: e8 8c ff ff ff callq 401204 <fun7>
401278: 83 f8 02 cmp $0x2,%eax
40127b: 74 05 je 401282 <secret_phase+0x40>
40127d: e8 b8 01 00 00 callq 40143a <explode_bomb>
401282: bf 38 24 40 00 mov $0x402438,%edi
401287: e8 84 f8 ff ff callq 400b10 <puts@plt>
40128c: e8 33 03 00 00 callq 4015c4 <phase_defused>
401291: 5b pop %rbx
401292: c3 retq
401293: 90 nop
401294: 90 nop
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 4/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
401295: 90 nop
401296: 90 nop
401297: 90 nop
401298: 90 nop
401299: 90 nop
40129a: 90 nop
40129b: 90 nop
40129c: 90 nop
40129d: 90 nop
40129e: 90 nop
40129f: 90 nop
After reading the input for this secret phase on 0x401243 , edx will store the
value 10 , esi will store NULL and rdi will store the input we gave. Then
strtol 3 will be called on 0x401255 and judging by the values on the
registers it means our input will be converted to a number in base 10. After that,
on 0x40125a the already converted number will be stored on rbx . On
0x40125d the value will be modified by subtracting 1 and placed again on
eax . Then a comparison against 0x3e8 which is 1000 in base 10. If our
input is less than 1000 the code will jump to 0x40126c to continue and if not
the bomb will explode.
At 0x40126c our value is placed on esi and edi gets an address. Both
values will be used in the next function fun7 that is called on 0x401273 . The
result that fun7 must return is 2 as you can see on 0x401278 .
Before looking at fun7 let's look at what is in the address that edi received
and is used as the first argument for fun7 :
(gdb) x 0x6030f0
0x6030f0 <n1>: 0x00000024
Hmm, n1 . This name doesn't give any clues about what exactly this is. Let's
look at fun7 then:
0000000000401204 <fun7>:
401204: 48 83 ec 08 sub $0x8,%rsp
401208: 48 85 ff test %rdi,%rdi
40120b: 74 2b je 401238 <fun7+0x34>
40120d: 8b 17 mov (%rdi),%edx
40120f: 39 f2 cmp %esi,%edx
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 5/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
It first checks whether rdi is NULL ( 0x0 ) and if it is the function will return
the value -1 ( 0xffffffff at 0x401238 ). If not, the value stored in the
address rdi is storing will be placed on edx and then compared (on
0x40120f ) with our input number. If the value on edx is less than or equal
to our number the code goes to 0x401220 , if not it continues on 0x401213 .
Let's continue on 0x401213 then we come back to see what happens in the
other branch.
On 0x401213 rdi will store whatever is 8 bytes after the address already on
rdi and call fun7 again.
In the other branch, when the number on edx is less than or equal to our
number, the code goes to 0x401220 that sets eax to 0 , compares what is
on edx with our number and if they are equal it goes to 0x40123d that
returns. If the numbers are different then the instruction at 0x401229 will
change rdi to store whatever is 16 bytes after the current address it has and
then call fun7 as the other branch does.
In each branch rdi is changed to hold the new address located either 8 or 16
bytes after its current address. The first thing that rdi holds is a number, the
other two are pointers, so this might be a binary tree:
struct node {
int data;
struct node *left;
struct node *right;
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 6/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
};
The root node, located at the initial address that fun7 is called with is the
following:
(gdb) x 0x6030f0
0x6030f0 <n1>: 0x00000024
(gdb) x 0x6030f0+0x8
0x6030f8 <n1+8>: 0x00603110
(gdb) x 0x6030f0+0x10
0x603100 <n1+16>: 0x00603130
After following the node pointers we can see that the tree structure is the
following:
We know how the tree is structured but we don't know what we need to do to
get to the right answer. secret_phase calls fun7 and expects it to return the
value 2 :
So let's see what fun7 returns. We know it is a recursive function. Let's see
what is the base case, which are actually two:
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 7/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
And:
Both show that the function returns when we reached a NULL pointer (first
case) or if the number we gave is equal to the one in the current node (second
case).
But in the first case the code jumps to 0x401238 that sets the return value to
-1 :
The second case jumps straight to 0x40123d but before comparing the
numbers it sets the return value to 0 at 0x401220 :
So if we provide a number that is not present in the tree the code will reach a
NULL pointer and return -1 and if our number is present it will return 0 .
Now we need to look at each recursive call to fun7 and see what the current
call will do with the result from the inner call. Let's see what happens after the
inner fun7 call returns:
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 8/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
This is the case when our number is smaller than the current node value. It
simply doubles the return value (on 0x40121c ) and jumps to 0x40123d to
return.
In the other branch, when our number is greater than or equal to the current
node value it goes to 0x401220 :
Here if the values are equal the function will return 0 as we saw earlier but if
they are different, fun7 will be called again and the return value from the
inner call will be doubled as in the other branch but in this case it will also add
1 to it:
Simplifying:
eax = 2*rax + 1
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html+… 9/11
5/29/2016 Defusing a binary bomb with gdb - Part 7 · carlosgaldino
Looking again at the tree structure we can try to guess which value will provide
the correct answer by visiting the correct nodes.
One option is to visit 0x8 and 0x16 . Replacing the node addresses with the
actual data they have we would have the following calls to fun7 :
There is another possible answer for this phase and finding it is left as an
exercise to the reader.
Notes
2. https://en.wikipedia.org/wiki/Buffer_overflow_protection ↩
The strtol() function converts the initial part of the string in nptr to a
long integer value according to the given base, which must be
between 2 and 36 inclusive, or be the special value 0.
4. If you want to learn more about lea , its difference with mov , how and
why arithmetic operations can be performed with lea you can start by
reading the following page:
https://en.wikibooks.org/wiki/X86_Assembly/Data_Transfer#Load_Effe
ctive_Address ↩
http://webcache.googleusercontent.com/search?q=cache:aW_YFEmXe2cJ:blog.carlosgaldino.com/2016/05/24/defusing-a-binary-bomb-with-gdb-part-7.html… 11/11