Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
zyrox — Zyrox: LLVMベースの、コンパイル時難読化プラグイン。 | Kitploit
ツール/GitHubGitHub/peterhackz/zyrox
静的分析コード分析リバースエンジニアリングバイナリ解析論文と研究学習と教育学習パスとコース
GitHubpeterhackz/zyrox

zyrox

Zyrox: LLVMベースの、コンパイル時難読化プラグイン。

リポジトリを見る
9411167ヶ月前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
ウェブサイト
共有

Zyrox LLVMオブフスケーター

ネイティブコードを難読化するLLVMコンパイル時およびリンク時プラグイン

なぜ作ったのか

なんでって? ¯\_(ツ)_/¯

私がLLVMの内部、バイナリフォーマット、アセンブリ、難読化技術について多くを学んだ最大のプロジェクトのひとつです。

作ることを通じて学ぶのが最良の学び方だと信じているので、このテーマについてもっと学ぶためにこのプロジェクトを構築しました。

リサーチ

Zyrox の背後にあるコンセプトを解説したブログを4つ書きました:

  • パートI: Zyroxの構築:カスタムLLVMオブフスケーター
  • パートII: 制御フローフラットニング
  • パートIII: 暗号化ジャンプテーブル
  • パートIV: フィナーレ

これらのパートはこのREADMEより深く掘り下げており、このテーマに興味があるなら一読の価値があります。

ビルド

テンプレートから(クイックスタート、推奨)

これはZyroxを_すばやくテスト_したい人、またはcmakeプロジェクトへの統合方法を学びたい人を対象としています。

Zyroxテンプレート リポジトリの手順に従ってください。

ソースから

llvmをインストール:

sudo apt update
sudo apt install llvm-18 llvm-18-dev clang-18

zyroxをクローンしてコンパイル:

git clone --recurse-submodules https://github.com/PeterHackz/zyrox.git
cd zyrox
cmake -S . -B build -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++
cmake --build build --parallel 4

Python(コンパイル後)プラグインのセットアップ

python3 と pip がインストールされていることを確認してください。

環境のセットアップ(推奨)

# 仮想環境を作成
python3 -m venv .venv

# 環境を有効化
source .venv/bin/activate

pip install -r requirements.txt

グローバルにインストール

pip install -r requirements.txt

使用方法

クイック使用法

clang -O0 -flto=full -c main.c -o out/main.o
clang -flto=full -fuse-ld=lld -Wl,--load-pass-plugin=./build/libzyrox.so out/main.o -o out/main

難読化後、PyPlugin.py を実行してジャンプテーブルを暗号化します:

# 依存関係を仮想環境にインストールした場合は、最初に有効化してください:
source .venv/bin/activate
#  その後、以下で実行:
python PyPlugin.py --in=<input_file> [--out=<output_file>] [--tables=<zyrox_tables_file>] [--android]

CMakeの場合

CMake統合の例については、Zyroxテンプレート リポジトリを確認してください。

連絡先

これは複雑なテーマであり、このプロジェクトは主に教育目的であるとともに、BSD Brawl に役立てるためのものであることを理解しています。 質問がある場合や、ただチャットしたい場合でも、お気軽にご連絡ください:

  • Discord: @s.b
  • Email: [email protected] または [email protected]
  • Discordサーバー

プルリクエストやissueによる支援はいつでも歓迎です!

動作の仕組み

ZyroxPlugin.cpp はパスを登録し、siphash をリンクして(詳細は後述)、StringEncryption を呼び出して文字列を暗号化します。

文字列を早期に暗号化するのは、復号ロジックも後で難読化されるようにするためです。

次に、ModuleUtils::ExpandCustomAnnotations と QuickConfig::RegisterPasses を呼び出して、すべての __attribute__((annotate("..."))) 式を解析し、QuickJs構成(ZyroxConfig.js に配置)を実行します。

すべての関数は ZyroxCore.cpp にある Zyrox::RunOnFunction を呼び出すことで難読化されます。これに関する詳細なドキュメントは今後提供される予定です。

追加ユーティリティ

switch文はジャンプテーブルを生成し、PHIノードは扱いにくいため、FunctionUtils と BasicBlockUtils を使用して、それぞれ(if文への)フラット化と降格を行います。

パス

いやはや、どこから始めればいいのか

  • ベーシックブロックスプリッター
  • 制御フローフラットニング
  • 間接分岐
  • シンプル間接分岐
  • 混合ブール演算

すべてのjsプラグイン引数は index.d.ts にあるため、このドキュメントでは説明しません。

アノテーションのドキュメントについては、こちらをクリック

ベーシックブロックスプリッター

このパスは、ベーシックブロックをより小さなブロックに分割してシャッフルします。次のコードがあるとします:

int __test_fn(int x)
{
    if (x == 2) {
        printf("x is 2\n");
    } else {
        printf("x is not 2!, x is: %d\n", x);
    }
    return x + 4 * x - 2 / 4;
}

これは次のようにコンパイルされます:

