Note:

  1. The virtual machine being used is 32-bit, as the skills acquired in 32-bit environments can easily be transferred to 64-bit.
  2. You should have prior knowledge of how to use gdb, how to set breakpoints, and how to pipe payloads into gdb.
  3. You should understand how the stack works, how addresses are pushed and popped, how swapping works, and what happens during a function call.
  4. Knowledge of assembly language is highly recommended.

Steps:

  1. Search for functions using the info functions command.
  2. Disassemble the main function. There is a string copy vulnerability that points to a buffer overflow:
  1. Disassemble validateArgs and howYouDoing functions:
  2. The validateArgs function checks whether you have provided two arguments:
  1. In howYouDoing, there is a strcpy and a printf function, where we can exploit a format string vulnerability:
  1. The flag is present in the giveMeTheFlagAlready function, but first, we need to know what is being displayed by whatIsDeadMayNeverDie. By disassembling whatIsDeadMayNeverDie, we discover that it is the first phase of our exploitation, and we need to update a global variable:
  1. We found the address of the global variable, but we need to update its value:
  1. 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 the main function—it is 256 bytes. So, 256 + 4 will corrupt the ebp, and another 4 will change the RIP to 0x08048548, which will give the following result:
  1. We successfully changed the value of the global variable.
  2. 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:
  1. 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 of giveMeTheFlagAlready, 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 that giveMeTheFlagAlready can access the value stored in the global variable.
  1. Run the payload with the command:
./Final_Q1.bin $(printf “\x6c\xa0\x04\x08”)-%33u-%1\$n `cat payload`

Voila! You get the flag.