Stack four carries the same idea s stack three where we want to control the program’s next execution. But instead of using a function pointer which the program had defined (therefore existed just beyod our buffer on the stack), we are trying to control the program counter ($pc).
This means we need to fill our buffer enough to control the $pc register. To do this, we can use pwntools to create a string long enough to fill our buffer and then some, and find where $pc is being filled with this buffer.
Once we have our string, we can run the binary with gdb and provide the string as inpug.
We can see that $pc is filled with 0x61616174 or “taaa”. To figure out where this lies in our buffer, we can use pwntools once again. Keep in mind that because of ARM and THUMB mode (discussed two paragraphs down), we will need to add 4 bytes to the result here.
Now that we have our buffer length, we need to find the address we want $pc to point to. As with stack three, there is a function called complete_level that we will want to jump to. In gdb, we get the address using the ‘info functions’ command.
Once we have our buffer lenth and our address we want $pc to jump to, we can create our exploit.
We could run into an issue here. Arm has two addressing modes - Thumb Mode and Arm Mode. The Thumb instruction set conists of 16-bit instructions compared to the standard 32-bit instructions of ARM mode. The choice between these two modes is decided using the Least Significant Bit of our Prgram Counter register. As an example, if we overflow our buffer and provide $pc with the address ‘0x00010545’, $pc will instead continue past our input and exit the function as the LSB of the address is an odd number, telling the processor to take 16 bit instructions.
Luckliy, however, the address we are jumping to has an address ending in an even number, meaning the program will branch to the ‘complete_level’ function.