define internal i32 @__test_fn(i32 noundef %0) #0 !zyrox !8 !obfuscated !11 {
  %2 = alloca i32, align 4
  store i32 %0, ptr %2, align 4
  %3 = load i32, ptr %2, align 4
  %4 = icmp eq i32 %3, 2
  br i1 %4, label %5, label %7

5:                                                ; preds = %1
  %6 = call i32 (ptr, ...) @printf(ptr noundef @.str.1)
  br label %10

7:                                                ; preds = %1
  %8 = load i32, ptr %2, align 4
  %9 = call i32 (ptr, ...) @printf(ptr noundef @.str.2, i32 noundef %8)
  br label %10

10:                                               ; preds = %7, %5
  %11 = load i32, ptr %2, align 4
  %12 = load i32, ptr %2, align 4
  %13 = mul nsw i32 4, %12
  %14 = add nsw i32 %11, %13
  %15 = sub nsw i32 %14, 0
  ret i32 %15
}

Basic Block Splitterをこの構成で使用すると:

z.RegisterPass(ObfuscationType.BasicBlockSplitter, {
    PassIterations: 1,
    "BasicBlockSplitter.SplitBlockChance": 100,
    "BasicBlockSplitter.SplitBlockMinSize": 2,
    "BasicBlockSplitter.SplitBlockMaxSize": 5,
});

次のようになります:

define internal i32 @__test_fn(i32 noundef %0) #0 !zyrox !8 !obfuscated !11 {
  %2 = alloca i32, align 4
  store i32 %0, ptr %2, align 4
  %3 = load i32, ptr %2, align 4
  %4 = icmp eq i32 %3, 2
  br i1 %4, label %5, label %14

5:                                                ; preds = %1
  %6 = call i32 (ptr, ...) @printf(ptr noundef @.str.1)
  br label %7

7:                                                ; preds = %14, %5
  %8 = load i32, ptr %2, align 4
  %9 = load i32, ptr %2, align 4
  %10 = mul nsw i32 4, %9
  %11 = add nsw i32 %8, %10
  br label %12

12:                                               ; preds = %7
  %13 = sub nsw i32 %11, 0
  ret i32 %13

14:                                               ; preds = %1
  %15 = load i32, ptr %2, align 4
  %16 = call i32 (ptr, ...) @printf(ptr noundef @.str.2, i32 noundef %15)
  br label %7
}

このような小さな関数ではあまり違いはありませんが、ベーシックブロックが分割されているのがわかりますか? これは 制御フローフラットニング のような他のパスと組み合わせると役立ちます。

制御フローフラットニング

ああ、このパスは全部の中で最も機能が多いんですよ、笑。 まず動作の仕組みを説明し、次にその構成について説明します。次のコードがあるとします:

LABEL_A: bool b = x == 2;
         IF EQ: goto LABEL_B
         goto LABEL_C
LABEL_B  do_stuff()
LABEL_C  do_other_stuff()
         goto LABEL_A

各ベーシックブロック(A、B、C)には一意のディスパッチャ状態が割り当てられます。例:(簡略化)

states = {
    1: LABEL_A,
    2: LABEL_B,
    3: LABEL_C,
};

次に、すべてを制御するディスパッチャブロックを注入すると、コードは次のようになります:

         int state = 0;
LABEL_D  goto LABEL_CA // ディスパッチャラベルは最初の条件ブロック、ラベル条件Aへジャンプ
LABEL_CA if state == 1: goto LABEL_A
         // 1でなければ、ラベルBかどうかのチェックへ進む(フォールバック)
LABEL_CB if state == 2: goto LABEL_B
LABEL_CC if state == 3: goto LABEL_CC
         // 到達不能
         goto LABEL_D
LABEL_A: bool b = x == 2;
         // IF EQ: goto LABEL_B
         // goto LABEL_C
         state = 2 if b else 3 // 目的のブロックの状態を更新してディスパッチャに戻る
         goto LABEL_D
LABEL_B  do_stuff()
LABEL_C  do_other_stuff()
         state = 1
         goto LABEL_D

これにはオブフスケーターが修正するいくつかの欠陥があります。ご覧のとおり、ディスパッチャ変数がひとつしかないため、ブロックが状態を設定した後にどこへ進むかがわかってしまい、難読化を解除するのは簡単です。修正も簡単です!

z.RegisterPass(ObfuscationType.ControlFlowFlattening, {
    PassIterations: 1,
    "ControlFlowFlattening.UseFunctionResolverChance": 60,
    "ControlFlowFlattening.UseGlobalStateVariablesChance": 60,
    "ControlFlowFlattening.UseOpaqueTransformationChance": 40,
    "ControlFlowFlattening.UseGlobalVariableOpaquesChance": 80,
    "ControlFlowFlattening.UseSipHashedStateChance": 40,
    "ControlFlowFlattening.CloneSipHashChance": 80,
});

オプションを1つずつ見ていきましょう:

ツールをダウンロード