Solución a los retos criptográficos de Rogerfm.net

- Introducción
- Cripto 1
- Cripto 2
- Cripto 3
- Cripto 4
- Cripto 5
- Cripto 6
- Cripto 7
- Cripto 8
- Cripto 9
- Cripto 10
- Enlaces
Introducción
Los retos de encriptación son muy variados como hemos comentado anteriormente. Aquí tenemos unos buenos ejemplos de ello.
Cripto 1
En este primer nivel nos encontramos con un método de encriptación muy antíguo. Sólo diré como pista, que es de los más antiguos que se conocen.
ozhlofxrlmvhxzorulimrz
Lo primero que suelo hacer en este tipo de retos cuando son solamente letras, es comprobar las dos opciones más típicas, que son el cifrado César y Vigenere. En este caso necesitamos ahondar un poco más, aunque enseguida llegamos a la conclusión de que el cifrado usado es el afín. Un ataque por fuerza bruta nos devuelve la solución y los coeficientes utilizados.
Solución: A=25,B=25 – LASOLUCIONESCALIFORNIA
Fuente: http://www.dcode.fr/chiffre-affine
Cripto 2
En este segundo nivel recordaremos a un general romano muy conocido. Lo complicaremos un poco, sólo lo justo para que cueste algo más de cinco minutos encontrar la clave 🙂
oehoeahhjoexhkzqhfsvzhffhwrhotqk
Lo primero que nos viene a la cabeza es el cifrado César pero no va. Probando varios cifrados por sustitución al final damos con el correcto. De nuevo un ataque por fuerza bruta nos da frutos.
Solución: (3,4,5)/1 – LACLAVEDELASEGUNDAPRUEBAESMEKONG
Fuente: https://www.dcode.fr/chiffre-decalages
Cripto 3
Este nivel también va a ser sencillo. Estos caracteres, pertenecientes a un sistema bastante conocido de encriptado, esconden una palabra que, al introducirla (en minúsculas), nos permitirá superar el nivel.
Investigando un poco llegamos a la conclusión de que se trata del cifrado Francmasón o Pig Pen.
Solución: primates
Fuente: https://www.dcode.fr/chiffre-pig-pen-francs-macons
Cripto 4
Esta prueba es tan simple que la he dividido en dos partes que, aunque de apariencia similar, se resuelven de distinta manera. La clave es la unión de las dos palabras resultantes de descifrar las dos líneas de números y que, juntas, forman una tercera palabra.
0111001101110101011100000110010101110010
0001001110011000111110100100110010010001
La primera parte se puede convertir en bloque:
0111001101110101011100000110010101110010 = super
Fuente: https://www.rapidtables.com/convert/number/binary-to-ascii.html
Para la segunda debemos separar en grupos de 5 dígitos y listo:
00010 01110 01100 01111 10100 10011 00100 10001
C O M P U T E R
Fuente: www.lindau-nobel.org
Cripto 5
Para descubrir la palabra clave sólo se necesita una mínima capacidad de observación.
31 04 40 23 20 34 33 13 23 22
Se trata del cuadrado de Polibio.

Cripto 6
Aquí hay que hacer un poco de trabajo de investigación: Hay que descubrir la clave que empleó un escritor francés (Una pista: «Lagardère») en una de sus novelas, que es la empleada aquí para formar la palabra clave (en minúsculas) que, por cierto, es alemana.
RI3I2MIL2I2A3
POR RESOLVER
Cripto 7
Seguimos con cosas fáciles. Se trata de descifrar este texto escrito en inglés.
kgw qkoev ol 617 qthpreoz iwjpz sdkg kgw pdeyeplk rwqdjzwe ipezwq spbbdq sgo sgwz goqkdbdkdwq iwjpz spq rwkwecdzwr ko cpmw gdq uweqozpb yozkedihkdoz ko kgw spe wlloek
Una vez descifrado, nos será fácil descubrir la clave:
pzpyozrp
Se trata de un cifrado de sustitución mono alfabético.
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ZLMIRVHUBGTFJKOASDWQPYEXCN
THE STORY OF 617 SQUADRON BEGAN WITH THE AIRCRAFT DESIGNER BARNES WALLIS WHO WHEN HOSTILITIES BEGAN WAS DETERMINED TO MAJE HIS PERSONAL CONTRIBUTION TO THE WAR EFFORT
Una vez descifrado el alfabeto la solución queda:
pzpyozrp = anaconda
Cripto 8
A veces, las cosas no son lo que parecen. Donde aparecen unos números, en realidad hay otros números distintos.
273664524572348321143738
853442616537643005319627
POR RESOLVER
Cripto 9
Para resolver algunos problemas, hay que tener una buena base. Este es un buen ejemplo de ello:
ZW50ZXJwcmlzZQ0K
¿Os suena base 64?
Solución: enterprise
Fuente: https://www.base64decode.org/
Cripto 10
Esto es más complicado. Para descifrar este texto que contiene la clave para superar el nivel, se necesita otra clave. Para que no sea demasiado difícil, he utilizado una palabra muy sencilla de sólo cuatro letras 🙂
myiemyuvbaeewcxweghkflxw
Mediante fuerza bruta matamos dos pájaros de un tiro.
lapalabraclaveesdiogenes
Fuente: https://www.guballa.de/vigenere-solver
Enlaces
Keygen para el KeygenMe#01 de eBuC – Comparación lineal

Primeras impresiones
Determinando la rutina de creación del serial con Ollydbg
Generando un serial válido
Como se muestra en la imagen siguiente, la creación del serial es muy sencilla y al final la comparación es lineal ya que se compara nuestro serial con el serial válido. Veamos el serial válido para el usuario “abc” cuyos dígitos en hexadecimal son 0x61, 0x62 y 0x63.
|
Letra a
|
Letra b
|
Letra c
|
|
Suma + 0x61
Suma * 0x20
Suma xor 0xBEFF
Suma / 4
Suma = 0x2CB7
|
Suma + 0x62
Suma * 0x20
Suma xor 0xBEFF
Suma / 4
Suma = 0x14777
|
Suma + 0x63
Suma * 0x20
Suma xor 0xBEFF
Suma / 4
Suma = 0xA116F
|
|
Suma xor 0xBEA4 = 0xAAFCB
|
||
|
Serial válido = 700363
|
||
Generando un keygen con WinASM studio desde cero
- szFormat está declarada en formato integer (%i). Más tarde la utilizaremos junto a la función wsprintf para dar formato a un número.
- szSizeMin: habla por sí misma.
- szSizeMax: habla por sí misma.
- szCap: habla por sí misma.
- szName: contendrá el nombre introducido.
- szCode: contendrá el serial válido.
Enlaces
Solución al Crackme RSA (RSA24) de TSC

Introducción
Esta vez se trata de un crackme realizado en VC++ 5.0/6.0 y en sus entrañas utiliza RSA-24. En este caso la peculiaridad es que el nombre no interviene en la generación del serial siendo un resultado único.
Resumen RSA
Parámetros
p = Primer número primo
q = Segundo número primo
e = Exponente público que cumpla MCD(e,(p-1)*(q-1))==1
n = Módulo público siendo n=p*q
d = Exponente privado que cumpla d=e^(-1) mod ((p-1)*(q-1))
De este modo e y n son la parte pública de la clave y d y n la parte privada. Los número primos p y q se utilizan solo para generar los parámetros y de ahí en adelante se pueden desechar.
Funciones de Cifrado/Descifrado
cifrado = descifrado ^ e mod n
descifrado = cifrado ^ d mod n
OllyDbg
Nuestro primer vistazo con OllyDbg nos muestra cuatro números de los que podemos hacernos una idea de que 9901 es un buen candidato a ser el exponente público (e) y 12790891 el módulo n ya que casualmente es un número de 24 bits. Los otros dos números de momento no nos dicen nada.

A continuación de los números tenemos la rutina de comprobación en la que comprueba que nuestro serial tenga 14 dígitos y lo divide en dos partes de 7 dígitos. Interesante ya que los otros dos números que aparecían en las referencias de texto tienen 7 dígitos cada uno.
004029CD |. 68 DC004200 PUSH RSA24.004200DC ; ASCII "9901"
004029D2 |. 8D8C24 E40000>LEA ECX,[DWORD SS:ESP+E4]
004029D9 |. E8 52E7FFFF CALL RSA24.00401130
004029DE |. 68 D0004200 PUSH RSA24.004200D0 ; ASCII "12790891"
004029E3 |. 8D4C24 1C LEA ECX,[DWORD SS:ESP+1C]
004029E7 |. C78424 640600>MOV [DWORD SS:ESP+664],0
004029F2 |. E8 39E7FFFF CALL RSA24.00401130
004029F7 |. 68 C8004200 PUSH RSA24.004200C8 ; ASCII "8483678"
004029FC |. 8D8C24 740200>LEA ECX,[DWORD SS:ESP+274]
00402A03 |. C68424 640600>MOV [BYTE SS:ESP+664],1
00402A0B |. E8 20E7FFFF CALL RSA24.00401130
00402A10 |. 68 C0004200 PUSH RSA24.004200C0 ; ASCII "5666933"
00402A15 |. 8D8C24 AC0100>LEA ECX,[DWORD SS:ESP+1AC]
00402A1C |. C68424 640600>MOV [BYTE SS:ESP+664],2
00402A24 |. E8 07E7FFFF CALL RSA24.00401130
00402A29 |. 8B9424 680600>MOV EDX,[DWORD SS:ESP+668]
00402A30 |. 83CE FF OR ESI,FFFFFFFF
00402A33 |. 8BFA MOV EDI,EDX
00402A35 |. 8BCE MOV ECX,ESI
00402A37 |. 33C0 XOR EAX,EAX
00402A39 |. C68424 600600>MOV [BYTE SS:ESP+660],3
00402A41 |. F2:AE REPNE SCAS [BYTE ES:EDI]
00402A43 |. F7D1 NOT ECX
00402A45 |. 49 DEC ECX
00402A46 |. 83F9 0E CMP ECX,0E ; serial 0xE chars -> 14 digitos
00402A49 |. 0F85 63010000 JNZ RSA24.00402BB2
00402A4F |. 33C9 XOR ECX,ECX
00402A51 |> 8A0411 /MOV AL,[BYTE DS:ECX+EDX] ; {
00402A54 |. 3C 30 |CMP AL,30
00402A56 |. 0F8C 56010000 |JL RSA24.00402BB2
00402A5C |. 3C 39 |CMP AL,39 ; comprueba que el serial sea numerico
00402A5E |. 0F8F 4E010000 |JG RSA24.00402BB2
00402A64 |. 41 |INC ECX
00402A65 |. 83F9 0E |CMP ECX,0E
00402A68 |.^ 7C E7 \JL SHORT RSA24.00402A51 ; }
00402A6A |. 8BC2 MOV EAX,EDX
00402A6C |. C64424 17 00 MOV [BYTE SS:ESP+17],0 ; {
00402A71 |. C64424 0F 00 MOV [BYTE SS:ESP+F],0
00402A76 |. 8B08 MOV ECX,[DWORD DS:EAX]
00402A78 |. 894C24 10 MOV [DWORD SS:ESP+10],ECX
00402A7C |. 66:8B48 04 MOV CX,[WORD DS:EAX+4]
00402A80 |. 66:894C24 14 MOV [WORD SS:ESP+14],CX
00402A85 |. 8B4A 07 MOV ECX,[DWORD DS:EDX+7]
00402A88 |. 8A40 06 MOV AL,[BYTE DS:EAX+6] ; divide el serial en dos partes de 7 digitos
00402A8B |. 894C24 08 MOV [DWORD SS:ESP+8],ECX
00402A8F |. 884424 16 MOV [BYTE SS:ESP+16],AL
00402A93 |. 8D42 07 LEA EAX,[DWORD DS:EDX+7]
00402A96 |. 8D4C24 10 LEA ECX,[DWORD SS:ESP+10]
00402A9A |. 66:8B50 04 MOV DX,[WORD DS:EAX+4]
00402A9E |. 8A40 06 MOV AL,[BYTE DS:EAX+6] ; }
A continuación hace una serie de operaciones matemáticas para finalmente comparar el resultado con 8483678 y con 5666933. Lo que está haciendo es cifrar con nuestro serial en dos partes para comprobar que tenemos el número descifrado. Veamos un ejemplo con el serial 12345678901234.
descifrado ^ e mod n = cifrado
x1 = 1234567 y x2 = 8901234
1º parte del serial
x1 ^ 9901 mod 12790891 != 8483678
2º parte del serial
x2 ^ 9901 mod 12790891 != 5666933
Obviamente el resultado de las operaciones anteriores no da ese resultado y el Crackme nos tira fuera de modo que no nos queda más que atacar a RSA para obtener los primos p y q y el módulo privado d. De este modo podremos obtener los números buenos.
Los primos p y q se obtienen factorizando (botón Factor N) y una vez que tenemos p y q hallamos d (botón Calc. D). Todo esto es coser y cantar con la ayuda de la herramienta RSA-Tool 2. El exponente público e se introduce en hexadecimal.
Una vez que tenemos d hallamos el serial de forma sencilla con la herramienta Big Integer Calculator.
cifrado ^ d mod n = descifrado
1º parte del serial
8483678 ^ 10961333 mod 12790891 = 7167622
2º parte del serial
5666933 ^ 10961333 mod 12790891 = 3196885
SERIAL = 71676223196885
Enlaces
- RSA (wikipedia)
- Exponenciación modular (wikipedia)
- RSA Tool
- Big Integer Calculator v1.14
- Crackme
Yoire PE Reversing Challenge (Crackme Very Hard)

