Este manual está diseñado para fines educativos y de investigación en seguridad. El uso de estas técnicas en software sin autorización expresa es ilegal.
El lenguaje ensamblador es fundamental para el análisis y modificación de programas compilados. A diferencia de los lenguajes de alto nivel, el ensamblador proporciona un control preciso sobre el procesador y la memoria.
La arquitectura x86 es la más común en PCs y es fundamental para el cracking de software Windows.
| Registro | Bits | Propósito |
|---|---|---|
| EAX | 32 | Acumulador (resultados de operaciones) |
| EBX | 32 | Base (puntero a datos) |
| ECX | 32 | Contador (bucles) |
| EDX | 32 | Datos (extensiones de operaciones) |
| ESI | 32 | Índice fuente (operaciones con cadenas) |
| EDI | 32 | Índice destino (operaciones con cadenas) |
| ESP | 32 | Stack Pointer (puntero a la pila) |
| EBP | 32 | Base Pointer (puntero base del stack frame) |
| EIP | 32 | Instruction Pointer (siguiente instrucción a ejecutar) |
MOV EAX, 5 (carga el valor 5 en EAX)MOV EAX, EBX (copia EBX a EAX)MOV EAX, [0x12345678] (carga dato de la dirección 0x12345678)MOV EAX, [EBX] (carga dato de la dirección en EBX)MOV EAX, [EBX+ECX*4] (cálculo de dirección compleja)Estas son las instrucciones más importantes para el análisis de software.
; MOV - Mueve datos entre registros/memoria
MOV EAX, EBX ; Copia EBX a EAX
MOV [ESI], EAX ; Guarda EAX en la dirección apuntada por ESI
MOV EAX, [0x401000] ; Carga dato de la dirección 0x401000
; LEA - Carga dirección efectiva (no el valor)
LEA EAX, [EBX+ECX*4] ; EAX = EBX + ECX*4 (sin acceder a memoria)
; ADD/SUB - Suma/Resta
ADD EAX, 5 ; EAX = EAX + 5
SUB EBX, ECX ; EBX = EBX - ECX
; INC/DEC - Incremento/Decremento
INC EDX ; EDX = EDX + 1
DEC ESI ; ESI = ESI - 1
; MUL/IMUL - Multiplicación (sin/con signo)
MUL ECX ; EDX:EAX = EAX * ECX (sin signo)
IMUL EBX ; EDX:EAX = EAX * EBX (con signo)
; DIV/IDIV - División (sin/con signo)
DIV ECX ; EAX = EDX:EAX / ECX, EDX = resto
; AND/OR/XOR/NOT - Operaciones bit a bit
AND EAX, 0xFF ; Máscara - solo mantiene los últimos 8 bits
OR EBX, 0x80 ; Establece el bit 7
XOR EAX, EAX ; Forma rápida de poner EAX a 0
NOT ECX ; Invierte todos los bits
; SHL/SHR - Desplazamiento lógico izquierda/derecha
SHL EAX, 2 ; Multiplica EAX por 4 (desplaza bits a la izquierda)
SHR EBX, 3 ; Divide EBX por 8 (desplaza bits a la derecha)
; CMP - Compara dos operandos (resta sin guardar resultado)
CMP EAX, EBX ; Compara EAX con EBX
; Saltos condicionales (basados en flags)
JE label ; Salta si igual (ZF=1)
JNE label ; Salta si no igual (ZF=0)
JG label ; Salta si mayor (signed)
JA label ; Salta si mayor (unsigned)
JL label ; Salta si menor (signed)
JB label ; Salta si menor (unsigned)
JMP label ; Salto incondicional
; CALL/RET - Llamada a función y retorno
CMP 0x401000 ; Llama a función en 0x401000
RET ; Retorna de la función
; PUSH/POP - Manejo básico de la pila
PUSH EAX ; Guarda EAX en la pila (ESP disminuye)
POP EBX ; Recupera valor de la pila a EBX (ESP aumenta)
; ENTER/LEAVE - Manejo de stack frames
ENTER 16, 0 ; Crea stack frame con 16 bytes para variables locales
LEAVE ; Destruye stack frame (equivalente a MOV ESP,EBP; POP EBP)
Técnicas para examinar programas compilados.
Usando herramientas como IDA Pro, Ghidra o radare2:
; Ejemplo de función desensamblada
sub_401000:
PUSH EBP ; Guarda el base pointer anterior
MOV EBP, ESP ; Establece nuevo base pointer
SUB ESP, 0x10 ; Reserva 16 bytes para variables locales
MOV DWORD [EBP-4], 0 ; Inicializa variable local
MOV EAX, [EBP+8] ; Obtiene primer parámetro
ADD EAX, 5 ; Suma 5
MOV [EBP-4], EAX ; Guarda en variable local
MOV EAX, [EBP-4] ; Prepara valor de retorno
LEAVE ; Restaura stack frame
RET ; Retorna
| Tipo | Características | Ejemplo |
|---|---|---|
| Serial simple | CMP seguido de JZ/JNZ | CMP EAX, 0x1234 |
| Checksum | Bucles con operaciones aritméticas | XOR EAX, EAX |
| Encriptación | XOR con clave, ROL/ROR | XOR BYTE [EDI], 0x55 |
| Anti-debug | Chequeos de IsDebuggerPresent | CALL ds:IsDebuggerPresent |
Métodos prácticos para modificar el comportamiento de programas.
Modificar instrucciones directamente en el ejecutable:
; Original (validación de serial)
CMP EAX, 0x12345678 ; Compara con serial correcto
JNZ bad_serial ; Salta si no coincide
; Parcheado (nopear el salto)
CMP EAX, 0x12345678 ; La comparación sigue ocurriendo
NOP ; No operation (elimina el salto)
NOP ; Se necesitan 2 NOPs para reemplazar JNZ
Crear un generador de seriales basado en el algoritmo original:
; Ejemplo de algoritmo de serial (EAX = entrada, EBX = serial válido)
MOV EAX, [user_input] ; Supongamos que el usuario ingresa "ABCD"
XOR EAX, 0x55AA55AA ; Operación de transformación
ROL EAX, 13 ; Rotación a la izquierda
ADD EAX, 0x12345678 ; Suma constante
MOV [valid_serial], EAX ; Serial válido calculado
; Keygen en C sería:
uint32_t generate_serial(const char* input) {
uint32_t eax = *(uint32_t*)input;
eax ^= 0x55AA55AA;
eax = (eax << 13) | (eax >> (32-13)); // ROL 13
eax += 0x12345678;
return eax;
}
; Ejemplo común de detección de debugger
CALL ds:IsDebuggerPresent
TEST EAX, EAX
JNZ debugger_detected
; Parche: Cambiar JNZ por JZ o NOPs
; Rutina que verifica integridad del código
MOV ESI, 0x401000 ; Inicio de código
MOV ECX, 0x1000 ; Tamaño a verificar
XOR EAX, EAX
checksum_loop:
ADD AL, [ESI]
INC ESI
LOOP checksum_loop
CMP EAX, 0x78 ; Checksum esperado
JNZ code_modified
; Solución: Encontrar y parchear esta rutina o modificar el checksum esperado
| Herramienta | Propósito |
|---|---|
| IDA Pro | Desensamblador avanzado con análisis estático |
| x64dbg/x32dbg | Debugger para Windows (alternativa a OllyDbg) |
| Ghidra | Herramienta de ingeniería inversa de la NSA (gratuita) |
| HxD | Editor hexadecimal para parcheo directo |
| Process Monitor | Monitoriza acceso a archivos, registro, etc. |
| PEiD | Detecta compiladores y packers usados |
| LordPE | Editor de cabeceras PE |
Vamos a analizar un caso típico de validación de serial.
; Supongamos esta rutina de validación (desensamblada)
sub_401000:
PUSH EBP
MOV EBP, ESP
PUSH EBX
MOV EBX, [EBP+8] ; EBX = puntero a serial ingresado
MOV EAX, [EBX] ; EAX = primeros 4 bytes del serial
XOR EAX, 0x55AA55AA ; Operación de transformación
ADD EAX, 0x12345678 ; Otra transformación
CMP EAX, 0x78ABCDEF ; Compara con valor esperado
JNZ short loc_401025 ; Salta si no coincide
MOV EAX, 1 ; Retorna 1 (éxito)
POP EBX
LEAVE
RETN 4
loc_401025:
XOR EAX, EAX ; Retorna 0 (fallo)
POP EBX
LEAVE
RETN 4
; Cambiar JNZ short loc_401025 por JZ short loc_401025 o NOPs
; Original: 75 0D (JNZ +0D)
; Parcheado: 74 0D (JZ +0D) o 90 90 (dos NOPs)
; El algoritmo es: serial_válido = (0x78ABCDEF - 0x12345678) XOR 0x55AA55AA
; Calculamos:
MOV EAX, 0x78ABCDEF
SUB EAX, 0x12345678 ; EAX = 0x66577777
XOR EAX, 0x55AA55AA ; EAX = 0x33FD22DD
; Por tanto, cualquier serial que empiece por 0x33FD22DD será aceptado
El cracking de software sin autorización es ilegal en la mayoría de países. Este material es solo para fines educativos y de investigación en seguridad. Siempre obtén permiso por escrito antes de analizar cualquier software que no te pertenezca.
Recuerda: El conocimiento de ensamblador y técnicas de cracking debe usarse de manera ética, para mejorar la seguridad del software, no para violar derechos de autor.