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 ?

Original source

Related problems