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.