Saltando el Anti-Debug
Abrimos el crackme con Ollydbg y nos salta una protección Anti-Debug.
Rutina de comprobación del serial
Retomemos analizando la rutina de comprobación.
FLD DWORD PTR DS:[403080] - Carga el entero "720300" en ST7 FSTP [LOCAL.1] - Guarda "720300" en memoria (Local 1) MOVSX EDX,BYTE PTR DS:[EAX] - Coje nuestro primer dígito en ascii y lo carga en EDX SUB EDX,30 - Le resta 30 a EDX PUSH EDX - Carga EDX en la pila FILD DWORD PTR SS:[ESP] - Carga el valor de EDX en ST0 POP EDX - Recupera el valor de la pila FDIVR [LOCAL.1] - Divide Local 1 entre nuestro dígito hex y lo guarda en ST0 FSTP [LOCAL.1] - Guarda el resultado de ST0 en Local 1 INC EAX - Siguiente dígito CMP BYTE PTR DS:[EAX],0 - Comprueba si quedan dígitos en nuestro serial JNZ SHORT 05_crack.004010F4 - Bucle
Después de la rutina de comprobación simplemente comprueba el valor del resultado de la división con 1 y si es verdad serial válido.
Buscando un serial válido
720300 / 2 = 360150 360150 / 2 = 180075 180075 / 5 = 36015 36015 / 5 = 7203 7203 / 3 = 2401 2401 / 7 = 343 343 / 7 = 49 49 / 7 = 7 7 / 7 = 1
Por lo que un serial válido sería: 225537777
La rutina de comprobación del serial podría resumirse también así:
720300 MOD serial = 720300
Links
Blooper Tech Movie II – Hackers

En esta ocasión vamos a hablar de una película de culto de los años 90, Hackers – Piratas Informáticos. La verdad es que aunque puede ser entretenida, tecnológicamente es una pesadilla y es que esta película es un claro ejemplo de cuando Hollywood prefiere agradar visualmente a representar escenas realistas.
Tras cuatro minutos en los que se nos presenta a Dade (Jonny Lee Miller) y sus problemas con la ley a una temprana edad, saltamos unos años después hasta ver a Dade encerrado en su habitación volviendo a las andadas intentando acceder ilegítimamente a los servidores de una cadena de televisión. Para ello hace uso de algo muy conocido en el mundillo Hacker, la Ingeniería Social, y es que aunque ahora disponemos de «cierta» conciencia en seguridad informática, en los años 90 no había ninguna. Bien, el caso es que Dade llama a las oficinas de la citada cadena de televisión a una hora en la que no hay más que el vigilante de seguridad y éste le proporciona un número que debemos suponer que es la IP de un Módem y comienza la intrusión.
BTM
Para empezar, se le ve al protagonista escribir comandos cuando en la pantalla no hay más que una animación en algo parecido a una ventana de terminal al estilo «Commander», pero no vemos lo que escribe, algo irreal.
A continuación y como por arte de magia entra en el sistema y lo que se muestra es una animación parpadeante con el logo de la compañia y el nombre del sistema al que estamos accediendo, también irreal.
Finalmente nos muestra sus intenciones, y son nada más y nada menos que cambiar la programación actual simplemente cambiando de VHS, inmejorable. A continuación os muestro la secuencia.
Por lo menos nos queda el consuelo de que cambia la tertulia de un tipejo con ciertos prejuicios raciales por una programación más interesante como «The Outer limits«, aquí conocida como «Más allá del límite«.
El resto de escenas informáticas de la película carecen de veracidad, la única que se salva, puede ser cuando accede al servidor del Instituto para programar el sistema contra incendios y vengarse de Kate (Angelina Jolie), ya que las imágenes que aparecen son de los primeros entornos gráficos de Mac.
Es extraño que casi todas las intrusiones las realiza desde su propia casa, algo poco inteligente, ya que por muy bueno que seas, siempre dejas huellas. Solo cuando se enfrentan a un Super-Hacker se empiezan a tomar las cosas en serio y realizan los ataques desde cabinas telefónicas.
En la película También hacen mención al Phreaking y a algunos de los libros que eran famosos por aquella época pero poco más que destacar. Por todo esto y mucho más, y aunque me caen igual de bien tanto Angelina como Jonny, la película se merece un majestuoso sello de BTM.
Enlaces
Canyouhack.it – Crack Challenge 4 (Brain Fuck Me)

