Cubes OFFZONE'24 (reseña) / Sudo Null IT News

Este texto es sólo un pequeño resumen de tres historias inversas sobre mascota conferencias Fuera de la zona 2024. El mismo símbolo de la conferencia es un cubo misterioso (un objeto misterioso con un ojo). Como explican los organizadores sobre los ojos de cubo: “la idea eraque no sólo las personas se sienten atraídas por las nuevas tecnologías y su potencial ilimitado, sino que los artefactos tecnológicos también se sienten atraídos por las personas en respuesta, tratando de comprender la naturaleza irracional del hombre.” Justo a tiempo para “nuevas tecnologías” podría resolverse resolviendo tres problemas inversos.

Las tareas en sí no son alucinantes, sin tediosa fuerza bruta, lógicas, compactas, con pequeños detalles agradables, por lo que respeto a su autor. @revker. Veámoslos en orden de complejidad creciente. Y sí, habrá muchas fotografías. El binario se puede tomar de nubes.

CUB_3_3 = Cubo verde (precio inicial 400)

Datos de leyenda y tarea en la figura.

¿Has intentado alguna vez, querido lector, medir algo sin regla? Entonces digamos 60 centímetros. Difícil, pero posible. Y esa gente vive entre nosotros. Camaradas increíbles: solo estimadlo a ojo y listo. Lo compruebas con una regla y tiene exactamente el tamaño correcto. Y todo gracias a la experiencia (“la hija de los errores difíciles”). En ingeniería inversa, personas respetadas llaman a este método “ojo inverso”. En este caso, no se requieren herramientas complejas; cualquier editor hexadecimal es suficiente (en mi caso WinHex). ¡Vamos!

Veamos los archivos. volcado_verde Y comandos.txt. Al observar el contenido de los comandos, asumimos con confianza que volcado_verde – este es un volcado de sesión del proceso python.exe. Repitamos los primeros cinco comandos para crear una clave aleatoria en una computadora (Crypto es un módulo del famoso paquete pycryptodome que debe instalarse previamente para Python.).

