
ファイルレス x64 Assembly C2 フレームワーク。デュアルチャネル ICMP/DNS プロトコルピボット、ダイレクト syscall 実行、および ptrace ベースのプロセスインジェクションにより、ステルスなコマンド実行とデータ流出を実現します。
________ ___ ___ ________ ________ _________ ________ ________
|\ ____\|\ \|\ \|\ __ \|\ ____\|\___ ___\ |\ ____\|\_____ \
\ \ \___| \ \ \\\ \ \ \|\ \ \ \___|\|___ \ \_| \ \ \___|\|____|\ \
\ \ \ __ \ \ __ \ \ \\\ \ \_____ \ \ \ \ \ \ \ ____\_\ \
\ \ \|\ \ \ \ \ \ \ \\\ \|____|\ \ \ \ \ \ \ \___|\____ \ \
\ \ \_______ \ \__\ \__\ \_______\____\_\ \ \ \__\ \ \______\\_________\
\ \_______|\|__|\|__|\|_______|\_________\ \|__| \|______|\_________|
\|_________|
ファイルレス、純粋なx64アセンブリで記述されたC2インプラント。デュアルチャネル(ICMP/DNS)アーキテクチャを採用。libc不要、ディスク不要。標準的なEDRフックには不可視。
⭐️ この研究が役に立ったと思われたら、今後の開発を支援するためにスターを付けていただけると幸いです。
🚨 完全な技術研究およびソースコードはこちら: このリポジトリは概要です。完全なアーキテクチャ解説、W^Xメモリ回避の詳細、VTable実装については、公式プロジェクトページをご覧ください:ICMP-Ghost 技術解説
Ghost-C2 は、libc に依存せず、純粋な x64 Linux アセンブリで完全に記述されたコマンド&コントロールフレームワークです。すべての操作は直接システムコールを経由します。インポートテーブル、動的リンカの痕跡、ディスクへの書き込みは一切ありません。
当初は生の ICMP ステルスチャネルとして構築されましたが、バージョン 3.6.2 ではデュアルチャネルプロトコルピボッティングアーキテクチャを導入しました。オペレータは、静かな ICMP Raw Socket と回避的な DNS UDP トンネリングの間で、インプラントの通信チャネルをシームレスに切り替えることができます。インプラントは RAM 上のみに存在し、カスタム ptrace ベースのローダーを介して実行中のシステムプロセスに注入されます。
このプロジェクトは、カーネルに触れることなく、ユーザー空間のステルス性とネットワーク状態同期をどこまで追求できるかを探求するために構築されました。
┌─────────────────────────────────────────────────────────────┐
│ オペレータマシン │
│ │
│ ┌──────────────┐ │
│ │ client.asm │ ← ターミナルUI: IP/ドメイン + コマンド │
│ │ (オペレータ │ ペイロードをローリングXORで暗号化 │
│ │ コンソール) │ 状態同期: ICMP モード / DNS モード │
│ └──────┬───────┘ │
│ │ │
└──────────┼──────────────────────────────────────────────────┘
│ チャネル1: Raw ICMP (ステートレス、ポート不要)
│ チャネル2: DNS UDP ポート53 (非対称)
┌──────────┼──────────────────────────────────────────────────┐
│ │ ターゲットマシン │
│ ▼ │
│ ┌──────────────┐ ┌─────────────────────────────────┐ │
│ │ loader.asm │────▶│ sniff.asm (PIC) │ │
│ │ (ファントム │ │ RAMのみに存在 │ │
│ │ ローダー) │ │ ホストプロセス内部 │ │
│ └──────────────┘ └────────────────┬────────────────┘ │
│ │ │
│ 1. /procをスキャンし対象PIDを特定 │ ICMP/DNSを待受 │
│ 2. ptrace ATTACH │ 認証を検証 │
│ 3. リモートmmap (RW) を強制 │ コマンドを復号 │
│ 4. PICシェルコードを注入 │ fork + execve │
│ 5. mprotect → RX │ memfd_create │
│ 6. RIPをシェルコードにリダイレクト │ 圧縮(DPCM-RLE) │
│ 7. ptrace DETACH → 終了 │ 暗号化&フラグ化 │
│ │ 応答を送信 │
└─────────────────────────────────────────┼───────────────────┘
│ 暗号化トラフィック
▼
[ client.asm ]
受信&検証
ペイロード復号
解凍(ハイブリッド)
再組立て&表示
client.asm — オペレータコンソール攻撃側の端末です。UI、動的メモリ管理、ターゲット状態同期を担当します。パケットをICMP Echo RequestまたはDNS TXTクエリとして送出できます。フラグメント化された応答を待ち受け、バッファオーバーフローを防止し、出力を再構築します。「アクティブターゲット再接続」モジュールにより、孤立したセッションを救出できます。
sniff.asm — PICインプラントエージェントターゲット上で動作するインプラントです。生のバイナリ(位置独立、ELFヘッダなし)としてコンパイルされるため、任意のメモリアドレスに注入できます。内部のVTableを動的に更新し、オペレータからのピボットコマンドに応じてICMPスニッフィングとUDP DNSバインディングを切り替えます。
Phantom_Loader/loader.asm — 注入エンジン配信メカニズムです。/procをスキャンし、comm名で対象プロセスを見つけ、多段階ptraceステートマシンを使用してPICシェルコードを注入します。注入後はクリーンに終了し、痕跡を残しません。
Ghost-C2 v3.6.2 では、エージェントを失うことなくネットワークプロトコルをホットスワップできます。特定のピボットコマンドを送信することで、マスターとエージェントの両方のVTableが動的に上書きされます。
!D (DNSにピボット): 両ノードがICMPソケットを閉じ、UDPポート53通信を初期化します。厳格なレイヤ3フィルタリングを回避し、企業のDNSトラフィックに溶け込むのに最適です。!I (ICMPにピボット): エージェントはUDPソケットを閉じ、ポートバインディングを解除し、静かなRaw Socketスニッフィングに戻ります。「ファントム」ステルスモードに最適です。Ghost-C2 のデータ送信エンジンは、x86-64 アセンブリで高度に最適化されたハイブリッド圧縮・エンコード層を利用しています。
送出されるすべてのICMPパケットは、標準的なLinuxのpingと見分けがつかないように構成されています。
struct timevalを模倣します。iputilsパディング(0x10~0x1F)により、基本的なヒューリスティックファイアウォールを回避します。双方向の通信は、段階的にシフトするQWORD鍵で暗号化されます。これによりシャノンエントロピーが低く抑えられます(AESでは約8.0のスコアがDPIの異常を引き起こすのとは対照的です)。ローリングXORは、自然にノイズの多いデータのように見えるエントロピーを生成します。暗号定数もS-boxもなく、YARAがマッチするものは何もありません。
インプラントは、ID + SEQ ≠ 45,000 のICMPパケットをすべて無視します。インプラントの応答パケットでは ID + SEQ = 55,000 となります。これによりOSのエコー混乱を防ぎ、インターネットスキャナーやハニーポットをフィルタリングします。
memfd_create によるファイルレス実行コマンド出力がディスクに触れることはありません。シェル出力は匿名RAMファイル(memfd_create)でキャプチャされ、[shm]という名前で、/proc/PID/fd内の正当な共有メモリマッピングに溶け込みます。
RWXメモリを禁止する最新のカーネル緩和策を打破します。ローダーは2段階アプローチ(Remote mmap で RW → 注入 → Remote mprotect で RX)を使用します。どのページもWとXが同時になることはありません。
すべてのシステムコール番号は2つの命令に分割され、静的解析や単純なgrepベースのスキャナーを無効化します。
厳格なOPSECを維持するため、Ghost-C2エージェント(sniff.asm)は外部設定を使用しません。コンパイルおよび注入の前に、マスターC2のIP、ポート、デコイDNSドメインをアセンブリコード内で直接定義する必要があります。
sniff.asm を開き、.text セグメントの最下部までスクロールします。(注:エージェントは厳密に位置独立コード(PIC)であるため、.dataセグメントはありません。すべての設定変数はインラインで格納されています。)
以下の値をマスターサーバーに合わせて変更します。
db 127, 0, 0, 1 をマスターのIPに変更します。dw 0xB414(ポート5300)を、希望するポートにネットワークバイトオーダーで変更します(例:ポート53の場合は 0x3500)。nasm -f bin sniff.asm -o shellcode.bin
python3 -c "data = open('shellcode.bin', 'rb').read(); lines = ['\tdb ' + ', '.join(f'0x{b:02x}' for b in data[i:i+12]) for i in range(0, len(data), 12)]; open('c2_payload.txt', 'w').write('\n'.join(lines))"
c2_payload.txt の内容をコピーします。xor.py を開き、raw_asm 変数の内容をコピーしたシェルコードに置き換えます。python3 xor.py を実行し、暗号化された出力をコピーします。loader.asm を開きます。c2_payload: ラベルを見つけます。target db "cron", 10 を変更して、注入対象プロセスを変更します。)nasm -f elf64 loader.asm -o loader.o
ld loader.o -o loader
ターゲットマシン上で root 権限で実行します(sudo ./loader)。これでエージェントは完全にファイルレスで動作します。
マスターコンソールをコンパイルする前に、そのリスナーとターゲットプロファイルがエージェントの設定と一致していることを確認する必要があります。client.asm を開き、.data セクションに移動します。
master_bind_addr を見つけます。ここはマスターが着信DNSビーコンを待ち受ける場所です。
UDPポート: dw 0xB414 を、エージェントが送信しているポートに合わせて変更します。
注: ネットワークバイトオーダーで指定する必要があります。ポート53の場合は
0x3500を使用します。
target_addr を見つけます。このポートは、DNSピボット(!D)または再接続モジュールを使用する際に使用されます。
ポート調整: dw 0xB414 を、エージェントが待ち受けているUDPポートに合わせて変更します。これらのポートが一致しない場合、マスターが間違った場所に送信することになり、デッドロックが発生します。
設定が完了したら、マスターをアセンブルおよびリンクします。
nasm -f elf64 client.asm -o client.o
ld client.o -o client
プロからのヒント:常に作戦の「プロファイルシート」を保管してください。sniff.asm でポートを 0x3500(ポート53)に変更した場合、作戦開始前に client.asm の master_bind_addr と target_addr の両方を更新する必要があります。
注: オペレータコンソールは、RawソケットとUDPポート53をバインドするために root 権限が必要です。
永続的なアクセスを確保し、セッション損失を防ぐために、マスターコンソールセッションを終了する前に、常にエージェントをICMPモード(!I)にピボットバックしてください。
論理:ICMP は Ghost-C2 の「ゴールデンチャネル」です。ステートレスでパッシブであり、ターゲットIP経由で常に到達可能です。
リスク:DNS モードは動的なUDPポート同期に依存しています。マスターコンソールがDNSモードのまま閉じられると、エージェントはUDP待ち受け状態に「閉じ込められた」ままになります。再接続するには、エージェントの特定のエフェメラルポートを知る必要がありますが、マスター再起動後は失われます。
!I (ICMPに切り替え)アクティブなトラフィック検査が行われている管理されたラボ環境でテストされました。
| テスト | 結果 |
|---|---|
| Suricata v8.0.3 (Emerging Threats ルールセット) | ✅ バイパス |
| Suricata v8.0.3 (カスタムICMPペイロードルール) | ✅ バイパス |
| DigitalOcean FRA1 ゲートウェイ | ✅ 100% 窃取成功 |
| 約25KBの窃取中に生成されたアラート | 0 |
Ghost-C2 は Linux カーネルと直接やり取りします。
mprotect 依存関係を排除するための動的ASLR破りの実装。PTY がないのはアーキテクチャ上の決定であり、制限ではありません。
/dev/ptmx と ioctl 呼び出しが必要であり、EDRはこれらを重点的に監視します。Ghost-C2 は超ステルスなコマンド実行およびデータ窃取インプラントです。インタラクティブ性は不可視性を利便性と引き換えにします。このプロジェクトは不可視性を選択しました。
設計上、プルリクエストとフォークは厳密に無視されます。このプロジェクトのアーキテクチャは著者自身によって直接管理されています。バグ、論理的な欠陥を見つけた場合、または機能提案がある場合は、Issueを開いてください。客観的かつ技術的な内容にしてください。
Ghost-C2 は情熱と汗と純粋な x64 アセンブリで作られています。このプロジェクトが低レベルの回避術やプロトコル模倣の理解に役立った場合、あるいはレッドチーミングの運用をスムーズにした場合は、開発の支援をご検討ください!
Ghost-C2 はもっぱら教育目的、リバースエンジニアリング、許可されたサイバーセキュリティ研究のために開発されています。
バージョン 3.6.1 以降、このプロジェクトはGNU Affero General Public License v3.0 (AGPLv3) の下でライセンスされています。ネットワークを介してこのソフトウェアと対話または修正するすべてのエンティティは、ライセンスの要求に従って完全なソースコードを開示する必要があります。商用利用やプロプライエタリ/クローズドソースプラットフォームへの統合は固く禁じられています。
Copyright (c) 2026 JM00NJ (commSync). All Rights Reserved.
著者は、このツールの不正使用またはそれによって生じた損害について一切の責任を負いません。自己責任で使用してください。
| システムコール | 番号 | 用途 |
|---|
sys_socket | 41 | Raw ICMP / UDP ソケット作成 |
sys_recvfrom | 45 | パッシブ ICMP/UDP パケットキャプチャ |
sys_sendto | 44 | ICMP/UDP 応答送信 |
sys_bind | 49 | UDP DNS ポートバインディング |
sys_memfd_create | 319 | 出力用匿名RAMファイル |
sys_dup2 | 33 | stdout/stderr リダイレクション |
sys_execve | 59 | シェルコマンド実行 |
sys_fork | 57 | プロセス分離 |
sys_ptrace | 101 | プロセス注入 + アンチデバッグ |
sys_getdents64 | 217 | /proc ディレクトリ解析 |
sys_mmap | 9 | リモートメモリ割り当て |
sys_mprotect | 10 | W^X 権限切り替え |