Aquí tenemos un crackme fuera de lo común, más que nada por que está programado en Brainfuck, un lenguaje de programación esotérico bastante complejo.
[-]>[-]<>++++++++[<++++++++++>-]<.+++++++++++++++++.>+++[<++++++>-]<..++++.- -------.+++.--------------.>++++++[<------>-]<-.>+++++[<------>-]<-.,>,>,>,> >>>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++>>>>+++++++++++++++++++++++++++++++++++++++++ +++++++++++>>>>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++>>>>++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<<< <<<<<<<<<<<<<<<<[>>>>>>>-<<<<<<<-]>>>>>>><<+>>[[-]++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++.<]<[>]<<<<<[>>>>>>>>>>-<<<<<<<< <<-]>>>>>>>>>><<+>>[[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++.<]<[>]<<<<<<<<[>>>>>>>>>>>>>-<<<<<<<<<<<<<-]>>>>>>>>>>>>><<+>>[ [-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .<]<[>]<<<<<<<<<<<[>>>>>>>>>>>>>>>>-<<<<<<<<<<<<<<<<-]>>>>>>>>>>>>>>>><<+>>[ [-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++.<]<[>]>>>[-]>[-]<+++++++++++++.---.>+++++++[<++++++++++++>-]<.>+++++++[< --------->-]<+.>+++++[<++++++++>-]<+.>++++[<+++++++>-]<+.>+++++++[<--------- ->-]<.>++++++++[<+++++++++>-]<+.+++++++++++.>+++++++[<----------->-]<.>+++++ ++[<+++++++++++>-]<-.>+++++++[<------------>-]<+.>++++++++[<+++++++++++>-]<- .-----.---------.+++++++++++..---------------.+++++++++.>++++++[<----------- -->-]<.+++++++.>+++++[<++++++>-]<+.-----.++++++++.+++.>++++++[<------>-]<-.- ------.>++++++++[<++++++++++>-]<-.+++.>+++++++++[<--------->-]<-.+++++++.>++ +++[<++++++>-]<+.-----.+++++++++++.>++++++[<------>-]<-.-------.>++++++++[<+ +++++++++>-]<-.+++.>+++++++++[<--------->-]<-.+++++++.>+++++[<+++++>-]<+.+++ +++++.+++.>++++++[<------>-]<-.+++++++...--------------.>++++++++[<+++++++++ ++>-]<+.----------.++++++.>+++++++[<------------>-]<-.>++++++++[<+++++++++>- ]<.-------.>+++[<+++++++>-]<.-----------------.>+++++++[<---------->-]<+.>++ +++++[<++++++++++>-]<.-----.++++++++.+++.-------.-.>++++++[<--------->-]<.-- ------------.>+++++[<++++++++>-]<+.>++++[<+++++++>-]<+.>+++++++[<----------> -]<.>+++++++[<++++++++++++>-]<.------------.---.+++++++++++++.-------------. >+++++++[<---------->-]<+.>++++++++[<+++++++++>-]<+.++++++++++.>+++++++[<--- --------->-]<+.>++++++[<+++++++++++++>-]<.+.+++++.------------.+.+++++.----- --.>++++++[<---------->-]<+.------------.>++++++++[<+++++++++++>-]<+.------- ---.++++++.>+++++++[<------------>-]<-.>++++++++[<+++++++++>-]<.-------.>+++ [<+++++++>-]<.-----------------.>+++++++[<---------->-]<+.>++++++++[<+++++++ ++++>-]<-.--------------.+++++.>++++++[<------------->-]<.+.
La solución que he encontrado yo, es convertir el código brainfuck a algo más amigable y depurarlo hasta encontrar la solución. La conversión la he realizado con VBBrainFNET y luego la depuración con Visual Studio. El crackme te pide una clave de cuatro cifras para darte la solución, pero si no quieres volverte loco puedes amañar los bucles para encontrar la solución.
¡SUERTE!
Enlaces
Blooper Tech Movie IV – La Jungla 4.0 (Live Free or Die Hard)

La esperada cuarta entrega de La Jungla de Cristal se metió de lleno en el mundo de los Hackers. Cuando la vi en su época he de reconocer que el detalle que explicaremos a continuación me pasó desapercibido.
Hablemos de mineralismo.. digo de IPs privadas
Digamos que a día de hoy, quien más y quien menos, sabe lo que es una IP y para que sirve. Si no lo sabes, digamos resumidamente que es un número que nos identifica dentro de una red. En el protocolo IPv4 son 4 grupos de números entre 0 y 255. Como todo protocolo que se precie, tiene ciertos rangos de direcciones reservados para redes privadas y el resto digamos que son públicas. El rango de direcciones privadas para IPv4 es el siguiente:
- De 10.0.0.0 a 10.255.255.255
- 172.16.0.0 a 172.31.255.255
- 192.168.0.0 a 192.168.255.255
- 169.254.0.0 a 169.254.255.255
BTM
Como hemos hablado en otras ocasiones, en el cine se exagera todo lo relacionado con el mundo tecnológico y en especial el mundo «Hacking«, y es normal encontrarnos elaborados entornos gráficos que quedan muy bien pero que no existen en el mundo real.
En la Jungla 4.0 usaron IPs privadas como públicas sin ton ni son y perdón si me repito pero, ¿nadie contrata consultores?, es decir, vas a realizar una película sobre hackers y ¿no contratas a alguien que tenga unos conocimientos mínimos?, pues al parecer es mucho pedir, las imágenes hablan por si solas.
En la imagen superior se puede ver como están conectados al sistema de ventilación del NDA. Podría pasar si estuvieran físicamente en las instalaciones del NDA y se conectaran desde un equipo de allí, pero al hacerlo de forma remota crean un enorme gazapo.
Esto es una pequeña muestra de lo que muestra la película. También hay escenas en las que se usan IPs públicas correctamente pero en general cometen el error de forma recurrente.
Enlaces
- ¿Qué es una IP? [Wikipedia]
- Redes privadas [Wikipedia]
- La Jungla 4.0 [IMDB]
Canyouhack.it – Cryptography Challenge 13

Los retos criptográficos son muy variados y muchas veces la dificultad está en saber a que te enfrentas. En este caso pasa eso, te dan un código y si no has visto algo parecido en la vida, no sabes por donde empezar. El título del autor da una pequeña pista pero para los desconocedores no es suficiente. La pista es el título y dice «WTF?!?» y el código a descifrar es el siguiente:
[-]>[-]< >+++++++++++[<+++++++++++>-]<. >+++[<--->-]<-. >++[<++>-]<++. +. >++++[<---->-]<-. ---. +++. . >+++[<+++>-]<. >+++[<--->-]<+. >++++[<++++>-]<-. >++++[<---->-]<--. >+++[<+++>-]<-. >++[<-->-]<--. -.
Si eres una persona con recursos, realizaras varias búsquedas por la red y al final llegarás a la conclusión de que te enfrentas a BRAINFUCK, un lenguaje de programación esotérico como ya vimos en el reto de Root-Me.
Enlaces
Digi Logic Challenge

AVISO: Debido a que este reto está en activo no publicaré a donde pertenece.
El reto en cuestión nos presenta un esquema de puertas lógicas y una secuencia binaria que al pasarla por las puertas nos devolverá la solución al reto.
La secuencia binaria es ésta:
110111000001110010010011101100011000001101111110000001011101110011101100011000001101011011111000011010100110111000001010100111111111000101110001010
Lo primero que necesitamos saber es que función realiza cada puerta. Si indagamos un poco enseguida llegamos a la conclusión de que el esquema lo componen 3 puertas NOT, cuatro puertas AND y una puerta OR.
El funcionamiento es muy sencillo, la puerta NOT simplemente invierte el dígito de entrada convirtiendo los unos en ceros y los ceros en unos. La puerta AND siempre dará como resultado cero excepto cuando todos dígitos de entrada sean unos, que dará como resultado uno. La puerta OR es contraria a la AND y siempre dará como resultado uno excepto cuando todos los dígitos de entrada sean ceros, que en este caso dará como resultado cero.

Nota: Aunque lo más normal es encontrarse puertas de dos entradas y una salida, cuando tenemos múltiples entradas el funcionamiento es el mismo pudiendo resolverlo de manera secuencial. Por ejemplo, a la primera puerta AND le entran la pista cuatro, la dos y la tres. La solución es hacer cuatro AND dos y el resultado AND tres -> (cuatro AND dos) AND tres.
Teniendo en cuenta el funcionamiento de las puertas y con la ayuda del esquema anterior podemos automatizar el proceso fácilmente. A continuación os dejo el código en .Net.
Dim encoded As String = "110111000001110010010011101100011000001101111110000001011101110011101100011000001101011011111000011010100110111000001010100111111111000101110001010"
Dim uno, dos, tres, cuatro, cinco, seis As String
Dim w, x, y, z, tmp As Integer
For i = 0 To encoded.Length - 1 Step 3
uno = Mid(encoded, i + 1, 1)
dos = Mid(encoded, i + 2, 1)
tres = Mid(encoded, i + 3, 1)
If uno = "1" Then cuatro = "0"
If uno = "0" Then cuatro = "1"
If dos = "1" Then cinco = "0"
If dos = "0" Then cinco = "1"
If tres = "1" Then seis = "0"
If tres = "0" Then seis = "1"
w = CInt(cuatro And dos) And CInt(tres)
x = CInt(uno And cinco) And CInt(tres)
y = CInt(uno And dos) And CInt(seis)
z = CInt(uno And dos) And CInt(tres)
tmp = (w Or x) Or (y Or z)
txt_s.Text &= tmp.ToString
Next
Obtenemos como resultado: 1100100110100111001111101001111010011000011101100
Si intentamos decodificar la secuencia resultante en bloque no obtenemos ningún resultado pero si tenemos en cuenta que cada letra en binario ocupa siete dígitos enseguida encontramos la solución.
1100100 1101001 1100111 1101001 1110100 1100001 1101100
d i g i t a l
Enlaces
TripleTordo’s Ice9 Keygen

Introducción
Este un crackme muy interesante para principiantes ya que la rutina no es muy compleja. Está hecho en ensamblador.
Saltar el antidebug
Arrancamos el crackme en Olly damos al play y se cierra. Buscamos en las «Intermodular Calls» y vemos «IsDebuggerPresent«, clickamos sobre ella y vemos el típico call, lo NOPeamos.
Aquí vemos el call.
Call Nopeado.
Encontrando un serial válido
Encontrar en serial válido en esta ocasión es muy sencillo, basta con buscar en las «String References» el mensaje de «Bad boy» y fijarse en la comparación.
El algoritmo
Si nos fijamos en el serial generado nos da muchas pistas pero vamos a destriparlo ya que tampoco tiene mucha complicación. De nuevo miramos en las «String references» y clickamos sobre el mensaje de «bad boy«. Encima de los mensajes vemos claramente la rutina de creación del serial.
004010EB |. 83F8 04 CMP EAX,4 ;Longitud del nombre >4 004010EE |. 72 05 JB SHORT Ice9.004010F5 004010F0 |. 83F8 0A CMP EAX,0A ;Longitud del nombre <=10 004010F3 |. 76 15 JBE SHORT Ice9.0040110A 004010F5 |> 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL 004010F7 |. 68 04304000 PUSH Ice9.00403004 ; |Title = "Error, Bad Boy" 004010FC |. 68 1C304000 PUSH Ice9.0040301C ; |Text = "name must be at least 4 chars" 00401101 |. 6A 00 PUSH 0 ; |hOwner = NULL 00401103 |. E8 70010000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA ........ 00401183 . 3BD3 CMP EDX,EBX 00401185 . 74 15 JE SHORT Ice9.0040119C 00401187 . 8A07 MOV AL,BYTE PTR DS:[EDI] 00401189 . 3C 5A CMP AL,5A ;Compara que el dígito < 5A 0040118B . 7E 05 JLE SHORT Ice9.00401192 0040118D > 03C8 ADD ECX,EAX ;ECX + Ascii(dígito) 0040118F . 47 INC EDI 00401190 .^ EB EE JMP SHORT Ice9.00401180 00401192 > 3C 41 CMP AL,41 ;Compara que el dígito > 41 00401194 . 7D 02 JGE SHORT Ice9.00401198 00401196 . EB 02 JMP SHORT Ice9.0040119A 00401198 > 04 2C ADD AL,2C ;Si cumple lo anterior dígito +2C 0040119A >^ EB F1 JMP SHORT Ice9.0040118D 0040119C > 81C1 9A020000 ADD ECX,29A ;ECX + 29A 004011A2 . 69C9 39300000 IMUL ECX,ECX,3039 ;ECX * 3039 004011A8 . 83E9 17 SUB ECX,17 ;ECX - 17 004011AB . 6BC9 09 IMUL ECX,ECX,9 ;ECX * 9 004011AE . 33DB XOR EBX,EBX 004011B0 . 8BC1 MOV EAX,ECX ;Mueve nuestro SUM en EAX 004011B2 . B9 0A000000 MOV ECX,0A ;ECX = A 004011B7 > 33D2 XOR EDX,EDX 004011B9 . F7F1 DIV ECX ;SUM / ECX (Resultado a EAX) 004011BB . 80C2 30 ADD DL,30 004011BE . 881433 MOV BYTE PTR DS:[EBX+ESI],DL 004011C1 . 83C3 01 ADD EBX,1 004011C4 . 83F8 00 CMP EAX,0 004011C7 . 74 02 JE SHORT Ice9.004011CB 004011C9 .^ EB EC JMP SHORT Ice9.004011B7 004011CB > BF C8304000 MOV EDI,Ice9.004030C8 004011D0 > 8A4433 FF MOV AL,BYTE PTR DS:[EBX+ESI-1] 004011D4 . 8807 MOV BYTE PTR DS:[EDI],AL 004011D6 . 47 INC EDI 004011D7 . 4B DEC EBX 004011D8 . 83FB 00 CMP EBX,0 004011DB .^ 75 F3 JNZ SHORT Ice9.004011D0 004011DD . C607 00 MOV BYTE PTR DS:[EDI],0 ;Coje letras del nombre en función 004011E0 . 8D3D B4304000 LEA EDI,DWORD PTR DS:[4030B4] ;del resultado anterior 004011E6 . 68 B7304000 PUSH Ice9.004030B7 ; ASCII "rus" 004011EB . 68 C8304000 PUSH Ice9.004030C8 ; ASCII "134992368rus" 004011F0 . E8 BB000000 CALL Ice9.004012B0 ; Concatena 004011F5 . 68 C8304000 PUSH Ice9.004030C8 ; /String2 = "136325628rus" 004011FA . 68 98314000 PUSH Ice9.00403198 ; |String1 = "12345" 004011FF . E8 98000000 CALL <JMP.&kernel32.lstrcmpA> ; \lstrcmpA
Resumen (valores hexadecimales):
- Len(Nombre ) >=4 y <=A
- Comprueba si el dígito está es mayúsculas y si está le sume 2C al valor ascii.
- Suma el valor ascii de todos los dígitos menos el último.
- SUM + 29A
- SUM * 3039
- SUM – 17
- SUM * 9
Finalmente concatena letras siguiendo este criterio:
- Len(nombre) = 4 -> coje la última letra
- Len(nombre) = 5 -> coje las dos últimas
- Len(nombre) = 6 -> coje las tres últimas
- Len(nombre) = 7 -> coje las cuatro últimas
- Len(nombre) = 8 -> coje las cinco últimas
- Len(nombre) = 9 -> coje las seis últimas
- Len(nombre) = A -> coje las siete últimas
Ejemplo para deurus
d e u r u (s) 64+65+75+72+75 = 225 225 + 29A = 4BF 4BF * 3039 = E4DE87 E4DE87 - 17 = E4DE70 E4DE70 * 9 = 80BD1F0 ;Pasamos a decimal y concatenamos 134992368rus
Ejemplo para Deurus
D e u r u (s) 44(+2C)+65+75+72+75 = 25D 25D + 29A = 4F7 4BF * 3039 = EF6AFF EF6AFF - 17 = EF6AE8 EF6AE8 * 9 = 86AC228 ;Pasamos a decimal y concatenamos 141214248rus
Como curiosidad decirtos que con el tiempo valores del estilo 29A y 3039 os pegarán rápido al ojo ya que equivalen a 666 y 12345 en decimal. Por cierto 29A fue un grupo de hackers creadores de virus muy conocido en la escena Nacional e Internacional.
Links
Solución al Crackme RSA (RSA24) de TSC

Introducción
Esta vez se trata de un crackme realizado en VC++ 5.0/6.0 y en sus entrañas utiliza RSA-24. En este caso la peculiaridad es que el nombre no interviene en la generación del serial siendo un resultado único.
Resumen RSA
Parámetros
p = Primer número primo
q = Segundo número primo
e = Exponente público que cumpla MCD(e,(p-1)*(q-1))==1
n = Módulo público siendo n=p*q
d = Exponente privado que cumpla d=e^(-1) mod ((p-1)*(q-1))
De este modo e y n son la parte pública de la clave y d y n la parte privada. Los número primos p y q se utilizan solo para generar los parámetros y de ahí en adelante se pueden desechar.
Funciones de Cifrado/Descifrado
cifrado = descifrado ^ e mod n
descifrado = cifrado ^ d mod n
OllyDbg
Nuestro primer vistazo con OllyDbg nos muestra cuatro números de los que podemos hacernos una idea de que 9901 es un buen candidato a ser el exponente público (e) y 12790891 el módulo n ya que casualmente es un número de 24 bits. Los otros dos números de momento no nos dicen nada.

A continuación de los números tenemos la rutina de comprobación en la que comprueba que nuestro serial tenga 14 dígitos y lo divide en dos partes de 7 dígitos. Interesante ya que los otros dos números que aparecían en las referencias de texto tienen 7 dígitos cada uno.
004029CD |. 68 DC004200 PUSH RSA24.004200DC ; ASCII "9901"
004029D2 |. 8D8C24 E40000>LEA ECX,[DWORD SS:ESP+E4]
004029D9 |. E8 52E7FFFF CALL RSA24.00401130
004029DE |. 68 D0004200 PUSH RSA24.004200D0 ; ASCII "12790891"
004029E3 |. 8D4C24 1C LEA ECX,[DWORD SS:ESP+1C]
004029E7 |. C78424 640600>MOV [DWORD SS:ESP+664],0
004029F2 |. E8 39E7FFFF CALL RSA24.00401130
004029F7 |. 68 C8004200 PUSH RSA24.004200C8 ; ASCII "8483678"
004029FC |. 8D8C24 740200>LEA ECX,[DWORD SS:ESP+274]
00402A03 |. C68424 640600>MOV [BYTE SS:ESP+664],1
00402A0B |. E8 20E7FFFF CALL RSA24.00401130
00402A10 |. 68 C0004200 PUSH RSA24.004200C0 ; ASCII "5666933"
00402A15 |. 8D8C24 AC0100>LEA ECX,[DWORD SS:ESP+1AC]
00402A1C |. C68424 640600>MOV [BYTE SS:ESP+664],2
00402A24 |. E8 07E7FFFF CALL RSA24.00401130
00402A29 |. 8B9424 680600>MOV EDX,[DWORD SS:ESP+668]
00402A30 |. 83CE FF OR ESI,FFFFFFFF
00402A33 |. 8BFA MOV EDI,EDX
00402A35 |. 8BCE MOV ECX,ESI
00402A37 |. 33C0 XOR EAX,EAX
00402A39 |. C68424 600600>MOV [BYTE SS:ESP+660],3
00402A41 |. F2:AE REPNE SCAS [BYTE ES:EDI]
00402A43 |. F7D1 NOT ECX
00402A45 |. 49 DEC ECX
00402A46 |. 83F9 0E CMP ECX,0E ; serial 0xE chars -> 14 digitos
00402A49 |. 0F85 63010000 JNZ RSA24.00402BB2
00402A4F |. 33C9 XOR ECX,ECX
00402A51 |> 8A0411 /MOV AL,[BYTE DS:ECX+EDX] ; {
00402A54 |. 3C 30 |CMP AL,30
00402A56 |. 0F8C 56010000 |JL RSA24.00402BB2
00402A5C |. 3C 39 |CMP AL,39 ; comprueba que el serial sea numerico
00402A5E |. 0F8F 4E010000 |JG RSA24.00402BB2
00402A64 |. 41 |INC ECX
00402A65 |. 83F9 0E |CMP ECX,0E
00402A68 |.^ 7C E7 \JL SHORT RSA24.00402A51 ; }
00402A6A |. 8BC2 MOV EAX,EDX
00402A6C |. C64424 17 00 MOV [BYTE SS:ESP+17],0 ; {
00402A71 |. C64424 0F 00 MOV [BYTE SS:ESP+F],0
00402A76 |. 8B08 MOV ECX,[DWORD DS:EAX]
00402A78 |. 894C24 10 MOV [DWORD SS:ESP+10],ECX
00402A7C |. 66:8B48 04 MOV CX,[WORD DS:EAX+4]
00402A80 |. 66:894C24 14 MOV [WORD SS:ESP+14],CX
00402A85 |. 8B4A 07 MOV ECX,[DWORD DS:EDX+7]
00402A88 |. 8A40 06 MOV AL,[BYTE DS:EAX+6] ; divide el serial en dos partes de 7 digitos
00402A8B |. 894C24 08 MOV [DWORD SS:ESP+8],ECX
00402A8F |. 884424 16 MOV [BYTE SS:ESP+16],AL
00402A93 |. 8D42 07 LEA EAX,[DWORD DS:EDX+7]
00402A96 |. 8D4C24 10 LEA ECX,[DWORD SS:ESP+10]
00402A9A |. 66:8B50 04 MOV DX,[WORD DS:EAX+4]
00402A9E |. 8A40 06 MOV AL,[BYTE DS:EAX+6] ; }
A continuación hace una serie de operaciones matemáticas para finalmente comparar el resultado con 8483678 y con 5666933. Lo que está haciendo es cifrar con nuestro serial en dos partes para comprobar que tenemos el número descifrado. Veamos un ejemplo con el serial 12345678901234.
descifrado ^ e mod n = cifrado
x1 = 1234567 y x2 = 8901234
1º parte del serial
x1 ^ 9901 mod 12790891 != 8483678
2º parte del serial
x2 ^ 9901 mod 12790891 != 5666933
Obviamente el resultado de las operaciones anteriores no da ese resultado y el Crackme nos tira fuera de modo que no nos queda más que atacar a RSA para obtener los primos p y q y el módulo privado d. De este modo podremos obtener los números buenos.
Los primos p y q se obtienen factorizando (botón Factor N) y una vez que tenemos p y q hallamos d (botón Calc. D). Todo esto es coser y cantar con la ayuda de la herramienta RSA-Tool 2. El exponente público e se introduce en hexadecimal.
Una vez que tenemos d hallamos el serial de forma sencilla con la herramienta Big Integer Calculator.
cifrado ^ d mod n = descifrado
1º parte del serial
8483678 ^ 10961333 mod 12790891 = 7167622
2º parte del serial
5666933 ^ 10961333 mod 12790891 = 3196885
SERIAL = 71676223196885
Enlaces
- RSA (wikipedia)
- Exponenciación modular (wikipedia)
- RSA Tool
- Big Integer Calculator v1.14
- Crackme
Solución al Crackme 3 de Sotanez

- Introducción
- Activar un botón en memoria
- Activar el botón de forma permanente
- Serial Hardcodeado
- Links
Introducción
Este crackme pertenece a la página de Karpoff Spanish Tutor. Data del año 2000 y está realizado en «Borland Delphi 6.0 – 7.0», además, para resolverlo deberemos activar un botón y conseguir la clave de registro. La principal dificultad proviene a la hora de activar el botón ya que el serial es en realidad un serial hardcodeado muy sencillo.
Activar un botón en memoria
Existen numerosas herramientas para facilitarnos esta tarea, una de las más conocidas en el entorno del Cracking es «Veoveo» realizado por Crack el Destripador & Marmota hace ya unos añitos. Con el crackme ejecutado, ejecutamos VeoVeo y nos aparece el icono en la barra de tareas, hacemos click derecho y elegimos Activar Botones (manual) y ya tenemos el botón activado. Claro está que en cada ejecución del Crackme debemos de Re-activarlo.
Activar el botón de forma permanente
Lo que siempre nos interesa es que el botón esté activado de forma permanente y eso nos exige un poco más de atención. En este caso nos enfrentamos a Delphi y no nos sirve ni Resource Hacker ni Dede. Cuando nos encontramos en un punto muerto el último recurso siempre es realizar un programa en Delphi con un botón activado y otro desactivado y compararlos con un editor hexadecimal para saber que cambia. Si hacemos esto llegaremos a la conclusión de que en Delphi el bit que equivale a desactivado es 8 y ha activado es 9. Con este simple cambio ya tenemos el crackme parcheado. Comentar que en este caso el crackme no tiene ningún timer ni ninguna rutina que desactive el botón de forma periódica, este es el caso más simple.
Serial Hardcodeado
Abrimos Ollydbg y en las «String references» encontramos los mensajes de versión registrada, pinchamos sobre ellos y vemos a simple vista la zona de comprobación del serial. Como podéis observar, el serial se vé a simple vista.
0045811A |. B8 10824500 MOV EAX,CrackMe3.00458210 ; ASCII "ESCRIBE ALGO JOER" 0045811F |. E8 D889FDFF CALL CrackMe3.00430AFC 00458124 |. EB 5C JMP SHORT CrackMe3.00458182 00458126 |> 807D FF 4F CMP BYTE PTR SS:[EBP-1],4F - O 0045812A |. 75 56 JNZ SHORT CrackMe3.00458182 0045812C |. 807D FE 41 CMP BYTE PTR SS:[EBP-2],41 - A 00458130 |. 75 50 JNZ SHORT CrackMe3.00458182 00458132 |. 807D FD 45 CMP BYTE PTR SS:[EBP-3],45 - E 00458136 |. 75 4A JNZ SHORT CrackMe3.00458182 00458138 |. 807D FC 4B CMP BYTE PTR SS:[EBP-4],4B - K 0045813C |. 75 44 JNZ SHORT CrackMe3.00458182 0045813E |. 807D FB 43 CMP BYTE PTR SS:[EBP-5],43 - C 00458142 |. 75 3E JNZ SHORT CrackMe3.00458182 00458144 |. 807D FA 41 CMP BYTE PTR SS:[EBP-6],41 - A 00458148 |. 75 38 JNZ SHORT CrackMe3.00458182 0045814A |. 807D F9 52 CMP BYTE PTR SS:[EBP-7],52 - R 0045814E |. 75 32 JNZ SHORT CrackMe3.00458182 00458150 |. 807D F8 4B CMP BYTE PTR SS:[EBP-8],4B - K 00458154 |. 75 2C JNZ SHORT CrackMe3.00458182 00458156 |. 807D F7 20 CMP BYTE PTR SS:[EBP-9],20 - 0045815A |. 75 26 JNZ SHORT CrackMe3.00458182 0045815C |. 807D F6 49 CMP BYTE PTR SS:[EBP-A],49 - I 00458160 |. 75 20 JNZ SHORT CrackMe3.00458182 00458162 |. 807D F5 4F CMP BYTE PTR SS:[EBP-B],4F - O 00458166 |. 75 1A JNZ SHORT CrackMe3.00458182 00458168 |. 807D F4 54 CMP BYTE PTR SS:[EBP-C],54 - T 0045816C |. 75 14 JNZ SHORT CrackMe3.00458182 0045816E |. 807D F3 20 CMP BYTE PTR SS:[EBP-D],20 - 00458172 |. 75 0E JNZ SHORT CrackMe3.00458182 00458174 |. 807D F2 41 CMP BYTE PTR SS:[EBP-E],41 - A 00458178 |. 75 08 JNZ SHORT CrackMe3.00458182 0045817A |. 807D F1 59 CMP BYTE PTR SS:[EBP-F],59 - Y 0045817E |. 75 02 JNZ SHORT CrackMe3.00458182 00458180 |. B3 01 MOV BL,1 00458182 |> 80FB 01 CMP BL,1 00458185 |. 75 4C JNZ SHORT CrackMe3.004581D3 00458187 |. BA 2C824500 MOV EDX,CrackMe3.0045822C 0045818C |. 8B86 F4020000 MOV EAX,DWORD PTR DS:[ESI+2F4] 00458192 |. E8 B5EBFDFF CALL CrackMe3.00436D4C 00458197 |. BA 48824500 MOV EDX,CrackMe3.00458248 ; ASCII "VERSION REGISTRADA :)" Serial = YA TOI KRACKEAO
Links
Solución al Crackme RSA (RSA24) de TSC

Introducción
Esta vez se trata de un crackme realizado en VC++ 5.0/6.0 y en sus entrañas utiliza RSA-24. En este caso la peculiaridad es que el nombre no interviene en la generación del serial siendo un resultado único.
Resumen RSA
Parámetros
p = Primer número primo
q = Segundo número primo
e = Exponente público que cumpla MCD(e,(p-1)*(q-1))==1
n = Módulo público siendo n=p*q
d = Exponente privado que cumpla d=e^(-1) mod ((p-1)*(q-1))
De este modo e y n son la parte pública de la clave y d y n la parte privada. Los número primos p y q se utilizan solo para generar los parámetros y de ahí en adelante se pueden desechar.
Funciones de Cifrado/Descifrado
cifrado = descifrado ^ e mod n
descifrado = cifrado ^ d mod n
OllyDbg
Nuestro primer vistazo con OllyDbg nos muestra cuatro números de los que podemos hacernos una idea de que 9901 es un buen candidato a ser el exponente público (e) y 12790891 el módulo n ya que casualmente es un número de 24 bits. Los otros dos números de momento no nos dicen nada.

A continuación de los números tenemos la rutina de comprobación en la que comprueba que nuestro serial tenga 14 dígitos y lo divide en dos partes de 7 dígitos. Interesante ya que los otros dos números que aparecían en las referencias de texto tienen 7 dígitos cada uno.
004029CD |. 68 DC004200 PUSH RSA24.004200DC ; ASCII "9901"
004029D2 |. 8D8C24 E40000>LEA ECX,[DWORD SS:ESP+E4]
004029D9 |. E8 52E7FFFF CALL RSA24.00401130
004029DE |. 68 D0004200 PUSH RSA24.004200D0 ; ASCII "12790891"
004029E3 |. 8D4C24 1C LEA ECX,[DWORD SS:ESP+1C]
004029E7 |. C78424 640600>MOV [DWORD SS:ESP+664],0
004029F2 |. E8 39E7FFFF CALL RSA24.00401130
004029F7 |. 68 C8004200 PUSH RSA24.004200C8 ; ASCII "8483678"
004029FC |. 8D8C24 740200>LEA ECX,[DWORD SS:ESP+274]
00402A03 |. C68424 640600>MOV [BYTE SS:ESP+664],1
00402A0B |. E8 20E7FFFF CALL RSA24.00401130
00402A10 |. 68 C0004200 PUSH RSA24.004200C0 ; ASCII "5666933"
00402A15 |. 8D8C24 AC0100>LEA ECX,[DWORD SS:ESP+1AC]
00402A1C |. C68424 640600>MOV [BYTE SS:ESP+664],2
00402A24 |. E8 07E7FFFF CALL RSA24.00401130
00402A29 |. 8B9424 680600>MOV EDX,[DWORD SS:ESP+668]
00402A30 |. 83CE FF OR ESI,FFFFFFFF
00402A33 |. 8BFA MOV EDI,EDX
00402A35 |. 8BCE MOV ECX,ESI
00402A37 |. 33C0 XOR EAX,EAX
00402A39 |. C68424 600600>MOV [BYTE SS:ESP+660],3
00402A41 |. F2:AE REPNE SCAS [BYTE ES:EDI]
00402A43 |. F7D1 NOT ECX
00402A45 |. 49 DEC ECX
00402A46 |. 83F9 0E CMP ECX,0E ; serial 0xE chars -> 14 digitos
00402A49 |. 0F85 63010000 JNZ RSA24.00402BB2
00402A4F |. 33C9 XOR ECX,ECX
00402A51 |> 8A0411 /MOV AL,[BYTE DS:ECX+EDX] ; {
00402A54 |. 3C 30 |CMP AL,30
00402A56 |. 0F8C 56010000 |JL RSA24.00402BB2
00402A5C |. 3C 39 |CMP AL,39 ; comprueba que el serial sea numerico
00402A5E |. 0F8F 4E010000 |JG RSA24.00402BB2
00402A64 |. 41 |INC ECX
00402A65 |. 83F9 0E |CMP ECX,0E
00402A68 |.^ 7C E7 \JL SHORT RSA24.00402A51 ; }
00402A6A |. 8BC2 MOV EAX,EDX
00402A6C |. C64424 17 00 MOV [BYTE SS:ESP+17],0 ; {
00402A71 |. C64424 0F 00 MOV [BYTE SS:ESP+F],0
00402A76 |. 8B08 MOV ECX,[DWORD DS:EAX]
00402A78 |. 894C24 10 MOV [DWORD SS:ESP+10],ECX
00402A7C |. 66:8B48 04 MOV CX,[WORD DS:EAX+4]
00402A80 |. 66:894C24 14 MOV [WORD SS:ESP+14],CX
00402A85 |. 8B4A 07 MOV ECX,[DWORD DS:EDX+7]
00402A88 |. 8A40 06 MOV AL,[BYTE DS:EAX+6] ; divide el serial en dos partes de 7 digitos
00402A8B |. 894C24 08 MOV [DWORD SS:ESP+8],ECX
00402A8F |. 884424 16 MOV [BYTE SS:ESP+16],AL
00402A93 |. 8D42 07 LEA EAX,[DWORD DS:EDX+7]
00402A96 |. 8D4C24 10 LEA ECX,[DWORD SS:ESP+10]
00402A9A |. 66:8B50 04 MOV DX,[WORD DS:EAX+4]
00402A9E |. 8A40 06 MOV AL,[BYTE DS:EAX+6] ; }
A continuación hace una serie de operaciones matemáticas para finalmente comparar el resultado con 8483678 y con 5666933. Lo que está haciendo es cifrar con nuestro serial en dos partes para comprobar que tenemos el número descifrado. Veamos un ejemplo con el serial 12345678901234.
descifrado ^ e mod n = cifrado
x1 = 1234567 y x2 = 8901234
1º parte del serial
x1 ^ 9901 mod 12790891 != 8483678
2º parte del serial
x2 ^ 9901 mod 12790891 != 5666933
Obviamente el resultado de las operaciones anteriores no da ese resultado y el Crackme nos tira fuera de modo que no nos queda más que atacar a RSA para obtener los primos p y q y el módulo privado d. De este modo podremos obtener los números buenos.
Los primos p y q se obtienen factorizando (botón Factor N) y una vez que tenemos p y q hallamos d (botón Calc. D). Todo esto es coser y cantar con la ayuda de la herramienta RSA-Tool 2. El exponente público e se introduce en hexadecimal.
Una vez que tenemos d hallamos el serial de forma sencilla con la herramienta Big Integer Calculator.
cifrado ^ d mod n = descifrado
1º parte del serial
8483678 ^ 10961333 mod 12790891 = 7167622
2º parte del serial
5666933 ^ 10961333 mod 12790891 = 3196885
SERIAL = 71676223196885
Enlaces
- RSA (wikipedia)
- Exponenciación modular (wikipedia)
- RSA Tool
- Big Integer Calculator v1.14
- Crackme
Blooper Tech Movie III – Mentiras arriesgadas

Continuamos con los BTM awards. Esta vez analizaremos brevemente una escena de la película del casi siempre excelente James Cameron, Mentiras Arriesgadas. En esta ocasión vamos a analizar una situación que se da mucho en el cine de Hollywood, esto es, el Plug and Play mágico. Cuando vemos películas de espías, es habitual encontrarnos con situaciones en las que el protagonista conecta un «algo» en el ordenador al que quiere acceder y ¡chas!, como por arte de magia sin tocar ninguna tecla se copian o se borran unos archivos, le da acceso remoto a algún compañero etc.
BTM
Este film no iba a ser menos y es que cuando Harry Tasker (Arnold Schwarzenegger) con sus inigualables dotes para el espionaje, entra en la mansión del objetivo en cuestión, conecta un módem, lo enciende y sin teclear un solo comando le da a su compañero Faisil (Grant Heslov) que se encuentra en una furgoneta a unos kilómetros, acceso a la máquina, nos quedamos perplejos.
Esta situación es posible en la vida real, lo que la hace difícil de creer es que Harry no teclee ni un solo comando al conectar el módem, independientemente del Sistema Operativo que corra la máquina. Si nos situamos un poco, estamos hablando del año 1995, con una máquina corriendo Windows 3.1 y estamos conectando un módem a un puerto RS-232. En aquella época, por avanzada que fuera la tecnología espía, es difícil de creer que las cosas funcionen solas. Otra cosa a destacar es que a no ser que Faisil estuviera conectados a un poste de teléfono, la conexión tendría que ser inalámbrica, casi una quimera hace 20 años. A continuación os muestro la secuencia.
Como se puede observar en el vídeo, incluso parece que el equipo de Faisil, que también corre Windows 3.1, accede al equipo en modo escritorio remoto, tecnología que no existía en aquella época. Para que la secuencia tuviera un mínimo de credibilidad, Harry al conectar el módem y encender el equipo, debiera de haber introducido un par de comandos como mínimo para asignarle un puerto COM al módem y así iniciar la comunicación con Faisil. Ni que decir tiene que Faisil hubiera tenido que hacer todas las transmisiones mediante línea de comandos.
Aunque la película es entretenida y me gustó mucho cuando la vi allá por el año 1998, no nos queda más remedio que ponerle nuestro sello BTM de NO credibilidad.
Enlaces
Otros posts que te pueden interesar
Migas de pan

Se nos entrega el siguiente ELF:
/* This file was generated by the Hex-Rays decompiler version 8.4.0.240320.
Copyright (c) 2007-2021 Hex-Rays <info@hex-rays.com>
Detected compiler: GNU C++
*/
#include <defs.h>
//-------------------------------------------------------------------------
// Function declarations
__int64 (**init_proc())(void);
void sub_1020();
// int printf(const char *format, ...);
// int getchar(void);
// int fflush(FILE *stream);
// __int64 __isoc99_scanf(const char *, ...); weak
// void __noreturn exit(int status);
// int __fastcall _cxa_finalize(void *);
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void));
FILE **deregister_tm_clones();
__int64 register_tm_clones(); // weak
FILE **_do_global_dtors_aux();
__int64 __fastcall frame_dummy(_QWORD, _QWORD, _QWORD); // weak
int __fastcall main(int argc, const char **argv, const char **envp);
_BOOL8 __fastcall comprobacion(char a1, char a2, int a3);
void _libc_csu_fini(void); // idb
void term_proc();
// int __fastcall _libc_start_main(int (__fastcall *main)(int, char **, char **), int argc, char **ubp_av, void (*init)(void), void (*fini)(void), void (*rtld_fini)(void), void *stack_end);
// int __fastcall __cxa_finalize(void *);
// __int64 _gmon_start__(void); weak
//-------------------------------------------------------------------------
// Data declarations
_UNKNOWN _libc_csu_init;
__int64 (__fastcall *_frame_dummy_init_array_entry)() = &frame_dummy; // weak
__int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)() = &_do_global_dtors_aux; // weak
void *_dso_handle = &_dso_handle; // idb
char *a = "MdfnJk"; // weak
char *b = "jYx}"; // weak
char *c = "gWmfk"; // weak
char *d = "mlvpc"; // weak
char *f = "neU++w"; // weak
FILE *_bss_start; // idb
char completed_0; // weak
//----- (0000000000001000) ----------------------------------------------------
__int64 (**init_proc())(void)
{
__int64 (**result)(void); // rax
result = &_gmon_start__;
if ( &_gmon_start__ )
return (__int64 (**)(void))_gmon_start__();
return result;
}
// 40D0: using guessed type __int64 _gmon_start__(void);
//----- (0000000000001020) ----------------------------------------------------
void sub_1020()
{
JUMPOUT(0LL);
}
// 1026: control flows out of bounds to 0
//----- (0000000000001090) ----------------------------------------------------
// positive sp value has been detected, the output may be wrong!
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void))
{
__int64 v3; // rax
int v4; // esi
__int64 v5; // [rsp-8h] [rbp-8h] BYREF
char *retaddr; // [rsp+0h] [rbp+0h] BYREF
v4 = v5;
v5 = v3;
_libc_start_main(
(int (__fastcall *)(int, char **, char **))main,
v4,
&retaddr,
(void (*)(void))_libc_csu_init,
_libc_csu_fini,
a3,
&v5);
__halt();
}
// 1096: positive sp value 8 has been found
// 109D: variable 'v3' is possibly undefined
//----- (00000000000010C0) ----------------------------------------------------
FILE **deregister_tm_clones()
{
return &_bss_start;
}
//----- (00000000000010F0) ----------------------------------------------------
__int64 register_tm_clones()
{
return 0LL;
}
// 10F0: using guessed type __int64 register_tm_clones();
//----- (0000000000001130) ----------------------------------------------------
FILE **_do_global_dtors_aux()
{
FILE **result; // rax
if ( !completed_0 )
{
if ( &__cxa_finalize )
_cxa_finalize(_dso_handle);
result = deregister_tm_clones();
completed_0 = 1;
}
return result;
}
// 4080: using guessed type char completed_0;
//----- (0000000000001175) ----------------------------------------------------
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4; // [rsp+7h] [rbp-9h] BYREF
int v5; // [rsp+8h] [rbp-8h]
bool v6; // [rsp+Fh] [rbp-1h]
v6 = 1;
v5 = 0;
while ( v6 )
{
fflush(_bss_start);
printf("\nIntroduce la letra correcta:\t");
__isoc99_scanf("%c", &v4);
getchar();
if ( v5 > 5 )
{
if ( v5 > 9 )
{
if ( v5 > 14 )
{
if ( v5 > 19 )
v6 = comprobacion(v4, f[v5 - 20], 10);
else
v6 = comprobacion(v4, d[v5 - 15], 2);
}
else
{
v6 = comprobacion(v4, c[v5 - 10], 8);
}
}
else
{
v6 = comprobacion(v4, b[v5 - 6], 17);
}
}
else
{
v6 = comprobacion(v4, a[v5], 5);
}
if ( !v6 )
{
printf("Incorrecta");
exit(1);
}
printf("\n%c\n", (unsigned int)v4);
if ( v5 == 25 )
{
printf("Ya tienes la flag!!");
exit(1);
}
++v5;
}
return 0;
}
// 1060: using guessed type __int64 __isoc99_scanf(const char *, ...);
// 4050: using guessed type char *a;
// 4058: using guessed type char *b;
// 4060: using guessed type char *c;
// 4068: using guessed type char *d;
// 4070: using guessed type char *f;
//----- (0000000000001352) ----------------------------------------------------
_BOOL8 __fastcall comprobacion(char a1, char a2, int a3)
{
return a1 == (a3 ^ a2);
}
//----- (0000000000001390) ----------------------------------------------------
void __fastcall _libc_csu_init(unsigned int a1, __int64 a2, __int64 a3)
{
signed __int64 v4; // rbp
__int64 i; // rbx
init_proc();
v4 = &_do_global_dtors_aux_fini_array_entry - &_frame_dummy_init_array_entry;
if ( v4 )
{
for ( i = 0LL; i != v4; ++i )
((void (__fastcall *)(_QWORD, __int64, __int64))*(&_frame_dummy_init_array_entry + i))(a1, a2, a3);
}
}
// 1170: using guessed type __int64 __fastcall frame_dummy(_QWORD, _QWORD, _QWORD);
// 3DE8: using guessed type __int64 (__fastcall *_frame_dummy_init_array_entry)();
// 3DF0: using guessed type __int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)();
//----- (00000000000013F4) ----------------------------------------------------
void term_proc()
{
;
}
Extracción de la Flag
Si nos fijamos en las líneas 41 a la 45 vemos las siguientes cadenas:
a = «MdfnJk»
b = «jYx}»
c = «gWmfk»
d = «mlvpc»
f = «neU++w»
Usaremos las cadenas y los valores XOR especificados para cada rango de v5 en el main (líneas 123 a 182) para determinar los caracteres correctos.
Para v5 de 0 a 5: v6 = comprobacion(v4, a[v5], 5);
Significa que: v4 debe ser igual a a[v5] ^ 5
Para v5 de 6 a 9: v6 = comprobacion(v4, b[v5 – 6], 17);
Significa que: v4 debe ser igual a b[v5 – 6] ^ 17
Para v5 de 10 a 14: v6 = comprobacion(v4, c[v5 – 10], 8);
Significa que: v4 debe ser igual a c[v5 – 10] ^ 8
Para v5 de 15 a 19: v6 = comprobacion(v4, d[v5 – 15], 2);
Significa que: v4 debe ser igual a d[v5 – 15] ^ 2
Para v5 de 20 a 25: v6 = comprobacion(v4, f[v5 – 20], 10);
Significa que: v4 debe ser igual a f[v5 – 20] ^ 10
Cálculo de los caracteres correctos:
Para v5 de 0 a 5:
a[0] = ‘M’, M ^ 5 = 0x4D ^ 0x05 = 0x48 -> ‘H’
a[1] = ‘d’, d ^ 5 = 0x64 ^ 0x05 = 0x61 -> ‘a’
a[2] = ‘f’, f ^ 5 = 0x66 ^ 0x05 = 0x63 -> ‘c’
a[3] = ‘n’, n ^ 5 = 0x6E ^ 0x05 = 0x6B -> ‘k’
a[4] = ‘J’, J ^ 5 = 0x4A ^ 0x05 = 0x4F -> ‘O’
a[5] = ‘k’, k ^ 5 = 0x6B ^ 0x05 = 0x6E -> ‘n’
Resulta en la cadena: HackOn
Para v5 de 6 a 9:
b[0] = ‘j’, j ^ 17 = 0x6A ^ 0x11 = 0x7B -> ‘{‘
b[1] = ‘Y’, Y ^ 17 = 0x59 ^ 0x11 = 0x48 -> ‘H’
b[2] = ‘x’, x ^ 17 = 0x78 ^ 0x11 = 0x69 -> ‘i’
b[3] = ‘}’, } ^ 17 = 0x7D ^ 0x11 = 0x6C -> ‘l’
Resulta en la cadena: {Hil
Para v5 de 10 a 14:
c[0] = ‘g’, g ^ 8 = 0x67 ^ 0x08 = 0x6F -> ‘o’
c[1] = ‘W’, W ^ 8 = 0x57 ^ 0x08 = 0x5F -> ‘_’
c[2] = ‘m’, m ^ 8 = 0x6D ^ 0x08 = 0x65 -> ‘e’
c[3] = ‘f’, f ^ 8 = 0x66 ^ 0x08 = 0x6E -> ‘n’
c[4] = ‘k’, k ^ 8 = 0x6B ^ 0x08 = 0x63 -> ‘c’
Resulta en la cadena: o_enc
Para v5 de 15 a 19:
d[0] = ‘m’, m ^ 2 = 0x6D ^ 0x02 = 0x6F -> ‘o’
d[1] = ‘l’, l ^ 2 = 0x6C ^ 0x02 = 0x6E -> ‘n’
d[2] = ‘v’, v ^ 2 = 0x76 ^ 0x02 = 0x74 -> ‘t’
d[3] = ‘p’, p ^ 2 = 0x70 ^ 0x02 = 0x72 -> ‘r’
d[4] = ‘c’, c ^ 2 = 0x63 ^ 0x02 = 0x61 -> ‘a’
Resulta en la cadena: ontra
Para v5 de 20 a 25:
f[0] = ‘n’, n ^ 10 = 0x6E ^ 0x0A = 0x64 -> ‘d’
f[1] = ‘e’, e ^ 10 = 0x65 ^ 0x0A = 0x6F -> ‘o’
f[2] = ‘U’, U ^ 10 = 0x55 ^ 0x0A = 0x5F -> ‘_‘
f[3] = ‘+’, + ^ 10 = 0x2B ^ 0x0A = 0x21 -> ‘!’
f[4] = ‘+’, + ^ 10 = 0x2B ^ 0x0A = 0x21 -> ‘!’
f[5] = ‘w’, w ^ 10 = 0x77 ^ 0x0A = 0x7D -> ‘}’
Resulta en la cadena: do_!!}
Uniendo todas las partes, obtenemos la flag completa: HackOn{Hilo_enc_ontrado_!!}
Reto Stego – Dos por Uno



