ドキュメント
/
VM 難読化
/

VM がコードを変換する仕組み

VM がコードを変換する仕組み

視聴する

Obfuscator.io: Targeting Functions in VM Obfuscation (IIFE and Comment Mode)

YouTube で視聴

vmTargetFunctionsMode: 'root'(デフォルト)では、VM 難読化はルートレベルの各関数(vmAsyncExecutor を使う場合は、最も外側の各 async 関数)の本体をバイトコードに変換します。ルートレベルの関数は名前を保持し、ネストされた関数は通常どおりリネームされます。代わりに任意のネストレベルにある個々の関数を選ぶには、comment モードを使ってください。

JavaScript

この設計により、グローバルスコープからこれらの関数を呼び出すコードや、グローバルオブジェクト上にこれらの関数があることを前提とするコードとの互換性が保たれます。関数本体は完全に保護されますが名前は見えたままで、難読化ツールはそのような名前を列挙した VMGlobalFunctionNamesNotRenamed 警告を出力します。

VM 難読化が保護するのは関数本体と、vmWrapTopLevelInitializers が有効な場合のトップレベルの変数初期化式です(後述)。入力に関数もそのような初期化式も 1 つもない場合(alert(1); のようなトップレベルだけのコード)は何も仮想化されません。それ以外の難読化は実行されますが VM による保護は適用されず、難読化ツールは VMNoFunctionsToVirtualize 警告を出力します(v7.14.1 以降。7.14.0 自体は無効化されています)。この警告は、関数が存在してもそのすべてが対象外になった場合(たとえば、直接 eval や動的な new Function、vmTargetFunctions/vmExcludeFunctions によって何も選択されなかった場合、または vmAsyncExecutor が async 関数を 1 つも見つけられなかった場合)にも出力されます。保護したいコードは、IIFE などの関数でラップしてください。

トップレベルの初期化式

root モードでは、vmWrapTopLevelInitializers が const MY_STRING = 'my-string'; のような対象となりうるトップレベルの変数初期化式を IIFE でラップし、その値がプレーンな JavaScript として見えたままにならず、バイトコードに移るようにします。現在の VM プリセットではこのオプションが有効です。対象は変数の初期化式だけで、それ以外のトップレベルの文は含まれず、comment モードでは効果がありません。プレーンな JavaScript のまま残った初期化式は VMTopLevelInitializerNotVirtualized 警告に列挙されます。

機密性の高い関数名を隠す

root モードでは名前が保持されるため、validateLicense や decryptData のように内容を明かしてしまう名前は、本体がバイトコードになった後も読めるまま残ります。対処法は、関数をトップレベルから移すこと(IIFE でラップすれば関数はルートレベルではなくなり、名前も含めて完全に VM 変換されます)、または renameGlobals でルートレベルの識別子をリネームすることです。両方の手法とそのトレードオフについては、LLM の解析から関数名を隠すを参照してください。