Basic analysis of the binary
Here we have a zip file, and after extracting the file we have a binary and the flag.txt.
Now, we can see the flag in the flag.txt file, but our target will be to use and manipulate the binary to show us the flag.
First, let’s have a look at the file type — file ret2win32
It’s a 32 bit executable. Not stripped. Now, we can check for what type of protections are enabled. We can use rabin2
or checksec
for that. I am going to use rabin2
.
rabin2 -I ret2win32
We can see that the NX is enabled. This option is referred to as Data Execution Prevention (DEP) or No-Execute (NX). When this option is enabled, it works with the processor to help prevent buffer overflow attacks by blocking code execution from memory that is marked as non-executable. In short, even if we inject code in the stack, it won’t execute.
Now, we will use the nm
command to see the symbols from the object file such as user-defined functions, variables, etc.
We can also use rabin2
for finding the user-defined functions.rabin2 -qs ret2win | grep -e -ve imp ‘ 0 ‘
Running strings -d ret2win32
we can see the strings from initialized, loaded data sections in the file.
In-depth Journey
I will be using gdb-pwndbg
for this challenge. You can use your favorite debuggers and play around with the binary.
To check for the functions we can run info functions
.
We can see the virtual address of the functions named ret2win
, pwnme
, main
.
We can disassemble a function to view the assembly translation of a specific function. We can do it with disass func_name
.
So, let’s have a look at the ret2win function.
disass ret2win
We can see the function calling system at some point. Interesting!
Let’s run the binary.
We can check for the addresses by running p ret2win
, p main
, p system
etc. We can also search for specific strings. search “/bin/cat”
.
Poke around with this stuff to understand a bit more about the binary.
Now, let’s create a pattern with cyclic 100
And, if we run the binary and put the value, it crashes. But, we can check for the eip(instruction pointer) offset with cyclic -l ‘laaa’
. It’s 44.
We can understand this by creating another pattern. We will have 44 A + 4 B + 20 C. python -c ‘print “A” * 44 + “BBBB” + “C” * 20’
If we enter this value in the binary, we can see the eip return address is overwritten with 0x42424242
, which is BBBB.
Now, what if we give it the address of ret2win
functions instead of B?
Address for the ret2win
function is 0x804862c
.
So, again, we can create the payload with python.
python -c ‘print “A” * 44 + “\x2c\x86\x04\08” > payload
We need to write the address in little-endian format. You can read about it more here.
Exploitation
Now, the final step. If we run the binary and pass the payload, it gives us the flag. In the eip
the original return address is overwritten with the address of the ret2win function, which prints the flag../ret2win32 < payload
You can try the 64-bit version yourself. If you can solve it, I hope you have a good understanding of the process.