El reto consiste en dos imágenes (v1.png y v2.png) que, a simple vista, parecen contener ruido aleatorio. Sin embargo, ambas forman parte de un sistema de criptografía visual en la que cada imagen contiene información parcial que no es interpretable por separado, pero que al combinarse correctamente revelan información oculta.
La trampa está en que la combinación no se hace con operaciones normales como suma, resta o multiplicación. El autor del reto espera que el jugador use una herramienta como StegSolve y pruebe distintas operaciones tipo XOR, AND o MUL hasta encontrar una transformación en la que uno de los métodos muestre algo significativo. El truco está en llegar a la conclusión de que una de las imágenes hay que invertirla antes de combinar ambas imágenes. Todo esto se puede hacer con StegSolve sin necesidad de utilizar ninguna herramienta adicional, pero voy a aprovechar para hacerlo con python y así de paso entendemos como realiza las operaciones StegSolve. En resumen, para resolver el reto basta con:
- Invertir (Colour Inversion XOR) una de las imágenes.
- Combinar ambas imágenes mediante Analyse > Combine images.
- Operación MUL del combinador.
La operación MUL no es una multiplicación normalizada, sino una multiplicación de enteros de 24 bits (0xRRGGBB) con overflow, algo que la mayoría de herramientas no replican correctamente.
¿Por qué aparece la solución con esa combinación
Las imágenes están preparadas para que ciertos bits de color en una imagen sean el complemento de los de la otra. Por tanto:
- Si se muestran tal cual → parecen ruido
- Si se combinan mediante XOR → parte de la estructura aparece, pero no se ve el resultado correcto
- Si se combinan mediante MUL «normal» → tampoco aparece
- Si se aplica la multiplicación bitwise exacta usada por StegSolve → se alinean las partes ocultas
La operación MUL de StegSolve no es una multiplicación de píxeles, es decir, no hace:
R = (R1 * R2) / 255
sino:
c1 = 0xRRGGBB (pixel 1) c2 = 0xRRGGBB (pixel 2) resultado = (c1 * c2) & 0xFFFFFF
Con todo esto claro, he preparado un script para combinar las imágenes de forma automática.
import os
import numpy as np
from PIL import Image
# =========================================================
# UTILIDADES
# =========================================================
def ensure_output():
if not os.path.exists("output"):
os.makedirs("output")
def load_rgb(path):
img = Image.open(path).convert("RGB")
return np.array(img, dtype=np.uint32)
def save_rgb(arr, name):
Image.fromarray(arr.astype(np.uint8), "RGB").save(os.path.join("output", name))
def invert_xor(arr):
"""Colour Inversion (Xor) de StegSolve."""
out = arr.copy()
out[..., :3] = 255 - out[..., :3]
return out
# =========================================================
# FUNCIONES DE COMBINER EXACTAS DE STEGSOLVE
# =========================================================
def to24(arr):
"""Convierte RGB → entero 0xRRGGBB."""
return ((arr[..., 0] << 16) |
(arr[..., 1] << 8) |
arr[..., 2])
def from24(c):
"""Convierte entero 0xRRGGBB → RGB."""
R = (c >> 16) & 0xFF
G = (c >> 8) & 0xFF
B = c & 0xFF
return np.stack([R, G, B], axis=-1).astype(np.uint8)
# ------------------------------
# Funciones auxiliares
# ------------------------------
def comb_xor(c1, c2):
return from24((c1 ^ c2) & 0xFFFFFF)
def comb_or(c1, c2):
return from24((c1 | c2) & 0xFFFFFF)
def comb_and(c1, c2):
return from24((c1 & c2) & 0xFFFFFF)
def comb_add(c1, c2):
return from24((c1 + c2) & 0xFFFFFF)
def comb_add_sep(c1, c2):
R = (((c1 >> 16) & 0xFF) + ((c2 >> 16) & 0xFF)) & 0xFF
G = (((c1 >> 8) & 0xFF) + ((c2 >> 8) & 0xFF)) & 0xFF
B = ((c1 & 0xFF) + (c2 & 0xFF)) & 0xFF
return from24((R << 16) | (G << 8) | B)
def comb_sub(c1, c2):
return from24((c1 - c2) & 0xFFFFFF)
def comb_sub_sep(c1, c2):
R = (((c1 >> 16) & 0xFF) - ((c2 >> 16) & 0xFF)) & 0xFF
G = (((c1 >> 8) & 0xFF) - ((c2 >> 8) & 0xFF)) & 0xFF
B = ((c1 & 0xFF) - (c2 & 0xFF)) & 0xFF
return from24((R << 16) | (G << 8) | B)
def comb_mul(c1, c2):
"""MUL EXACTO StegSolve"""
return from24((c1 * c2) & 0xFFFFFF)
def comb_mul_sep(c1, c2):
R = (((c1 >> 16) & 0xFF) * ((c2 >> 16) & 0xFF)) & 0xFF
G = (((c1 >> 8) & 0xFF) * ((c2 >> 8) & 0xFF)) & 0xFF
B = ((c1 & 0xFF) * (c2 & 0xFF)) & 0xFF
return from24((R << 16) | (G << 8) | B)
def comb_lightest(c1, c2):
"""Máximo por canal"""
R = np.maximum((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF)
G = np.maximum((c1 >> 8) & 0xFF, (c2 >> 8) & 0xFF)
B = np.maximum(c1 & 0xFF, c2 & 0xFF)
return from24((R << 16) | (G << 8) | B)
def comb_darkest(c1, c2):
"""Mínimo por canal"""
R = np.minimum((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF)
G = np.minimum((c1 >> 8) & 0xFF, (c2 >> 8) & 0xFF)
B = np.minimum(c1 & 0xFF, c2 & 0xFF)
return from24((R << 16) | (G << 8) | B)
# Lista de transformaciones
TRANSFORMS = {
"xor": comb_xor,
"or": comb_or,
"and": comb_and,
"add": comb_add,
"add_sep": comb_add_sep,
"sub": comb_sub,
"sub_sep": comb_sub_sep,
"mul": comb_mul,
"mul_sep": comb_mul_sep,
"lightest": comb_lightest,
"darkest": comb_darkest,
}
# =========================================================
# GENERACIÓN DE TODAS LAS COMBINACIONES
# =========================================================
def generate_all(imA, imB, labelA, labelB):
print(f"Generando combinaciones: {labelA} vs {labelB}")
c1 = to24(imA)
c2 = to24(imB)
for name, fun in TRANSFORMS.items():
out = fun(c1, c2)
save_rgb(out, f"{labelA}__{labelB}__{name}.png")
print(f"{labelA}-{labelB} completado.")
# =========================================================
# MAIN
# =========================================================
ensure_output()
print("Cargando imágenes v1.png y v2.png...")
im1 = load_rgb("v1.png")
im2 = load_rgb("v2.png")
print("Generando invertidas estilo StegSolve...")
im1_x = invert_xor(im1)
im2_x = invert_xor(im2)
save_rgb(im1_x, "v1_xored.png")
save_rgb(im2_x, "v2_xored.png")
# Generar las 52 combinaciones:
generate_all(im1, im2, "v1", "v2")
generate_all(im1_x, im2, "v1x", "v2")
generate_all(im1, im2_x, "v1", "v2x")
generate_all(im1_x, im2_x, "v1x", "v2x")
print("\nResultados en carpeta ./output/")
A continuación os muestro parte de las imágenes generadas por el script. El secreto oculto era un código QR que nos da la solución al reto.



























SPECtacular

AVISO: Debido a que este reto está en activo no publicaré a donde pertenece.
En este reto stego nos proporcionan un archivo MP3 y nos dan una pequeña pista con el título.
Inicialmente lo pasé con GoldWave y me fijé en el la parte de control en el SPECtrogram y en el SPECtrum, pero no conseguí ver nada. A punto de rendirme di con un programa online llamado SPEK, que me dio la respuesta al instante.

Se puede apreciar una palabra que escrita en Inglés nos da la solución al reto.
CoSH’s Crackme 3 KeyGen

Intro
Hoy tenemos un crackme realizado en Visual C++ 6. Es el típico serial asociado a un nombre.
El algoritmo
Localizamos con Olly la rutina de comprobación del serial y empezamos a analizar. Vemos una serie de Calls que lo único que hacen es comprobar el tamaño de nuestro nombre y serial y si es <5 dígitos nos tira afuera.
Una vez pasada la traba anterior procede con un bucle para el nombre y otro para el serial. Yo he metido deurus y 123456. El bucle del nombre hace xor al los dígitos ascii con un valor incremental a partir de 1. Reconvierte el valor resultante en su caracter correspondiente y lo almacena.
00401576 |. B9 01000000 MOV ECX,1 ; ECX = 1 0040157B |. 33D2 XOR EDX,EDX 0040157D |. 8B45 E4 MOV EAX,[LOCAL.7] ; EAX = Nombre 00401580 |> 8A18 /MOV BL,BYTE PTR DS:[EAX] ; BL = digito que toque <-- 00401582 |. 32D9 |XOR BL,CL ; digito XOR ECX 00401584 |. 8818 |MOV BYTE PTR DS:[EAX],BL ; sustituye el digito nombre por el resultante del xor 00401586 |. 41 |INC ECX ; ECX++ 00401587 |. 40 |INC EAX ; Siguiente digito 00401588 |. 8038 00 |CMP BYTE PTR DS:[EAX],0 0040158B |.^ 75 F3 \JNZ SHORT crackme3.00401580 ; Bucle -->
Ejemplo:
d e u r u s 64 65 75 72 75 73 (d)64 xor 1 = 65(e) (e)65 xor 2 = 67(g) (u)75 xor 3 = 76(v) (r)72 xor 4 = 76(v) (u)75 xor 5 = 70(p) (s)73 xor 6 = 75(u) Nombre: deurus Resultado: egvvpu
Hace lo mismo con el serial pero con el valor incremental a partir de 0xA (10).
00401593 |. B9 0A000000 MOV ECX,0A ; ECX = A 00401598 |. 33D2 XOR EDX,EDX 0040159A |. 8B45 F0 MOV EAX,[LOCAL.4] ; EAX = Serial 0040159D |> 8A18 /MOV BL,BYTE PTR DS:[EAX] ; BL = digito que toque <-- 0040159F |. 32D9 |XOR BL,CL ; BL XOR CL 004015A1 |. 8818 |MOV BYTE PTR DS:[EAX],BL ; sustituye el digito serial por el resultante del xor 004015A3 |. 41 |INC ECX ; ECX++ 004015A4 |. 40 |INC EAX ; Siguiente digito 004015A5 |. 8038 00 |CMP BYTE PTR DS:[EAX],0 004015A8 |.^ 75 F3 \JNZ SHORT crackme3.0040159D ; Bucle -->
Ejemplo:
1 2 3 4 5 6 31 32 33 34 35 35 (1)31 xor A = 3B(;) (2)32 xor B = 39(9) (3)33 xor C = 3F(?) (4)34 xor D = 39(9) (5)35 xor E = 3B(;) (6)36 xor F = 39(9) Serial: 123456 Resultado: ;9?9;9
A continuación compara «egvvpu» con «;9?9;9» byte a byte.
KeyGen
El KeyGen quedaría así
for(int i = 0; i <= strlen(Nombre); i = i + 1)
{
Serial[i] = (Nombre[i]^(i+1))^(0xA + i);
}
Links
Algoritmo de HEdit 2.1.11

Rebuscando entre todo el caos que puede llegar a ser mi disco duro, he encontrado una serie de programas que utilizaba antiguamente cuando empezó a interesarme el Cracking. Ya sabéis que no soy partidario de crackear programas comerciales pero hoy voy a hacer una excepción ya que la versión del programa es muy vieja (1997) e incluso podría considerarse abandonware.
Este ejercicio es ideal para los que están empezando ya que es fácil localizar donde está el algoritmo y éste es sumamente sencillo.
Algoritmo
Address Hex dump Command Comments
00402213 E8 78170000 CALL HEdit.00403990
........
004039C0 8BC1 MOV EAX,ECX
004039C2 99 CDQ
004039C3 33C2 XOR EAX,EDX
004039C5 2BC2 SUB EAX,EDX
004039C7 83E0 03 AND EAX,00000003
004039CA 33C2 XOR EAX,EDX
004039CC 2BC2 SUB EAX,EDX
004039CE 8A540C 04 MOV DL,BYTE PTR SS:[ECX+ESP+4] ;Coge el dígito i*3
004039D2 8A5C04 04 MOV BL,BYTE PTR SS:[EAX+ESP+4] ;Coge el dígito i
004039D6 8D4404 04 LEA EAX,[EAX+ESP+4] ;Guarda en memoria 12EE90
004039DA 32DA XOR BL,DL
004039DC 41 INC ECX ; i +=1
004039DD 81F9 00010000 CMP ECX,100 ;El bucle se repite 256 veces (0x100)
004039E3 8818 MOV BYTE PTR DS:[EAX],BL
004039E5 ^ 7C D9 JL SHORT HEdit.004039C0
004039E7 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
004039EB 85C0 TEST EAX,EAX ;Comprueba que el serial no sea 0
004039ED 7D 02 JGE SHORT HEdit.004039F1 ;Si es 0 se acabó
004039EF F7D8 NEG EAX
004039F1 3B8424 0C010000 CMP EAX,DWORD PTR SS:[ESP+10C] ;Comprobación de serial válido
004039F8 75 13 JNE SHORT HEdit.00403A0D ;Si no es igual bad boy
004039FA 85C0 TEST EAX,EAX ;Comprueba que el serial no sea 0
004039FC 74 0F JE SHORT HEdit.00403A0D ;Si es 0 se acabó
004039FE B8 01000000 MOV EAX,1
00403A03 5B POP EBX
00403A04 81C4 00010000 ADD ESP,100
00403A0A C2 0800 RETN 8
En resumen hace esto:
- Nombre introducido: deurus
- Convierte el nombre a mayúsculas
D E U R U S
44 45 55 52 55 53 (En Hexadecimal)
1) 55 xor 44 = 11
2) 53 xor 45 = 16
3) 00 xor 55 = 55
4) 00 xor 52 = 52
--------------- solo vale hasta aquí EAX(32 bits)
5) 00 xor 55 = 55
6) 00 xor 53 = 53
7) 00 xor 00 = 00
8) ...
HEX DEC
Serial = 52551611 = 1381307921
Como veis, realiza un bucle 256 veces pero como al final utiliza el registro EAX para hacer la comparación, solamente nos sirven las cuatro primeras operaciones. De hecho, no comprueba ni la longitud del nombre por lo que si introducimos un solo dígito como nombre, el serial será el valor ascii de ese dígito en decimal. La única comprobación que realiza es que el serial no sea 0.
Keygen
Os dejo una prueba de concepto en Javascript.
var nombre = "deurus";
nombre = nombre.toUpperCase();
var serial = "";
serial = serial + nombre.charCodeAt(3).toString(16) + nombre.charCodeAt(2).toString(16);
serial = serial + (nombre.charCodeAt(5) ^ nombre.charCodeAt(1)).toString(16);
serial = serial + (nombre.charCodeAt(2) ^ nombre.charCodeAt(0)).toString(16);
serial = "Nº Serie: " + parseInt(serial,16);
document.write(serial);
Enlaces
VideoTutorial – Desempacando Aspack 2.1, Pe-Pack 1.0 y UPX del Crackme Sweeet Dream 1.0 de 2Sweeet

