Note:
- The virtual machine being used is 32-bit, as the skills acquired in 32-bit environments can easily be transferred to 64-bit.
- You should have prior knowledge of how to use gdb, how to set breakpoints, and how to pipe payloads into gdb.
- You should understand how the stack works, how addresses are pushed and popped, how swapping works, and what happens during a function call.
- Knowledge of assembly language is highly recommended.
Steps:
- Search for functions using the
info functions
command. - Disassemble the
main
function. There is a string copy vulnerability that points to a buffer overflow:
- Disassemble
validateArgs
andhowYouDoing
functions: - The
validateArgs
function checks whether you have provided two arguments:
- In
howYouDoing
, there is astrcpy
and aprintf
function, where we can exploit a format string vulnerability:
- The flag is present in the
giveMeTheFlagAlready
function, but first, we need to know what is being displayed bywhatIsDeadMayNeverDie
. By disassemblingwhatIsDeadMayNeverDie
, we discover that it is the first phase of our exploitation, and we need to update a global variable:
- We found the address of the global variable, but we need to update its value:
- This can be done using the format string vulnerability. As we know, the program accepts two arguments: one is vulnerable to both buffer overflow and format string vulnerabilities, while the other is vulnerable to buffer overflow alone. Using the format string vulnerability in the first argument, we can change the global variable to 39 (0x27), and then overflow the second buffer to change the return address to the address of
whatIsDeadMayNeverDie
. We can determine the buffer size from themain
function—it is 256 bytes. So, 256 + 4 will corrupt theebp
, and another 4 will change theRIP
to 0x08048548, which will give the following result:
- We successfully changed the value of the global variable.
- Now, by disassembling the
giveMeTheFlagAlready
function, we can see that it has one argument. The address 0x4(%ebp) is the return address, and 0x8(%ebp) will be the argument:
- Since we know it accepts an argument, we can develop a payload that performs a format string attack to change the global variable and call
whatIsDeadMayNeverDie
. Then, we can create a buffer overflow payload with 260 NOPs and concatenate two addresses to it. The last address should be that ofgiveMeTheFlagAlready
, because the next two address spaces on the stack will be for the return address and the function’s first argument. We will set the return address to a valid address ahead of this function, and then add the address of the global variable so thatgiveMeTheFlagAlready
can access the value stored in the global variable.
- Run the payload with the command:
./Final_Q1.bin $(printf “\x6c\xa0\x04\x08”)-%33u-%1\$n `cat payload`
Voila! You get the flag.