Karpoff’s CrackME1 Keygen

Introducción
El otro día navegando por la red fuí a dar a un mirror de la gran web «Karpoff Spanish Tutor«. Para los que no la conozcais, debeis saber que fué una referencia para el Cracking en la escena nacional. Contenía manuales, cursos, utilidades y todo lo que te pudieras imaginar y/o necesitar para iniciarte en el mundillo del Cracking. Por aquel entonces yo era un cigoto en esto de la Ingeniería Inversa pero la web de Karpoff sentó mis bases y contribuyó a mi afán por saber y compartir. El lector debería saber que estamos hablando de finales de los 90, por lo que este crackme y sucesivos de la web de Karpoff ahora pueden parecer más fáciles pero hay que tener en cuenta que ahora tenemos mejores herramientas.
El objetivo es sacar un serial valido o hacer un generador de llaves, esta hecho para newbies y no tiene ninguna otra proteccion.
El crackme está hecho en Delphi y no tiene ningún tipo de protección antidebug ni nada por el estilo.
El algoritmo
Abrimos Delphi Decompiler y buscamos en los eventos el botón de registro, en este caso se llama «focusClick» y vemos que su RVA apunta a la dirección «442AEC«, lo apuntamos y abrimos el crackme con Ollydbg.
En Olly pulsamos Ctrl+G e introducimos el offset anterior. Un poco más abajo vemos un Call interesante, entramos en el.
Dentro del Call vemos a simple vista dos funciones muy interesantes como son «GetVolumeInformationA» y «GetUserNameA«.
Traceamos el código y vemos que obtiene el número de serie del disco C y el usuario de windows y finalmente los concatena. Se puede ver a simple vista en el Stack o Pila.
No necesitamos saber nada más, probamos el número de serie cazado y funciona. Os adjunto el keygen hecho en C++.
Links
Reto forense de HackThis!!

Intro
We require your services once again. An employee from our company had recently been identified as a known criminal named Brett Thwaits. He is considered to have stolen missile launch codes from the US navy which unfortunately were handed to us for a brief period of time. As of now, we are accussed of the theft and unless we do something about it, we’re gonna end in some serious trouble. Before Brett left, he formatted the thumbdrive which used to store the launch codes. Fortunately, our system had made a backup image of the drive. See if you can recover the fourth launch code. Good luck!
Requerimos una vez más sus servicios. Un empleado de nuestra empresa había sido identificado recientemente como el conocido criminal Brett Thwaites. Se considera que ha robado los códigos de lanzamiento de misiles de la Armada de Estados Unidos, que por desgracia fueron entregados a nosotros por un breve período de tiempo. A partir de ahora, se nos acusa del robo y a menos que hagamos algo al respecto, vamos a tener serios problemas. Antes de que Brett se fuera formateó el dispositivo que se usa para almacenar los códigos de lanzamiento. Afortunadamente, nuestro sistema había hecho una copia de seguridad de la unidad. Mira a ver si puedes recuperar los cuatro códigos de lanzamiento. ¡Buena suerte!
Análisis del archivo
- Fichero: forensics1
- Extensión: img
- Tamaño: 25 MB (26.214.400 bytes)
- Hash MD5: 56e4cd5b8f076ba8b7c020c7339caa2b
Echamos un vistazo al archivo con un editor hexadecimal y vemos encabezados de tipos de archivos conocidos, por lo que la unidad no está encriptada. Al no estar encriptada la imagen, usaremos una herramienta de creación propia, Ancillary. En esta ocasión usaremos la versión 2 alpha, que actualmente está en desarrollo, pero podéis usar tranquilamente la versión 1.x.
Ancillary nos muestra lo que ha encontrado en el archivo por lo que pasamos a analizarlo.
Como siempre os digo en este tipo de retos, es difícil discriminar unos ficheros en favor de otros, ya que no sabemos si lo que buscamos va a estar en una imagen, documento u otro tipo de fichero codificado o no.
Tras analizar todos los ficheros, rápidamente suscitan nuestro interés los ficheros RAR, y más cuando el fichero que contienen es un fichero de audio y su nombre es tan sugerente como «conversation_dtmf.wav«. Como podéis apreciar en la imagen, el fichero RAR está protegido con clave por lo que necesitamos esquivar ese obstaculo.
Recuperando una clave de un archivo RAR
En este caso el software que voy a utilizar es cRARk, pero podéis utilizar cualquier otro. Como se muestra en la imagen de abajo, mi procesador es más bien modesto pero la clave no tiene más que tres dígitos por lo que no supone ninguna dificultad recuperarla.
DTMF (Dual-Tone Multi-Frequency)
Una vez recuperado el archivo WAV, al reproducirlo escuchamos 16 tonos telefónicos que inmediatamente me recuerdan las aventuras del mítico «Capitán Crunch«. Os animo a leer la historia de John Draper y su famosa «Blue Box» ya que no tiene desperdicio y forma parte de la historia del Phreaking.
Por si no conocías la historia, el propio nombre del fichero wav nos da la pista clave de qué buscar al contener las siglas «DTMF«.
Al ser pulsada en el teléfono la tecla correspondiente al dígito que quiere marcar, se envían dos tonos, de distinta frecuencia: uno por columna y otro por fila en la que esté la tecla, que la central decodifica a través de filtros especiales, detectando qué dígito se marcó.
No tenemos más que buscar un decodificador de tonos para obtener los preciados códigos de lanzamiento.
Links
JS Deobfuscator

Se nos entrega un html con un juego que consiste en hacer clic en un botón tantas veces como podamos para ganar al juego. Acompañando al html tenemos un código javascript ofuscado aparentemente con Obfuscator.io
El código javascript ofuscado tiene el siguiente aspecto.
(function(_0x144932, _0xfc69c5) { var _0x187428 = _0x588c,
_0x3064c6 = _0x144932(); while (!![]) { try { var _0xb96d19 = -parseInt(_0x187428(0x1bd)) / 0x1 + parseInt(_0x187428(0x137)) / 0x2 + -parseInt(_0x187428(0x140)) / 0x3 * (-parseInt(_0x187428(0x13b)) / 0x4) + parseInt(_0x187428(0x15e)) / 0x5 * (parseInt(_0x187428(0x18c)) / 0x6) + -parseInt(_0x187428(0x159)) / 0x7 * (parseInt(_0x187428(0x1c3)) / 0x8) + parseInt(_0x187428(0x129)) / 0x9 * (-parseInt(_0x187428(0x149)) / 0xa) + parseInt(_0x187428(0x16d)) / 0xb; if (_0xb96d19 === _0xfc69c5) break;
else _0x3064c6['push'](_0x3064c6['shift']()); } catch (_0x377a04) { _0x3064c6['push'](_0x3064c6['shift']()); } } }(_0x5be3, 0x6fe59));;
function _0x5be3() { var _0x5a2048 = ['Utf8', 'push', 'createDecryptor', 'Malformed\x20UTF-8\x20data', '_ENC_XFORM_MODE', 'string', '_prevBlock', 'extend', '_doReset', 'AnsiX923', 'error', 'fromCharCode', 'object', '130340XnpiqM', '#res', 'HmacSHA256', 'DES', '4FuuDzS', 'finalize', 'byteLength', 'salt', '_keyPriorReset', '372669TnxSTf', '_xformMode', 'HMAC', 'stringify', 'Latin1', 'cfg', 'start', 'padding', 'show', '47650FNyFfQ', 'parse', 'TripleDES', 'MD5', 'ZeroPadding', 'length', 'Rabbit', 'console', 'Base', 'HmacSHA3', 'kdf', '_doFinalize', 'drop', 'BufferedBlockAlgorithm', 'Cipher', 'HmacSHA1', '7PKTjbP', 'CTR', '_reverseMap', 'clone', 'Encryptor', '43750GcrrDy', 'SHA384', 'byteOffset', 'indexOf', 'Word', '#loader', 'algo', 'apply', 'bind', 'HmacMD5', 'Base64', '_key', 'createEncryptor', 'min', '_counter', '4232173VijiOj', '_lBlock', 'You\x20Lose', 'ECB', 'BlockCipherMode', 'ciphertext', 'floor', 'constructor', 'log', 'search', 'flush', 'Iso10126', 'update', 'NoPadding', 'max', 'HmacSHA384', 'SHA512', 'decrypt', '_des2', '(((.+)+)+)+$', 'high', 'U2FsdGVkX189ylLOlgNSxq/TLeSxBr7cYDcRBgMXXS9VmwusKZx1XFDNdpkwg24v98iYGnUATwQVyWwFnlyoCg==', 'charAt', 'return\x20(function()\x20', 'pow', 'prototype', 'compute', 'reset', 'warn', '_rBlock', 'HmacSHA512', '498WcTnbi', 'join', 'HmacSHA224', 'display', '#trim', 'StreamCipher', 'enc', 'click', '#statistic', 'random', 'keySize', 'SHA1', '_process', 'sigBytes', '$super', '#mybut', 'clamp', 'RC4', '_invSubKeys', 'loader', '_cipher', '#backstart', 'BlockCipher', 'formatter', 'WordArray', 'slice', 'decryptBlock', '_minBufferSize', 'execute', '_iv', '_hash', 'mixIn', '__proto__', 'text', 'concat', 'RabbitLegacy', 'ceil', 'splice', 'Utf16LE', 'array[0]', 'function', 'SHA3', 'charCodeAt', 'EvpKDF', 'toString', 'css', '_state', 'Decryptor', 'Hex', '82275HVLogQ', 'ivSize', 'encrypt', '_des1', '_mode', 'words', '5353976ERfqhe', 'init', '_hasher', '_createHmacHelper', '_oKey', 'lib', 'CipherParams', 'x64', '_keySchedule', 'RC4Drop', 'PBKDF2', '__creator', '_subKeys', '_nDataBytes', '_DEC_XFORM_MODE', 'format', 'substr', '_createHelper', '_data', '_parse', '#cssfilter', '_map', 'create', 'OpenSSL', 'hasher', 'table', 'key', 'hide', 'iterations', '#timecount', 'undefined', 'pad', '_iKey', 'CBC', 'OFB', '#apply', 'SHA224', '_keystream', 'mode', 'exception', 'call', 'hasOwnProperty', 'Utf16', 'encryptBlock', '_invKeySchedule', '#buttons', '_doCryptBlock', 'RIPEMD160', 'blockSize', 'low', '_des3', '{}.constructor(\x22return\x20this\x22)(\x20)', '_nRounds', 'Hasher', 'addClass', 'AES', 'CFB', 'sqrt', '171bibExj'];
_0x5be3 = function() { return _0x5a2048; }; return _0x5be3(); }
...
Deofuscado el código con la web Obfuscator.io llegamos a interpretar la estructura aunque sigue siendo un galimatías en gran parte. Aún así, si nos fijamos al final encontramos una parte interesante con una clave encriptada cuya desencriptación depende de una comparación (línea 13 resaltada). Invirtiendo esa comparación engañamos al código y obtenemos la flag.
$("#mybut").click(function () {
_0x4171cc++;
$("#cssfilter").text(_0x4171cc);
});
$("#statistic").addClass("hide");
_0x35a8b9 = setInterval(function () {
_0x97292c--;
$("#timecount").text(_0x97292c);
if (_0x97292c == 0x0) {
clearInterval(_0x35a8b9);
$("#mybut").hide();
$("#buttons").show(0x64);
if (_0x4171cc > _0x43eef3) {
$('#trim').text(CryptoJS.AES.decrypt("U2FsdGVkX189ylLOlgNSxq/TLeSxBr7cYDcRBgMXXS9VmwusKZx1XFDNdpkwg24v98iYGnUATwQVyWwFnlyoCg==", "array[0]").toString(CryptoJS.enc.Utf8));
} else {
$("#trim").text("You Lose");
}
}
}, 0x3e8);
intervalcomp = setInterval(function () {
_0x43eef3++;
$('#apply').text(_0x43eef3);
if (_0x97292c == 0x0) {
clearInterval(intervalcomp);
}
}, 0x32);
}
});
¿El crackme de android más famoso del mundo?

Hace unos años cuando empecé a trastear con Android y animado por mi afición a la Ingeniería Inversa, decidí realizar una serie de crackmes. Los dos primeros pasaron algo desapercibidos, pero el Crackme nº3 tuvo una gran repercusión en el mundillo y, aunque no fue el primer crackme para Android ni mucho menos, si que fue uno de los más estudiados. Todos ellos fueron publicados a través de crackmes.de y el nº3 en cuestión el 6 de Noviembre de 2010. Os dejo una lista de unas cuantas webs donde aparece analizado para que veáis la repercusión que a mi parecer tuvo.
Soluciones al crackme
- http://securityxploded.com/android_reversing.php
- http://www.spageek.net/deuruss-android-crackme03/
- https://github.com/spageek/solutions-to-crackmes/commits/master
- https://www.mgp25.com/androidCrackme03/
- http://www.techpluto.com/how-to-crack-games-on-android/
- http://docslide.us/documents/club-hack-mag-dec-2010.html
- http://www.symbianize.com/archive/index.php/t-678834.html
- http://feeds.feedburner.com/nyoret
- http://crackmes.de/users/deurus/android_crackme03/solutions/diff/browse
- Android Reverse Engineering – A Kick Start (Indian First Digital Security Magazine)
- http://www.programlife.net/android-crackme3.html
- http://www.codexiu.cn/android/blog/36058/
- http://blog.btrisk.com/2014/04/AndroidReverseTersineMuhendislikSmali.html
Referencias al crackme
Links
Solución al KeyGenMe1 (RSA127) de C00lw0lf

- Introducción
- Funcionamiento de RSA
- OllyDbg
- Calculando la clave privada (d)
- Ejemplo operacional
- Keygen
- Links
Introducción
Segunda crackme con RSA que afrontamos. Esta vez se trata de un crackme realizado en VC++ 7.0 y en sus entrañas utiliza RSA-127. Una cosa que no comenté en la entrega anterior (RSA-200), es que conviene utilizar el plugin Kanal de PEiD para localizar cuando se utilizan números grandes o determinados hashes como MD5 o SHA1.
Otra cosa es que os quería comentar es la coletilla 127. Esta lo determina el módulo n e indica el número de bits de éste.
Funcionamiento de RSA
- Inicialmente es necesario generar aleatoriamente dos números primos grandes, a los que llamaremos p y q.
- A continuación calcularemos n como producto de p y q:
n = p * q
- Se calcula fi:
fi(n)=(p-1)(q-1)
- Se calcula un número natural e de manera que MCD(e, fi(n))=1 , es decir e debe ser primo relativo de fi(n). Es lo mismo que buscar un numero impar por el que dividir fi(n) que de cero como resto.
- Mediante el algoritmo extendido de Euclides se calcula d que es el inverso modular de e.
Puede calcularse d=((Y*fi(n))+1)/e para Y=1,2,3,... hasta encontrar un d entero.
- El par de números (e,n) son la clave pública.
- El par de números (d,n) son la clave privada.
- Cifrado: La función de cifrado es.
c = m^e mod n
- Descifrado: La función de descifrado es.
m = c^d mod n
OllyDbg
Con OllyDbg analizamos la parte del código que nos interesa.
0040109B . 68 00010000 PUSH 100 ; /Count = 100 (256.) 004010A0 . 52 PUSH EDX ; |Buffer = RSA127.<ModuleEntryPoint> 004010A1 . 68 EA030000 PUSH 3EA ; |ControlID = 3EA (1002.) 004010A6 . 8B8C24 28020000 MOV ECX,DWORD PTR SS:[ESP+228] ; | 004010AD . 51 PUSH ECX ; |hWnd = NULL 004010AE . FF15 F0B04000 CALL DWORD PTR DS:[<&USER32.GetDlgItemTex>; \GetDlgItemTextA 004010B4 . 8D5424 04 LEA EDX,DWORD PTR SS:[ESP+4] 004010B8 . 57 PUSH EDI 004010B9 . 52 PUSH EDX ; RSA127.<ModuleEntryPoint> 004010BA . 50 PUSH EAX ; kernel32.BaseThreadInitThunk 004010BB . E8 201E0000 CALL RSA127.00402EE0 004010C0 . 83C4 0C ADD ESP,0C 004010C3 . 8D9424 04010000 LEA EDX,DWORD PTR SS:[ESP+104] 004010CA . 68 00010000 PUSH 100 ; /Count = 100 (256.) 004010CF . 52 PUSH EDX ; |Buffer = RSA127.<ModuleEntryPoint> 004010D0 . 68 EB030000 PUSH 3EB ; |ControlID = 3EB (1003.) 004010D5 . 8B8C24 28020000 MOV ECX,DWORD PTR SS:[ESP+228] ; | 004010DC . 51 PUSH ECX ; |hWnd = NULL 004010DD . FF15 F0B04000 CALL DWORD PTR DS:[<&USER32.GetDlgItemTex>; \GetDlgItemTextA 004010E3 . 8D9424 04010000 LEA EDX,DWORD PTR SS:[ESP+104] 004010EA . 52 PUSH EDX ; RSA127.<ModuleEntryPoint> 004010EB . 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] 004010EF . 51 PUSH ECX 004010F0 . E8 5B1F0000 CALL RSA127.00403050 004010F5 . 68 08B14000 PUSH RSA127.0040B108 ; ASCII "666AAA422FDF79E1D4E41EDDC4D42C51" 004010FA . 55 PUSH EBP 004010FB . E8 501F0000 CALL RSA127.00403050 00401100 . 68 2CB14000 PUSH RSA127.0040B12C ; ASCII "29F8EEDBC262484C2E3F60952B73D067" 00401105 . 56 PUSH ESI 00401106 . E8 451F0000 CALL RSA127.00403050 0040110B . 53 PUSH EBX 0040110C . 55 PUSH EBP 0040110D . 56 PUSH ESI 0040110E . 8B5424 24 MOV EDX,DWORD PTR SS:[ESP+24] 00401112 . 52 PUSH EDX ; RSA127.<ModuleEntryPoint> 00401113 . E8 38250000 CALL RSA127.00403650 00401118 . 53 PUSH EBX 00401119 . 57 PUSH EDI 0040111A . E8 31130000 CALL RSA127.00402450 0040111F . 83C4 30 ADD ESP,30 00401122 . 85C0 TEST EAX,EAX ; kernel32.BaseThreadInitThunk 00401124 . 74 12 JE SHORT RSA127.00401138 00401126 . B8 01000000 MOV EAX,1 0040112B . 81C4 08020000 ADD ESP,208 00401131 . 5B POP EBX ; kernel32.7590EE1C 00401132 . 5D POP EBP ; kernel32.7590EE1C 00401133 . 5E POP ESI ; kernel32.7590EE1C 00401134 . 5F POP EDI ; kernel32.7590EE1C 00401135 . C2 1000 RETN 10 00401138 > 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL 0040113A . 68 5CB14000 PUSH RSA127.0040B15C ; |Title = "Yeah!" 0040113F . 68 50B14000 PUSH RSA127.0040B150 ; |Text = "Nice job!!!" 00401144 . 6A 00 PUSH 0 ; |hOwner = NULL 00401146 . FF15 F4B04000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; \MessageBoxA
El código nos proporciona el exponente público (e) y el módulo (n).
- e = 29F8EEDBC262484C2E3F60952B73D067
- n = 666AAA422FDF79E1D4E41EDDC4D42C51
Finalmente realiza un PowMod con el número de serie del disco C y el par de claves (e,n).
Calculando la clave privada (d)
Una vez localizados los datos anteriores lo siguiente es factorizar para obtener los primos p y q y finalmente d.
d = 65537
Ejemplo operacional
Nº serie disco C = -1295811883 Serial = hdd.getBytes()^d mod n Serial = 2d31323935383131383833^65537 mod 666AAA422FDF79E1D4E41EDDC4D42C51 Serial = 1698B6CE6BE0D388C31E8E7895AF445A
Keygen
El keygen está hecho en Java ya que permite trabajar con números grandes de forma sencilla.
JButton btnNewButton = new JButton("Generar");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
BigInteger serial = new BigInteger("0");
BigInteger n = new BigInteger("136135092290573418981810449482425576529");
BigInteger d = new BigInteger("415031");
String hdd = t1.getText();
BigInteger tmp = new BigInteger(hdd.getBytes());
serial = tmp.modPow(d, n);
t2.setText(serial.toString(16).toUpperCase());
}
});
Links
- RSA (wikipedia)
- El algoritmo RSA y la factorización de números grandes (recomendable)
- Exponenciación modular (wikipedia)
- RSA Tool
- Big Integer Calculator v1.14
- Crackme y Keygen
ThisIsLegal.com – Realistic Challenge 5

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
Analizando a la víctima
Echamos un vistazo a la web y lo único interesante que vemos es un buscador.
Miramos el código fuente y vemos una ruta interesante.
Ahora fijémonos en el menú productos. Pinchamos sobre cualquier producto y a continuación en la imagen para ampliarla, veremos el siguiente enlace.
Explotando la víctima
Vamos a ver si podemos explotar «i.php«. Probamos a obtener información sensible del servidor.
Probamos «http://www.thisislegal.com/nc/i.php?img=adm/login.pwd» y nos da error, seguramente por que está anexionando la extensión de la imagen, es decir, el script está interpretando esto:
Vamos a anularlo con un caracter nulo. Probamos y ahora si.
El password está en base64. Lo decodificamos online, nos logueamos y reto superado.
Links
Solución al Time Trial de Detten

