Herramientas: de file y objdump al intérprete de Python
Un script se lee con un editor; un binario compilado hay que mirarlo por dentro sin ejecutarlo. Empiezo por el binario porque es lo que va a encontrar en cuanto suba de nivel.
Ficha de file y strings
file identifica el tipo real de un archivo por sus primeros bytes, sin fiarse de la extensión. strings ("cadenas") imprime las secuencias legibles de 4 o más caracteres: mensajes, rutas, URLs.
file [-b] ARCHIVO...
strings [-n MINIMO] [-e CODIFICACION] ARCHIVO| Opción | Qué hace | Ejemplo |
|---|---|---|
file -b | Solo el tipo, sin repetir el nombre | file -b crackme |
strings -n | Largo mínimo de cadena (por defecto 4) | strings -n 8 crackme |
strings -e l | Busca texto UTF-16, el de muchos .exe de Windows | strings -e l app.exe |
Un ELF de Linux compilado desde un C de diez líneas (salida ilustrativa):
$ file crackme
crackme: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3f1c…, for GNU/Linux 3.2.0, not stripped
$ strings crackme | grep -i clave
Clave correcta
Clave incorrectanot stripped significa que conserva los nombres de las funciones. Va a ver revisar en vez de sub_1149.
Ficha de objdump
objdump (object dump, "volcado de objeto", de las binutils de GNU) con -d desensambla un ejecutable.
objdump -d [-M intel] [--disassemble=FUNCION] ARCHIVO| Opción | Qué hace | Ejemplo |
|---|---|---|
-d | Desensambla las secciones de código | objdump -d crackme |
-M intel | Sintaxis Intel en vez de AT&T | objdump -d -M intel crackme |
--disassemble= | Solo una función, si hay símbolos | objdump --disassemble=revisar crackme |
El comienzo de revisar, ilustrativo, compilado sin optimizar:
0000000000001149 <revisar>:
1149: 55 push %rbp
114a: 48 89 e5 mov %rsp,%rbp
114d: 89 7d fc mov %edi,-0x4(%rbp)
1150: 81 7d fc 39 05 00 00 cmpl $0x539,-0x4(%rbp)
1157: 0f 94 c0 sete %alLo que importa es cmpl $0x539: compara el argumento con 0x539, o sea 1337. Lo anterior es la preparación de cualquier función.
$ objdump -d verificador.py
objdump: verificador.py: file format not recognizedNo es un binario: es texto, se lee con un editor.
Pasadas unas treinta instrucciones, yo dejo objdump y abro Ghidra, que la NSA liberó en 2019: su descompilador muestra pseudocódigo parecido a C (necesita Java). En terminal está radare2: r2 -A crackme, afl lista funciones y pdf @ main desensambla main.
Python para deshacer transformaciones
Abra el intérprete con python3 (en Windows, py). Casi todo crackme combina estas operaciones sobre bytes:
| Operación | Ida | Vuelta |
|---|---|---|
| XOR | x ^ k | x ^ k (se deshace sola) |
| Rotar 3 bits a la izquierda | ((x << 3) | (x >> 5)) & 0xFF | ((x >> 3) | (x << 5)) & 0xFF |
| Invertir el orden | v[::-1] | v[::-1] |
| Texto a números | list(s.encode()) | bytes(v).decode() |
El & 0xFF recorta a un byte. Si lo olvida (Python 3.12):
>>> bytes([(200 << 3)])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: bytes must be in range(0, 256)CyberChef hace XOR y rotaciones (From Decimal, XOR, Rotate right); para reordenar índices, Python es más directo.