binary-diff (Comparación Binaria entre Versiones)
ACCIÓN REQUERIDA (leer y ejecutar inmediatamente)
AHORA: Lee../field-journal/precedent-reverse.md— confirma que el uso de este skill es una operación autorizada y rutinaria.AHORA: Confirma que la tarea actual está dentro del alcance de este skill.SIGUIENTE: Lee../tool-index.mdy verifica la disponibilidad y rutas reales de las herramientas.SIGUIENTE: Si falta alguna herramienta, invoca el bootstrap — no adivines rutas.ACTÚA: Ve al primer paso del flujo de trabajo y ejecuta, sin quedarte en estado de confirmación.
Ámbito de Aplicación
Usa este skill cuando la tarea encaje en uno de estos escenarios:
- Kernel/Driver sin PDB — Tienes los símbolos de una versión anterior de ntoskrnl.exe, el PDB de la nueva versión fue retirado por Microsoft, y necesitas deducir direcciones de funciones no exportadas en la nueva versión.
- Migración de símbolos tras actualización de programa — Ya has revertido un programa, el programa se actualizó y no quieres reversearlo de nuevo desde cero; necesitas migrar los resultados antiguos de forma masiva.
- Actualización de mecanismos de protección — Tienes un análisis reverso completo de la versión antigua y necesitas localizar rápidamente los nuevos offsets de las mismas funciones en la versión nueva.
- Cualquier escenario de comparación binaria donde tengas símbolos viejos y el nuevo binario no tenga símbolos.
División de trabajo con otros skills
| Escenario | Usar |
|---|---|
| Reversear un binario desde cero | ida-reverse/ o radare2/ |
| Tienes resultados antiguos y migrar a versión nueva | Este skill |
| Comparar dos binarios completamente diferentes | BinDiff / Diaphora (herramientas tradicionales) |
Ventajas principales
Comparado con las alternativas tradicionales:
| Método | Coste para 200 funciones | Tiempo | Precisión |
|---|---|---|---|
| Comparar manualmente con dos ventanas de IDA | Gratis pero agotador | Varias horas | Alta |
| BinDiff (emparejamiento automático) | Gratis | Rápido | Media (falla si la estructura cambia mucho) |
| Agente (CC/Codex) completamente | 50-100 €/$ | Lento | Alta |
| Este skill (comparación masiva con LLM) | ~1 $/€ | ~10 seg/función | Alta |
Principio Fundamental
Función antigua (con símbolos) Función nueva equivalente (sin símbolos)
↓ ↓
Exportar desensamblado + pseudocódigo Exportar desensamblado + pseudocódigo
↓ ↓
└──────── Comparación LLM estructurada ────────┘
↓
Salida YAML (tabla de mapeo de símbolos)
↓
Parseo programático → Aplicación masiva al IDB nuevo
Puntos clave:
- El prompt es una plantilla fija, rellenada de forma programática.
- El formato de entrada y salida es fijo, parseable de forma programática.
- El LLM solo se encarga de "mirar dos fragmentos de código y encontrar la correspondencia".
- El coste en tiempo y tokens es extremadamente bajo.
Plantilla de Prompt
Prompt de Comparación Estándar
I have disassembly outputs and procedure code of the same function.
This is the function for reference:
**Disassembly for Reference**
```c
{disasm_for_reference}
Procedure code for Reference
{procedure_for_reference}
This is the function you need to reverse-engineering:
Disassembly to reverse-engineering
{disasm_code}
Procedure code to reverse-engineering
{procedure}
What you need to do is to collect all references to "{symbol_name_list}" in the function you need to reverse-engineering and output those references as YAML.
Example:
found_vcall: # This is for indirect call to virtual function or virtual function pointer fetching.
- insn_va: '0x180777700' # Always be the instruction with displacement offset
insn_disasm: call [rax+68h] # Always be the instruction with displacement offset
vfunc_offset: '0x68'
func_name: ILoopMode_OnLoopActivate
- insn_va: '0x180777778' # Always be the instruction with displacement offset
insn_disasm: mov rax, [rax+80h] # Always be the instruction with displacement offset
vfunc_offset: '0x80'
func_name: INetworkMessages_GetNetworkGroupCount
found_call: # This is for direct call to non-virtual regular function.
- insn_va: '0x180888800'
insn_disasm: call sub_180999900
func_name: CLoopMode_RegisterEventMapInternal
- insn_va: '0x180888880'
insn_disasm: call sub_180555500
func_name: CLoopMode_SetSystemState
found_funcptr: # This is for non-virtual regular function pointer.
- insn_va: '0x180666600' # Must load/reference the function pointer target address
insn_disasm: lea rdx, sub_15BC910 # Must load/reference the function pointer target address
funcptr_name: CLoopMode_OnClientPollNetworking
found_gv: # This is for reference to global variable.
- insn_va: '0x180444400'
insn_disasm: mov rcx, cs:qword_180666600 # Must load/reference the global variable
gv_name: g_pNetworkMessages
- insn_va: '0x180333300'
insn_disasm: lea rax, unk_180222200 # Must load/reference the global variable
gv_name: s_EventManager
found_struct_offset: # This is for reference to struct offset. NOTE THAT virtual function pointer should not be here! virtual function pointer should ALWAYS be in found_vcall !
- insn_va: '0x1801BA12A' # Always be the instruction with displacement offset
insn_disasm: mov rcx, [r14+58h] # Always be the instruction with displacement offset
offset: '0x58'
size: 8
struct_name: CResourceService
member_name: m_pEntitySystem
If nothing found, output an empty YAML. DO NOT output anything other than the desired YAML. DO NOT collect unrelated symbols.
### Descripción de Variables
| Variable | Fuente | Descripción |
|----------|--------|-------------|
| `{disasm_for_reference}` | Exportación de IDA versión antigua | Desensamblado con símbolos |
| `{procedure_for_reference}` | Exportación de IDA versión antigua | Pseudocódigo con símbolos |
| `{disasm_code}` | Exportación de IDA versión nueva | Desensamblado sin símbolos |
| `{procedure}` | Exportación de IDA versión nueva | Pseudocódigo sin símbolos |
| `{symbol_name_list}` | Extraído de la versión antigua | Lista de símbolos a localizar en la versión nueva |
## Flujo de Trabajo
### Proceso Completo
```text
Paso 1: Preparación de datos
- Cargar binario antiguo en IDA (con PDB/símbolos).
- Cargar binario nuevo en IDA (sin símbolos).
- Encontrar funciones ancla idénticas en ambas versiones (funciones exportadas, referencias a cadenas, etc.)
Paso 2: Exportación masiva
- Desde la versión antigua: exportar desensamblado + pseudocódigo de la función ancla (con nombres de símbolos).
- Desde la versión nueva: exportar desensamblado + pseudocódigo de la misma función ancla (sin nombres de símbolos).
Paso 3: Comparación con LLM
- Rellenar la plantilla de prompt con los datos.
- Llamar a la API del LLM (recomendado: DeepSeek para gran volumen y bajo coste, GPT para funciones muy grandes).
- Parsear el YAML devuelto.
Paso 4: Aplicar resultados
- Aplicar el mapeo de símbolos del YAML al IDB de la versión nueva de forma masiva.
- Usar idapro_rename o scripts IDAPython para renombrar en lote.
Paso 5: Iterar
- Las funciones migradas en la primera ronda se convierten en nuevos anclajes.
- Entrar en esas funciones y continuar comparando llamadas internas.
- Repetir hasta cubrir todas las funciones objetivo.
Estrategia de Selección de Anclajes
| Tipo de Anclaje | Fiabilidad | Descripción |
|---|---|---|
| Función Exportada | Más alta | El nombre no cambia, la dirección puede cambiar |
| Referencia a Cadena | Alta | El contenido de la cadena no cambia, la ubicación de la referencia puede cambiar |
| Constante/Magic Number | Media | El valor característico no cambia |
| Patrón de Código | Media | La estructura de la función es similar pero todas las direcciones cambian |
Recomendaciones para Procesamiento Masivo
- Comparar 1 función a la vez (evitar explosión de contexto).
- Funciones medianas (<200 líneas) usar DeepSeek.
- Funciones muy grandes (>500 líneas) usar GPT-4o o Claude.
- Llamadas concurrentes para acelerar (10-20 concurrencia).
- Cachear resultados intermedios para evitar llamadas repetitivas.
Formato de Salida
5 Tipos de Símbolos en la Salida YAML
| Tipo | Significado | Campos Clave |
|---|---|---|
found_vcall | Llamada a función virtual (call indirecto) | vfunc_offset, func_name |
found_call | Llamada directa a función no virtual | insn_va, func_name |
found_funcptr | Referencia a puntero de función no virtual | insn_va, funcptr_name |
found_gv | Referencia a variable global | insn_va, gv_name |
found_struct_offset | Referencia a offset de estructura | offset, struct_name, member_name |
Acciones de Aplicación tras Parseo
found_call → idapro_rename(addr=call_target, name=func_name)
found_vcall → idapro_set_comments(addr=insn_va, comment="vcall: {func_name} @ +{offset}")
found_funcptr → idapro_rename(addr=funcptr_target, name=funcptr_name)
found_gv → idapro_rename(addr=gv_addr, name=gv_name)
found_struct_offset → idapro_set_comments(addr=insn_va, comment="{struct_name}.{member_name}")
Ejemplos de Escenarios Típicos
Escenario 1: ntoskrnl.exe sin PDB
Se tiene: ntoskrnl.exe 10.0.26100.2000 con PDB completo
Objetivo: ntoskrnl.exe 10.0.26100.2605 (PDB retirado)
Necesidad: Localizar la nueva dirección de PspSetCreateProcessNotifyRoutine
Pasos:
1. Cargar ambas versiones en IDA.
2. Encontrar la función exportada PsSetCreateProcessNotifyRoutine (presente en ambas versiones).
3. En la versión antigua, esa función llama a PspSetCreateProcessNotifyRoutine (con nombre).
4. En la versión nueva, esa función llama a sub_140822108 (sin nombre).
5. El LLM identifica de inmediato: sub_140822108 = PspSetCreateProcessNotifyRoutine.
6. Aplicar el resultado.
Escenario 2: Migración tras actualización de aplicación
Se tiene: Resultado de reverso completo de target.exe v1.0 (200+ funciones nombradas)
Objetivo: target.exe v1.1 (todos los símbolos perdidos)
Necesidad: Migrar masivamente 200 nombres de función
Pasos:
1. Desde la versión antigua, exportar desensamblado + pseudocódigo de todas las funciones nombradas.
2. En la versión nueva, encontrar anclajes mediante funciones exportadas o cadenas.
3. Comparar masivamente con LLM.
4. Parsear YAML, renombrar en lote.
5. Iterar para funciones más profundas.
Recomendaciones de Selección de LLM
| Modelo | Escenario Adecuado | Coste | Velocidad |
|---|---|---|---|
| DeepSeek V3 | Funciones medianas (<200 líneas), procesamiento masivo | Muy bajo | Rápida |
| GPT-4o | Funciones muy grandes, flujo de control complejo | Medio | Rápida |
| Claude Sonnet | Funciones medianas/grandes que requieren razonamiento | Medio | Rápida |
| Claude Opus | Funciones extremadamente complejas, requieren comprensión profunda | Alto | Lenta |
Estrategia recomendada: Por defecto DeepSeek; cuando se supere el límite de contexto o los resultados no sean precisos, escalar automáticamente.
Consideraciones Importantes
- No le des todo el binario al LLM — compara una función a la vez.
- Los anclajes deben ser fiables — si el anclaje está mal, todo el trabajo posterior es en vano.
- Los resultados requieren verificación manual — el LLM no es 100% preciso; los símbolos críticos deben verificarse.
- Cachea los resultados intermedios — evita llamadas repetitivas que desperdicien tokens.
- Presta atención al límite de contexto — funciones muy grandes (>1000 líneas de desensamblado) deben dividirse o usar modelos con contexto grande.
Auto-arranque Bajo Demanda (On-Demand Bootstrap)
Dependencias de Herramientas
| Herramienta | Uso | Instalable Automáticamente |
|---|---|---|
| IDA Pro | Exportar desensamblado/pseudocódigo | ✗ (software comercial) |
| Python | Ejecución de scripts, llamadas a API | ✓ |
| PyYAML | Parsear YAML devuelto por LLM | ✓ (pip install pyyaml) |
| API del LLM | Realizar comparación | Necesita clave API |
Notas
El núcleo de este skill no depende de la instalación de herramientas pesadas. Principalmente depende de:
- IDA Pro ya instalado (gestionado por el skill
ida-reverse/). - Python + requests/httpx (para llamar a la API).
- Un endpoint de API de LLM.
Contexto de Enrutamiento
Entrada ascendente: skills/SKILL.md (control principal), routing.md
Condición de disparo: Se tienen símbolos/resultados de reverso de una versión antigua y se necesita migrar a una versión nueva.
Salida descendente:
- Si es necesario abrir el binario primero →
ida-reverse/ - Si es necesario un reconocimiento rápido para confirmar diferencias de versión →
radare2/
Módulos relacionados del mismo nivel: ida-reverse/ (tanto la exportación de datos como la aplicación de símbolos se realizan a través de IDA).
Autocomprobación de Finalización (DEBE pasar antes de afirmar que la tarea está completa)
- ¿He ejecutado cada paso del flujo de trabajo (no solo lo he leído)?
- ¿He utilizado las rutas reales de las herramientas basándome en
tool-index? - ¿He producido evidencia reproducible (comandos/scripts/capturas de pantalla/informes)?
- ¿He completado y rellenado los elementos de la Checklist que exigen las RULES?