Intro
Hoy tenemos aquí otro crackme sacado del baúl de los recuerdos. En este caso se trata de una protección por tiempo límite a través de un keyfile llamado «data.det«. Disponemos de tres días o nueve sesiones antes de que el crackme expire.
El algoritmo
La primera vez que ejecutamos el crackme, crea el fichero «data.det» y realiza lo siguiente:
- Lee el fichero data.det que inicialmente tiene 10 bytes a cero y el último byte un 60(`).
- Comprueba que tenga 11 bytes (B) y continúa.
- Al detectar el fichero vacío le mete valores codificandolos con XOR 6969. Los almacena en memoria 4030AB y siguientes.
00401000 t>/$ 6A 00 PUSH 0 ; /pModule = NULL 00401002 |. E8 0B020000 CALL <JMP.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA 00401007 |. A3 F4304000 MOV DWORD PTR DS:[4030F4],EAX ; kernel32.BaseThreadInitThunk 0040100C |. 6A 00 PUSH 0 ; /hTemplateFile = NULL 0040100E |. 68 80000000 PUSH 80 ; |Attributes = NORMAL 00401013 |. 6A 03 PUSH 3 ; |Mode = OPEN_EXISTING 00401015 |. 6A 00 PUSH 0 ; |pSecurity = NULL 00401017 |. 6A 00 PUSH 0 ; |ShareMode = 0 00401019 |. 68 000000C0 PUSH C0000000 ; |Access = GENERIC_READ|GENERIC_WRITE 0040101E |. 68 A2304000 PUSH timetria.004030A2 ; |FileName = "DATA.DET" 00401023 |. E8 DE010000 CALL <JMP.&KERNEL32.CreateFileA> ; \CreateFileA 00401028 |. 83F8 FF CMP EAX,-1 0040102B |. 74 07 JE SHORT timetria.00401034 0040102D |. A3 14314000 MOV DWORD PTR DS:[403114],EAX ; kernel32.BaseThreadInitThunk 00401032 |. EB 18 JMP SHORT timetria.0040104C 00401034 |> 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL 00401036 |. 68 38304000 PUSH timetria.00403038 ; |Title = "I don't like this !" 0040103B |. 68 02304000 PUSH timetria.00403002 ; |Text = "Where is my DATA.DET file?\r\nI can't run without it..." 00401040 |. 6A 00 PUSH 0 ; |hOwner = NULL 00401042 |. E8 B3010000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA 00401047 |. E9 22010000 JMP timetria.0040116E 0040104C |> 6A 00 PUSH 0 ; /pOverlapped = NULL 0040104E |. 68 E0304000 PUSH timetria.004030E0 ; |pBytesRead = timetria.004030E0 00401053 |. 6A 32 PUSH 32 ; |BytesToRead = 32 (50.) 00401055 |. 68 AB304000 PUSH timetria.004030AB ; |Buffer = timetria.004030AB 0040105A |. FF35 14314000 PUSH DWORD PTR DS:[403114] ; |hFile = NULL 00401060 |. E8 B9010000 CALL <JMP.&KERNEL32.ReadFile> ; \ReadFile 00401065 |. 833D E0304000 0B CMP DWORD PTR DS:[4030E0],0B 0040106C |. 0F85 E9000000 JNZ timetria.0040115B 00401072 |. BB AB304000 MOV EBX,timetria.004030AB 00401077 |. 68 E4304000 PUSH timetria.004030E4 ; /pSystemTime = timetria.004030E4 0040107C |. E8 97010000 CALL <JMP.&KERNEL32.GetSystemTime> ; \GetSystemTime 00401081 |. 803B 00 CMP BYTE PTR DS:[EBX],0 00401084 |. 75 22 JNZ SHORT timetria.004010A8 ; Si existe el fichero salta a las comprobaciones 00401086 |. 51 PUSH ECX 00401087 |. 33C9 XOR ECX,ECX 00401089 |. EB 15 JMP SHORT timetria.004010A0 0040108B |> 66:8B81 E4304000 /MOV AX,WORD PTR DS:[ECX+4030E4] ; | 00401092 |. 66:35 6969 |XOR AX,6969 ; | 00401096 |. 66:8981 AB304000 |MOV WORD PTR DS:[ECX+4030AB],AX ; | 0040109D |. 83C1 02 |ADD ECX,2 ; | Bucle de codificacion de data.det por primera vez 004010A0 |> 83F9 08 CMP ECX,8 ; | 004010A3 |.^ 76 E6 \JBE SHORT timetria.0040108B ; | 004010A5 |. 59 POP ECX ; kernel32.7580EE1C 004010A6 |. EB 3A JMP SHORT timetria.004010E2
Vigilando el proceso de creación del archivo podemos llegar a la conclusión de como se genera.
- Los dos primeros bytes son el año = 2014 = 0x7DE. 7DE XOR 6969 = 6EB7.
- Los dos siguientes son el mes = 10 = 0xA. A XOR 6969 = 6963.
- Los dos siguientes usa un 4 (día de la semana???) = 0x4. 4 XOR 6969 = 696D.
- Los dos siguientes son el día del mes = 2 = 0x2. 2 XOR 6969 = 696B
- Los dos siguientes usa un 1 = 0x1. 1 XOR 6969 = 6968.
- El número de sesiones lo deja como está, 60.
Estado de la memoria:
004030AB B7 6E 63 69 6D 69 6B 69 68 69 60 ·ncimikihi`
- Finalmente le resta 1 al número de sesiones y guarda el fichero.
004010E2 |> \A0 B5304000 MOV AL,BYTE PTR DS:[4030B5] 004010E7 |. 34 69 XOR AL,69 004010E9 |. 3C 00 CMP AL,0 004010EB |. /74 59 JE SHORT timetria.00401146 004010ED |. |FEC8 DEC AL 004010EF |. |A2 01304000 MOV BYTE PTR DS:[403001],AL 004010F4 |. |34 69 XOR AL,69 004010F6 |. |A2 B5304000 MOV BYTE PTR DS:[4030B5],AL 004010FB |. |6A 00 PUSH 0 ; /Origin = FILE_BEGIN 004010FD |. |6A 00 PUSH 0 ; |pOffsetHi = NULL 004010FF |. |6A 00 PUSH 0 ; |OffsetLo = 0 00401101 |. |FF35 14314000 PUSH DWORD PTR DS:[403114] ; |hFile = 00000034 (window) 00401107 |. |E8 18010000 CALL <JMP.&KERNEL32.SetFilePointer> ; \SetFilePointer 0040110C |. |6A 00 PUSH 0 ; /pOverlapped = NULL 0040110E |. |68 E0304000 PUSH timetria.004030E0 ; |pBytesWritten = timetria.004030E0 00401113 |. |6A 0B PUSH 0B ; |nBytesToWrite = B (11.) 00401115 |. |68 AB304000 PUSH timetria.004030AB ; |Buffer = timetria.004030AB 0040111A |. |FF35 14314000 PUSH DWORD PTR DS:[403114] ; |hFile = 00000034 (window) 00401120 |. |E8 05010000 CALL <JMP.&KERNEL32.WriteFile> ; \WriteFile
En cada ejecución realiza tres comprobaciones.
Recordemos el contenido del fichero:
B7 6E 63 69 6D 69 6B 69 68 69 60 ·ncimikihi`
1) Mes y año (4 primeros bytes)
004010A8 |> \8B0D AB304000 MOV ECX,DWORD PTR DS:[4030AB] ; ECX=69636EB7 004010AE |. 81F1 69696969 XOR ECX,69696969 ; 69636EB7 xor 69696969 = A07DE (A = mes y 7DE = año) 004010B4 |. A1 E4304000 MOV EAX,DWORD PTR DS:[4030E4] 004010B9 |. 3BC1 CMP EAX,ECX ; Compara con mes y año actuales 004010BB |. 0F85 85000000 JNZ timetria.00401146 ; Bad boy
2) Día (7º y 8º byte)
004010C1 |. 66:8B0D B1304000 MOV CX,WORD PTR DS:[4030B1] ; CX = 696B 004010C8 |. 66:81F1 6969 XOR CX,6969 ; 696B xor 6969 = 2 004010CD |. 66:A1 EA304000 MOV AX,WORD PTR DS:[4030EA] ; AX = día actual obtenido con GetSystemTime 004010D3 |. 66:2BC1 SUB AX,CX ; Los resta 004010D6 |. 66:83F8 03 CMP AX,3 ; Compara con 3 004010DA |. 77 6A JA SHORT timetria.00401146 ; Si el resultado >=3 Bad Boy
3) Sesiones (11º byte)
004010DC |. 2805 00304000 SUB BYTE PTR DS:[403000],AL ; 004010E2 |> A0 B5304000 MOV AL,BYTE PTR DS:[4030B5] ; AL = numero de sesiones actual 004010E7 |. 34 69 XOR AL,69 ; 61 Xor 69 = 8 004010E9 |. 3C 00 CMP AL,0 ; Compara con 0 004010EB |. 74 59 JE SHORT timetria.00401146 ; Salta si hemos superado las 9 sesiones. Bad boy 004010ED |. FEC8 DEC AL ; Si no le resta 1 004010EF |. A2 01304000 MOV BYTE PTR DS:[403001],AL 004010F4 |. 34 69 XOR AL,69 ; y le hace xor 69 para codificar el nuevo valor de sesión 004010F6 |. A2 B5304000 MOV BYTE PTR DS:[4030B5],AL
Con esto ya podemos alterar el archivo a nuestro antojo sin necesidad de parchear.
Keygen
Try
ano = ano Xor 26985
mes = mes Xor 26985
dia = dia Xor 26985
anos = Hex(ano).ToString
mess = Hex(mes).ToString
dias = Hex(dia).ToString
If txtsesiones.Text <= 255 Then
sesioness = Hex(sesiones)
Else
sesiones = 255
End If
sesioness = Hex(sesiones)
'key = 00 00 00 00 00 00 00 00 00 00 00
'key = año+año+mes+mes+X+X+dia+dia+X+sesiones
key = Chr(Convert.ToInt32(anos.Substring(2, 2), 16)) & Chr(Convert.ToInt32(anos.Substring(0, 2), 16)) _
& Chr(Convert.ToInt32(mess.Substring(2, 2), 16)) & Chr(Convert.ToInt32(mess.Substring(0, 2), 16)) _
& Chr(106) & Chr(105) _
& Chr(Convert.ToInt32(dias.Substring(2, 2), 16)) & Chr(Convert.ToInt32(dias.Substring(0, 2), 16)) _
& Chr(103) & Chr(105) _
& Chr(Convert.ToInt32(sesioness.Substring(0, 2), 16))
'Creo el archivo llave
Dim ruta As String = Application.StartupPath & "\DATA.DET"
If File.Exists(ruta) Then
File.Delete(ruta)
End If
Using sw As StreamWriter = New StreamWriter(ruta, True, System.Text.Encoding.Default)
sw.Write(key)
sw.Close()
End Using
MsgBox("DATA.DET generado correctamente", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Info")
Catch ex As Exception
MsgBox("Ocurrió algún error" & vbCrLf & ex.Message)
End Try
Links
Solución al Crackme 7 de Scarebyte

- Introducción
- Desempacado
- Eliminar la NAG
- Password
- Nº serie asociado a un nombre
- Checkbox
- Trackbar
- Links
Introducción
Aquí tenemos un Crackme clásico creado por Scarebyte hallá por el año 2000 y que cuenta con varias fases siendo un crackme muy interesante para iniciarse o simplemente para divertirse. Al estar realizado en Delphi, los apartados de las checkboxes y de las trackbars se simplifican y mucho, pero aún así hay que currarselo un poco para dejar todo bien atado. Si os fijáis en las soluciones que aparecen en crackmes.de, en aquellos años se usaba DEDE y aunque yo usaré otra herramienta, DEDE sigue siendo igual de útil.
Desempacado
PEiD nos dice que nos enfrentamos a ASPack 1.08.03 -> Alexey Solodovnikov, así que vamos al lío.
Eliminar la NAG
Tan sencillo como poner un Breakpoint a User32.MessageBoxA. La llamada a NOPear está en la dirección 441CF2.
Password
Desde las string references localizamos los mensajes de chico bueno y chico malo que nos llevan al código a analizar.
0044C3CD |. E8 5294FDFF CALL CrackMe_.00425824 0044C3D2 |. 8B45 FC MOV EAX,[LOCAL.1] 0044C3D5 |. E8 9A76FBFF CALL CrackMe_.00403A74 0044C3DA |. 83F8 0C CMP EAX,0C ; Lengh C = 12 0044C3DD |. 0F85 53010000 JNZ CrackMe_.0044C536 ; Salto a chico malo 0044C3E3 |. 8D55 FC LEA EDX,[LOCAL.1] 0044C3E6 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C3EC |. E8 3394FDFF CALL CrackMe_.00425824 0044C3F1 |. 8B45 FC MOV EAX,[LOCAL.1] 0044C3F4 |. 8038 43 CMP BYTE PTR DS:[EAX],43 ; 1º dígito serial = C 0044C3F7 |. 0F85 27010000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C3FD |. 8D55 F8 LEA EDX,[LOCAL.2] 0044C400 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C406 |. E8 1994FDFF CALL CrackMe_.00425824 0044C40B |. 8B45 F8 MOV EAX,[LOCAL.2] 0044C40E |. 8078 03 6F CMP BYTE PTR DS:[EAX+3],6F ; 4º dígito serial = o 0044C412 |. 0F85 0C010000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C418 |. 8D55 F4 LEA EDX,[LOCAL.3] 0044C41B |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C421 |. E8 FE93FDFF CALL CrackMe_.00425824 0044C426 |. 8B45 F4 MOV EAX,[LOCAL.3] 0044C429 |. 8078 08 6F CMP BYTE PTR DS:[EAX+8],6F ; 9º dígito serial = o 0044C42D |. 0F85 F1000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C433 |. 8D55 F0 LEA EDX,[LOCAL.4] 0044C436 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C43C |. E8 E393FDFF CALL CrackMe_.00425824 0044C441 |. 8B45 F0 MOV EAX,[LOCAL.4] 0044C444 |. 8078 01 6C CMP BYTE PTR DS:[EAX+1],6C ; 2º dígito serial = l 0044C448 |. 0F85 D6000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C44E |. 8D55 EC LEA EDX,[LOCAL.5] 0044C451 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C457 |. E8 C893FDFF CALL CrackMe_.00425824 0044C45C |. 8B45 EC MOV EAX,[LOCAL.5] 0044C45F |. 8078 04 20 CMP BYTE PTR DS:[EAX+4],20 ; 5º dígito serial = espacio 0044C463 |. 0F85 BB000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C469 |. 8D55 E8 LEA EDX,[LOCAL.6] 0044C46C |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C472 |. E8 AD93FDFF CALL CrackMe_.00425824 0044C477 |. 8B45 E8 MOV EAX,[LOCAL.6] 0044C47A |. 8078 0A 52 CMP BYTE PTR DS:[EAX+A],52 ; 11º dígito serial = R 0044C47E |. 0F85 A0000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C484 |. 8D55 E4 LEA EDX,[LOCAL.7] 0044C487 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C48D |. E8 9293FDFF CALL CrackMe_.00425824 0044C492 |. 8B45 E4 MOV EAX,[LOCAL.7] 0044C495 |. 8078 07 75 CMP BYTE PTR DS:[EAX+7],75 ; 8º dígito serial = u 0044C499 |. 0F85 85000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C49F |. 8D55 E0 LEA EDX,[LOCAL.8] 0044C4A2 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4A8 |. E8 7793FDFF CALL CrackMe_.00425824 0044C4AD |. 8B45 E0 MOV EAX,[LOCAL.8] 0044C4B0 |. 8078 09 6E CMP BYTE PTR DS:[EAX+9],6E ; 10º dígito serial = n 0044C4B4 |. 75 6E JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4B6 |. 8D55 DC LEA EDX,[LOCAL.9] 0044C4B9 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4BF |. E8 6093FDFF CALL CrackMe_.00425824 0044C4C4 |. 8B45 DC MOV EAX,[LOCAL.9] 0044C4C7 |. 8078 02 6E CMP BYTE PTR DS:[EAX+2],6E ; 3º dígito serial = n 0044C4CB |. 75 57 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4CD |. 8D55 D8 LEA EDX,[LOCAL.10] 0044C4D0 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4D6 |. E8 4993FDFF CALL CrackMe_.00425824 0044C4DB |. 8B45 D8 MOV EAX,[LOCAL.10] 0044C4DE |. 8078 05 69 CMP BYTE PTR DS:[EAX+5],69 ; 6º dígito serial = i 0044C4E2 |. 75 40 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4E4 |. 8D55 D4 LEA EDX,[LOCAL.11] 0044C4E7 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4ED |. E8 3293FDFF CALL CrackMe_.00425824 0044C4F2 |. 8B45 D4 MOV EAX,[LOCAL.11] 0044C4F5 |. 8078 0B 6E CMP BYTE PTR DS:[EAX+B],6E ; 12º dígito serial = n 0044C4F9 |. 75 29 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4FB |. 8D55 D0 LEA EDX,[LOCAL.12] 0044C4FE |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C504 |. E8 1B93FDFF CALL CrackMe_.00425824 0044C509 |. 8B45 D0 MOV EAX,[LOCAL.12] 0044C50C |. 8078 06 67 CMP BYTE PTR DS:[EAX+6],67 ; 7º dígito serial = g 0044C510 |. 75 12 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C512 |. BA 78C54400 MOV EDX,CrackMe_.0044C578 ; ASCII "Right Password" 0044C517 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C51D |. E8 3293FDFF CALL CrackMe_.00425854 0044C522 |. EB 22 JMP SHORT CrackMe_.0044C546 0044C524 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password" 0044C529 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C52F |. E8 2093FDFF CALL CrackMe_.00425854 0044C534 |. EB 10 JMP SHORT CrackMe_.0044C546 0044C536 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password" Chequeo rápido ABCD EFGHIJK Clno iguonRn ; 1º dígito serial = C ; 4º dígito serial = o ; 9º dígito serial = o ; 2º dígito serial = l ; 5º dígito serial = espacio ; 11º dígito serial = R ; 8º dígito serial = u ; 10º dígito serial = n ; 3º dígito serial = n ; 6º dígito serial = i ; 12º dígito serial = n ; 7º dígito serial = g
Básicamente chequea la frase «Cool Running» de forma desordenada como se ve justo encima, siendo el password correcto «Clno iguonRn«. Os dejo el código para que lo analicéis.
Nº serie asociado a un nombre
De nuevo con las string references localizamos el código.
0044C648 /. 55 PUSH EBP 0044C649 |. 8BEC MOV EBP,ESP 0044C64B |. 83C4 F8 ADD ESP,-8 0044C64E |. 53 PUSH EBX 0044C64F |. 56 PUSH ESI 0044C650 |. 33C9 XOR ECX,ECX 0044C652 |. 894D F8 MOV [LOCAL.2],ECX 0044C655 |. 8BF0 MOV ESI,EAX 0044C657 |. 33C0 XOR EAX,EAX 0044C659 |. 55 PUSH EBP 0044C65A |. 68 83C74400 PUSH CrackMe_.0044C783 0044C65F |. 64:FF30 PUSH DWORD PTR FS:[EAX] 0044C662 |. 64:8920 MOV DWORD PTR FS:[EAX],ESP 0044C665 |. 33C0 XOR EAX,EAX 0044C667 |. 8945 FC MOV [LOCAL.1],EAX 0044C66A |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre 0044C66F |. E8 0074FBFF CALL CrackMe_.00403A74 0044C674 |. 83F8 06 CMP EAX,6 ; Cmp lengh nombre con 6 0044C677 |. 0F8E F0000000 JLE CrackMe_.0044C76D ; Salta si <= 6 0044C67D |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre 0044C682 |. E8 ED73FBFF CALL CrackMe_.00403A74 0044C687 |. 83F8 14 CMP EAX,14 ; Cmp lengh nombre con 20 (14h) 0044C68A |. 0F8D DD000000 JGE CrackMe_.0044C76D ; salta si >= 20 0044C690 |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] 0044C695 |. E8 DA73FBFF CALL CrackMe_.00403A74 0044C69A |. 85C0 TEST EAX,EAX 0044C69C |. 7E 17 JLE SHORT CrackMe_.0044C6B5 0044C69E |. BA 01000000 MOV EDX,1 0044C6A3 |> 8B0D 80F84400 /MOV ECX,DWORD PTR DS:[44F880] ; Bucle in 0044C6A9 |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1] 0044C6AE |. 014D FC |ADD [LOCAL.1],ECX ; Suma dig nombre y guarda en 12FBC4 0044C6B1 |. 42 |INC EDX 0044C6B2 |. 48 |DEC EAX 0044C6B3 |.^ 75 EE \JNZ SHORT CrackMe_.0044C6A3 ; Bucle out 0044C6B5 |> A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia 0044C6BA |. E8 B573FBFF CALL CrackMe_.00403A74 0044C6BF |. 83F8 02 CMP EAX,2 ; Cmp lengh compañia con 2 0044C6C2 |. 7E 18 JLE SHORT CrackMe_.0044C6DC ; Salta si <= 2 0044C6C4 |. A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia 0044C6C9 |. E8 A673FBFF CALL CrackMe_.00403A74 0044C6CE |. 83F8 08 CMP EAX,8 ; Cmp lengh compañia con 8 0044C6D1 |. 7D 09 JGE SHORT CrackMe_.0044C6DC ; Salta si >= 8 0044C6D3 |. 8B45 FC MOV EAX,[LOCAL.1] ; Eax = sum nombre 0044C6D6 |. 6BC0 02 IMUL EAX,EAX,2 ; Sum nombre * 2 0044C6D9 |. 8945 FC MOV [LOCAL.1],EAX 0044C6DC |> 68 98C74400 PUSH CrackMe_.0044C798 ; ASCII "I Love Cracking and " 0044C6E1 |. 8D55 F8 LEA EDX,[LOCAL.2] 0044C6E4 |. 8B45 FC MOV EAX,[LOCAL.1] 0044C6E7 |. E8 68B0FBFF CALL CrackMe_.00407754 0044C6EC |. FF75 F8 PUSH [LOCAL.2] ; sum del nombre 0044C6EF |. 68 B8C74400 PUSH CrackMe_.0044C7B8 ; ASCII " Girls ;)" 0044C6F4 |. B8 8CF84400 MOV EAX,CrackMe_.0044F88C 0044C6F9 |. BA 03000000 MOV EDX,3 0044C6FE |. E8 3174FBFF CALL CrackMe_.00403B34 ; Concatena 1º frase + sum nombre + 2ºfrase 0044C703 |. 33C0 XOR EAX,EAX 0044C705 |. 8945 FC MOV [LOCAL.1],EAX 0044C708 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888] ; Eax = Serial 0044C70D |. E8 6273FBFF CALL CrackMe_.00403A74 0044C712 |. 8BD8 MOV EBX,EAX 0044C714 |. A1 8CF84400 MOV EAX,DWORD PTR DS:[44F88C] 0044C719 |. E8 5673FBFF CALL CrackMe_.00403A74 0044C71E |. 3BD8 CMP EBX,EAX ; Compara tamaño frase con tamaño serial 0044C720 |. 75 4B JNZ SHORT CrackMe_.0044C76D 0044C722 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888] 0044C727 |. E8 4873FBFF CALL CrackMe_.00403A74 0044C72C |. 85C0 TEST EAX,EAX 0044C72E |. 7E 27 JLE SHORT CrackMe_.0044C757 0044C730 |. BA 01000000 MOV EDX,1 0044C735 |> 8B0D 88F84400 /MOV ECX,DWORD PTR DS:[44F888] ; Bucle in --> 0044C73B |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1] 0044C740 |. 034D FC |ADD ECX,[LOCAL.1] 0044C743 |. 8B1D 8CF84400 |MOV EBX,DWORD PTR DS:[44F88C] 0044C749 |. 0FB65C13 FF |MOVZX EBX,BYTE PTR DS:[EBX+EDX-1] ; Compara dígito a dígito nuestro serial 0044C74E |. 2BCB |SUB ECX,EBX ; con la concatenación anterior 0044C750 |. 894D FC |MOV [LOCAL.1],ECX 0044C753 |. 42 |INC EDX 0044C754 |. 48 |DEC EAX 0044C755 |.^ 75 DE \JNZ SHORT CrackMe_.0044C735 ; <-- Bucle out 0044C757 |> 837D FC 00 CMP [LOCAL.1],0 0044C75B |. 75 10 JNZ SHORT CrackMe_.0044C76D ; Salta si algo ha ido mal 0044C75D |. 8B86 14030000 MOV EAX,DWORD PTR DS:[ESI+314] 0044C763 |. BA CCC74400 MOV EDX,CrackMe_.0044C7CC ; "You have found the correct Serial :)"
En resumen
- Tamaño del nombre entre 7 y 19.
- Tamaño de la compañía entre 3 y 7 aunque no interviene en el serial.
- Suma los valores ascii de los dígitos del nombre y lo multiplica por 2.
- Concatena «I Love Cracking and » + «sum del nombre» + » Girls ;)».
Checkbox
Para afrontar esta parte del reto vamos a usar una herramienta llamada Interactive Delphi Reconstructor o IDR. En su día la mejor herramienta era DEDE, pero IDR a mi parecer es algo más potente.
Básicamente IDR nos permite sin quebraderos de cabeza localizar el código del botón que comprueba la secuencia de checkboxes correcta. Cargamos el crackme en IDR y dentro de la pestaña «Units (F2)«, abajo del todo hacemos doble click sobre «F Crack» y vemos que nos muestra todos los controles del formulario. El botón que nos interesa se llama «SpeedButton3«.
Si hacemos doble click sobre el nos muestra el código que se muestra a continuación.
crack::TForm1.SpeedButton3Click 0044C7F4 push ebp 0044C7F5 mov ebp,esp 0044C7F7 push 0 0044C7F9 push ebx 0044C7FA mov ebx,eax 0044C7FC xor eax,eax 0044C7FE push ebp 0044C7FF push 44C920 0044C804 push dword ptr fs:[eax] 0044C807 mov dword ptr fs:[eax],esp 0044C80A mov eax,dword ptr [ebx+324]; TForm1.cb3:TCheckBox 0044C810 mov edx,dword ptr [eax] 0044C812 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C818 test al,al >0044C81A je 0044C8ED 0044C820 mov eax,dword ptr [ebx+328]; TForm1.cb5:TCheckBox 0044C826 mov edx,dword ptr [eax] 0044C828 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C82E test al,al >0044C830 je 0044C8ED 0044C836 mov eax,dword ptr [ebx+32C]; TForm1.cb6:TCheckBox 0044C83C mov edx,dword ptr [eax] 0044C83E call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C844 test al,al >0044C846 je 0044C8ED 0044C84C mov eax,dword ptr [ebx+358]; TForm1.cb12:TCheckBox 0044C852 mov edx,dword ptr [eax] 0044C854 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C85A test al,al >0044C85C je 0044C8ED 0044C862 mov eax,dword ptr [ebx+364]; TForm1.cb15:TCheckBox 0044C868 mov edx,dword ptr [eax] 0044C86A call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C870 test al,al >0044C872 je 0044C8ED 0044C874 mov eax,dword ptr [ebx+330]; TForm1.cb20:TCheckBox 0044C87A mov edx,dword ptr [eax] 0044C87C call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C882 test al,al >0044C884 je 0044C8ED 0044C886 mov eax,dword ptr [ebx+34C]; TForm1.cb9:TCheckBox 0044C88C mov edx,dword ptr [eax] 0044C88E call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C894 test al,al >0044C896 je 0044C8ED 0044C898 mov eax,dword ptr [ebx+354]; TForm1.cb11:TCheckBox 0044C89E mov edx,dword ptr [eax] 0044C8A0 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C8A6 test al,al >0044C8A8 je 0044C8ED 0044C8AA mov eax,dword ptr [ebx+35C]; TForm1.cb13:TCheckBox 0044C8B0 mov edx,dword ptr [eax] 0044C8B2 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C8B8 test al,al >0044C8BA je 0044C8ED 0044C8BC mov eax,dword ptr [ebx+33C]; TForm1.cb19:TCheckBox 0044C8C2 mov edx,dword ptr [eax] 0044C8C4 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C8CA test al,al >0044C8CC je 0044C8ED 0044C8CE lea eax,[ebp-4] 0044C8D1 mov edx,44C934; 'Ìõô¸ö÷ê¥ó¤ÉÚÀÆ²Äæââîàä¶¶' 0044C8D6 call @LStrLAsg 0044C8DB lea eax,[ebp-4] 0044C8DE call 0044BF00 0044C8E3 mov eax,dword ptr [ebp-4] 0044C8E6 call ShowMessage >0044C8EB jmp 0044C90A 0044C8ED lea eax,[ebp-4] 0044C8F0 mov edx,44C958; 'Åÿæò衦óàù¨ïêçð®øé¤íüàî诹' 0044C8F5 call @LStrLAsg 0044C8FA lea eax,[ebp-4] 0044C8FD call 0044BF00 0044C902 mov eax,dword ptr [ebp-4] 0044C905 call ShowMessage 0044C90A xor eax,eax 0044C90C pop edx 0044C90D pop ecx 0044C90E pop ecx 0044C90F mov dword ptr fs:[eax],edx 0044C912 push 44C927 0044C917 lea eax,[ebp-4] 0044C91A call @LStrClr 0044C91F ret <0044C920 jmp @HandleFinally <0044C925 jmp 0044C917 0044C927 pop ebx 0044C928 pop ecx 0044C929 pop ebp 0044C92A ret
Como podéis apreciar, las checkboxes involucradas son la 3, 5, 6, 9, 11, 12, 13, 15, 19 y 20. Solo nos falta saber cuales se corresponden con esa numeración y aquí ya depende de cada uno, yo en su día saqué los números a mano mediante el orden de tabulación, pero ya que tenemos IDR, el nos va a dar la solución de una forma sencilla y rápida.
Vamos a la pestaña «Forms (F5)«, seleccionamos la opción Form y hacemos doble click sobre el formulario.
Veréis que aparece el formulario con todos los recursos, incluso los puedes modificar. Localizar los checkboxes ahora es un juego de niños.
Os dejo un vídeo.
Trackbar
De nuevo, con la ayuda de IDR, localizamos la parte del código y analizamos su funcionamiento. Esta parte es la más divertida ya que requiere de un keygen pero en vez de coger el número de serie de una caja de texto lo obtiene de 5 trackbars como muestra la siguiente imagen.
El código de comprobación es el siguiente.
CPU Disasm Address Hex dump Command Comments 0044C1FF |. E8 ECF6FCFF CALL 0041B8F0 ; b^3 0044C204 |. D805 50C34400 FADD DWORD PTR DS:[44C350] ; b^3+5 0044C20A |. D9FA FSQRT ; sqrt(b^3+5) 0044C20C |. E8 F365FBFF CALL 00402804 ; Cos(sqrt(b^3+5)) = U 0044C211 |. DB7D B8 FSTP TBYTE PTR SS:[EBP-48] 0044C214 |. 9B WAIT 0044C215 |. D905 54C34400 FLD DWORD PTR DS:[44C354] ; Coje a 0044C21B |. DC45 E8 FADD QWORD PTR SS:[EBP-18] ; a+1 0044C21E |. D9FA FSQRT ; sqrt(a+1) 0044C220 |. D9E0 FCHS ; -sqrt(a+1) = V 0044C222 |. DB6D B8 FLD TBYTE PTR SS:[EBP-48] 0044C225 |. DEC1 FADDP ST(1),ST 0044C227 |. DB7D AC FSTP TBYTE PTR SS:[EBP-54] 0044C22A |. 9B WAIT 0044C22B |. D905 58C34400 FLD DWORD PTR DS:[44C358] ; coje c 0044C231 |. DC4D D8 FMUL QWORD PTR SS:[EBP-28] ; c*3 0044C234 |. D805 54C34400 FADD DWORD PTR DS:[44C354] ; c*3+1 0044C23A |. D9ED FLDLN2 ; Ln(c*3+1) = X 0044C23C |. D9C9 FXCH ST(1) 0044C23E |. D9F1 FYL2X 0044C240 |. DB6D AC FLD TBYTE PTR SS:[EBP-54] 0044C243 |. DEC1 FADDP ST(1),ST ; U+V+X 0044C245 |. DB7D A0 FSTP TBYTE PTR SS:[EBP-60] 0044C248 |. 9B WAIT 0044C249 |. D905 5CC34400 FLD DWORD PTR DS:[44C35C] ; coje d 0044C24F |. DC45 D0 FADD QWORD PTR SS:[EBP-30] ; d+2 0044C252 |. D9FA FSQRT ; sqrt(d+2) = Y 0044C254 |. DB6D A0 FLD TBYTE PTR SS:[EBP-60] 0044C257 |. DEE1 FSUBRP ST(1),ST ; U+V+X+(-Y) 0044C259 |. D905 58C34400 FLD DWORD PTR DS:[44C358] ; coje e 0044C25F |. DC4D C8 FMUL QWORD PTR SS:[EBP-38] ; e*3 0044C262 |. D835 5CC34400 FDIV DWORD PTR DS:[44C35C] ; (e*3)/2 = Z 0044C268 |. DEC1 FADDP ST(1),ST ; U+V+X+Y+Z 0044C26A |. DB2D 60C34400 FLD TBYTE PTR DS:[44C360] 0044C270 |. DEC1 FADDP ST(1),ST ; U+V+X+Y+Z+0.37 0044C272 |. D80D 6CC34400 FMUL DWORD PTR DS:[44C36C] ; (U+V+X+Y+Z+0.37)*1000 0044C278 |. DD5D F0 FSTP QWORD PTR SS:[EBP-10] 0044C27B |. 9B WAIT 0044C27C |. DD45 F0 FLD QWORD PTR SS:[EBP-10] 0044C27F |. E8 9065FBFF CALL 00402814 ; Redondea((U+V+X+Y+Z+0,37)*1000) 0044C284 |. 8945 98 MOV DWORD PTR SS:[EBP-68],EAX 0044C287 |. 8955 9C MOV DWORD PTR SS:[EBP-64],EDX 0044C28A |. DF6D 98 FILD QWORD PTR SS:[EBP-68] 0044C28D |. 83C4 F4 ADD ESP,-0C 0044C290 |. DB3C24 FSTP TBYTE PTR SS:[LOCAL.33] 0044C293 |. 9B WAIT 0044C294 |. 8D45 FC LEA EAX,[EBP-4] 0044C297 |. E8 68BFFBFF CALL 00408204 0044C29C |. 8D45 FC LEA EAX,[EBP-4] 0044C29F |. E8 5CFCFFFF CALL 0044BF00 ; Llamada de generación de hash ........ 0044BF04 |. 8BF0 MOV ESI,EAX 0044BF06 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] ; EAX = 5415 0044BF08 |. E8 677BFBFF CALL 00403A74 0044BF0D |. 8B15 98EE4400 MOV EDX,DWORD PTR DS:[44EE98] 0044BF13 |. 8902 MOV DWORD PTR DS:[EDX],EAX 0044BF15 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] 0044BF17 |. E8 587BFBFF CALL 00403A74 0044BF1C |. 84C0 TEST AL,AL 0044BF1E |. 76 38 JBE SHORT 0044BF58 0044BF20 |. 880424 MOV BYTE PTR SS:[LOCAL.3],AL 0044BF23 |. B3 01 MOV BL,1 0044BF25 |> B8 1C000000 /MOV EAX,1C 0044BF2A |. E8 516AFBFF |CALL 00402980 0044BF2F |. 0D 80000000 |OR EAX,00000080 0044BF34 |. 8BFB |MOV EDI,EBX 0044BF36 |. 81E7 FF000000 |AND EDI,000000FF 0044BF3C |. 8B16 |MOV EDX,DWORD PTR DS:[ESI] 0044BF3E |. 0FB6543A FF |MOVZX EDX,BYTE PTR DS:[EDI+EDX-1] ; Coje dig a dig el hash, en este caso 5415 0044BF43 |. 33C2 |XOR EAX,EDX ; 1 dig XOR 83; 2 dig XOR 89; 3 dig XOR 86; 4 dig XOR 8D 0044BF45 |. 50 |PUSH EAX 0044BF46 |. 8BC6 |MOV EAX,ESI 0044BF48 |. E8 F77CFBFF |CALL 00403C44 0044BF4D |. 5A |POP EDX 0044BF4E |. 885438 FF |MOV BYTE PTR DS:[EDI+EAX-1],DL 0044BF52 |. 43 |INC EBX 0044BF53 |. FE0C24 |DEC BYTE PTR SS:[LOCAL.3] 0044BF56 |.^ 75 CD \JNZ SHORT 0044BF25 ........ 0044C2AC |. E8 D378FBFF CALL 00403B84 ; Llamada a comparación ........ 00403BAD |> /8B0E /MOV ECX,DWORD PTR DS:[ESI] ; ECX = nuestro Serial XOReado 00403BAF |. |8B1F |MOV EBX,DWORD PTR DS:[EDI] ; EBX = Serial bueno 00403BB1 |. |39D9 |CMP ECX,EBX ; Compara 00403BB3 |. |75 58 |JNE SHORT 00403C0D ; Chico malo 00403BB5 |. |4A |DEC EDX 00403BB6 |. |74 15 |JZ SHORT 00403BCD 00403BB8 |. |8B4E 04 |MOV ECX,DWORD PTR DS:[ESI+4] 00403BBB |. |8B5F 04 |MOV EBX,DWORD PTR DS:[EDI+4] 00403BBE |. |39D9 |CMP ECX,EBX 00403BC0 |. |75 4B |JNE SHORT 00403C0D 00403BC2 |. |83C6 08 |ADD ESI,8 00403BC5 |. |83C7 08 |ADD EDI,8 00403BC8 |. |4A |DEC EDX 00403BC9 |.^\75 E2 \JNZ SHORT 00403BAD
En resumen
1) Siendo nuestro serial : 1 2 3 4 5
a b c d e
2) Realiza las operaciones matemáticas:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000))
3) Obtenemos un hash resultante de 5415
4) XORea los dígitos de la siguiente manera:
(5)35 xor 86 = B6
(4)34 xor 83 = BD
(1)31 xor 86 = B7
(5)35 xor 8D = B8
De modo que tenemos B6BDB7B8
5) Compara B6BDB7B8 con B5BAB2BA
6) Revertimos el XOR para obtener el hash bueno
B5 xor 86 = 36(6)
BA xor 83 = 33(3)
B2 xor 86 = 34(4)
BA xor 8D = 37(7)
Luego el hash bueno es 6347
7) Debemos hacer fuerza bruta buscando:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000)) = 6347
Para obtener los seriales válidos podemos hacer bucles recursivos hasta recorrer las 10^5 opciones posibles. Una forma de hacerlo en VBNet es la siguiente.
Dim tmp As Double
Dim an, bn, cn, dn, en As Integer
For an = 0 To 9
For bn = 0 To 9
For cn = 0 To 9
For dn = 0 To 9
For en = 0 To 9
tmp = Round(((Cos(Sqrt((Pow(bn, 3)) + 5)) + (-Sqrt(an + 1)) + Log(cn * 3 + 1) + (-Sqrt(dn + 2)) + ((en * 3) / 2) + 0.37) * 1000))
txtdebug.Text = "a-b-c-d-e = Hash || " & an & "-" & bn & "-" & cn & "-" & dn & "-" & en & " = " & tmp
If tmp = 6347 Then
ListBox1.Items.Add("Serial: " & an & bn & cn & dn & en)
End If
Application.DoEvents()
Next
Next
Next
Next
Next
Os dejo como siempre el crackme y el keygen en los enlaces.
Links
- Crackme y keygen.
- Interactive Delphi Reconstructor aka IDR.
- DEDE.
- Crackme y otras soluciones [crackmes.de]
Crypto – Vodka

Hemos interceptado un mensaje secreto, pero ninguno de nuestros traductores lo sabe interpretar, ¿sabrías interpretarlo tú? Lo único que hemos encontrado es esto en un foro: шжзклмнпфъ = 1234567890
Mensaje secreto: нж, фн, фф, шън, нф, шшъ, шжз, мф, шъп, фл, пк, шъш, шшм, шшк, шъл, шшл, фл, шъш, шшл, фл, шшн, шшъ, фл, шъм, шшн, шъш, шъз, шшш, фл, пж, шшн, шшл, шшш, шжл
Solución
Parece que el mensaje secreto está encriptado utilizando un alfabeto cifrado que corresponde a números. Según la clave proporcionada (шжзклмнпфъ = 1234567890), cada letra del alfabeto cirílico se sustituye por un número.
Primero, descompondremos la clave dada:
ш = 1
ж = 2
з = 3
к = 4
л = 5
м = 6
н = 7
п = 8
ф = 9
ъ = 0
Ahora, aplicamos esta clave al mensaje secreto:
нж, фн, фф, шън, нф, шшъ, шжз, мф, шъп, фл, пк, шъш, шшм, шшк, шъл, шшл, фл, шъш, шшл, фл, шшн, шшъ, фл, шъм, шшн, шъш, шъз, шшш, фл, пж, шшн, шшл, шшш, шжл
Sustituyendo cada letra según la clave:
нж = 72
фн = 97
фф = 99
шън = 107
нф = 79
шшъ = 110
шжз = 123
мф = 69
шъп = 108
фл = 95
пк = 84
шъш = 101
шшм = 116
шшк = 114
шъл = 105
шшл = 115
фл = 95
шъш = 101
шшл = 115
фл = 95
шшн = 117
шшъ = 110
фл = 95
шъм = 106
шшн = 117
шъш = 101
шъз = 130
шшш = 111
фл = 95
пж = 82
шшн = 117
шшл = 115
шшш = 111
шжл = 125
El mensaje traducido a números es:
72, 97, 99, 107, 79, 110, 123, 69, 108, 95, 84, 101, 116, 114, 105, 115, 95, 101, 115, 95, 117, 110, 95, 106, 117, 101, 130, 111, 95, 82, 117, 115, 111, 125
Este parece ser un mensaje cifrado en números. La secuencia de números se puede interpretar de varias maneras (como ASCII, coordenadas, etc.). Si asumimos que es un texto codificado en ASCII:
Convertimos cada número a su correspondiente carácter ASCII:
72 = H
97 = a
99 = c
107 = k
79 = O
110 = n
123 = {
69 = E
108 = l
95 = _
84 = T
101 = e
116 = t
114 = r
105 = i
115 = s
95 = _
101 = e
115 = s
95 = _
117 = u
110 = n
95 = _
106 = j
117 = u
101 = e
130 = ?
111 = o
95 = _
82 = R
117 = u
115 = s
111 = o
125 = }
Juntando todo:
HackOn{El_Tetris_e_s_u_n_j_u_e?o_Ruso}
La parte «{El_Tetris_e_s_u_n_j_u_e?o_Ruso}» parece un mensaje en español. Probablemente deba ser leído como: HackOn{El_Tetris_es_un_juego_Ruso}
Así, el mensaje secreto es: HackOn{El_Tetris_es_un_juego_Ruso}.
La imagen de portada de la entrada ha sido generada con ChatGPT.
ThisIsLegal.com – Realistic Challenge 1

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
Firebug
Links
ThisIsLegal.com – Realistic Challenge 3

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
Analizando a la víctima
¡Funcionó!, el enlace ha pasado el filtro.
¿Cómo podemos aprovechar esto?, pués la forma más común es «XSS cross site scripting«. Veamos una prueba. Con el parámetro oculto otra vez en 0 mandamos el siguiente enlace y reto superado.
Links
Cruehead’s Crackme 1.0 Keygen [1/3]

Introducción
Esta es la primera entrega de tres en las que vamos a ver tres crackmes que todo reverser debería hacer. Son la serie del autor Cruehead. Aunque los hice hace ya muchos años, he decidido documentarlos para que el lector que empieza pueda deleitarse. En este caso se trata del típico Nombre / Serial.
El algoritmo
El algoritmo de este crackme es lo más sencillo que nos podemos encontrar.
Abrimos el crackme con Olly y buscamos en las «string references» el mensaje de error. Pinchamos sobre el y en la parte superior enseguida vemos 2 calls muy interesantes.
Veamos que hace con el nombre.
Para «deurus» pondría todo en mayúsculas, sumaría su valor ascii y le haría XOR 0x5678.
Ejemplo:
deurus –> DEURUS –> 0x44+0x45+0x55+0x52+0x55+0x53 = 0x1D8 XOR 0x5678 = 0x57A0
Veamos que hace con el serial introducido.
Convierte nuestro serial a hexadecimal y le hace XOR 0x1234.
Ejemplo:
Serial = 12345 –> 0x3039 XOR 0x1234 = 0x220D
Una vez que tenemos el SUMNombre y el SUMSerial los compara. Lo vemos en CMP EAX, EBX.
En resumen, si a nuestro SUMNombre le hacemos XOR 0x5678 y XOR 0x1234 ya tenemos el serial bueno.
Ejemplo:
deurus –> DEURUS –> 0x44+0x45+0x55+0x52+0x55+0x53 = 0x1D8 XOR 0x5678 = 0x57A0 XOR 0x1234 = 0x4594
0x4594 = 17812
El Keygen
char Nombre[20];
GetWindowText(hwndEdit1, Nombre, 20);
char Serial[20];
int len = strlen(Nombre);
int suma = 0;
boolean error = false;
for(int i = 0; i <= len; i = i + 1)
{
suma += toupper(Nombre[i]);
}
suma = suma^0x444C; //444C == 5678 xor 1234
wsprintf(Serial,"%d",suma);
SetWindowText(hwndEdit2, TEXT(Serial));
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
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
Blooper Tech Movie VII – Absentia 1×06 (S01E06)

En el BTM anterior nos remontábamos al año 2006 para ver un pequeño gazapo ocurrido en la serie Dexter. En esta ocasión vamos a hablar sobre un pequeño detalle de una serie actual, Absentia. No es un gazapo, pero es algo bastante poco creíble hoy día.
Hide me
La escena la protagoniza Emily Byrne (Stana Katic) y en ella se ve a Emily buscar algo sospechoso en un portátil.
Primer detalle
En la primera imagen y antes de que Emily haga clic en Documents, se puede apreciar un acceso directo que reza Browser con un icono de la bola del mundo y una lupa. Muy chulo pero para darle más credibilidad a la escena se podía mostrar un acceso directo de Chrome, Firefox o Internet Explorer que son los navegadores más usados.
Para rematar…
A lo que vamos. Emily decide mirar en la carpeta Documents > Videos y para su sorpresa está vacía. Pero como Emily es una mujer de recursos decide comprobar si hay archivos ocultos y para ello retoca las opciones de carpeta.
¡Tachán!, como por arte de magia aparecen todas las carpetas del supuesto asesino con todo tipo de vídeos incriminatorios. Como he comentado anteriormente, parece poco creíble pensar que algo que te puede llevar a la cárcel de por vida sea protegido de forma tan pobre.
Enlaces
ideku_nih’s Code this Keygen

Introducción
Hoy tenemos aquí un crackme hecho en Visual Basic 6 (pcode), pero lo vamos a abordar de una manera diferente, ya que, vamos a conseguir el código fuente mediante VB Decompiler, le vamos a hacer una serie de modificaciones para hacerlo funcional con la ayuda de ExDec, y a partir de eso vamos a generar nuestro propio keygen.
El funcionamiento del crackme es simple, tenemos una primera caja de texto «Code» que en función de lo que introduzcamos nos activa el botón «OK». Al pulsar el botón comprueba lo que tengamos en la caja de texto «Serial» para haber si está todo correcto.
Obteniendo el código fuente
Abrimos el crackme con VB Decompiler y vemos sus fauces.
Pinchando en cada parte obtenemos su respectivo código fuente.
El botón OK
Private Sub Command1_Click() '402F70 'Data Table: 402724 Dim ourserial As Variant ourserial = CVar(Me.SERIAL.Text) 'String If (ourserial = cript(Left$(Me.CODE.Text, &HA))) Then MsgBox "Great", 0, ourserial End End If Dim x As String x = cript(Left$(Me.CODE.Text, &HA)) MsgBox "Not Completed - " & x, 0, ourserial Me.CODE.Text = "" Me.SERIAL.Text = "" Exit Sub End Sub
El evento KeyUp
Private Sub CODE_KeyUp(KeyCode As Integer, Shift As Integer) 'Data Table: 402724 If (Len(Me.CODE.Text) > 4) Then ourserialsum = checkcode(Me.CODE.Text) If CBool((ourserialsum > 70) And (ourserialsum < 90)) Then Me.Command1.Enabled = True End If End If Exit Sub End Sub
La función cript
Public Function cript(a) 'Data Table: 402724 Dim var_9C As Long var_98 = CStr(UCase(a)) For var_10C = 1 To CVar(Len(var_98)): var_CC = var_10C 'Variant var_9C = CLng((CVar(var_9C) + (CVar((Asc(Mid$(var_98, CLng(var_CC), 1)) - 9) Xor &H58) + var_CC) ^ 2)) Next var_10C 'Variant For var_160 = 1 To 100: var_140 = var_160 If (Mid$(CVar(Me.CODE.Text), CLng(var_140), 1) = vbNullString) Then GoTo loc_4030C0 End If Next var_160 loc_4030C0: var_9C = CLng(((CVar(var_9C) * Int((var_140 / 2))) * 16)) var_94 = Hex(var_9C) 'Variant cript = var_94 End Function
La función checkcode
Public Function checkcode(a) For var_F4 = 1 To CVar(Len(a)): var_A4 = var_F4 var_128 = var_128 + (CVar(Asc(Mid$(a, CLng(var_A4), 1)))) Next var_F4 var_94 = Int(((var_128 / CVar(Len(a) / CVar(Len(a))))) checkcode = var_94 End Function
La rutina de comprobación del serial
Se compone de dos partes, el código y el serial.
El código
Si el resultado de la función checkcode está entre 70 y 90 nos activa el botón OK.
El serial
Lo genera la función cript en función del código anterior.
Arreglando el código fuente
Con lo obtenido anteriormente podemos entender perfectamente el comportamiento de la comprobación del serial pero si los cargamos en Visual Basic 6 y lo intentamos ejecutar tal cual nos dará una serie de errores. Es aquí cuando entra ExDec, ya que, nos proporciona el desensamblado del programa en forma de Opcode para poder comparar con el código obtenido.
En este caso el único problema se encuentra en la función checkcode en concreto en ésta línea:
var_94 = Int(((var_128 / CVar(Len(a) / CVar(Len(a)))))
El problema está en que divide dos veces entre el número de dígitos de a, si lo analizamos vemos que es imposible ya que nunca nos daría un código entre 70 y 90. La corrección queda así:
var_94 = Int(((var_128 / CVar(Len(a)))))
El KeyGen
Finalmente el código fuente de nuestro keygen quedaría así:
Private Sub Command1_Click() 'Generate CODE
Dim CODE As String
Dim var As Integer
Randomize
var = CLng((0 - 9999) * Rnd + 9999)
Me.CODE.Text = "deurus" & var
codesum = checkcode(Me.CODE.Text)
If CBool((codesum > 70) And (codesum < 90)) Then
lbl.Caption = "Code valid, now generate a serial"
Command2.Enabled = True
Else
Command2.Enabled = False
Command1_Click
End If
End Sub
Private Sub Command2_Click() 'Generate SERIAL
If (Len(Me.CODE.Text) > 4) Then
codesum = checkcode(Me.CODE.Text)
If CBool((codesum > 70) And (codesum < 90)) Then
SERIAL.Text = cript(Left$(Me.CODE.Text, 10))
Else
lbl.Caption = "Code not valid, first gen code"
End If
End If
End Sub
Private Sub CODE_KeyUp(KeyCode As Integer, Shift As Integer)
If (Len(Me.CODE.Text) > 4) Then
var_B0 = checkcode(Me.CODE.Text)
lbl.Caption = "Value must be between 70 - 90. Yours: " & var_B0
If CBool((var_B0 > 70) And (var_B0 < 90)) Then
lbl.Caption = "Code valid, now generate a serial"
Command2.Enabled = True
Else
Command2.Enabled = False
End If
End If
Exit Sub
End Sub
Public Function cript(a)
Dim var_9C As Long
var_98 = CStr(UCase(a))
For var_10C = 1 To CVar(Len(var_98)): var_CC = var_10C
var_9C = CLng((CVar(var_9C) + (CVar((Asc(Mid$(var_98, CLng(var_CC), 1)) - 9) Xor &H58) + var_CC) ^ 2))
Next var_10C
For var_160 = 1 To 100: var_140 = var_160
If (Mid$(CVar(Me.CODE.Text), CLng(var_140), 1) = vbNullString) Then
GoTo loc_4030C0
End If
Next var_160
loc_4030C0:
var_9C = CLng(((CVar(var_9C) * Int((var_140 / 2))) * 16))
var_94 = Hex(var_9C)
cript = var_94
End Function
Public Function checkcode(a)
For var_F4 = 1 To CVar(Len(a)): var_A4 = var_F4
'Suma el valor ascii de todos los caracteres / Add the ascii value of our code
var_128 = var_128 + (CVar(Asc(Mid$(a, CLng(var_A4), 1))))
Next var_F4
'Lo divide entre la longitud del code / Divide our codesum by code lenght
var_94 = Int(((var_128 / CVar(Len(a))))) 'corrección
checkcode = var_94
End Function
En crackmes.de podéis conseguir el crackme y el keygen.
Links
Blooper Tech Movie XIII – Copycat

Hoy analizamos Copycat, un thriller psicológico de 1995 que, como muchas películas de la época, no pudo resistirse a incorporar elementos tecnológicos que, vistos desde una perspectiva actual, nos sacan una sonrisa. Vamos a desmontar algunos gazapos tecnológicos y curiosidades relacionadas con los sistemas informáticos que aparecen en la película.
El escritorio de tres pantallas: ¿el futuro en 1995?
La protagonista, la Dra. Helen Hudson (Sigourney Weaver), trabaja en un escritorio con tres pantallas, algo futurista para la época. En 1995, esto no era tan común como hoy en día. Para lograrlo, probablemente necesitaría tres ordenadores conectados de forma independiente, ya que los sistemas operativos y hardware de la época no solían soportar múltiples monitores en una sola máquina. Esto plantea preguntas interesantes sobre la logística de su set-up: ¿Cómo sincronizaba su trabajo entre tres PCs?

Un detalle curioso es que, en algunas tomas, se distingue la marca Compaq en los equipos. Compaq era una de las compañías líderes en la fabricación de ordenadores personales durante los 90 y conocida por sus soluciones de alta calidad. Este dato refuerza la idea de que el set-up de Helen estaba diseñado para representar lo último en tecnología de la época, aunque hoy resulte un tanto rudimentario. La elección de Compaq no es casual: en ese momento, era sinónimo de equipos potentes, usados tanto en oficinas como en entornos domésticos avanzados.
Internet y la magia de los módems
En una escena, Helen navega por internet con lo que suponemos es un módem de 28.8 kbps (o como mucho, un flamante 33.6 kbps, tecnología de vanguardia allá por 1995). Hasta ahí, vale. Sin embargo, la fluidez de su conexión sorprende: carga archivos, recibe correos y no se queda esperando con una pantalla de “Conectando…”. Pero lo mejor llega cuando, estando conectada, ¡suena el teléfono! En la realidad, esto cortaría la conexión o comunicaría, a menos que tuviera dos líneas telefónicas (algo raro en domicilios particulares de la época) o algún dispositivo milagroso que no conocemos.
¿Qué sistema operativo usa?
Aunque no se distingue claramente el sistema operativo, vemos una interfaz gráfica con ventanas y una consola de comandos. Esto podría ser un guiño a Windows 3.1 o Windows 3.11, ya maduro en esa época aunque la interfaz no termina de encajar. Sin embargo, también podría ser una mezcla ficticia para hacer que el entorno luciera “tecnológico” sin comprometerse demasiado con la realidad. Detalle curioso: en los 90, las películas solían personalizar las interfaces para no tener problemas legales.
El email como el epicentro de la tecnología
En los 90, el email era el rey. En las películas, los escritorios siempre tenían un gran icono de correo (a menudo animado, porque lo cool siempre parpadeaba). En Copycat, Helen recibe un correo con un archivo AVI de unos 30 segundos, lo cual plantea otra duda técnica: ¿Cuánto espacio ocupaba ese archivo en 1995?
Un AVI de 30 segundos probablemente tendría una resolución baja (320×240 píxeles o menos) y una tasa de compresión eficiente para la época, pero aun así podría pesar entre 2 y 5 MB, dependiendo de la calidad del audio y vídeo. Eso hubiera supuesto una odisea por email, ya que los servidores de la época limitaban los adjuntos a unos pocos cientos de KB. ¿Quizás el villano usó un protocolo privado para saltarse las restricciones?
Tomorrow.AVI
Tras recibir un inquietante archivo AVI, la protagonista llama a la policía, lo que desencadena una conversación cargada de decisiones tecnológicas cuestionables:
- «¿Cómo le han enviado esto?» / «Consiguiendo su dirección de internet»: El archivo es descrito como enviado a través de «su dirección de internet», un término extraño para la época en la que lo habitual habría sido referirse al correo electrónico. Esto refleja un intento de sonar sofisticado sin usar los términos correctos.
- «¿No podríamos localizarlo?»: La respuesta de los policías es que no pueden rastrear el origen del archivo «a no ser que esté conectado». Sin embargo, incluso en 1995, las cabeceras de los emails contenían suficiente información para rastrear el servidor de origen, aunque la práctica era más rudimentaria que en la actualidad. Ignorar esto parece una licencia creativa del guion o un concepto equivocado de localizar asociándolo quizá a las llamadas telefónicas.
- «Es demasiado grande para pasarlo a disco»: Aquí surge el principal obstáculo: el archivo AVI es considerado «demasiado grande» para transferirlo a un disquete de 3,5 pulgadas (con una capacidad máxima de 1,44 MB). Aunque esto tiene sentido desde una perspectiva técnica, resulta extraño que fuera posible enviarlo por email en primer lugar, dado que los servidores de correo de la época tenían limitaciones más estrictas que un disquete. Esto sugiere una inconsistencia en la lógica tecnológica de la escena.
- «Lo pasaremos a vídeo»: Ante la imposibilidad de transferirlo a un disquete, la solución propuesta es convertir el archivo a un formato reproducible en un dispositivo analógico (probablemente una cinta VHS) para transportarlo físicamente. Aunque esta decisión es plausible dentro de las limitaciones tecnológicas de la época, omite soluciones más digitales, como volver a enviarlo por email (¿acaso la policía no tenía correo electrónico?). Además, surge la pregunta de por qué no se recurre a los forenses técnicos de la policía (o del FBI) para analizar el disco duro, quienes, curiosamente, no aparecen en ningún momento de la película.
- «Oh, Dios. ¿Cómo sabes todas estas cosas?» / «Malgasté mi juventud en los salones de videojuegos»: Esta frase añade un toque humorístico, pero no tiene relación alguna con las habilidades necesarias para resolver el problema en cuestión. Más bien, refuerza la desconexión entre los diálogos y las acciones tecnológicas presentadas.
Conclusión
Copycat (1995) es un buen ejemplo de cómo el cine de los 90 abordaba la tecnología con una mezcla de admiración y confusión. Desde la exageración de tener tres monitores en el escritorio de Helen hasta la torpe gestión del archivo Tomorrow.AVI, la película refleja tanto las limitaciones tecnológicas de la época como las libertades creativas de los guionistas.
En el caso del archivo AVI, los personajes deciden que no se puede gestionar digitalmente y optan por convertirlo a vídeo analógico, ignorando soluciones más simples como volver a enviarlo por correo electrónico (suponiendo que fuera posible). Este detalle, combinado con la ausencia aparente de personal técnico en la policía, subraya una desconexión entre la narrativa y las capacidades reales de la tecnología, incluso para 1995.
Aunque estos detalles pueden parecer cómicos 30 años después, forman parte del encanto de un cine que imaginaba el futuro sin comprender del todo su presente. Más que errores, son un recordatorio de cómo la tecnología ha evolucionado y de cómo nuestra percepción de ella también lo ha hecho.
Enlaces
- Copycat [IMDb]
- Historia de Internet [Wikipedia]
- Correo electrónico [Wikipedia]
- Compaq [Wikipedia]
- Silicon Cowboys: la historia de cómo Compaq retó (y venció) a IBM y Apple [Xataka]
- Formato de vídeo AVI [Wikipedia]
- Analysis of video file formats in forensics (.avi example) [DiViLine]
Galería













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
Solución al CrackMe DAE 430

- Introducción
- Herramientas utilizadas
- Desempacado con Ollydbg 2 (Videotutorial)
- Desempacado con Ollydbg 1 (Videotutorial)
- Análisis de la rutina del número de serie
- Links
Introducción
Este Crackme está basado en la protección de DVD Audio Extractor 4.3. Afrontaremos dos partes, una primera donde desempacaremos PECompact 2.x y otra donde analizaremos la rutina de comprobación del número de serie. Os adelante que la única dificultad reside en desempacar ya que la rutina del serial es bastante floja.
El motivo que me ha llevado a realizar un apartado para Ollydbg 1 y otro para Ollydbg 2 es principalmente por que con Ollydbg 2 lo haremos desde Windows 7 x64 y con Ollydbg 1 desde Windos 7 x32.
Herramientas utilizadas
- Ollydbg2 con los plugins OllyDumEX y CmdBar.
- Ollydbg1 con plugin OllyDump.
- Import Reconstructor 1.6.
Desempacado con Ollydbg 2
Videotutorial disponible: http://youtu.be/-63yEUTqP-c.
Resumen de pasos:
- Cargar Crackme en Ollydbg.
- Pulsar F9.
- Poner breakpoint «bp VirtualFree»
- Pulsamos F9 dos veces.
- Pulsamos Ctrl+F9.
- Pulsamos F8 hasta salir del RETN.
- Ponemos breakpoint a JMP EAX.
- Dumpeamos.
- Reconstruimos las importaciones.
1. Cargamos el Crackme en Olly y aparecemos aquí.
2. Pulsamos una vez F9 y veremos esto:
3. Ponemos un breakpoint de la siguiente manera «bp VirtualFree» con la ayuda del plugin CmdBar.
4. Pulsamos F9 dos veces y aparecemos aquí.
5. A continuación pulsamos Ctrl+F9 y veremos esto.
6. Pulsamos F8 hasta salir del RETN anterior y veremos esto.
7. Al final vemos lo que estábamos buscando. El JMP EAX es el salto que nos lleva al punto de entrada original (OEP). Ponemos un breakpoint en JMP EAX y pulsamos F9, cuando se detenga Ollydbg, pulsamos F8 y aparecemos aquí.
8. Ya tenemos a PECompact contra las cuerdas, ahora mismo tenemos el Crackme desempacado en memoria.
Hacemos click en Plugins > OllyDumpEx > Dump process y veremos esto.
Pulsamos en Dump y esto nos generará un archivo que se llama DAE430_CrackMe_dump.
9. A continuación con Import Reconstructor seleccionamos el crackme y pulsamos IAT AutoSearch y Get Imports.
Veremos unas importaciones NO válidas, pulsamos en Show Invalid y las clickamos con el botón derecho > Delete thunks.
Finalmente pulsamos Fix Dump y elegimos el crackme dumpeado anteriormente. Con esto ya hemos finalizado el desempacado.
Desempacado con Ollydbg 1
Videotutorial disponible: http://youtu.be/mm42HRlPXOE
Resumen de pasos:
- Cargamos el crackme en Ollydbg.
- Pulsamos F8 hasta el segundo Call y en éste entramos con F7.
- Seguimos con F8.
- Buscamos JMP EAX, le ponemos un breakpoint y ejecutamos hast que pare en el.
- Situados en JMP EAX, pulsamos F8 y llegamos al OEP.
- Dumpeamos.
- Reconstruimos las importaciones.
1. Cargamos el crackme en Ollydbg y vemos esto.
2. Pulsamos F8 hasta que veamos dos Calls. Pulsamos F8 hasta el segundo Call y cuando estemos situados encima de él pulsamos F7 para entrar en el.
Dentro del segundo call veremos esto.
3. Seguimos con F8 y llegamos aquí.
4. Sin tracear, nos desplazamos por el código hasta encontrar un poco más abajo JMP EAX. Le ponemos un breakpoint y pulsamos F9.
5. Cuando estemos situados en JMP EAX pulsamos F8 y llegamos al punto de entrada original (OEP).
6. Ahora con el plugin OllyDump vamos a dumpear el ejecutable que tenemos desempacado en memoria.
Dumpeamos.
7. Finalmente con Import reconstructor arreglamos las importaciones.
Análisis de la rutina del número de serie
Cargamos en Ollydbg el crackme desempacado y en las referencias de texto encontramos el mensaje «Gracias por registrarte». Pulsamos en él y llegamos a la rutina de comprobación del serial que desgranamos a continuación.
00401B89 . 83F9 03 CMP ECX,3 ; Len(nombre) >=3 00401B8C . 0F8E 46010000 JLE DAE430_C.00401CD8 00401B92 . B2 44 MOV DL,44 ; Dl=44(Letra D) 00401B94 . 31C0 XOR EAX,EAX 00401B96 . 31FF XOR EDI,EDI 00401B98 . 381403 CMP BYTE PTR DS:[EBX+EAX],DL ; Compara 1er digito con la letra D 00401B9B . 74 05 JE SHORT DAE430_C.00401BA2 00401B9D > BF 01000000 MOV EDI,1 00401BA2 > 40 INC EAX 00401BA3 . 83F8 04 CMP EAX,4 00401BA6 . 74 0C JE SHORT DAE430_C.00401BB4 00401BA8 . 8A5404 45 MOV DL,BYTE PTR SS:[ESP+EAX+45] ; Memoria 22FAF5 a 22FAF | Lee los digitos A1X 00401BAC . 381403 CMP BYTE PTR DS:[EBX+EAX],DL ; Los compara 00401BAF .^ 75 EC JNZ SHORT DAE430_C.00401B9D 00401BB1 .^ EB EF JMP SHORT DAE430_C.00401BA2 00401BB3 90 NOP 00401BB4 > 66:0FBE4424 53 MOVSX AX,BYTE PTR SS:[ESP+53] ; EAX = 5ºdígito 00401BBA . 8D1480 LEA EDX,DWORD PTR DS:[EAX+EAX*4] ; EAX*4+EAX = A 00401BBD . 8D04D0 LEA EAX,DWORD PTR DS:[EAX+EDX*8] ; A*8 + 5ºdigito=B 00401BC0 . 66:C1E8 08 SHR AX,8 ; B/100=C 00401BC4 . C0F8 02 SAR AL,2 ; C/4=D 00401BC7 . 8A5424 53 MOV DL,BYTE PTR SS:[ESP+53] ; DL = 5ºdígito 00401BCB . C0FA 07 SAR DL,7 ; 5ºdígito/80=E 00401BCE . 29D0 SUB EAX,EDX ; E-D=F 00401BD0 . 8D0480 LEA EAX,DWORD PTR DS:[EAX+EAX*4] ; F*4*F=G 00401BD3 . 8D0480 LEA EAX,DWORD PTR DS:[EAX+EAX*4] ; G*4+G=H 00401BD6 . 8A5424 53 MOV DL,BYTE PTR SS:[ESP+53] ; DL = 5ºdígito 00401BDA . 29C2 SUB EDX,EAX ; 5ºdigito - H = I 00401BDC . 83C2 41 ADD EDX,41 ; I+41 = J 00401BDF . 885424 4A MOV BYTE PTR SS:[ESP+4A],DL ; GUARDA J EN LA MEMORIA 22FAFA 00401BE3 . 66:0FBE4424 54 MOVSX AX,BYTE PTR SS:[ESP+54] 00401BE9 . 8D3480 LEA ESI,DWORD PTR DS:[EAX+EAX*4] 00401BEC . 8D04F0 LEA EAX,DWORD PTR DS:[EAX+ESI*8] 00401BEF . 66:C1E8 08 SHR AX,8 00401BF3 . C0F8 02 SAR AL,2 00401BF6 . 8A4C24 54 MOV CL,BYTE PTR SS:[ESP+54] 00401BFA . C0F9 07 SAR CL,7 00401BFD . 29C8 SUB EAX,ECX 00401BFF . 89C6 MOV ESI,EAX 00401C01 . 8D34B6 LEA ESI,DWORD PTR DS:[ESI+ESI*4] 00401C04 . 8D34B6 LEA ESI,DWORD PTR DS:[ESI+ESI*4] 00401C07 . 8A4424 54 MOV AL,BYTE PTR SS:[ESP+54] 00401C0B . 89F1 MOV ECX,ESI 00401C0D . 29C8 SUB EAX,ECX 00401C0F . 89C6 MOV ESI,EAX 00401C11 . 8D46 41 LEA EAX,DWORD PTR DS:[ESI+41] 00401C14 . 884424 4B MOV BYTE PTR SS:[ESP+4B],AL ; GUARDA J2 EN LA MEMORIA 22FAFB para el 6ºdígito 00401C18 . 66:0FBE4424 55 MOVSX AX,BYTE PTR SS:[ESP+55] 00401C1E . 8D3480 LEA ESI,DWORD PTR DS:[EAX+EAX*4] 00401C21 . 8D04F0 LEA EAX,DWORD PTR DS:[EAX+ESI*8] 00401C24 . 66:C1E8 08 SHR AX,8 00401C28 . C0F8 02 SAR AL,2 00401C2B . 8A4C24 55 MOV CL,BYTE PTR SS:[ESP+55] 00401C2F . C0F9 07 SAR CL,7 00401C32 . 29C8 SUB EAX,ECX 00401C34 . 89C6 MOV ESI,EAX 00401C36 . 8D34B6 LEA ESI,DWORD PTR DS:[ESI+ESI*4] 00401C39 . 8D34B6 LEA ESI,DWORD PTR DS:[ESI+ESI*4] 00401C3C . 8A4424 55 MOV AL,BYTE PTR SS:[ESP+55] 00401C40 . 89F1 MOV ECX,ESI 00401C42 . 29C8 SUB EAX,ECX 00401C44 . 89C6 MOV ESI,EAX 00401C46 . 8D46 41 LEA EAX,DWORD PTR DS:[ESI+41] 00401C49 . 884424 4C MOV BYTE PTR SS:[ESP+4C],AL ; GUARDA J3 EN LA MEMORIA 22FAFC para el 7ºdígito 00401C4D . 66:0FBE4424 56 MOVSX AX,BYTE PTR SS:[ESP+56] 00401C53 . 8D3480 LEA ESI,DWORD PTR DS:[EAX+EAX*4] 00401C56 . 8D04F0 LEA EAX,DWORD PTR DS:[EAX+ESI*8] 00401C59 . 66:C1E8 08 SHR AX,8 00401C5D . C0F8 02 SAR AL,2 00401C60 . 8A4C24 56 MOV CL,BYTE PTR SS:[ESP+56] 00401C64 . C0F9 07 SAR CL,7 00401C67 . 29C8 SUB EAX,ECX 00401C69 . 89C6 MOV ESI,EAX 00401C6B . 8D34B6 LEA ESI,DWORD PTR DS:[ESI+ESI*4] 00401C6E . 8D34B6 LEA ESI,DWORD PTR DS:[ESI+ESI*4] 00401C71 . 8A4424 56 MOV AL,BYTE PTR SS:[ESP+56] 00401C75 . 89F1 MOV ECX,ESI 00401C77 . 29C8 SUB EAX,ECX 00401C79 . 89C6 MOV ESI,EAX 00401C7B . 8D46 41 LEA EAX,DWORD PTR DS:[ESI+41] 00401C7E . 884424 4D MOV BYTE PTR SS:[ESP+4D],AL ; GUARDA J4 EN LA MEMORIA 22FAFD para el 8ºdígito 00401C82 . B8 08000000 MOV EAX,8 00401C87 . 381403 CMP BYTE PTR DS:[EBX+EAX],DL 00401C8A . 74 05 JE SHORT DAE430_C.00401C91 00401C8C > BF 01000000 MOV EDI,1 00401C91 > 40 INC EAX 00401C92 . 83F8 0C CMP EAX,0C 00401C95 . 74 0D JE SHORT DAE430_C.00401CA4 00401C97 . 8A5404 42 MOV DL,BYTE PTR SS:[ESP+EAX+42] 00401C9B . 381403 CMP BYTE PTR DS:[EBX+EAX],DL ; Compara 22FAFA y siguientes con 9, 10, 11 y 12avo digito 00401C9E .^ 75 EC JNZ SHORT DAE430_C.00401C8C 00401CA0 .^ EB EF JMP SHORT DAE430_C.00401C91 00401CA2 . 66:90 NOP 00401CA4 > 89F8 MOV EAX,EDI ; | 00401CA6 . FEC8 DEC AL ; | 00401CA8 . 74 5C JE SHORT DAE430_C.00401D06 ; | 00401CAA . C74424 0C 40000000 MOV DWORD PTR SS:[ESP+C],40 ; | 00401CB2 . C74424 08 4C004100 MOV DWORD PTR SS:[ESP+8],DAE430_C.0041004>; |ASCII "Info" 00401CBA . C74424 04 51004100 MOV DWORD PTR SS:[ESP+4],DAE430_C.0041005>; |ASCII "Gracias por registrarte." 00401CC2 . C70424 00000000 MOV DWORD PTR SS:[ESP],0 ; | 00401CC9 . E8 EE000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA 00401CCE . 83EC 10 SUB ESP,10 00401CD1 . 31C0 XOR EAX,EAX 00401CD3 .^ E9 F2FBFFFF JMP DAE430_C.004018CA 00401CD8 > C74424 0C 40000000 MOV DWORD PTR SS:[ESP+C],40 ; | 00401CE0 . C74424 08 4C004100 MOV DWORD PTR SS:[ESP+8],DAE430_C.0041004>; |ASCII "Info" 00401CE8 . C74424 04 6A004100 MOV DWORD PTR SS:[ESP+4],DAE430_C.0041006>; |ASCII "Nombre mínimo 4 caracteres." 00401CF0 . C70424 00000000 MOV DWORD PTR SS:[ESP],0 ; | 00401CF7 . E8 C0000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA 00401CFC . 83EC 10 SUB ESP,10 00401CFF . 31C0 XOR EAX,EAX 00401D01 .^ E9 C4FBFFFF JMP DAE430_C.004018CA 00401D06 > C74424 0C 10000000 MOV DWORD PTR SS:[ESP+C],10 ; | 00401D0E . C74424 08 34004100 MOV DWORD PTR SS:[ESP+8],DAE430_C.0041003>; |ASCII "Error" 00401D16 . C74424 04 3A004100 MOV DWORD PTR SS:[ESP+4],DAE430_C.0041003>; |ASCII "Registro fallido." 00401D1E . C70424 00000000 MOV DWORD PTR SS:[ESP],0 ; | 00401D25 . E8 92000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
Resumen
- El nombre debe tener más de 3 dígitos aunque no lo usa para el número de serie. - El serial tiene 12 dígitos dividiendose en tres partes, 111122223333. - La primera parte 1111 es comparada directamente con DA1X. - Segunda parte (2222), para los dígitos 5º, 6º, 7º y 8º hace lo siguiente: dígito *4 + dígito = A A*8 + dígito=B B/100 = C C/4 = D dígito/80 = E E-D = F F*4*F = G G*4+G = H digito - H = I I+41 = J GUARDA J EN LA MEMORIA 22FAFA **Todo esto se puede resumir en dígito mod 19 + 41 - Tercera parte (3333). Finalmente compara el resultado del 5º, 6º, 7º y 8º dígitos con el 9º, 10º, 11º y 12º dígitos.
Ejemplo:
Serial = DA1X12345678 1 - (31h mod 19h) + 41h = 48h(Y) 2 - (32h mod 19h) + 41h = 41h(A) 3 - (33h mod 19h) + 41h = 42h(B) 4 - (34h mod 19h) + 41h = 43h(C) Compara Y con 5 Compara A con 6 Compara B con 7 Compara C con 8 Luego el serial correcto sería DA1X1234YABC
Links
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.
lost_in_bin

Estamos ante un ELF un poco más interesante que los vistos anteriormente. Básicamente porque es divertido y fácil encontrar la solución en el decompilado y quizá por evocar recuerdos de tiempos pretéritos.
ELF Decompilado
/* 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);
__int64 sub_400650(); // weak
// int printf(const char *format, ...);
// int puts(const char *s);
// void __noreturn exit(int status);
// size_t strlen(const char *s);
// __int64 __fastcall MD5(_QWORD, _QWORD, _QWORD); weak
// int sprintf(char *s, const char *format, ...);
// __int64 ptrace(enum __ptrace_request request, ...);
// __int64 strtol(const char *nptr, char **endptr, int base);
// __int64 __isoc99_scanf(const char *, ...); weak
// int memcmp(const void *s1, const void *s2, size_t n);
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void));
void *sub_400730();
__int64 sub_400760();
void *sub_4007A0();
__int64 sub_4007D0();
void 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);
// __int64 _gmon_start__(void); weak
//-------------------------------------------------------------------------
// Data declarations
_UNKNOWN main;
_UNKNOWN init;
__int64 (__fastcall *funcs_400E29)() = &sub_4007D0; // weak
__int64 (__fastcall *off_601DF8)() = &sub_4007A0; // weak
__int64 (*qword_602010)(void) = NULL; // weak
char *off_602080 = "FLAG-%s\n"; // idb
char a7yq2hryrn5yJga[16] = "7Yq2hrYRn5Y`jga"; // weak
const char aO6uH[] = "(O6U,H\""; // idb
_UNKNOWN unk_6020B8; // weak
_UNKNOWN unk_6020C8; // weak
char byte_6020E0; // weak
char s1; // idb
char byte_602110[]; // weak
char byte_602120[33]; // weak
char byte_602141[7]; // idb
__int64 qword_602148; // weak
__int64 qword_602150; // weak
__int64 qword_602158; // weak
__int64 qword_602160; // weak
__int64 qword_602178; // weak
//----- (0000000000400630) ----------------------------------------------------
__int64 (**init_proc())(void)
{
__int64 (**result)(void); // rax
result = &_gmon_start__;
if ( &_gmon_start__ )
return (__int64 (**)(void))_gmon_start__();
return result;
}
// 6021D8: using guessed type __int64 _gmon_start__(void);
//----- (0000000000400650) ----------------------------------------------------
__int64 sub_400650()
{
return qword_602010();
}
// 400650: using guessed type __int64 sub_400650();
// 602010: using guessed type __int64 (*qword_602010)(void);
//----- (0000000000400700) ----------------------------------------------------
// 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))init, fini, a3, &v5);
__halt();
}
// 400706: positive sp value 8 has been found
// 40070D: variable 'v3' is possibly undefined
//----- (0000000000400730) ----------------------------------------------------
void *sub_400730()
{
return &unk_6020C8;
}
//----- (0000000000400760) ----------------------------------------------------
__int64 sub_400760()
{
return 0LL;
}
//----- (00000000004007A0) ----------------------------------------------------
void *sub_4007A0()
{
void *result; // rax
if ( !byte_6020E0 )
{
result = sub_400730();
byte_6020E0 = 1;
}
return result;
}
// 6020E0: using guessed type char byte_6020E0;
//----- (00000000004007D0) ----------------------------------------------------
__int64 sub_4007D0()
{
return sub_400760();
}
//----- (00000000004007D7) ----------------------------------------------------
__int64 __fastcall main(int a1, char **a2, char **a3)
{
size_t v3; // rax
size_t v4; // rax
int i; // [rsp+1Ch] [rbp-24h]
int n; // [rsp+20h] [rbp-20h]
int m; // [rsp+24h] [rbp-1Ch]
int k; // [rsp+28h] [rbp-18h]
int j; // [rsp+2Ch] [rbp-14h]
if ( ptrace(PTRACE_TRACEME, 0LL, 0LL, 0LL) == -1 )
goto LABEL_2;
if ( a1 > 4 )
{
qword_602148 = strtol(a2[1], 0LL, 10);
if ( qword_602148 )
{
qword_602150 = strtol(a2[2], 0LL, 10);
if ( qword_602150 )
{
qword_602158 = strtol(a2[3], 0LL, 10);
if ( qword_602158 )
{
qword_602160 = strtol(a2[4], 0LL, 10);
if ( qword_602160 )
{
if ( -24 * qword_602148 - 18 * qword_602150 - 15 * qword_602158 - 12 * qword_602160 == -18393
&& 9 * qword_602158 + 18 * (qword_602150 + qword_602148) - 9 * qword_602160 == 4419
&& 4 * qword_602158 + 16 * qword_602148 + 12 * qword_602150 + 2 * qword_602160 == 7300
&& -6 * (qword_602150 + qword_602148) - 3 * qword_602158 - 11 * qword_602160 == -8613 )
{
qword_602178 = qword_602158 + qword_602150 * qword_602148 - qword_602160;
sprintf(byte_602141, "%06x", qword_602178);
v4 = strlen(byte_602141);
MD5(byte_602141, v4, byte_602110);
for ( i = 0; i <= 15; ++i )
sprintf(&byte_602120[2 * i], "%02x", (unsigned __int8)byte_602110[i]);
printf(off_602080, byte_602120);
exit(0);
}
}
}
}
}
LABEL_2:
printf("password : ");
__isoc99_scanf("%s", &s1);
if ( strlen(&s1) > 0x10 )
{
puts("the password must be less than 16 character");
exit(1);
}
for ( j = 0; j < strlen(&s1); ++j )
*(&s1 + j) ^= 6u;
if ( !strcmp(&s1, a7yq2hryrn5yJga) )
{
v3 = strlen(&s1);
MD5(&s1, v3, byte_602110);
for ( k = 0; k <= 15; ++k )
sprintf(&byte_602120[2 * k], "%02x", (unsigned __int8)byte_602110[k]);
printf(off_602080, byte_602120);
exit(0);
}
puts("bad password!");
exit(0);
}
printf("password : ");
__isoc99_scanf("%s", &s1);
if ( strlen(&s1) > 0x10 )
{
puts("the password must be less than 16 character");
exit(1);
}
for ( m = 0; m < strlen(&s1); ++m )
{
*(&s1 + m) ^= 2u;
++*(&s1 + m);
*(&s1 + m) = ~*(&s1 + m);
}
if ( !memcmp(&s1, &unk_6020B8, 9uLL) )
{
for ( n = 0; n < strlen(aO6uH); n += 2 )
{
aO6uH[n] ^= 0x45u;
aO6uH[n + 1] ^= 0x26u;
}
puts(aO6uH);
}
else
{
puts("bad password!");
}
return 0LL;
}
// 4006A0: using guessed type __int64 __fastcall MD5(_QWORD, _QWORD, _QWORD);
// 4006E0: using guessed type __int64 __isoc99_scanf(const char *, ...);
// 602148: using guessed type __int64 qword_602148;
// 602150: using guessed type __int64 qword_602150;
// 602158: using guessed type __int64 qword_602158;
// 602160: using guessed type __int64 qword_602160;
// 602178: using guessed type __int64 qword_602178;
//----- (0000000000400DE0) ----------------------------------------------------
void __fastcall init(unsigned int a1, __int64 a2, __int64 a3)
{
signed __int64 v3; // rbp
__int64 i; // rbx
v3 = &off_601DF8 - &funcs_400E29;
init_proc();
if ( v3 )
{
for ( i = 0LL; i != v3; ++i )
(*(&funcs_400E29 + i))();
}
}
// 601DF0: using guessed type __int64 (__fastcall *funcs_400E29)();
// 601DF8: using guessed type __int64 (__fastcall *off_601DF8)();
//----- (0000000000400E54) ----------------------------------------------------
void term_proc()
{
;
}
// nfuncs=33 queued=10 decompiled=10 lumina nreq=0 worse=0 better=0
// ALL OK, 10 function(s) have been successfully decompiled
Análisis estático
Anti-debug
Si la función ptrace retorna -1, significa que el programa está siendo depurado y redirige a LABEL_2.
if (ptrace(PTRACE_TRACEME, 0LL, 0LL, 0LL) == -1) {
goto LABEL_2;
}
Cálculos y validaciones
El programa espera al menos 5 argumentos (nombre del programa y cuatro números enteros). Si se proporcionan los cuatro números enteros, se realizan los siguientes cálculos:
if (-24 * qword_602148 - 18 * qword_602150 - 15 * qword_602158 - 12 * qword_602160 == -18393
&& 9 * qword_602158 + 18 * (qword_602150 + qword_602148) - 9 * qword_602160 == 4419
&& 4 * qword_602158 + 16 * qword_602148 + 12 * qword_602150 + 2 * qword_602160 == 7300
&& -6 * (qword_602150 + qword_602148) - 3 * qword_602158 - 11 * qword_602160 == -8613)
Esto es un sistema de ecuaciones lineales mondo y lirondo que debe ser resuelto para encontrar los valores correctos de qword_602148, qword_602150, qword_602158 y qword_602160. Una vez resuelto el sistema de ecuaciones se realiza la operación:
qword_602178 = qword_602158 + qword_602150 * qword_602148 - qword_602160;
A continuación se pasa el resultado de la variable qword_602178 a hexadecimal y se genera su hash MD5.
Solución en Python
Lo más rápido en esta ocasión es usar Python, pero esto se puede resolver hasta con lápiz y papel 😉
from sympy import symbols, Eq, solve
import hashlib
# Definir las variables
A, B, C, D = symbols('A B C D')
# Definir las ecuaciones
eq1 = Eq(-24*A - 18*B - 15*C - 12*D, -18393)
eq2 = Eq(9*C + 18*(A + B) - 9*D, 4419)
eq3 = Eq(4*C + 16*A + 12*B + 2*D, 7300)
eq4 = Eq(-6*(A + B) - 3*C - 11*D, -8613)
# Resolver el sistema de ecuaciones
solution = solve((eq1, eq2, eq3, eq4), (A, B, C, D))
# Verificar si se encontró una solución
if solution:
print("Solución encontrada:")
print(solution)
# Obtener los valores de A, B, C y D
A_val = solution[A]
B_val = solution[B]
C_val = solution[C]
D_val = solution[D]
# Mostrar los valores encontrados
print(f"A = {A_val}")
print(f"B = {B_val}")
print(f"C = {C_val}")
print(f"D = {D_val}")
# Calcular qword_602178
qword_602178 = C_val + B_val * A_val - D_val
qword_602178 = int(qword_602178) # Convertir a entero de Python
print(f"qword_602178 = {qword_602178}")
# Convertir qword_602178 a una cadena en formato hexadecimal
byte_602141 = f"{qword_602178:06x}"
print(f"byte_602141 (hex) = {byte_602141}")
# Calcular el MD5 de la cadena
md5_hash = hashlib.md5(byte_602141.encode()).hexdigest()
print(f"MD5 hash = {md5_hash}")
# Generar la flag
flag = f"FLAG-{md5_hash}"
print(f"Flag = {flag}")
else:
print("No se encontró una solución.")
Al ejecutar el script veremos algo como esto:
Solución encontrada:
{A: 227, B: 115, C: 317, D: 510}
A = 227
B = 115
C = 317
D = 510
qword_602178 = 25912
byte_602141 (hex) = 006538
MD5 hash = 21a84f2c7c7fd432edf1686215db....
Flag = FLAG-21a84f2c7c7fd432edf1686215db....
Solución al Crackme 7 de Scarebyte

