
このプロジェクトは識別不能難読化を実現していません。この製品を秘密を保護するために使用すべきではありません。それはリバースエンジニアリングを防ぐのではなく、抑止するために存在します。
人間とLLMの両方にとってコードの読み取りと解析を極めて困難にするように設計されたJavaScript難読化ツールです。TypeScriptで記述されています。査読済みの暗号学的難読化研究の手法を実装しています。
npm install
npm run build
# 基本使用法
node dist/index.js input.js > output.js
# ターゲットトークン予算を指定(デフォルト: 2,000,000)
node dist/index.js --target-tokens 500000 input.js > output.js
# 最小限の難読化(小さい出力)
node dist/index.js --target-tokens 10000 input.js > output.js
# 最大の肥大化(10Mトークン)
node dist/index.js --target-tokens 10000000 input.js > output.js
# 環境変数を使用
INPUT_FILE=input.js node dist/index.js > output.js
# ヘルプ
node dist/index.js --help
| オプション | デフォルト | 説明 |
|---|---|---|
--target-tokens <n> | 2000000 | トークン単位のターゲット出力サイズ。小さな入力はこの制限まで肥大化されます。大きな入力は予算内に収めるために肥大化を抑えます。 |
--help, -h | ヘルプメッセージを表示 |
npm run build # TypeScriptをdist/にコンパイル
npm run start # 難読化ツールを実行(input.jsを読み込む)
npm run test # テストスイートを実行
npm run obfuscate-package # npmパッケージとの互換性テストを実行
const { obfuscate } = require('./dist/obfuscator');
const code = 'function add(a, b) { return a + b; }';
const obfuscated = obfuscate(code);
// オプション付き
const obfuscated = obfuscate(code, { targetTokens: 500000 });
難読化ツールは4つのフェーズで20の変換を適用します。各段階は前の段階に基づいて構築されます。
| 順序 | 変換 | ファイル | 説明 |
|---|---|---|---|
| 1 | アンチデバッグトラップ | transforms/antiDebug.ts | eval("debugger")文と10〜20のsetIntervalループを素数間隔(5秒〜600秒)で注入し、繰り返しデバッガーブレークポイントをトリガーします。各インスタンスは一意のエンコードされた文字列を使用します。 |
| 2 | パンクチャードプログラムトリップワイヤ | transforms/tripwires.ts | パラメータハッシュを秘密の値と比較する隠されたチェックを埋め込みます。5つのハッシュパターン(ビット単位フィンガープリント、モジュラー算術、charCodeAt、数値ハッシュ、typeof+length)。秘密の入力に対してサイレントな状態破壊、ビジーループ、または例外をスローします。 [論文 4] |
| 3 | LPNノイズ注入 | transforms/noiseInjection.ts | 算術計算の分割パスを通じてランダムノイズを追加およびキャンセルします。6つのパターン: add/sub、XOR、mul/div、split dual-variable、computed hash-chain、bit-rotate。中間値は完全なキャンセルを追跡しない限り無意味です。 [論文 7] |
| 順序 | 変換 | ファイル | 説明 |
|---|---|---|---|
| 4 | 制御フロー平坦化 | transforms/controlFlowFlattening.ts | 関数本体を while(true) { switch((_s * P) % M) { ... } } 状態機械に変換し、モジュラー算術ディスパッチを使用 — ケース値は (stateId * multiplier) % modulus によりランダムな素数パラメータでエンコードされます。 [論文 3] |
| 5 | 不透明述語 | transforms/opaquePredicates.ts | 常にtrueまたはfalseと評価されるが数学的に証明が困難なif条件を注入します(例: (x*x+x)%2===0)。モジュラー算術、ビット単位、型チェックカテゴリにわたる15の述語式。 |
| 6 | プロキシ関数 | transforms/proxyFunctions.ts | すべての関数呼び出しを2つのディスパッチャ経由でルーティングします: 単純な呼び出しには_fc(fn, ...args)、メソッド呼び出しには_mc(obj, prop, ...args)。耐障害性のためにローカル変数にキャプチャされたFunction.prototype.applyを使用します。 |
| 7 | コンテキストウィンドウ枯渇 | transforms/contextExhaustion.ts | 式を深くネストされた三項演算子(不透明条件付き)、void式チェーン、条件付きvoidパディングでラップします。LLMにノイズでコンテキストウィンドウトークンを浪費させます。 |
| 8 | カンマ式マージ | transforms/commaExpressions.ts | 連続する式文を単一のカンマ式に圧縮します: a(); b(); return c() は return a(), b(), c() になります。 |
| 順序 | パス | ファイル | 説明 |
|---|---|---|---|
| 9 | パス1: カタログ化 | passes/firstPass.ts | ASTを走査し、すべての識別子をカタログ化し、16のスクリプト範囲(CJK、ハングル、ギリシャ語、キリル文字、デーヴァナーガリー、タイ語、アラビア語、カタカナなど)から6〜16文字のランダムなUnicode名を割り当てるグローバルマップを構築します。 |
| 10 | パス2: 置換 | passes/secondPass.ts | すべての識別子名を難読化されたUnicode相当に置き換えます。require()の引数をString.fromCharCode(...)としてエンコードします。静的import/exportソースをUnicodeエスケープされた文字列リテラルとしてエンコードします。クラスのsuperClass参照、テンプレートリテラル式、分割代入パターンを置換します。 |
| 11 | パス3: ダミーパラメータ | passes/thirdPass.ts | すべての関数宣言と式に0〜15のランダムな未使用パラメータを注入します。残余パラメータを持つ関数はスキップします。すべてのコメントを削除します。 |
| 順序 | 変換 | ファイル | 説明 |
|---|---|---|---|
| 12 | グローバル変数エンコード | transforms/globalVariableEncoding.ts | グローバル(globalThis + windowパッケージから動的に発見)への参照を eval("Name<suffix>".replace(new RegExp("<suffix>$"), "")) で置き換えます。両方の文字列は文字列配列を通じて流れます。 |
| 13 | プロパティキーエンコード | transforms/propertyKeyEncoding.ts | ドットアクセスをスコープごとのレジストリを持つ計算アクセスに変換します。すべてのサフィックスが.replace()を介して実行時に同じプロパティ名に解決されるため、スコープをまたぐアクセスが機能します。 |
| 14 | 数値エンコード | transforms/numberEncoding.ts | 11のエンコード戦略: シフト+加算、XOR恒等、補数、除算、ネストシフト、二重否定、モジュラーなど。各インスタンスは一意に生成されます。プロパティキーとswitchケース値はスキップします。 |
| 15 | 自己完全性検証 | transforms/selfIntegrity.ts | 2〜4の実行時チェックを注入: evalネイティブコード検証、Function.prototype.toString完全性、タイミング異常検出、コード構造検証。改ざん防止応答: ビジーウェイト、スロー、サイレント破壊。 [論文 10] |
| 16 | 文字列配列抽出 | transforms/stringArrayExtraction.ts | すべての文字列を 連鎖XOR復号(エントリNのキーはエントリN-1のデコード済みコンテンツに依存)と 疎な位置依存エラーパターン(各文字は異なるXORキーを持ち、選択された位置にLPNに着想を得た疎エラーが発生)を持つ単一の配列に収集します。 [論文 2, 9] |
| 17 | Consoleスタブ | obfuscator.ts | すべてのconsoleメソッドを動的に発見し、それぞれをno-op関数に設定します。 |
| 18 | Terser最小化 | obfuscator.ts | terserを介して空白/書式を削除(mangle: false、compress: false)。terserが出力を解析できない場合は、正規表現ベースの削除にフォールバックします。 |
デッドコードは複数ポイントで2つの生成戦略とともに注入されます:
| 戦略 | ソース | 説明 |
|---|---|---|
| テンプレートベース | transforms/deadCodeInjection.ts | 9つのテンプレートタイプ: ループ累積、配列構築、オブジェクト操作、文字列連結、ネスト条件、try/catch、whileカウントダウン、switch計算、ビットチェーン。テンプレートは実際のスコープ変数を参照します。 |
| 突然変異ベース | transforms/deadCodeInjection.ts | 実際の文をクローンし、突然変異させます: 等価グループ内の演算子を交換、定数を攪乱、識別子をリネーム。構造的に実際のコードと区別がつかないAST構造的に同一のデッドコードを生成します。 [論文 3] |
デッドコード注入ポイント:
いくつかの変換は査読済みの暗号学的難読化研究に触発されています:
| 論文 | 著者 | 実装された手法 |
|---|---|---|
| [論文 1] On the (Im)possibility of Obfuscating Programs | Barak, Goldreich, Impagliazzo, Rudich, Sahai, Vadhan, Yang | 難読化不可能関数テストケース — 秘密が難読化を生き残るかどうかをテストする検証ツール |
| [論文 2] Candidate iO and Functional Encryption for all Circuits | Garg, Gentry, Halevi, Raykova, Sahai, Waters | 連鎖文字列復号 — 各エントリのキーが前のデコード済み文字列に依存するKilianスタイルのランダム化 |
| [論文 3] iO from the Multilinear Subgroup Elimination Assumption | Gentry, Lewko, Sahai, Waters | 突然変異ベースのデッドコード(実際のコードと構造的に同一); CFFにおけるモジュラー算術状態遷移 |
| [論文 4] How to Use iO: Deniable Encryption, and More | Sahai, Waters | パンクチャードプログラムトリップワイヤ — 秘密の入力でトリガーする隠されたチェック |
| [論文 7] iO from Well-Founded Assumptions | Jain, Lin, Sahai | 数値計算におけるLPNに着想を得たノイズ注入 |
| [論文 9] iO from Bilinear Maps and LPN Variants | Ragavan, Vafa, Vaikuntanathan | 位置依存エラーパターンを持つ疎XORエンコード |
| [論文 10] iO of Null Quantum Circuits and Applications | Bartusek, Malavolta | デッドコード品質検証のためのNull回路テスト; 自己完全性検証(デュアルモード) |
2つの検証ツールが難読化品質を測定します。src/verification/にあります:
verification/nullCircuitTest.ts)実際の関数と「null」関数(同じ形状で何もしない)を難読化し、14の構造的メトリクスを比較してそれらがどの程度区別可能かをスコアリングします。類似性が高いほど難読化が良好です。
import { runNullCircuitTest } from './verification/nullCircuitTest';
const result = runNullCircuitTest(realCode, paramCount, stmtCount, threshold, targetTokens);
console.log('Similarity:', result.similarity); // 0.0-1.0
verification/unobfuscatableTests.ts)論文1の不可能性証明からの7つのテストケースで、難読化されたコードから秘密を抽出しようと試みます:
import { runAllTests, printSummary } from './verification/unobfuscatableTests';
console.log(printSummary(runAllTests(10000)));
テスト: ポイント関数(パスワード)、マジックナンバー、カナリア文字列、埋め込みキー、URL、正規表現パターン、制御フローシグネチャ。
--target-tokensオプションは、デッドコード注入(主要なボリュームレバー)をスケーリングする肥大化予算を介して出力サイズを制御します。予算ゲート付き変換: