For this one, we will be given with a binary named “READ”
Let’s take a quicklook at main()
with Ghidra:
We can see that it does three things:
- read user input and stores in
input
(I have renamed the variable) - read the
flag.txt
and stores it content inlocal_10
. - send our
input
totext1()
Let’s see what is in text1()
So, it calls another function text2()
The text2
function uses our input as an argument for printf
directly. This will cause the format string vulnerability where we can send a format string (e.g., %x
, %s
, %p
) to printf()
and printf()
will grab whatever is on the stack as the value to show in the format of the supplied format earlier.
Before we begin, I will debug the binary using gdb
to see 2 things:
- what address holding the content of the flag
- how much
%x
I need to reach that address
P.S. I have create a file named flag.txt
locally with the content of AAAABBBBCCCC
so that I know what address is holding it.
With GDB openned, I put a breakpoint at the call of printf():
At the breakpoint, I don’t see our AAAABBBBCCCC
:
So, I use stack <num>
command to see more items in our stack:
Our flag is at 0x4000006330
!
What about the data returned from binary?
I have counted the offset for you. It is at the 19th !
To read the string stores in that location, we need to use %s
which will treat the address as a pointer to string and read it until \x00
Now, if we just send multiple of %s
, we will encounter Segmentation fault.
However, we can do something called direct parameter access which allows us to specify the offset to the target for the format string to get the data from. The format is:
%<number>$<format>
In our case, it is %19$s
Let’s try:
We got the flag!