We have now established that we can jump (modifying EIP) to any point in memory. We may want to jump to a function in our program, or a function in a library included in our program. For jumping inside a function we will need to prepare the parameters on the stack for the function to execute properly.
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
} // content of %eax is returned
void main() {
printf("0x%x\n", get_sp());
}
With this code we can have the ESP of the get_sp function that will be similar to the main one, In general it is difficult to get the actual value of ESP, but we can make a good guess about it. The NOPsled technique can help if we do not know precisely where our code will be placed
The hystorical objectiva was to spawn a privileged shell
runnign a so called shellcode
In linux we could use a command like execve
For launching the needed system call we need to fire an interrupt.
ex: we use an int
op with code 0x80
The parameters we will need to pass to execve
are the following:
If we disassemble the function __execve
we know that
the function pass the parameters through the registers and then
calls int 0x80
movl $0xb,%eax
movl 0x8(%ebp),%ebx
movl 0xc(%ebp),%ecx
movl 0x10(%ebp),%edx
int $0x80
Then we could use this code for our shellcode
The problem is that we need to have the address of the string for argv[0]
to pass it as parameter.
But now we have already the possibility of running code,
so we can get the machine will in the address on its own.
The trick used is jump and call
For which we use the jmp
op with the offset to call
function
the call function jumps again to the second instruction (pop)
Then we pop the ADDRESS from stack to ESI register,
then we have the ADDRESS to use to build the parameters for the execve
The 0 bytes in the assembly code create problems with screen operations,
to avoid this we can use the jmp short
instruction instead of jmp
The problem with 0 is that since we use C string functions to manipulate
our exploit code, the function may terminate the string when they find
a NULL byte (0x00 or /0), that usually terminates strings.