- Introducción
- Desempacado
- Eliminar la NAG
- Password
- Nº serie asociado a un nombre
- Checkbox
- Trackbar
- Links
Introducción
Aquí tenemos un Crackme clásico creado por Scarebyte hallá por el año 2000 y que cuenta con varias fases siendo un crackme muy interesante para iniciarse o simplemente para divertirse. Al estar realizado en Delphi, los apartados de las checkboxes y de las trackbars se simplifican y mucho, pero aún así hay que currarselo un poco para dejar todo bien atado. Si os fijáis en las soluciones que aparecen en crackmes.de, en aquellos años se usaba DEDE y aunque yo usaré otra herramienta, DEDE sigue siendo igual de útil.
Desempacado
PEiD nos dice que nos enfrentamos a ASPack 1.08.03 -> Alexey Solodovnikov, así que vamos al lío.
Eliminar la NAG
Tan sencillo como poner un Breakpoint a User32.MessageBoxA. La llamada a NOPear está en la dirección 441CF2.
Password
Desde las string references localizamos los mensajes de chico bueno y chico malo que nos llevan al código a analizar.
0044C3CD |. E8 5294FDFF CALL CrackMe_.00425824 0044C3D2 |. 8B45 FC MOV EAX,[LOCAL.1] 0044C3D5 |. E8 9A76FBFF CALL CrackMe_.00403A74 0044C3DA |. 83F8 0C CMP EAX,0C ; Lengh C = 12 0044C3DD |. 0F85 53010000 JNZ CrackMe_.0044C536 ; Salto a chico malo 0044C3E3 |. 8D55 FC LEA EDX,[LOCAL.1] 0044C3E6 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C3EC |. E8 3394FDFF CALL CrackMe_.00425824 0044C3F1 |. 8B45 FC MOV EAX,[LOCAL.1] 0044C3F4 |. 8038 43 CMP BYTE PTR DS:[EAX],43 ; 1º dígito serial = C 0044C3F7 |. 0F85 27010000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C3FD |. 8D55 F8 LEA EDX,[LOCAL.2] 0044C400 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C406 |. E8 1994FDFF CALL CrackMe_.00425824 0044C40B |. 8B45 F8 MOV EAX,[LOCAL.2] 0044C40E |. 8078 03 6F CMP BYTE PTR DS:[EAX+3],6F ; 4º dígito serial = o 0044C412 |. 0F85 0C010000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C418 |. 8D55 F4 LEA EDX,[LOCAL.3] 0044C41B |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C421 |. E8 FE93FDFF CALL CrackMe_.00425824 0044C426 |. 8B45 F4 MOV EAX,[LOCAL.3] 0044C429 |. 8078 08 6F CMP BYTE PTR DS:[EAX+8],6F ; 9º dígito serial = o 0044C42D |. 0F85 F1000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C433 |. 8D55 F0 LEA EDX,[LOCAL.4] 0044C436 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C43C |. E8 E393FDFF CALL CrackMe_.00425824 0044C441 |. 8B45 F0 MOV EAX,[LOCAL.4] 0044C444 |. 8078 01 6C CMP BYTE PTR DS:[EAX+1],6C ; 2º dígito serial = l 0044C448 |. 0F85 D6000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C44E |. 8D55 EC LEA EDX,[LOCAL.5] 0044C451 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C457 |. E8 C893FDFF CALL CrackMe_.00425824 0044C45C |. 8B45 EC MOV EAX,[LOCAL.5] 0044C45F |. 8078 04 20 CMP BYTE PTR DS:[EAX+4],20 ; 5º dígito serial = espacio 0044C463 |. 0F85 BB000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C469 |. 8D55 E8 LEA EDX,[LOCAL.6] 0044C46C |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C472 |. E8 AD93FDFF CALL CrackMe_.00425824 0044C477 |. 8B45 E8 MOV EAX,[LOCAL.6] 0044C47A |. 8078 0A 52 CMP BYTE PTR DS:[EAX+A],52 ; 11º dígito serial = R 0044C47E |. 0F85 A0000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C484 |. 8D55 E4 LEA EDX,[LOCAL.7] 0044C487 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C48D |. E8 9293FDFF CALL CrackMe_.00425824 0044C492 |. 8B45 E4 MOV EAX,[LOCAL.7] 0044C495 |. 8078 07 75 CMP BYTE PTR DS:[EAX+7],75 ; 8º dígito serial = u 0044C499 |. 0F85 85000000 JNZ CrackMe_.0044C524 ; Salto a chico malo 0044C49F |. 8D55 E0 LEA EDX,[LOCAL.8] 0044C4A2 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4A8 |. E8 7793FDFF CALL CrackMe_.00425824 0044C4AD |. 8B45 E0 MOV EAX,[LOCAL.8] 0044C4B0 |. 8078 09 6E CMP BYTE PTR DS:[EAX+9],6E ; 10º dígito serial = n 0044C4B4 |. 75 6E JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4B6 |. 8D55 DC LEA EDX,[LOCAL.9] 0044C4B9 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4BF |. E8 6093FDFF CALL CrackMe_.00425824 0044C4C4 |. 8B45 DC MOV EAX,[LOCAL.9] 0044C4C7 |. 8078 02 6E CMP BYTE PTR DS:[EAX+2],6E ; 3º dígito serial = n 0044C4CB |. 75 57 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4CD |. 8D55 D8 LEA EDX,[LOCAL.10] 0044C4D0 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4D6 |. E8 4993FDFF CALL CrackMe_.00425824 0044C4DB |. 8B45 D8 MOV EAX,[LOCAL.10] 0044C4DE |. 8078 05 69 CMP BYTE PTR DS:[EAX+5],69 ; 6º dígito serial = i 0044C4E2 |. 75 40 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4E4 |. 8D55 D4 LEA EDX,[LOCAL.11] 0044C4E7 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C4ED |. E8 3293FDFF CALL CrackMe_.00425824 0044C4F2 |. 8B45 D4 MOV EAX,[LOCAL.11] 0044C4F5 |. 8078 0B 6E CMP BYTE PTR DS:[EAX+B],6E ; 12º dígito serial = n 0044C4F9 |. 75 29 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C4FB |. 8D55 D0 LEA EDX,[LOCAL.12] 0044C4FE |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C504 |. E8 1B93FDFF CALL CrackMe_.00425824 0044C509 |. 8B45 D0 MOV EAX,[LOCAL.12] 0044C50C |. 8078 06 67 CMP BYTE PTR DS:[EAX+6],67 ; 7º dígito serial = g 0044C510 |. 75 12 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo 0044C512 |. BA 78C54400 MOV EDX,CrackMe_.0044C578 ; ASCII "Right Password" 0044C517 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C51D |. E8 3293FDFF CALL CrackMe_.00425854 0044C522 |. EB 22 JMP SHORT CrackMe_.0044C546 0044C524 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password" 0044C529 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8] 0044C52F |. E8 2093FDFF CALL CrackMe_.00425854 0044C534 |. EB 10 JMP SHORT CrackMe_.0044C546 0044C536 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password" Chequeo rápido ABCD EFGHIJK Clno iguonRn ; 1º dígito serial = C ; 4º dígito serial = o ; 9º dígito serial = o ; 2º dígito serial = l ; 5º dígito serial = espacio ; 11º dígito serial = R ; 8º dígito serial = u ; 10º dígito serial = n ; 3º dígito serial = n ; 6º dígito serial = i ; 12º dígito serial = n ; 7º dígito serial = g
Básicamente chequea la frase «Cool Running» de forma desordenada como se ve justo encima, siendo el password correcto «Clno iguonRn«. Os dejo el código para que lo analicéis.
Nº serie asociado a un nombre
De nuevo con las string references localizamos el código.
0044C648 /. 55 PUSH EBP 0044C649 |. 8BEC MOV EBP,ESP 0044C64B |. 83C4 F8 ADD ESP,-8 0044C64E |. 53 PUSH EBX 0044C64F |. 56 PUSH ESI 0044C650 |. 33C9 XOR ECX,ECX 0044C652 |. 894D F8 MOV [LOCAL.2],ECX 0044C655 |. 8BF0 MOV ESI,EAX 0044C657 |. 33C0 XOR EAX,EAX 0044C659 |. 55 PUSH EBP 0044C65A |. 68 83C74400 PUSH CrackMe_.0044C783 0044C65F |. 64:FF30 PUSH DWORD PTR FS:[EAX] 0044C662 |. 64:8920 MOV DWORD PTR FS:[EAX],ESP 0044C665 |. 33C0 XOR EAX,EAX 0044C667 |. 8945 FC MOV [LOCAL.1],EAX 0044C66A |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre 0044C66F |. E8 0074FBFF CALL CrackMe_.00403A74 0044C674 |. 83F8 06 CMP EAX,6 ; Cmp lengh nombre con 6 0044C677 |. 0F8E F0000000 JLE CrackMe_.0044C76D ; Salta si <= 6 0044C67D |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre 0044C682 |. E8 ED73FBFF CALL CrackMe_.00403A74 0044C687 |. 83F8 14 CMP EAX,14 ; Cmp lengh nombre con 20 (14h) 0044C68A |. 0F8D DD000000 JGE CrackMe_.0044C76D ; salta si >= 20 0044C690 |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] 0044C695 |. E8 DA73FBFF CALL CrackMe_.00403A74 0044C69A |. 85C0 TEST EAX,EAX 0044C69C |. 7E 17 JLE SHORT CrackMe_.0044C6B5 0044C69E |. BA 01000000 MOV EDX,1 0044C6A3 |> 8B0D 80F84400 /MOV ECX,DWORD PTR DS:[44F880] ; Bucle in 0044C6A9 |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1] 0044C6AE |. 014D FC |ADD [LOCAL.1],ECX ; Suma dig nombre y guarda en 12FBC4 0044C6B1 |. 42 |INC EDX 0044C6B2 |. 48 |DEC EAX 0044C6B3 |.^ 75 EE \JNZ SHORT CrackMe_.0044C6A3 ; Bucle out 0044C6B5 |> A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia 0044C6BA |. E8 B573FBFF CALL CrackMe_.00403A74 0044C6BF |. 83F8 02 CMP EAX,2 ; Cmp lengh compañia con 2 0044C6C2 |. 7E 18 JLE SHORT CrackMe_.0044C6DC ; Salta si <= 2 0044C6C4 |. A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia 0044C6C9 |. E8 A673FBFF CALL CrackMe_.00403A74 0044C6CE |. 83F8 08 CMP EAX,8 ; Cmp lengh compañia con 8 0044C6D1 |. 7D 09 JGE SHORT CrackMe_.0044C6DC ; Salta si >= 8 0044C6D3 |. 8B45 FC MOV EAX,[LOCAL.1] ; Eax = sum nombre 0044C6D6 |. 6BC0 02 IMUL EAX,EAX,2 ; Sum nombre * 2 0044C6D9 |. 8945 FC MOV [LOCAL.1],EAX 0044C6DC |> 68 98C74400 PUSH CrackMe_.0044C798 ; ASCII "I Love Cracking and " 0044C6E1 |. 8D55 F8 LEA EDX,[LOCAL.2] 0044C6E4 |. 8B45 FC MOV EAX,[LOCAL.1] 0044C6E7 |. E8 68B0FBFF CALL CrackMe_.00407754 0044C6EC |. FF75 F8 PUSH [LOCAL.2] ; sum del nombre 0044C6EF |. 68 B8C74400 PUSH CrackMe_.0044C7B8 ; ASCII " Girls ;)" 0044C6F4 |. B8 8CF84400 MOV EAX,CrackMe_.0044F88C 0044C6F9 |. BA 03000000 MOV EDX,3 0044C6FE |. E8 3174FBFF CALL CrackMe_.00403B34 ; Concatena 1º frase + sum nombre + 2ºfrase 0044C703 |. 33C0 XOR EAX,EAX 0044C705 |. 8945 FC MOV [LOCAL.1],EAX 0044C708 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888] ; Eax = Serial 0044C70D |. E8 6273FBFF CALL CrackMe_.00403A74 0044C712 |. 8BD8 MOV EBX,EAX 0044C714 |. A1 8CF84400 MOV EAX,DWORD PTR DS:[44F88C] 0044C719 |. E8 5673FBFF CALL CrackMe_.00403A74 0044C71E |. 3BD8 CMP EBX,EAX ; Compara tamaño frase con tamaño serial 0044C720 |. 75 4B JNZ SHORT CrackMe_.0044C76D 0044C722 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888] 0044C727 |. E8 4873FBFF CALL CrackMe_.00403A74 0044C72C |. 85C0 TEST EAX,EAX 0044C72E |. 7E 27 JLE SHORT CrackMe_.0044C757 0044C730 |. BA 01000000 MOV EDX,1 0044C735 |> 8B0D 88F84400 /MOV ECX,DWORD PTR DS:[44F888] ; Bucle in --> 0044C73B |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1] 0044C740 |. 034D FC |ADD ECX,[LOCAL.1] 0044C743 |. 8B1D 8CF84400 |MOV EBX,DWORD PTR DS:[44F88C] 0044C749 |. 0FB65C13 FF |MOVZX EBX,BYTE PTR DS:[EBX+EDX-1] ; Compara dígito a dígito nuestro serial 0044C74E |. 2BCB |SUB ECX,EBX ; con la concatenación anterior 0044C750 |. 894D FC |MOV [LOCAL.1],ECX 0044C753 |. 42 |INC EDX 0044C754 |. 48 |DEC EAX 0044C755 |.^ 75 DE \JNZ SHORT CrackMe_.0044C735 ; <-- Bucle out 0044C757 |> 837D FC 00 CMP [LOCAL.1],0 0044C75B |. 75 10 JNZ SHORT CrackMe_.0044C76D ; Salta si algo ha ido mal 0044C75D |. 8B86 14030000 MOV EAX,DWORD PTR DS:[ESI+314] 0044C763 |. BA CCC74400 MOV EDX,CrackMe_.0044C7CC ; "You have found the correct Serial :)"
En resumen
- Tamaño del nombre entre 7 y 19.
- Tamaño de la compañía entre 3 y 7 aunque no interviene en el serial.
- Suma los valores ascii de los dígitos del nombre y lo multiplica por 2.
- Concatena «I Love Cracking and » + «sum del nombre» + » Girls ;)».
Checkbox
Para afrontar esta parte del reto vamos a usar una herramienta llamada Interactive Delphi Reconstructor o IDR. En su día la mejor herramienta era DEDE, pero IDR a mi parecer es algo más potente.
Básicamente IDR nos permite sin quebraderos de cabeza localizar el código del botón que comprueba la secuencia de checkboxes correcta. Cargamos el crackme en IDR y dentro de la pestaña «Units (F2)«, abajo del todo hacemos doble click sobre «F Crack» y vemos que nos muestra todos los controles del formulario. El botón que nos interesa se llama «SpeedButton3«.
Si hacemos doble click sobre el nos muestra el código que se muestra a continuación.
crack::TForm1.SpeedButton3Click 0044C7F4 push ebp 0044C7F5 mov ebp,esp 0044C7F7 push 0 0044C7F9 push ebx 0044C7FA mov ebx,eax 0044C7FC xor eax,eax 0044C7FE push ebp 0044C7FF push 44C920 0044C804 push dword ptr fs:[eax] 0044C807 mov dword ptr fs:[eax],esp 0044C80A mov eax,dword ptr [ebx+324]; TForm1.cb3:TCheckBox 0044C810 mov edx,dword ptr [eax] 0044C812 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C818 test al,al >0044C81A je 0044C8ED 0044C820 mov eax,dword ptr [ebx+328]; TForm1.cb5:TCheckBox 0044C826 mov edx,dword ptr [eax] 0044C828 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C82E test al,al >0044C830 je 0044C8ED 0044C836 mov eax,dword ptr [ebx+32C]; TForm1.cb6:TCheckBox 0044C83C mov edx,dword ptr [eax] 0044C83E call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C844 test al,al >0044C846 je 0044C8ED 0044C84C mov eax,dword ptr [ebx+358]; TForm1.cb12:TCheckBox 0044C852 mov edx,dword ptr [eax] 0044C854 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C85A test al,al >0044C85C je 0044C8ED 0044C862 mov eax,dword ptr [ebx+364]; TForm1.cb15:TCheckBox 0044C868 mov edx,dword ptr [eax] 0044C86A call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C870 test al,al >0044C872 je 0044C8ED 0044C874 mov eax,dword ptr [ebx+330]; TForm1.cb20:TCheckBox 0044C87A mov edx,dword ptr [eax] 0044C87C call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C882 test al,al >0044C884 je 0044C8ED 0044C886 mov eax,dword ptr [ebx+34C]; TForm1.cb9:TCheckBox 0044C88C mov edx,dword ptr [eax] 0044C88E call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C894 test al,al >0044C896 je 0044C8ED 0044C898 mov eax,dword ptr [ebx+354]; TForm1.cb11:TCheckBox 0044C89E mov edx,dword ptr [eax] 0044C8A0 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C8A6 test al,al >0044C8A8 je 0044C8ED 0044C8AA mov eax,dword ptr [ebx+35C]; TForm1.cb13:TCheckBox 0044C8B0 mov edx,dword ptr [eax] 0044C8B2 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C8B8 test al,al >0044C8BA je 0044C8ED 0044C8BC mov eax,dword ptr [ebx+33C]; TForm1.cb19:TCheckBox 0044C8C2 mov edx,dword ptr [eax] 0044C8C4 call dword ptr [edx+0B8]; TCustomCheckBox.GetChecked 0044C8CA test al,al >0044C8CC je 0044C8ED 0044C8CE lea eax,[ebp-4] 0044C8D1 mov edx,44C934; 'Ìõô¸ö÷ê¥ó¤ÉÚÀÆ²Äæââîàä¶¶' 0044C8D6 call @LStrLAsg 0044C8DB lea eax,[ebp-4] 0044C8DE call 0044BF00 0044C8E3 mov eax,dword ptr [ebp-4] 0044C8E6 call ShowMessage >0044C8EB jmp 0044C90A 0044C8ED lea eax,[ebp-4] 0044C8F0 mov edx,44C958; 'Åÿæò衦óàù¨ïêçð®øé¤íüàî诹' 0044C8F5 call @LStrLAsg 0044C8FA lea eax,[ebp-4] 0044C8FD call 0044BF00 0044C902 mov eax,dword ptr [ebp-4] 0044C905 call ShowMessage 0044C90A xor eax,eax 0044C90C pop edx 0044C90D pop ecx 0044C90E pop ecx 0044C90F mov dword ptr fs:[eax],edx 0044C912 push 44C927 0044C917 lea eax,[ebp-4] 0044C91A call @LStrClr 0044C91F ret <0044C920 jmp @HandleFinally <0044C925 jmp 0044C917 0044C927 pop ebx 0044C928 pop ecx 0044C929 pop ebp 0044C92A ret
Como podéis apreciar, las checkboxes involucradas son la 3, 5, 6, 9, 11, 12, 13, 15, 19 y 20. Solo nos falta saber cuales se corresponden con esa numeración y aquí ya depende de cada uno, yo en su día saqué los números a mano mediante el orden de tabulación, pero ya que tenemos IDR, el nos va a dar la solución de una forma sencilla y rápida.
Vamos a la pestaña «Forms (F5)«, seleccionamos la opción Form y hacemos doble click sobre el formulario.
Veréis que aparece el formulario con todos los recursos, incluso los puedes modificar. Localizar los checkboxes ahora es un juego de niños.
Os dejo un vídeo.
Trackbar
De nuevo, con la ayuda de IDR, localizamos la parte del código y analizamos su funcionamiento. Esta parte es la más divertida ya que requiere de un keygen pero en vez de coger el número de serie de una caja de texto lo obtiene de 5 trackbars como muestra la siguiente imagen.
El código de comprobación es el siguiente.
CPU Disasm Address Hex dump Command Comments 0044C1FF |. E8 ECF6FCFF CALL 0041B8F0 ; b^3 0044C204 |. D805 50C34400 FADD DWORD PTR DS:[44C350] ; b^3+5 0044C20A |. D9FA FSQRT ; sqrt(b^3+5) 0044C20C |. E8 F365FBFF CALL 00402804 ; Cos(sqrt(b^3+5)) = U 0044C211 |. DB7D B8 FSTP TBYTE PTR SS:[EBP-48] 0044C214 |. 9B WAIT 0044C215 |. D905 54C34400 FLD DWORD PTR DS:[44C354] ; Coje a 0044C21B |. DC45 E8 FADD QWORD PTR SS:[EBP-18] ; a+1 0044C21E |. D9FA FSQRT ; sqrt(a+1) 0044C220 |. D9E0 FCHS ; -sqrt(a+1) = V 0044C222 |. DB6D B8 FLD TBYTE PTR SS:[EBP-48] 0044C225 |. DEC1 FADDP ST(1),ST 0044C227 |. DB7D AC FSTP TBYTE PTR SS:[EBP-54] 0044C22A |. 9B WAIT 0044C22B |. D905 58C34400 FLD DWORD PTR DS:[44C358] ; coje c 0044C231 |. DC4D D8 FMUL QWORD PTR SS:[EBP-28] ; c*3 0044C234 |. D805 54C34400 FADD DWORD PTR DS:[44C354] ; c*3+1 0044C23A |. D9ED FLDLN2 ; Ln(c*3+1) = X 0044C23C |. D9C9 FXCH ST(1) 0044C23E |. D9F1 FYL2X 0044C240 |. DB6D AC FLD TBYTE PTR SS:[EBP-54] 0044C243 |. DEC1 FADDP ST(1),ST ; U+V+X 0044C245 |. DB7D A0 FSTP TBYTE PTR SS:[EBP-60] 0044C248 |. 9B WAIT 0044C249 |. D905 5CC34400 FLD DWORD PTR DS:[44C35C] ; coje d 0044C24F |. DC45 D0 FADD QWORD PTR SS:[EBP-30] ; d+2 0044C252 |. D9FA FSQRT ; sqrt(d+2) = Y 0044C254 |. DB6D A0 FLD TBYTE PTR SS:[EBP-60] 0044C257 |. DEE1 FSUBRP ST(1),ST ; U+V+X+(-Y) 0044C259 |. D905 58C34400 FLD DWORD PTR DS:[44C358] ; coje e 0044C25F |. DC4D C8 FMUL QWORD PTR SS:[EBP-38] ; e*3 0044C262 |. D835 5CC34400 FDIV DWORD PTR DS:[44C35C] ; (e*3)/2 = Z 0044C268 |. DEC1 FADDP ST(1),ST ; U+V+X+Y+Z 0044C26A |. DB2D 60C34400 FLD TBYTE PTR DS:[44C360] 0044C270 |. DEC1 FADDP ST(1),ST ; U+V+X+Y+Z+0.37 0044C272 |. D80D 6CC34400 FMUL DWORD PTR DS:[44C36C] ; (U+V+X+Y+Z+0.37)*1000 0044C278 |. DD5D F0 FSTP QWORD PTR SS:[EBP-10] 0044C27B |. 9B WAIT 0044C27C |. DD45 F0 FLD QWORD PTR SS:[EBP-10] 0044C27F |. E8 9065FBFF CALL 00402814 ; Redondea((U+V+X+Y+Z+0,37)*1000) 0044C284 |. 8945 98 MOV DWORD PTR SS:[EBP-68],EAX 0044C287 |. 8955 9C MOV DWORD PTR SS:[EBP-64],EDX 0044C28A |. DF6D 98 FILD QWORD PTR SS:[EBP-68] 0044C28D |. 83C4 F4 ADD ESP,-0C 0044C290 |. DB3C24 FSTP TBYTE PTR SS:[LOCAL.33] 0044C293 |. 9B WAIT 0044C294 |. 8D45 FC LEA EAX,[EBP-4] 0044C297 |. E8 68BFFBFF CALL 00408204 0044C29C |. 8D45 FC LEA EAX,[EBP-4] 0044C29F |. E8 5CFCFFFF CALL 0044BF00 ; Llamada de generación de hash ........ 0044BF04 |. 8BF0 MOV ESI,EAX 0044BF06 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] ; EAX = 5415 0044BF08 |. E8 677BFBFF CALL 00403A74 0044BF0D |. 8B15 98EE4400 MOV EDX,DWORD PTR DS:[44EE98] 0044BF13 |. 8902 MOV DWORD PTR DS:[EDX],EAX 0044BF15 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] 0044BF17 |. E8 587BFBFF CALL 00403A74 0044BF1C |. 84C0 TEST AL,AL 0044BF1E |. 76 38 JBE SHORT 0044BF58 0044BF20 |. 880424 MOV BYTE PTR SS:[LOCAL.3],AL 0044BF23 |. B3 01 MOV BL,1 0044BF25 |> B8 1C000000 /MOV EAX,1C 0044BF2A |. E8 516AFBFF |CALL 00402980 0044BF2F |. 0D 80000000 |OR EAX,00000080 0044BF34 |. 8BFB |MOV EDI,EBX 0044BF36 |. 81E7 FF000000 |AND EDI,000000FF 0044BF3C |. 8B16 |MOV EDX,DWORD PTR DS:[ESI] 0044BF3E |. 0FB6543A FF |MOVZX EDX,BYTE PTR DS:[EDI+EDX-1] ; Coje dig a dig el hash, en este caso 5415 0044BF43 |. 33C2 |XOR EAX,EDX ; 1 dig XOR 83; 2 dig XOR 89; 3 dig XOR 86; 4 dig XOR 8D 0044BF45 |. 50 |PUSH EAX 0044BF46 |. 8BC6 |MOV EAX,ESI 0044BF48 |. E8 F77CFBFF |CALL 00403C44 0044BF4D |. 5A |POP EDX 0044BF4E |. 885438 FF |MOV BYTE PTR DS:[EDI+EAX-1],DL 0044BF52 |. 43 |INC EBX 0044BF53 |. FE0C24 |DEC BYTE PTR SS:[LOCAL.3] 0044BF56 |.^ 75 CD \JNZ SHORT 0044BF25 ........ 0044C2AC |. E8 D378FBFF CALL 00403B84 ; Llamada a comparación ........ 00403BAD |> /8B0E /MOV ECX,DWORD PTR DS:[ESI] ; ECX = nuestro Serial XOReado 00403BAF |. |8B1F |MOV EBX,DWORD PTR DS:[EDI] ; EBX = Serial bueno 00403BB1 |. |39D9 |CMP ECX,EBX ; Compara 00403BB3 |. |75 58 |JNE SHORT 00403C0D ; Chico malo 00403BB5 |. |4A |DEC EDX 00403BB6 |. |74 15 |JZ SHORT 00403BCD 00403BB8 |. |8B4E 04 |MOV ECX,DWORD PTR DS:[ESI+4] 00403BBB |. |8B5F 04 |MOV EBX,DWORD PTR DS:[EDI+4] 00403BBE |. |39D9 |CMP ECX,EBX 00403BC0 |. |75 4B |JNE SHORT 00403C0D 00403BC2 |. |83C6 08 |ADD ESI,8 00403BC5 |. |83C7 08 |ADD EDI,8 00403BC8 |. |4A |DEC EDX 00403BC9 |.^\75 E2 \JNZ SHORT 00403BAD
En resumen
1) Siendo nuestro serial : 1 2 3 4 5
a b c d e
2) Realiza las operaciones matemáticas:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000))
3) Obtenemos un hash resultante de 5415
4) XORea los dígitos de la siguiente manera:
(5)35 xor 86 = B6
(4)34 xor 83 = BD
(1)31 xor 86 = B7
(5)35 xor 8D = B8
De modo que tenemos B6BDB7B8
5) Compara B6BDB7B8 con B5BAB2BA
6) Revertimos el XOR para obtener el hash bueno
B5 xor 86 = 36(6)
BA xor 83 = 33(3)
B2 xor 86 = 34(4)
BA xor 8D = 37(7)
Luego el hash bueno es 6347
7) Debemos hacer fuerza bruta buscando:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000)) = 6347
Para obtener los seriales válidos podemos hacer bucles recursivos hasta recorrer las 10^5 opciones posibles. Una forma de hacerlo en VBNet es la siguiente.
Dim tmp As Double
Dim an, bn, cn, dn, en As Integer
For an = 0 To 9
For bn = 0 To 9
For cn = 0 To 9
For dn = 0 To 9
For en = 0 To 9
tmp = Round(((Cos(Sqrt((Pow(bn, 3)) + 5)) + (-Sqrt(an + 1)) + Log(cn * 3 + 1) + (-Sqrt(dn + 2)) + ((en * 3) / 2) + 0.37) * 1000))
txtdebug.Text = "a-b-c-d-e = Hash || " & an & "-" & bn & "-" & cn & "-" & dn & "-" & en & " = " & tmp
If tmp = 6347 Then
ListBox1.Items.Add("Serial: " & an & bn & cn & dn & en)
End If
Application.DoEvents()
Next
Next
Next
Next
Next
Os dejo como siempre el crackme y el keygen en los enlaces.
Links
- Crackme y keygen.
- Interactive Delphi Reconstructor aka IDR.
- DEDE.
- Crackme y otras soluciones [crackmes.de]
Keygen para el Crackme 1 de VisionZ

