tags:

views:

348

answers:

8

Source: http://milw0rm.org/papers/145

#include <stdio.h>
#include <stdlib.h>

int main()
{
 char scode[]="\x31\xc0\xb0\x01\x31\xdb\xcd\x80";
 (*(void(*) ()) scode) ();
}

This papers is tutorial about shellcode on Linux platform, however it did not explain how the following statement "(*(void(*) ()) scode) ();" works. I'm using the book "The C Language Programming Reference, 2ed by Brian.W.Kernighan, Dennis.M.Ritchie" to lookup for an answer but found no answer. May someone can point to the right directions, maybe a website, another C reference book where I can find an answer.

+1  A: 

The character array contains executable code and the cast is a function cast.

(*(void(*) ()) means "cast to a function pointer that produces void, i.e. nothing. The () after the name is the function call operator.

Greg Mattes
+13  A: 

Its machine code (compiled assembly instructions) in scode then it casts to a callable void function pointer and calls it. GMan demonstrated an equivalent, clearer approach:

typedef void(*void_function)(void);
int main()
{
  char scode[]="\x31\xc0\xb0\x01\x31\xdb\xcd\x80";
  void_function f = (void_function)scode;
  f(); //or (*f)();
}

scode contains x86 machine code which disassembles into (thanks Michael Berg)

31 c0        xor    %eax,%eax
b0 01        mov    $0x1,%al
31 db        xor    %ebx,%ebx
cd 80        int    $0x80

This is the code for a system call in Linux (interrupt 0x80). According to the system call table, this is calling the sys_exit() system call (eax=1) with parameter 0 (in ebx). This causes the process to exit immediately, as if it called _exit(0).

Jonathan Leffler pointed out that this is most commonly used to call shellcode, "a small piece of code used as the payload in the exploitation of a software vulnerability." Thus, modern OSes take measures to prevent this.

If the stack is non-executable, this code will fail horribly. The shell code is loaded into a local variable in the stack, and then we jump to that location. If the stack is non-executable, then a CPU fault of some kind will occur as soon as the CPU tries to execute the code, and control will be shifted into the kernel's interrupt handlers. The kernel will then kill the process in an abnormal fashion. One case where the stack might be non-executable would be if you're running on a CPU that supports Physical Address Extensions, and you have the NX (non-executable) bit set in your page tables.

There may also be instruction cache issues on some CPUs -- if the instruction cache hasn't been flushed, the CPU may read stale data (instead of the shell code we explicitly loaded into the stack) and start executing random instructions.

Dustin Getz
+6  A: 

What this code does is assign some machine code (the bytes in scode) then it converts the address of that code into a function pointer of type void function () then calls it.

In C/C++, this function's type definition is expressed:

typedef void (* basicFunctionPtr) (void);
Nick Bedford
caf
+3  A: 

scode is an address. (void(*)()) casts scode to a function returning void and accepting no parameters. The leading * calls the function pointer, and the trailing () indicates that no arguments are given to the function.

Mark Rushakoff
+6  A: 

In C:

(some_type) some_var

casts some_var to be of type some_type.

In your code sample "void(*) ()" is the some_type and is the signature for a function pointer that takes no arguments and returns nothing. "(void(*) ()) scode" casts scode to be a function pointer. "(*(void(*) ()) scode)" dereferences that function pointer. And the final () calls the function defined in scode.

And the bytes in scode disassemble to the following i386 assembly:

   31 c0        xor    %eax,%eax
   b0 01        mov    $0x1,%al
   31 db        xor    %ebx,%ebx
   cd 80        int    $0x80
Michael Berg
This shell code is calling the `sys_exit()` system call with parameter 0. It should also be noted that if the stack is non-executable (e.g. using the NX bit with Physical Address Extensions on a CPU supporting PAE), this will fail horribly.
Adam Rosenfield
+1  A: 

The characters encoded in scode are the char/byte representations of some compiled assembly code. The code you have posted takes that assembly, encoded as characters for simplicity, and then calls that string as a function.

The assembly seems to translate out to:

xor %eax,
%eax mov $0x1,
%al xor %ebx,
%ebx int $0x80

Yup, that would indeed create a shell in Linux.

gdc
+2  A: 

To learn a lot more about shell-coding technique, look at the book:

The Shellcoder's Handbook, 2nd Edn

There are several other similar books as well - I think this is the best, but could be persuaded otherwise. You can also find numerous related resources with Google and "shellcoder's handbook" (or your search engine of choice, no doubt).

Jonathan Leffler
+5  A: 

A typedef helps:

// function that takes and returns nothing
typedef void(*generic_function)(void);

// cast to function
generic_function f = (generic_function)scode;

// call
(*f)();

// same thing written differently:
// call
f();
GMan