can anyone explain this code to me?
c, exploit, shellcode, stack
Solution
Apparently, this code attempts to change the stack so that when the `main` function returns, program execution does not return regularly into the runtime library (which would normally terminate the program), but would jump instead into the code saved in the `shellcode` array.
1) `int *ret;`
defines a variable on the stack, just beneath the `main` function's arguments.
2) `ret = (int *)&ret + 2;`
lets the `ret` variable point to a `int *` that is placed two `int`s above `ret` on the stack. Supposedly that's where the return address is located where the program will continue when `main` returns.
2) `(*ret) = (int)shellcode;`
The return address is set to the address of the `shellcode` array's contents, so that `shellcode`'s contents will be executed when `main` returns.
`shellcode` seemingly contains machine instructions that possibly do a system call to launch `/bin/sh`. I could be wrong on this as I didn't actually disassemble `shellcode`.
P.S.: This code is machine- and compiler-dependent and will possibly not work on all platforms.
Reply to your second question:
and what happens if I use ret=(int)&ret +2 and why did we add 2? why not 3 or 4??? and I think that int is 4 bytes so 2 will be 8bytes no?
`ret` is declared as an `int*`, therefore assigning an `int` (such as `(int)&ret`) to it would be an error. As to why 2 is added and not any other number: apparently because this code assumes that the return address will lie at that location on the stack. Consider the following:
This code assumes that the call stack grows downward when something is pushed on it (as it indeed does e.g. with Intel processors). That is the reason why a number is added and not subtracted: the return address lies at a higher memory address than automatic (local) variables (such as `ret`).
From what I remember from my Intel assembly days, a C function is often called like this: First, all arguments are pushed onto the stack in reverse order (right to left). Then, the function is called. The return address is thus pushed on the stack. Then, a new stack frame is set up, which includes pushing the `ebp` register onto the stack. Then, local variables are set up on the stack beneath all that has been pushed onto it up to this point.
Now I assume the following stack layout for your program:
+-------------------------+
| function arguments | |
| (e.g. argv, argc) | | (note: the stack
+-------------------------+ <-- ss:esp + 12 | grows downward!)
| return address | |
+-------------------------+ <-- ss:esp + 8 V
| saved ebp register |
+-------------------------+ <-- ss:esp + 4 / ss:ebp - 0 (see code below)
| local variable (ret) |
+-------------------------+ <-- ss:esp + 0 / ss:ebp - 4
At the bottom lies `ret` (which is a 32-bit integer). Above it is the saved `ebp` register (which is also 32 bits wide). Above that is the 32-bit return address. (Above that would be `main`'s arguments -- `argc` and `argv` -- but these aren't important here.) When the function executes, the stack pointer points at `ret`. The return address lies 64 bits "above" `ret`, which corresponds to the `+ 2` in
ret = (int*)&ret + 2;
It is `+ 2` because `ret` is a `int*`, and an `int` is 32 bit, therefore adding 2 means setting it to a memory location 2 × 32 bits (=64 bits) above `(int*)&ret`... which would be the return address' location, if all the assumptions in the above paragraph are correct.
Excursion: Let me demonstrate in Intel assembly language how a C function might be called (if I remember correctly -- I'm no guru on this topic so I might be wrong):
// first, push all function arguments on the stack in reverse order:
push argv
push argc
// then, call the function; this will push the current execution address
// on the stack so that a return instruction can get back here:
call main
// (afterwards: clean up stack by removing the function arguments, e.g.:)
add esp, 8
Inside main, the following might happen:
// create a new stack frame and make room for local variables:
push ebp
mov ebp, esp
sub esp, 4
// access return address:
mov edi, ss:[ebp+4]
// access argument 'argc'
mov eax, ss:[ebp+8]
// access argument 'argv'
mov ebx, ss:[ebp+12]
// access local variable 'ret'
mov edx, ss:[ebp-4]
...
// restore stack frame and return to caller (by popping the return address)
mov esp, ebp
pop ebp
retf
See also: Description of the procedure call sequence in C for another explanation of this topic.
Problem
WARNING: This is an exploit. Do not execute this code. ``` //shellcode.c char shellcode[] = "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; int main() { int *ret; //ret pointer for manipulating saved return. ret = (int *)&ret + 2; //setret to point to the saved return //value on the stack. (*ret) = (int)shellcode; //change the saved return value to the //address of the shellcode, so it executes. } ``` can anyone give me a better explanation ?