Intro
Aquí tenemos un crackme clásico realizado en Visual C++. La única particularidad que tiene es que no muestra MessageBox al introducir bien o mal el serial, simplemente cambia una imagen de un emoticono. Si observamos el comportamiento del crackme notaremos que inicialmente el emoticono está neutral y al fallar se pone triste y por lo tanto es de suponer que al acertar se pondrá contento.
El BreakPoint

Al mirar en las Intermodular Calls de OllyDbg vemos que LoadIconA es un buen candidato para ubicar la comprobación del serial. Si nos fijamos hay tres llamadas, ponemos un breakpoint en las tres y enseguida llegamos a la zona de comprobación del serial.
La comprobación
00401180 . 6A FF PUSH -1 00401182 . 68 68194000 PUSH CrackMe_.00401968 00401187 . 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] 0040118D . 50 PUSH EAX 0040118E . 64:8925 000000>MOV DWORD PTR FS:[0],ESP 00401195 . 83EC 0C SUB ESP,0C 00401198 . 53 PUSH EBX 00401199 . 55 PUSH EBP 0040119A . 8BE9 MOV EBP,ECX 0040119C . 56 PUSH ESI 0040119D . 57 PUSH EDI 0040119E . 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10] 004011A2 . E8 2F050000 CALL <JMP.&MFC42.#540> 004011A7 . 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+14] 004011AB . C74424 24 0000>MOV DWORD PTR SS:[ESP+24],0 004011B3 . E8 1E050000 CALL <JMP.&MFC42.#540> 004011B8 . 8D4424 10 LEA EAX,DWORD PTR SS:[ESP+10] 004011BC . 8BCD MOV ECX,EBP 004011BE . 50 PUSH EAX 004011BF . 68 E9030000 PUSH 3E9 004011C4 . C64424 2C 01 MOV BYTE PTR SS:[ESP+2C],1 004011C9 . E8 02050000 CALL <JMP.&MFC42.#3097> ; Lee el tamano del nombre 004011CE . 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+14] 004011D2 . 51 PUSH ECX 004011D3 . 68 EA030000 PUSH 3EA 004011D8 . 8BCD MOV ECX,EBP 004011DA . E8 F1040000 CALL <JMP.&MFC42.#3097> ; Lee el tamano del serial 004011DF . 51 PUSH ECX 004011E0 . 8D5424 14 LEA EDX,DWORD PTR SS:[ESP+14] 004011E4 . 8BCC MOV ECX,ESP 004011E6 . 896424 1C MOV DWORD PTR SS:[ESP+1C],ESP 004011EA . 52 PUSH EDX 004011EB . E8 DA040000 CALL <JMP.&MFC42.#535> 004011F0 . 8D4424 1C LEA EAX,DWORD PTR SS:[ESP+1C] 004011F4 . 8BCD MOV ECX,EBP 004011F6 . 50 PUSH EAX 004011F7 . E8 D4010000 CALL CrackMe_.004013D0 004011FC . 50 PUSH EAX 004011FD . 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+14] 00401201 . C64424 28 02 MOV BYTE PTR SS:[ESP+28],2 00401206 . E8 B9040000 CALL <JMP.&MFC42.#858> 0040120B . 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP+18] 0040120F . C64424 24 01 MOV BYTE PTR SS:[ESP+24],1 00401214 . E8 A5040000 CALL <JMP.&MFC42.#800> 00401219 . 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] 0040121D . 8B5424 14 MOV EDX,DWORD PTR SS:[ESP+14] 00401221 . 8B41 F8 MOV EAX,DWORD PTR DS:[ECX-8] 00401224 . 8B4A F8 MOV ECX,DWORD PTR DS:[EDX-8] 00401227 . 3BC1 CMP EAX,ECX ; CMP len nombre y len serial 00401229 . 0F85 2C010000 JNZ CrackMe_.0040135B 0040122F . 83F8 03 CMP EAX,3 ; len nombre >=3 00401232 . 0F8C 23010000 JL CrackMe_.0040135B 00401238 . 50 PUSH EAX 00401239 . E8 7A040000 CALL <JMP.&MFC42.#823> 0040123E . 8BF0 MOV ESI,EAX 00401240 . 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14] 00401244 . 83C4 04 ADD ESP,4 00401247 . 33C9 XOR ECX,ECX 00401249 . 8B50 F8 MOV EDX,DWORD PTR DS:[EAX-8] 0040124C . 4A DEC EDX 0040124D . 85D2 TEST EDX,EDX 0040124F . 7E 37 JLE SHORT CrackMe_.00401288 ....... 1ºBUCLE ....... 00401251 > 8A1401 MOV DL,BYTE PTR DS:[ECX+EAX] 00401254 . 8A5C01 01 MOV BL,BYTE PTR DS:[ECX+EAX+1] 00401258 . 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14] 0040125C . 0FBED2 MOVSX EDX,DL 0040125F . 0FBE0401 MOVSX EAX,BYTE PTR DS:[ECX+EAX] 00401263 . 8D4410 FE LEA EAX,DWORD PTR DS:[EAX+EDX-2] 00401267 . 99 CDQ 00401268 . 2BC2 SUB EAX,EDX 0040126A . 0FBED3 MOVSX EDX,BL 0040126D . D1F8 SAR EAX,1 0040126F . 40 INC EAX 00401270 . 83EA 02 SUB EDX,2 00401273 . 3BC2 CMP EAX,EDX 00401275 . 0F94C0 SETE AL 00401278 . 880431 MOV BYTE PTR DS:[ECX+ESI],AL 0040127B . 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] 0040127F . 41 INC ECX 00401280 . 8B50 F8 MOV EDX,DWORD PTR DS:[EAX-8] 00401283 . 4A DEC EDX 00401284 . 3BCA CMP ECX,EDX 00401286 .^7C C9 JL SHORT CrackMe_.00401251 ........ Última comprobación ........ 00401288 > 0FBE1401 MOVSX EDX,BYTE PTR DS:[ECX+EAX] 0040128C . 0FBE78 01 MOVSX EDI,BYTE PTR DS:[EAX+1] 00401290 . 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14] 00401294 . 83C7 FE ADD EDI,-2 00401297 . 0FBE0401 MOVSX EAX,BYTE PTR DS:[ECX+EAX] 0040129B . 8D4410 FE LEA EAX,DWORD PTR DS:[EAX+EDX-2] 0040129F . 99 CDQ 004012A0 . 2BC2 SUB EAX,EDX 004012A2 . D1F8 SAR EAX,1 004012A4 . 40 INC EAX 004012A5 . 3BC7 CMP EAX,EDI 004012A7 . 0F94C2 SETE DL 004012AA . 881431 MOV BYTE PTR DS:[ECX+ESI],DL
La comprobación es muy sencilla, en resumen hace esto con todas las letras del nombre excepto la última:
1º Caracter
(1ºname + 1ºserial - 2 = X)
(X / 2)
(X + 1)
(2ºname - 2 = Y)
¿Y = X?
2º Caracter
(2ºname + 2ºserial - 2 = X)
(X / 2)
(X + 1)
(3ºname - 2 = Y)
¿Y = X?
...
Con el último caracter del nombre hace lo siguiente:
(6ºname + 6ºserial - 2 = X)
(X / 2)
(X + 1)
(2ºname - 2 = Y)
¿Y = X?
---------
Para revertir la primera parte de la comprobación para el nombre deurus quedaría:
X1 = (((2ºname-2-1)*2)+2)-1ºname
X2 = (((3ºname-2-1)*2)+2)-2ºname
X3 = (((4ºname-2-1)*2)+2)-3ºname
X4 = (((5ºname-2-1)*2)+2)-4ºname
X5 = (((6ºname-2-1)*2)+2)-5ºname
X6 = (((2ºname-2-1)*2)+2)-6ºname
Keygen
var nombre = "deurus";
nombre = nombre.toUpperCase();
var serial = "";
var tmp = "";
var i;
for (i = 0; i < nombre.length-1 ; i++) {
tmp = ((nombre.charCodeAt(i+1)-2-1)*2+2)-nombre.charCodeAt(i);
serial += String.fromCharCode(tmp);
}
tmp = ((nombre.charCodeAt(1)-2-1)*2+2)-nombre.charCodeAt(nombre.length-1);
serial += String.fromCharCode(tmp);
document.write(serial);
Enlaces
Y eso es todo, ¡a disfrutar!
Mirror Crackmes.de

While Crackmes.de returns, I leave a couple of files for practice.
Mientras vuelve Crackmes.de, os dejo un par de archivos para practicar.
In the folder crackmes.de_mirror you have two files:
En la carpeta crackmes.de_mirror tienes dos archivos:
Crackmes.de (2011 – 2015).rar [491 MB] [password: tuts4you]crackmes.de-2016-12.7z [639 MB]
password of files = deurus.info
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 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
5 Retos Stego sencillos

Computer Password Security Hacker

En el primer vistazo con el editor hexadecimal ya vemos la solución al reto:
Pho

Al igual que el caso anterior con el editor hexadecimal tenemos más que suficiente para resolver el reto.
Minions

En el análisis inicial no destaca prácticamente nada excepto la palabra myadmin que podemos ver con un editor hexadecimal.
La palabra myadmin es una buena candidata a ser contraseña ante una decodificación. Probamos con lo estándar y conseguimos resultados con steghide. La decodificación nos devuelve la cadena AEMAVABGAGwAZQBhAHIAbgB7AHQAaABpAHMAXwBpAHMAXwBmAHU***** que rápidamente catalogamos como base64 para resolver el reto.
Unopenable
Se nos entrega una imagen GIF aparentemente corrupta. Estudiando un poco la cabecera de los archivos GIF llegamos rápidamente a la conclusión de que faltan los cuatro primeros bytes del archivo.
Bytes originales
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 39 61 F4 01 F4 01 F4 00 00 00 00 00 3A 00 00 00 9aô.ô.ô.....:...
00000010 00 3A 3A 00 3A 66 00 00 66 00 3A 00 00 66 90 3A .::.:f..f.:..f.:
00000020 00 90 3A 3A B6 66 00 B6 66 3A 90 90 3A DB 90 3A ..::¶f.¶f:..:Û.:
00000030 FF B6 66 00 3A 90 66 3A 90 00 66 90 00 66 B6 3A ÿ¶f.:.f:..f..f¶:
Después de insertar los bytes que faltan
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 47 49 46 38 39 61 F4 01 F4 01 F4 00 00 00 00 00 GIF89aô.ô.ô.....
00000010 3A 00 00 00 00 3A 3A 00 3A 66 00 00 66 00 3A 00 :....::.:f..f.:.
00000020 00 66 90 3A 00 90 3A 3A B6 66 00 B6 66 3A 90 90 .f.:..::¶f.¶f:..
00000030 3A DB 90 3A FF B6 66 00 3A 90 66 3A 90 00 66 90 :Û.:ÿ¶f.:.f:..f.
Una vez insertados los bytes podemos ver una animación que contiene una cadena de texto fácilmente reconocible como base64. La decodificamos y ya tenemos la solución.
Oreo

Mirando con un editor hexadecimal no encontramos nada excepto la frase This is not the flag you are looking for para intentar disuadirnos.
Cargamos la imagen en Aperi’Solve y enseguida nos llama la atención la sección Binwalk y un suculento Rar.
Descargamos el archivo Rar y al descomprimir nos encontramos con un archivo de texto con la misma frase desalentadora del inicio y una imagen JPG, esta vez con dos oreos. Inspeccionando la imagen damos con la solución.
VideoTutorial – KeyGen para el Crackme#1 de WinFan

VideoTutorial – Desempacando Aspack 2.1, Pe-Pack 1.0 y UPX del Crackme Sweeet Dream 1.0 de 2Sweeet

VideoTutorial – RegisterMe de Shadow – Parcheando un NET




























































































