Stego d33p

En este reto se nos entrega un archivo WAV de 9,92 MB. Tras escucharlo y analizarlo por encima con Audacity no llego a ningún lado por lo que me tiro al descarte de herramientas conocidas, y en ésta ocasión sale a escena DeepSound.
Sin más dilación extraemos el JPG y continuamos.
La aparición en escena de DeepSound me hace sospechar sobre el uso de herramientas conocidas y ¡bingo!, sale a escena StegHide. En esta ocasión el autor del reto nos lo ha puesto fácil y la extracción no requiere clave.
Al abrir el archivo TXT como texto vemos lo siguiente:
y si lo abrimos con un editor hexadecimal vemos esto otro:
Claramente el archivo esconde algo que por la repetición de los caracteres me hace sospechar de un simple XOR y efectivamente la flag está XOReada. Tras un ataque preliminar, digamos que los árboles no me dejaban ver el bosque, de modo que limpié los bytes correspondientes a la frase «this is the flag :)» y procesé de nuevo obteniendo por fin la ansiada flag.
RAW bytes
FF FE 74 00 68 00 69 00 73 00 20 00 40 DB 53 DC 40 DB 48 DC 40 DB 53 DC 40 DB 7B DC 40 DB 74 DC 69 00 73 00 20 00 40 DB 30 DC 40 DB 30 DC 40 DB 5F DC 40 DB 33 DC 40 DB 34 DC 74 00 68 00 65 00 20 00 40 DB 73 DC 40 DB 79 DC 40 DB 5F DC 40 DB 6D DC 40 DB 34 DC 66 00 6C 00 61 00 67 00 20 00 40 DB 6E DC 40 DB 7D DC 40 DB 20 DC 3A 00 29 00
Cleaned bytes [quitando this is the flag :)]
FF FE 40 DB 53 DC 40 DB 48 DC 40 DB 53 DC 40 DB 7B DC 40 DB 74 DC 40 DB 30 DC 40 DB 30 DC 40 DB 5F DC 40 DB 33 DC 40 DB 34 DC 40 DB 73 DC 40 DB 79 DC 40 DB 5F DC 40 DB 6D DC 40 DB 34 DC 40 DB 6E DC 40 DB 7D DC 40 DB 20 DC
clave XOR == 00fc60fb
Resultado
S H S { t 0 0 _ 3 4 s y _ m 4 n }
ThisIsLegal.com – Realistic Challenge 4

Warning: This challenge is still active and therefore should not be resolved using this information.
Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
Introducción
Realistic Challenge 4: There is a site offering protection against hackers to website owners, the service is far too overpriced and the people running the service don’t know anything about security. Look around their site, and see how protected it is.
Hay un sitio que ofrece protección contra los hackers. El servicio tiene un precio abusivo, echa un vistazo a la web y evalúa su pretección.
Analizando a la víctima
Vemos un escueto menú pero con cosas interesantes.
Pinchamos sobre «Testimonials» y a continuación en «Customer 1»
Vemos que hay solo 3 «customers», vamos a introducir manualmente un 5 haber que pasa.
Ok, nos genera el siguiente error.
Probamos ahora con un enlace interno que nos genera el siguiente error.
Nos llama la atención «../beqref.cuc«. Parece una encriptación simple, probemos a poner eso mismo en el navegador.
Nuestras sospechas son acertadas, ahora el error muestra esto.
Explotando a la víctima
Probamos varias cosas y al final conseguimos algo relevante con «order2.php«.
Una vez obtenido el contenido del archivo «.htpasswd» lo siguiente es crackear el password con John the Ripper. Nos logueamos en la carpeta secure y reto superado.












































