El último comando ingresado en la imagen de arriba: “key, iv” envía el contenido de la clave generada y el vector de inicialización iv a la consola en el formato “(b'…', b'…')” La clave generada será diferente de la clave en el volcado, por lo que buscamos el contenido de la clave por formato (los primeros caracteres “(b'“ya es suficiente) en volcado_verde.

Encontramos dos ocurrencias. El contenido de key y iv es el mismo en ambos, pero tenga en cuenta que en la segunda aparición antes del bloque seleccionado hay una estructura: una determinada dirección (Realmente no importa lo que apunte) y tamaño 63h, que coincide con la longitud de nuestro resultado. Entonces, la clave y el vector son:

Y esta clave se utiliza para cifrar un determinado archivo green_cube.png utilizando el algoritmo AES CBC.

¿Qué tiene de bueno un archivo png? Porque los primeros 16 bytes son una constante. Bueno, casi.

La búsqueda de esta constante en el volcado no fue exitosa. Luego ciframos los primeros 16 bytes del encabezado png con la clave encontrada e intentamos encontrar el encabezado cifrado en el volcado.

Resultado encontrado con estructura similar: dirección (y otra vez Realmente no importa lo que apunte) + tamaño (150560h). Todo lo que queda es descifrar estos datos y obtener la bandera.

El problema resultó ser tan popular que el segundo día de la conferencia los organizadores dejaron de emitir offcoin (moneda acuñada localmente).

Moralidad. Practica el ojo invertido.

CUB_3_4 = Cubo sinusoidal (precio inicial 700)

Datos de leyenda y tarea en la figura.

En el libro “El arte de pensar con claridad» Rolfa Dobelli Hay un pasaje sobre caminos alternativos usando el ejemplo de dos personas. Uno arriesgó su vida y ganó 10 limones en la ruleta rusa, y el otro trabajó duro y ganó los mismos 10 limones en sólo 20 años. Y una persona desde fuera, mirando a estas personas ya ricas, no sabe cuál es la diferencia fundamental entre ellas: en el nivel de riesgo a la hora de adquirir dinero. “¿Cuáles son las rutas alternativas? Todo lo que pudo haber pasado, pero no sucedió. Los caminos alternativos son invisibles para los demás, por eso rara vez pensamos en ellos.” Las vulnerabilidades son caminos alternativos en el mundo digital. Y este problema es un buen ejemplo de ello.

Práctico binario de 64 bits en STL C++. ¿Por qué conveniente? Hay símbolos de depuración, no hay antidepuración, ofuscaciones, etc.

¿Qué hace el programa, además de pedirte que introduzcas un nombre al inicio? Le permite recorrer siete salas CubeRoom (en los símbolos de depuración se usa el nombre “cuberoom”, pero en la consola está escrito como “habitación”). Cuando inicias el programa, nos encontramos en uno de ellos (más precisamente, en el mismo; este momento está codificado), por lo que solo puedes pasar a otros seis. Cada habitación tiene un número (9 dígitos para que sea más fácil de recordar ), que indica cuál pasa a la siguiente. Y una cosa más. Antes de cambiarse de habitación se le pedirá que introduzca un mensaje por si regresa. Aquellos. Al regresar a una habitación visitada, se mostrará el mensaje dejado.

La mayoría de las vulnerabilidades giran en torno a entradas de usuario no validadas. Qué influye aquí el usuario: número, nombre, mensaje. Es más fácil con un número. El número se compara con una lista de números de habitaciones, que se almacena dentro de cada CubeRoom: si hay una coincidencia, pasamos a la siguiente habitación, si no hay coincidencias, nos quedamos en la misma habitación. Aquí no hay engaño. Será más interesante con un nombre.

En la función CubeRoom::GetLastVisitorMessage (muestra un mensaje en la sala visitada), se descubrió que el nombre no está verificado de ninguna manera y puede causar una vulnerabilidad de Path Traversal. La función sprintf trunca el búfer resultante a 255 caracteres. Aquellos. todo el búfer se puede llenar con una entrada muy larga en el formato “/../../../../..///////nombredearchivo” y restarse del archivo.

Pero hay un matiz. ¡Esta rama de código de Path Traversal NUNCA se ejecutará! Porque al cambiar de habitación se le pide constantemente al usuario que ingrese un mensaje (campo de mensaje en la figura siguiente). La entrada vacía no funcionará; siempre se complementará con la cadena “Ninguno”. En una palabra, el campo del mensaje siempre será distinto de cero y la rama de código con una vulnerabilidad requiere un mensaje vacío.

Buena conclusión. La vulnerabilidad existe, pero no es accesible. Entonces veamos el campo de mensaje. Y aquí encontramos la segunda vulnerabilidad. Al mensaje se le asignan 256 bytes y no se lee más que eso. Entonces la pregunta es: si el mensaje tiene exactamente 256 bytes, entonces el final de la línea (cero) se escribirá en el carácter 257 y ¿qué se reescribirá en este caso? En este caso, debe observar la estructura del objeto CubeRoom, donde se encuentra el campo de mensaje.

Almacenamos los siete objetos CubeRoom en el contenedor std::map (después de todo, STL), donde la clave es el número de habitación y el valor es el objeto CubeRoom (en la figura siguiente). El campo de mensaje se encuentra antes de la matriz de conexiones, en la que almacenamos el número de habitaciones a mover. Y si escribimos 256 caracteres en el mensaje, entonces el 257 será el primer byte del primer elemento de la matriz de conexiones. Es decir, el número de la sala de copas es 148395987 (8D857D3h). Y como resultado de reescribir D3 57 D8 08 con cero, obtenemos 00 57 D8 08 = 8D85700h (148395776). Número de habitación inexistente. Pero esto ya es una sorpresa, una sorpresa.

La segunda vulnerabilidad le permite cambiar el número de la habitación y romper la lógica del programa, lo que conducirá a la creación de una habitación inexistente. Esta es la manera de resolver el problema. El caso es que para seleccionar una habitación se utiliza el método std::map::.operador()(gCubo, &número). Su comportamiento estándar en STL es que si un objeto no se encuentra por clave (y en nuestro caso, la clave es el número de habitación), entonces std::map agregará un nuevo elemento “clave = objeto CubeRoom” a su colección. Y según el diseñador, el nuevo CubeRoom tendrá todos los campos VACÍOS (en la imagen de abajo), excepto el nombre. Luego de seleccionar una habitación se ejecuta la función CubeRoom::GetLastVisitorMessage, y con un mensaje vacío podemos leer el archivo flag.txt.

El lector observador prestará atención a la función CubeRoom::IsVisited. El CubeRoom creado no se puede visitar ya si el indicador is_visited en el objeto es cero. Simplemente, CubeRoom::IsVisited toma una decisión no sólo basándose en la bandera, sino también en la presencia del campo de nombre (se inicializa en el nuevo objeto).

Algoritmo de solución:

  1. Ejecute blue_code

  2. Indique su nombre “../../../../../..////////////////////////////// ///flag.txt” (254 caracteres)

  3. Nos encontramos en la habitación 987133987 (este es un número codificado, siempre comenzamos aquí)

  4. Ingrese el siguiente número de habitación 148395987

  5. Dejamos un mensaje para la habitación 987133987 – “AAA…AAA” (256 caracteres), con lo que cambiar el primer número en la lista de números de sala de copa (148395987 se convertirá en 148395776)

  6. Nos encontramos en la habitación 148395987

  7. Introduce el siguiente número de habitación 987133987 (volver atrás)

  8. Deje un mensaje para la sala 148395987 – cualquiera

  9. Nos encontramos en la habitación 987133987 (y aquí la lista de números en la pantalla de la consola comienza con 148395776)

  10. Introduce el número de la siguiente habitación. 148395776 (se creará con campos vacíos)

  11. Dejamos mensaje para la habitación 987133987 – aquí ya indicamos cualquiera

  12. Nos encontramos en la habitación 000 (en la habitación 148395776 la lista de números no está inicializada) y lea el archivo flag.txt

Por supuesto, flag.txt estaba en el servidor de los organizadores. De donde fue necesario sacarlo, decidiendo en el camino POW (Prueba de Trabajo). En el segundo día de la conferencia, el desafío se convirtió en un éxito justo. Porque al recibir mercadería en una tienda local, el lema de los acosadores era: “Hay botín: habrá un mercado. Sin botín, sin bazar».

Moraleja: busque formas alternativas, a los inversores/pentesters se les paga por esto.

CUB_3_2 = Cubo rojo (precio inicial 2000)

Datos de leyenda y tarea en la figura.

Final. Una tarea rica en monedas. Pero el precio no siempre implica complejidad. El problema se resolvió tras finalizar la conferencia en un ambiente familiar tranquilo y parecía bastante sencillo.

Las primeras pruebas se realizaron con la carga elemental de un binario en Ida. Así es como se ve el punto de entrada con la dirección 404670h al programa:

Instrucciones atípicas para el prólogo de funciones, especialmente al inicio. ¿Es realmente una especie de empaquetador? Simplemente no es algo muy agradable, como el manuscrito Voynich. Una de las razones por las que el problema se solucionó tras el suceso.

Al final no se descubrió nada malo. Ésta es la llamada “contraidea”. Un medio para confundir a los usuarios que trabajan con IDA, se podría decir, una característica para un desensamblador específico al procesar archivos ELF. Se trata de procesar las tablas PHT (Tabla de encabezados de programa) y SHT (Tabla de encabezados de sección). En el sistema operativo, el cargador de archivos ejecutables siempre se basa en la tabla de encabezados del programa PHT, mientras ignora la tabla de encabezados de la sección SHT. Ida, por otro lado, intenta abarcar ambos lados del pasillo analizando tanto PHT como SHT al crear segmentos. Prestando más atención a SHT. Y aquí es donde los SHT especialmente preparados conducen a artefactos divertidos.

En nuestro caso, PHTEntry 1 es un segmento de código de la dirección virtual 401000, y SHTEntry 1 también apunta a un segmento de código, pero desde la dirección virtual 4010BF. Como resultado, obtendremos dos segmentos: 401000 (Ida lo recortará al tamaño BFh) y 4010BF (tamaño 1784DEh, como en SHTEntry 1), y los datos en ellos se proyectarán desde el mismo lugar, comenzando desde el desplazamiento del archivo. 1000h. Resulta que los primeros bytes BFh coincidirán en ambos segmentos, y el punto de entrada 404670h se desplazará exactamente en bytes BFh y caerá en el medio de una determinada función. En realidad, el segmento de datos debería comenzar en la dirección 57A000 (es decir, PHTEntry 2), pero SHTEntry 2 en realidad apunta al encabezado del archivo 400000h (es decir, PHTEntry 0). Así es como se ve la imagen en la versión 7.7/8.4. Y en la versión 6.95, Ida se centra principalmente sólo en SHT al crear segmentos, sin prestar atención al resto de PHTEntry.

Solo hay una salida: parchear la entrada SHT para una carga correcta. Una foto más.

Hemos solucionado la carga en Ida.

Volvamos a la tarea. Un binario sin información de depuración, STL C++ incluido junto con un ensamblado estático (lo que explica el gran tamaño del archivo ejecutable). Cuando se inicia el programa, se le solicita que ingrese una contraseña de 18 caracteres. Además, al inicio, se crea un objeto que consta de 6 matrices de tamaño 4×4, a partir de 6 cuadrados. Los cuadrados están llenos de números al principio. Marquemos especialmente los ceros en la figura; habrá exactamente 18 según la cantidad de caracteres de la contraseña. Estas posiciones se establecerán en valores basados ​​en los caracteres de la contraseña.

Entonces, ¿por qué necesitamos estos cuadrados? Veremos su significado en la comprobación final antes de pasar la bandera, situada en la función 404C7Ch. La propia prueba confirma que la plaza es mágica.

Los cuadrados mágicos tienen más de 4000 años. Algo antiguo: desde la antigua China, India hasta la Edad Media y hoy (más detalles aquí). Los cubos OffZone también son mágicos, también se agregaron aquí. En nuestro caso, el cuadrado es de 4×4.

Resolvamos el cuadrado mágico usando el ejemplo del primero de los seis. Denotamos elementos cero (de arriba a abajo) como x, y, z. Alrededor de la tabla habrá sumas de filas, columnas y dos diagonales.

La suma en todas las direcciones debe ser igual e igual a 8С00h para un cuadrado dado. Es fácil calcular que x=2000h, y=3000h, z=1000h. En el mismo estilo encontraremos todos los demás valores. Aunque para los perezosos escribiremos un script usando el segundo cuadrado como ejemplo (basado en la biblioteca simpático).

from sympy import symbols, Eq, solve

x, y, z = symbols('x,y,z')

M = (
    0x27F6, 0x33F3, x, 0x0BFD,
    0x43EF, y, 0x23F7, 0x37F2,
    0x13FB, 0x4FEC, 0x2BF5, 0x1FF8,
    0x2FF4, z, 0x17FA, 0x4BED
)

equations = (
    Eq(M(0)+M(5)+M(10)+M(15), M(3)+M(6)+M(9)+M(12)), #sum diag1 == sum diag2
    Eq(M(0)+M(5)+M(10)+M(15), M(0)+M(1)+M(2)+M(3)), #sum diag1 == sum row 0
    Eq(M(0)+M(1)+M(2)+M(3), M(0)+M(4)+M(8)+M(12)), #sum row 0 == sum col 0
    Eq(M(0)+M(4)+M(8)+M(12), M(2)+M(6)+M(10)+M(14)), #sum col 0 == sum col 2
    Eq(M(2)+M(6)+M(10)+M(14), M(3)+M(7)+M(11)+M(15)), #sum col 2 == sum col 3
    Eq(M(0)+M(4)+M(8)+M(12), M(1)+M(5)+M(9)+M(13)), #sum col 0 == sum col 1
    Eq(M(0)+M(1)+M(2)+M(3), M(8)+M(9)+M(10)+M(11)), #sum row 0 == sum row 2
    Eq(M(4)+M(5)+M(6)+M(7), M(12)+M(13)+M(14)+M(15)), #sum row 1 == sum row 3
    Eq(M(0)+M(1)+M(2)+M(3), M(4)+M(5)+M(6)+M(7)), #sum row 0 == sum row 1
)

solution = solve(equations)
print("x = %Xh (%d)" % (solution(x), solution(x)))
print("y = %Xh (%d)" % (solution(y), solution(y)))
print("z = %Xh (%d)" % (solution(z), solution(z)))

De esta manera obtenemos todos los valores de los caracteres de contraseña convertidos (en la figura siguiente). La mayor parte del problema ha sido resuelta. Sólo queda un poco por hacer: descubrir cómo convertir símbolos.

El diagrama de conversión de caracteres de contraseña se muestra en la siguiente figura. Todo el poder está en el generador pseudoaleatorio, para lo cual es necesario averiguar el valor inicial (semilla). La implementación del generador se puede encontrar en la fuente libc de freebsd “random.c” (por ejemplo, aquí).

La contraseña encontrada es “JfivkLA49f0LawFp1C”. El contenido del flag.txt no se pudo leer; el concurso ya había finalizado.

Moraleja: contraidea (un desensamblador puede convertirse en tu enemigo, dificultando la tarea)

Epílogo

Parafraseando al personaje principal de Forrest Gump, podemos decir: “Los rompecabezas inversos son como una caja de bombones: nunca sabes qué relleno te encontrarás”. Pruebas, vanidad, juegos mentales, tiempo perdido, tiempo bien empleado, algo nuevo, algo viejo olvidado, comprender lo oculto, ocultar lo comprensible, fuerza bruta, desaliento, simplemente utsatsuga. Y todavía estamos esperando nuevas tareas en la próxima conferencia.

El informe está terminado.

PD: Un epígrafe extremo para aquellos maestros que fueron escuchados y comunicados al escribir este texto, especialmente cuando guardaron silencio.

Una vez, un transeúnte se acercó al Buda y le preguntó: “¿Puedes decirme la verdad sin usar palabras, pero sin desperdiciarlas?”

Buda permaneció en silencio.

El hombre se inclinó y agradeció al Buda: “Gracias a tu más elevada misericordia, me deshice de todas las cadenas e ilusiones y entré en el Camino”.

Cuando el hombre se fue, Ananda, el discípulo más cercano, le preguntó al Buda:

– Entonces, ¿por qué recibió la vista?

– ¡Un buen caballo sólo empieza a galopar al ver la sombra del látigo! – respondió Buda.

¡Lo más íntimo y sutil siempre se transmite más allá de las palabras, los gestos y los tratados! Pero, ¿significa esto que basta con estar cerca del maestro, observar cómo guarda un silencio significativo e inmediatamente ver toda la profundidad de la existencia? Por supuesto que no. Es importante que la conciencia de una persona esté preparada para esto y que el maestro solo dé un pequeño empujón.

Del libro “Diálogos de sabios chinos” de Alexei Maslov

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *