Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shellcode in C - What does this mean?

Tags:

c

shellcode

I'm not really getting how this code does what it does:

char shellcode[] = "\xbb\x00\x00\x00\x00"           
                   "\xb8\x01\x00\x00\x00"                  
                   "\xcd\x80";                  

int main()
{
    int *ret;
    ret = (int *)&ret + 2;
    (*ret) = (int)shellcode;
}

Okay, I know:

int *ret;

sets a pointer of int. and:

ret = (int *)&ret + 2;

sets the address of ret and 2 bytes (I think.)

But I don't get what this means:

(int *)&ret

I know what &ret means but not what (int *)&ret means. Also, how does it execute the shellcode by assigning the value of shellcode to ret?

UPDATE: What is the difference between:

(int *)&ret  + 2

and:

&ret + 2
like image 695
user1284923 Avatar asked Mar 22 '12 03:03

user1284923


People also ask

Why is it called shellcode?

It is called "shellcode" because it typically starts a command shell from which the attacker can control the compromised machine, but any piece of code that performs a similar task can be called shellcode.

What is shellcode written in?

In relation to a vulnerability, it's a set of instructions used as a payload. In most cases, the shellcode is written in assembly language. In most situations, a command shell or a Meterpreter shell will be supplied after the target computer has completed the set of instructions.

Why is shellcode written in assembly?

Shellcodes are typically written in assembly language, in order to gain full control on the layout of code and data in stack and heap memory, to make the shellcode more compact, to obfuscate the code, and to perform low-level operations on data representation (Deckard 2005; Foster 2005; Anley et al.

How many bytes is a shellcode?

Linux/x86 - execve(/bin/sh) Shellcode (20 bytes)


1 Answers

The 'string' shellcode contains some machine code of some sort.

The int *ret; defines a variable ret which is a pointer to an int.

The assignment ret = (int *)&ret + 2; makes ret point to a location the size of two int from its own actual location (or address); this is an address in the stack, presumably where the return address of the function (main()) is stored on the stack.

The assignment *ret = (int)shellcode; assigns the address of the shell code to the return address. Therefore, when the main() function exits, the return address is the shell code, which does whatever it does instead of exiting the program normally.

The casts cover up a multitude of sins. The code makes a large number of non-portable assumptions which are probably justified on the target environment but not necessarily anywhere else.


What's the difference between: &ret+2 and (int *)&ret + 2?

Type, mainly; this is one of the multitude of sins mentioned previously. &ret has the type int ** (pointer to pointer to int) instead of int * which is the type of ret itself. Since sizeof(int *) == sizeof(int **) on all actual machines, the cast merely quells a complaint from the compiler (about assigning the wrong type of pointer to ret) without changing the numerical result.

like image 108
Jonathan Leffler Avatar answered Oct 10 '22 11:10

Jonathan Leffler