Depuración y desensamblado práctico de x86-64
Recuperar contratos de función, pila, ABI y memoria desde una dirección de fallo
Depuración y desensamblado práctico de x86-64
Este artículo se ha creado con fines didácticos. El desensamblado observa comportamiento binario; no demuestra intención del fuente ni autorización. Analice solo programas y fallos para los que tenga permiso.
En builds optimizados desaparecen variables, se inlinean funciones y el instruction pointer cae en un mov. Lo importante es un procedimiento que conecte registros, pila, memoria y ABI por orden de evidencia.
Preservar pruebas
Guarde executable/modules exactos con build ID o hash, PDB/DWARF coincidente, excepción/señal, dirección y offset de módulo, registros/flags, stack trace y bytes, tipo read/write/execute, entrada, hilo, SO y CPU. Símbolos de un build parecido pueden mapear el offset a otra función.
Normalice ASLR:
module_offset = faulting_address - loaded_module_base
Empezar en la instrucción de fallo
mov eax, dword ptr [rcx + rdx*4]
effective_address = RCX + RDX * 4
access_width = 4 bytes
Compruebe si rcx es null, liberado u otro objeto; si rdx es índice u offset; si el cálculo coincide con el fallo; si los cuatro bytes son válidos; y dónde se originaron ambos registros. El lugar del fallo no siempre es el origen.
Provenance y restricciones de camino
mov rcx, [rbx + 20h]
test rcx, rcx
je error
mov edx, [rsi + 8]
mov eax, [rcx + rdx*4]
Investigue objetos padre, camino real y cambios de lifetime por otros hilos. Un race puede no probarse con un snapshot de un hilo.
cmp rdx, r8
jae fail
mov eax, [rcx + rdx*4]
La arista normal prueba unsigned rdx < r8. Anote estas restricciones y no confunda jl con jb.
Auditar stack trace y ABI
El stack trace depende de símbolos y unwind. Buffer overflow, metadatos ASM erróneos, símbolos incorrectos, tail calls, inlining o context switches pueden dañarlo. Cada retorno debe pertenecer a módulo ejecutable y call site plausible.
Windows inicia argumentos en rcx,rdx,r8,r9; System V en rdi,rsi,rdx,rcx,r8,r9, pero se reutilizan. Retroceda hasta el caller antes de poner nombres de parámetros.
push rbx
sub rsp, 40h
mov rbx, rcx
Con entrada rsp=S, derive posiciones de registros guardados y retorno y verifique todos los exits. En Windows compare .pdata/.xdata con el prólogo real.
Calls indirectos y memoria
call qword ptr [rax + 18h]
Puede ser tabla de funciones, vtable, import thunk o callback. Siga rax, acceso a tabla, destino ejecutable, convención, argumentos, lifetime y CFG/CET. Una dirección ejecutable no prueba la firma correcta.
Inspeccione memoria como bytes con anchura y little endian. Use-after-free puede seguir legible; guard pages y AddressSanitizer detectan antes la causa.
El disassembler decodifica, debugger observa una ejecución, decompiler infiere nivel alto, profiler muestrea y sanitizer instrumenta contratos. Nombres y if del decompiler son hipótesis que deben cruzarse con instrucciones y ABI reales.
Resumen
El análisis x86-64 se amplía desde la instrucción de fallo a dirección efectiva, provenance, restricciones, ABI, pila y lifetime. Binary y símbolos exactos son requisito; stack trace y decompiler también se verifican. Cierre con corrección de fuente y tests de regresión.