The program is shown in the similar thread here.
Let's assume that my OS doesn't implement ASLR or other protections from buffer overflow.
Long story short, the author is spawning a child process from a parent process and passing the buffer created by the parent process to the child to overwrite the return address on the child stack to spawn a shell. So far so good.
The thing that I have troubles with understanding is that the return address is calculated in the parent process, i.e.:
ret = (unsigned int) &i - offset; // Set return address
This return address is the address of the stack of the parent process, but the child process has its own stack i.e. address space. How did the author conclude that the ret
calculated above will be the approximate location to the nop-sleds / shell on child stack frame as both these stacks are different and not related?
For experimentation, I tried switching off the ASLR temporarily, individually debugged these programs using gdb
and found out that when I set a breakpoint on the main
function the $ESP
always points to 0xffffd02c
for the parent process and 0xffffd04c
for the child process.
The stacks of the two processes are unrelated, but they have the same address (virtual address). The operating system places the stacks of all user processes at the same address (if no ASLR). Even if one program invokes the other. This was actually a great debugging help 10 years ago!
When you know that, how do you determine the "magical" address? You could write a program which prints an address of a stack variable and then write that "magical" address on paper, to use it for all your exploits. But even better, if you invoke the exploitable program from your own program, you already have that "magical address" in your program.