Let's say we're exploiting buffer overflow in some foo
function. Consider the following stack after overflowing the buffer, stopping at ret
instruction in foo
function:
....
------------------------
"system" fn address <-- stack pointer
------------------------
4 bytes of garbage
------------------------
"bin/sh" address
------------------------
...
After that, when we execute ret
instruction, we'll jump right to the system
function. Then, stack will look like this:
....
------------------------
4 bytes of garbage <-- stack pointer
------------------------
"bin/sh" address
------------------------
...
so, now we are in system
function. Those 4 bytes of garbage are now the return address for system
function, and the values below return address are system
function arguments – in our case it's single *char argument that points to "/bin/sh" string.