En este post la solución a uno de los retos de 'reversing' de la plataforma RingZer0 Team.
Este reto tiene el título "Windows x86 Reversing is cool!" y mi valoración sobre su dificultad es: ★★☆☆☆.
Su enunciado dice lo siguiente:
The key of this challenge is to understood what`s going on.
Y nos dan un archivo ejecutable (1231fa8523f32a9118993946bccfb9ec203.exe).
Solución: Ejecuto este fichero y se me pide que introduzca una clave:
Introduzco una cadena cualquiera de caracteres y dígitos, por ejemplo: "abc123", y se muestra un mensaje de error:
Utilizo OllyDbg para realizar un análisis dinámico de la aplicación. Abro en esta herramienta el archivo ejecutable y empiezo el análisis buscando todas las cadenas de texto o 'strings' utilizadas en el programa (en la parte superior izquierda de la ventana principal: clic botón derecho, 'Search for' > 'All referenced strings'):
Y obtengo lo siguiente:
Como se observa en la figura anterior, entre las cadenas de texto está el mensaje de error que me ha aparecido al ejecutar el programa: "Wrong Key!". Si hago doble clic sobre este mensaje voy a la parte del código donde se encuentra esta cadena de texto:
Dos líneas más arriba de la instrucción en 0x0040140B, veo una instrucción que comparará la longitud de la cadena que introduzca como clave con 6, y la instrucción que está justo debajo de ésta (JE) no saltará a la instrucción indicada si dicha longitud es diferente de 6 y, en ese caso, se mostrará el mensaje de error. Es decir, la longitud de la clave correcta es 6.
Para ver lo que he dicho en el párrafo anterior pongo un punto de interrupción en la instrucción de salto condicional (JE) en 0x00401409. Reinicio la ejecución en modo depuración e introduzco nuevamente la cadena "abc123" como clave:
En las figuras anteriores veo que el registro ECX contiene la dirección a partir de la cual se almacena la cadena de caracteres que he introducido como clave y el registro EAX contiene la longitud de ésta, y, en consecuencia, como el valor de este último registro es igual a 6, en la instrucción en la que he puesto el punto de interrupción se producirá el salto a la dirección 0x0040146F.
A continuación el programa se introduce en un bucle que ejecuta 6 veces (longitud de la cadena incluida como clave y también de la correcta) y realiza una operación XOR entre cada uno de los caracteres de la cadena incluida como clave y el valor D3 en hexadecimal (211 en decimal).
Para ver esto último pongo un punto de interrupción en la instrucción de salto condicional (JB) en 0x00401483 y continúo con la ejecución en modo depuración hasta ese 'breakpoint':
En las figuras anteriores se ve que el registro EBX contiene el valor 0 y el registro EAX contiene la longitud de la cadena que he introducido como clave, y, en consecuencia, como el valor contenido en EBX es menor que 6, en la instrucción en la que he puesto el punto de interrupción se producirá el salto a la dirección 0x00401423.
A partir de la dirección a la que se produce el salto el programa realizará una operación XOR entre el primer carácter de la cadena incluida como clave (el código ASCII en hexadecimal de "a" es 61, en decimal 97) y el valor D3 en hexadecimal (211 en decimal).
Posteriormente el programa comparará el resultado de esa operación XOR con un valor determinado y si ambos son distintos se mostrará el mensaje de error, mientras que si ambos son iguales se continuará con el segundo carácter de la clave introducida, y así sucesivamente.
Para verlo pongo dos puntos de interrupción, el primero en la instrucción que realiza la operación XOR y el segundo en la instrucción de salto condicional (JE) en función de si el resultado de dicha operación es igual a un valor determinado o no.
Como se ve en las figuras anteriores:
1.- En la instrucción XOR en 0x00401430 se almacena en DX el resultado de la operación:
2.- En la instrucción CMP en 0x0040144E se compara el valor de AL (97 en hexadecimal) con el valor de DL (B2 en hexadecimal).
3.- Como AL y DL son diferentes no se produce el salto en la instrucción JE en 0x00401450 y se mostrará el mensaje de error.
Por tanto, me queda claro que el primer carácter de la clave tiene que ser el resultado de:
El carácter correspondiente al código ASCII 44 en hexadecimal (68 en decimal) es "D".
Como he introducido como clave una cadena cualquiera ("abc123") y, como era más que probable, el resultado de la operación XOR del primer carácter ("a", 61 en hexadecimal) con D3 no es igual que el esperado por el programa (97 en hexadecimal), tal y como ya he dicho, el programa finalizará mostrando el mensaje de error. Para evitar esto último y poder calcular los 5 caracteres restantes de la clave correcta hago lo siguiente:
1.- Tras la primera operación XOR modifico DL poniendo 97 en lugar de B2:
Con lo que el programa realizará la operación XOR entre el segundo carácter de la clave introducida ("b", en hexadecimal 62) y D3, almacenándose el resultado en DX:
Después se comparará AL (E0) con DL (B1), por lo que el segundo carácter de la clave tiene que ser el resultado de:
El carácter correspondiente al código ASCII 33 en hexadecimal (51 en decimal) es "3".
2.- Tras la segunda operación XOR modifico DL poniendo E0 en lugar de B1:
Con lo que el programa realizará la operación XOR entre el tercer carácter de la clave introducida ("c", en hexadecimal 63) y D3, almacenándose el resultado en DX:
Después se comparará AL (EB) con DL (B0), por lo que el tercer carácter de la clave tiene que ser el resultado de:
El carácter correspondiente al código ASCII 38 en hexadecimal (56 en decimal) es "8".
3.- Tras la tercera operación XOR modifico DL poniendo EB en lugar de B0:
Con lo que el programa realizará la operación XOR entre el cuarto carácter de la clave introducida ("1", en hexadecimal 31) y D3, almacenándose el resultado en DX:
Después se comparará AL (A0) con DL (E2), por lo que el cuarto carácter de la clave tiene que ser el resultado de:
El carácter correspondiente al código ASCII 73 en hexadecimal (115 en decimal) es "s".
4.- Tras la cuarta operación XOR modifico DL poniendo A0 en lugar de E2:
Con lo que el programa realizará la operación XOR entre el quinto carácter de la clave introducida ("2", en hexadecimal 32) y D3, almacenándose el resultado en DX:
Después se comparará AL (B8) con DL (E1), por lo que el quinto carácter de la clave tiene que ser el resultado de:
El carácter correspondiente al código ASCII 6B en hexadecimal (107 en decimal) es "k".
5.- Finalmente, tras tras la quinta operación XOR modifico DL poniendo B8 en lugar de E1:
Con lo que el programa realizará la operación XOR entre el sexto carácter de la clave introducida ("3", en hexadecimal 33) y D3, almacenándose el resultado en DX:
Después se comparará AL (E1) con DL (E0), por lo que el sexto carácter de la clave tiene que ser el resultado de:
El carácter correspondiente al código ASCII 32 en hexadecimal (50 en decimal) es "2".
Por tanto, la clave correcta es "D38sk2". Ejecuto el programa e introduzco esta clave:
Y para superar este reto lo único que me falta por hacer es introducir la flag en la plataforma:
Este reto tiene el título "Windows x86 Reversing is cool!" y mi valoración sobre su dificultad es: ★★☆☆☆.
Su enunciado dice lo siguiente:
The key of this challenge is to understood what`s going on.
Y nos dan un archivo ejecutable (1231fa8523f32a9118993946bccfb9ec203.exe).
Solución: Ejecuto este fichero y se me pide que introduzca una clave:
Introduzco una cadena cualquiera de caracteres y dígitos, por ejemplo: "abc123", y se muestra un mensaje de error:
Utilizo OllyDbg para realizar un análisis dinámico de la aplicación. Abro en esta herramienta el archivo ejecutable y empiezo el análisis buscando todas las cadenas de texto o 'strings' utilizadas en el programa (en la parte superior izquierda de la ventana principal: clic botón derecho, 'Search for' > 'All referenced strings'):
Y obtengo lo siguiente:
Dos líneas más arriba de la instrucción en 0x0040140B, veo una instrucción que comparará la longitud de la cadena que introduzca como clave con 6, y la instrucción que está justo debajo de ésta (JE) no saltará a la instrucción indicada si dicha longitud es diferente de 6 y, en ese caso, se mostrará el mensaje de error. Es decir, la longitud de la clave correcta es 6.
Para ver lo que he dicho en el párrafo anterior pongo un punto de interrupción en la instrucción de salto condicional (JE) en 0x00401409. Reinicio la ejecución en modo depuración e introduzco nuevamente la cadena "abc123" como clave:
En las figuras anteriores veo que el registro ECX contiene la dirección a partir de la cual se almacena la cadena de caracteres que he introducido como clave y el registro EAX contiene la longitud de ésta, y, en consecuencia, como el valor de este último registro es igual a 6, en la instrucción en la que he puesto el punto de interrupción se producirá el salto a la dirección 0x0040146F.
A continuación el programa se introduce en un bucle que ejecuta 6 veces (longitud de la cadena incluida como clave y también de la correcta) y realiza una operación XOR entre cada uno de los caracteres de la cadena incluida como clave y el valor D3 en hexadecimal (211 en decimal).
Para ver esto último pongo un punto de interrupción en la instrucción de salto condicional (JB) en 0x00401483 y continúo con la ejecución en modo depuración hasta ese 'breakpoint':
A partir de la dirección a la que se produce el salto el programa realizará una operación XOR entre el primer carácter de la cadena incluida como clave (el código ASCII en hexadecimal de "a" es 61, en decimal 97) y el valor D3 en hexadecimal (211 en decimal).
Posteriormente el programa comparará el resultado de esa operación XOR con un valor determinado y si ambos son distintos se mostrará el mensaje de error, mientras que si ambos son iguales se continuará con el segundo carácter de la clave introducida, y así sucesivamente.
Para verlo pongo dos puntos de interrupción, el primero en la instrucción que realiza la operación XOR y el segundo en la instrucción de salto condicional (JE) en función de si el resultado de dicha operación es igual a un valor determinado o no.
Como se ve en las figuras anteriores:
1.- En la instrucción XOR en 0x00401430 se almacena en DX el resultado de la operación:
00000061 XOR FFFFFFD3 = FFFFFFB2
2.- En la instrucción CMP en 0x0040144E se compara el valor de AL (97 en hexadecimal) con el valor de DL (B2 en hexadecimal).
3.- Como AL y DL son diferentes no se produce el salto en la instrucción JE en 0x00401450 y se mostrará el mensaje de error.
Por tanto, me queda claro que el primer carácter de la clave tiene que ser el resultado de:
97 XOR D3 = 44
El carácter correspondiente al código ASCII 44 en hexadecimal (68 en decimal) es "D".
Como he introducido como clave una cadena cualquiera ("abc123") y, como era más que probable, el resultado de la operación XOR del primer carácter ("a", 61 en hexadecimal) con D3 no es igual que el esperado por el programa (97 en hexadecimal), tal y como ya he dicho, el programa finalizará mostrando el mensaje de error. Para evitar esto último y poder calcular los 5 caracteres restantes de la clave correcta hago lo siguiente:
1.- Tras la primera operación XOR modifico DL poniendo 97 en lugar de B2:
Con lo que el programa realizará la operación XOR entre el segundo carácter de la clave introducida ("b", en hexadecimal 62) y D3, almacenándose el resultado en DX:
00000062 XOR FFFFFFD3 = FFFFFFB1
Después se comparará AL (E0) con DL (B1), por lo que el segundo carácter de la clave tiene que ser el resultado de:
E0 XOR D3 = 33
El carácter correspondiente al código ASCII 33 en hexadecimal (51 en decimal) es "3".
2.- Tras la segunda operación XOR modifico DL poniendo E0 en lugar de B1:
Con lo que el programa realizará la operación XOR entre el tercer carácter de la clave introducida ("c", en hexadecimal 63) y D3, almacenándose el resultado en DX:
00000063 XOR FFFFFFD3 = FFFFFFB0
Después se comparará AL (EB) con DL (B0), por lo que el tercer carácter de la clave tiene que ser el resultado de:
EB XOR D3 = 38
El carácter correspondiente al código ASCII 38 en hexadecimal (56 en decimal) es "8".
Con lo que el programa realizará la operación XOR entre el cuarto carácter de la clave introducida ("1", en hexadecimal 31) y D3, almacenándose el resultado en DX:
00000031 XOR FFFFFFD3 = FFFFFFE2
Después se comparará AL (A0) con DL (E2), por lo que el cuarto carácter de la clave tiene que ser el resultado de:
A0 XOR D3 = 73
El carácter correspondiente al código ASCII 73 en hexadecimal (115 en decimal) es "s".
4.- Tras la cuarta operación XOR modifico DL poniendo A0 en lugar de E2:
Con lo que el programa realizará la operación XOR entre el quinto carácter de la clave introducida ("2", en hexadecimal 32) y D3, almacenándose el resultado en DX:
00000032 XOR FFFFFFD3 = FFFFFFE1
Después se comparará AL (B8) con DL (E1), por lo que el quinto carácter de la clave tiene que ser el resultado de:
B8 XOR D3 = 6B
El carácter correspondiente al código ASCII 6B en hexadecimal (107 en decimal) es "k".
5.- Finalmente, tras tras la quinta operación XOR modifico DL poniendo B8 en lugar de E1:
Con lo que el programa realizará la operación XOR entre el sexto carácter de la clave introducida ("3", en hexadecimal 33) y D3, almacenándose el resultado en DX:
00000033 XOR FFFFFFD3 = FFFFFFE0
Después se comparará AL (E1) con DL (E0), por lo que el sexto carácter de la clave tiene que ser el resultado de:
E1 XOR D3 = 32
El carácter correspondiente al código ASCII 32 en hexadecimal (50 en decimal) es "2".
Por tanto, la clave correcta es "D38sk2". Ejecuto el programa e introduzco esta clave:
Y para superar este reto lo único que me falta por hacer es introducir la flag en la plataforma:
Comentarios
Publicar un comentario