Debugging Refresher
level 1
Use the command
continue
, orc
for short, in order to continue program execution.
Before we do anything else we need to open the file in GDB.
This challenge is fairly simple, we just have to run the file.
The program will hit a breakpoint at 0x000055e9b5da2be3
in main
function.
We can continue the execution and get the flag.
level 2
In order to solve this level, you must figure out the current random value of register r12 in hex.
We can find the value of the r12
register using the p
command which is a short from of print.
The x
option prints the value in hexadecimal.
Rest of the steps remain the same.
level 3
In order to solve this level, you must figure out the random value on the stack (the value read in from
/dev/urandom
). Think about what the arguments to the read system call are.
The contents of a file can be read using the read
syscall.
Read syscall
We can see that the second argument is the location of the buffer in which the data is to be read. This argument is loaded in the rsi
register.
Let's look at how this loaded in our assembly code.
If we look at the address main+423
, we can see that the value of rsi
is being copied from rax
.
lea instruction
The lea
instruction loads the effective address of the instruction being pointed to.
This value in rax
is set to rbp-0x18
as seen in the instruction at main+414
address.
Now that we know the location of the buffer is rbp-0x18
, we can now check the data copied there using the x
command.
The format is set to hexadecimal using x
and the unit size is set to giga word using g
.
level 4
In order to solve this level, you must figure out a series of random values which will be placed on the stack. You are highly encouraged to try using combinations of
stepi
,nexti
,break
,continue
, andfinish
to make sure you have a good internal understanding of these commands. The commands are all absolutely critical to navigating a program's execution.
The program takes user input and then compares it with a value.
In order to correctly provide user input, we need to know what it is being compared with before the comparison even happens.
Let's begin by disassembling the main
function.
We can see that the instruction at main+626
compares the value of the rax
register with the value of the rdx
register.
If the values are equal, it skips over the exit
syscall.
Let's look at the values of these registers.
So rdx
is the register that holds user input and rax
is the one that holds the value it is to be compared to. We also know that the value in rax
is copied from rbp-0x18
by looking at the instruction at main+622
.
We have to restart the program again.
Read syscall
We know that the read
syscall reads data into a buffer pointed to by it's second argument. We also know that this second argument is loaded into the rsi
register.
In this case the buffer is located at rbp-0x18
as shown by the instruction at main+498
.
All we have to do now is to set a breakpoint at the instruction after the read
syscall is made.
Once our program has stopped at the breakpoint, we can check the data that was copied into the buffer.
Next continue the program execution until we are asked for the user input.
We can see that the check was successfully passed. This process will repeat a couple of times but the method will be the same.
level 5
Use gdb scripting to help you collect the random values.
From the previous level, we already know that the value that our input is being compared to is stored at rbp-0x18
. This is the location of the read
syscall's buffer.
This time the read
syscall is made at main+704
. Therefore in order to check the data that is read we need to set a breakpoint at the next instruction which is at main+709
.
Next we want to display the current variable.
These commands will be executed every time the breakpoint is hit.
We defined a variable currentValue
and set it's value equal to the local variable rbp-0x18
.
All we have to do now is put it all together in a script so that we don't have to type it out over and over.
GDB script
The complete script looks like follows:
The commands will be executed every time the breakpoint is hit.
level 7
In this level we are introduced to another way of executing the win
function.
level 8
This time the win
function has been broken.
So we can no longer use our old technique.
We can check the instruction that is the cause of this segmentation fault.
The dereferenced value of rax
is being moved to eax
.
Let us check the value of rax
.
The value of rax
is 0x0
, and we are not allowed to access that memory location, which causes the program to crash.
On disassembling win
, we can see that 0x0
is being stored on the stack, and being moved to rax
.
Let's set a breakpoint at win
.
Let's disassemble win
.
This time we have stopped execution before the code-breaking instructions.
There is an open
syscall at win+64
which opens the /flag
file.
We can directly jump to the setup.
That gives us the flag.
Last updated