ホームページ >ウェブフロントエンド >jsチュートリアル >ここでは、AST、Babel、プラグインを使用して、ラボを無駄にすることなく JavaScript で難読化を作成する方法を説明します。

ここでは、AST、Babel、プラグインを使用して、ラボを無駄にすることなく JavaScript で難読化を作成する方法を説明します。

DDD
DDDオリジナル
2025-01-10 12:34:44149ブラウズ

導入

ねえ、あなたのアルゴリズムがどれほどクールでユニークであるかについて考えたことはありますか? ?多くのプログラマーや企業がそうしているため、自分の仕事を全員と共有することをためらっているのかもしれません。この問題は、コードの一部をサーバーに移動すると (クライアント/サーバー アプリケーションの場合) 多少は改善されますが、このアプローチは常に可能であるとは限りません。場合によっては、機密性の高いコード セクションをそのまま公開しておく必要があります。

この記事では、JavaScript の難読化について説明し、アルゴリズムを非表示にしてコードの学習を困難にする方法を作成します。また、AST とは何かを調査し、難読化を実装するために AST と対話するために使用できるツールを提供する予定です。

どうしたの?

これは愚かな例です。この状況を想像してみましょう:

  1. ボブは、コンピューター モニターを配布しているサイトに行きます (ここでは -> ?)。ボブのモニターの方が優れていますが、無料のものはいつでも素晴らしいものです。
  2. ボブがサイトにアクセスすると、ブラウザ内で JavaScript が実行され、ユーザーのデバイスに関するデータが収集され、サーバーに送信されます。これがそれであるとしましょう:
let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);
  1. 残念ながら、ボブはプレゼントページにアクセスできず、そのことにかなり動揺しています。彼にはその理由が分かりません。その後、プレゼントのルールで、大きくて優れたモニターを使用しているユーザーは許可されていないことを知りました。

  2. 幸いなことに、ボブは高校でコンピューター サイエンスのクラスをいくつか受講していました。彼は思い切って F12 キーを押して開発者コンソールを開き、スクリプトを検討し、主催者が画面解像度をチェックしていることに気づきました。その後、彼は携帯電話から参加することを決意し、テストに無事合格しました。

ハッピーエンドの架空の物語 - しかし、主人公が前のコードの代わりにこれを見ていたら、これほど良いものにはならなかったでしょう:

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();

Here
保証します、これは意味不明なものではなく、JavaScript です。そして、同じ動作を実行します。ここでコンソールでコードを実行してみることができます。

この場合、私たちのヒーローはプレゼント企画に参加せずに自分の運命を受け入れただろうし、主催者も計画を守っただろう。

それで、ここでのポイントは何でしょうか?おめでとうございます。jjencode ツールについて、難読化とは何か、そしてそれがどのような役割を果たすことができるのかを学びました。

要約すると、難読化とは、プログラム コードまたはデータを、人間には理解しにくいが、マシンやプログラムでは機能する形式に変換するプロセスです。

秘密を隠している。簡単な方法

理論は十分なので、より実践的な例に移りましょう?‍?。次に、インターネット上でよく見かける難読化を利用してコードを変換してみましょう。 「ノウハウ」操作を含む、より興味深いコードを見てみましょう。そして、F12 にアクセスするのが面倒でない人全員がそれらのことを知ることができるのは非常に望ましくありません:

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);

このコードは、デバイスとブラウザーのデータを収集し、結果をコンソールに出力します (出力はコードのパフォーマンスの指標として使用します)。

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();

次に、上記のコードを、JS 用の一般的な難読化ツール obfuscator.io で変更してみましょう。結果として、次のようなコードが得られます:

function getGpuData(){
  let cnv = document.createElement("canvas");
  let ctx = cnv.getContext("webgl");
  const rendererInfo = ctx.getParameter(ctx.RENDERER);
  const vendorInfo = ctx.getParameter(ctx.VENDOR);

  return [rendererInfo, vendorInfo]
}

function getLanguages(){
  return window.navigator.languages;
}

let data = {};
data.gpu = getGpuData();
data.langs = getLanguages();
console.log(JSON.stringify(data))

出来上がり!さて、このコードを喜んで解析できるのは機械だけです (あなたと私はおそらくその中にはいないでしょう ?)。それにもかかわらず、それでも動作し、同じ結果が得られます。変更点に注意してください:

  1. 改行と余分なスペースはなくなりました。
  2. 変数名は、_0x587f42 のような役に立たない名前に置き換えられています。
  3. 文字列とオブジェクトのプロパティは、インデックスによって配列から値を返す関数呼び出しに変換されました。たとえば、document.createElement(“canvas”) は document[_0x12260c(0x197)](_0x12260c(0x191)) に変わりました。これは、計算されたプロパティを使用することで可能になりました。

最後の手法は、静的コード分析に負荷をかけるという点で、おそらくこの場合最も厄介です。

よし、すべての秘密が隠されているようだ。コードを実稼働環境にデプロイしましょうか?

待ってください... コード難読化のためのサービスがある場合、おそらくこの機能を元に戻すことができるサービスもあるでしょうか?もちろん、それも複数あります!そのうちの 1 つである WebCrack を使用してみましょう。そして、元の読みやすいコードを取得できるかどうかを確認してください。以下は、この難読化解除ツールを使用した結果です:

{"gpu":["ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0), or similar","Mozilla"],"langs":["en-US","en"]}

おっと ?。 もちろん、変数の名前は返されませんでしたが、ありがとうございました。

つまり、この場合、コードを冷静に研究する唯一の障害は、難読化解除ツールを使用するという研究者の意志の力であることがわかります。もちろん、他のソリューションやカスタマイズを使用することも可能ですが、一般的な難読化の場合は、一般的な難読化解除を期待する必要があります。

私たちは絶望して、戦うことなく秘密を放棄すべきでしょうか?もちろん違います!さらに何ができるか見てみましょう....

Here

難読化者になる方法

難読化装置 - ファンタジーの世界の魔術師のような感じですね。 ??‍♂️
間違いなく、コードを作成中にコードを難読化できる人は生まれつきの魔術師です。あなたも、しばらくの間、意図せずにそのような呪文を自分で唱えることができたかもしれません。しかし、「上級プログラマー」の批判のせいでスキルが失われ、プログラムの調査を困難にする可能性のあるアイデアを持っている場合はどうすればよいでしょうか?この場合、コード構造自体を操作して変更できるツールを利用するのが合理的です。それらを見てみましょう。

ASツール

テキストと同じように単純にコードを操作したり、特定の構造を正規表現に置き換えたりすることで、コードを変更してみることもできます。しかし、この方法に従うと、コードを難読化するよりも、コードと時間を台無しにする可能性の方が高いと思います。

より信頼性が高く、制御された変更を行うには、それを抽象構造であるツリー (AST - 抽象構文ツリー) に持ち込んで、そこを通過して、関心のある要素や構成を変更することができます。 .

JS コードを操作するにはさまざまなソリューションがあり、最終的な AST が異なります。この記事では、この目的のために babel を使用します。何もインストールする必要はなく、astexplorer などのリソースですべてを試すことができます。

(babel をいじりたくない場合は、shift-refactor をチェックしてください。**CSS セレクター を使用して AST と対話できるようになります。非常にミニマルで学習に便利なアプローチです。ただし、babel とは異なる特定のバージョンの AST を使用します。このツールの CSS クエリは、shift-query interactive でテストできます。デモ)。

0. AST の使用

それでは、簡単な例に基づいて、ブラウザを離れることなくこれらのツールを簡単に使用する方法を見てみましょう。同じ名前の関数内のテスト変数の名前を変更する必要があるとします:

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);

このコードを astexplorer に貼り付けると (上から JavaScript@babel/parser を選択します)、そこに AST として表示されるはずです。テスト変数をクリックすると、右側のウィンドウにこのコード セクションの構文が表示されます:
Here

問題を解決するには、次の babel プラグインを作成します。このプラグインはコードを解析し、その中のすべての名前識別子を検索し、特定の条件が満たされた場合に名前を変更します。これを astexplorer の左下のウィンドウに貼り付けましょう (transform スライダーをオンにし、babelv7 を選択して表示させます):

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);

コンソール出力がこのプラグインに含まれているのには理由があります。これにより、ブラウザ コンソールの出力を調べてプラグインをデバッグできるようになります。この場合、識別子タイプのすべてのノードに関する情報を出力します。この情報には、ノード自体 (node)、親ノード (parent)、および環境に関するデータが含まれます (スコープ - 現在のコンテキストで作成された変数とそれらへの参照が含まれます):
Here

したがって、右下のウィンドウでは、ソース コード内の変数が他の識別子に影響を与えることなく正常に変更されたことがわかります。

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();

この例に基づいて、コードを解析して変更する方法がもう少し明確になったと思います。とにかく、完了した作業を要約しましょう:

  1. astexplorer 経由で babel を使用してコードを AST に変換しました。
  2. AST を調べると、テスト変数が識別子タイプでラベル付けされており、その名前は name プロパティを使用して定義できることがわかりました。
  3. 次に、babel プラグインを使用して、すべての識別子をバイパスし、関数内の識別子の名前を test という名前で変更しました。

1. 関数名と変数名を非表示にする

コードを変更する方法が明らかになりました。もっと便利なものを試してみましょう。難読化と呼ぶことができます:) 前のセクションで難読化しようとしたより複雑なコードを取り上げます。次に、その中のすべての変数と関数の名前をランダムな名前に変更します。したがって、リバース エンジニアリングを行う可能性のある人は、一部のコード要素の目的についての情報が少なくなります。

また、問題をデバッグするために任意の JS コードを自由に使用してください。 よく言われるように、痛みほど優れた教師はいない?.

次のプラグインは、作業を完了するのに役立ちます:

function getGpuData(){
  let cnv = document.createElement("canvas");
  let ctx = cnv.getContext("webgl");
  const rendererInfo = ctx.getParameter(ctx.RENDERER);
  const vendorInfo = ctx.getParameter(ctx.VENDOR);

  return [rendererInfo, vendorInfo]
}

function getLanguages(){
  return window.navigator.languages;
}

let data = {};
data.gpu = getGpuData();
data.langs = getLanguages();
console.log(JSON.stringify(data))

このコードは何をするのでしょうか?前の例とほぼ同じです:

  1. 識別子タイプのすべての AST ノードを通過します;
  2. 今回は、generateRndName 関数を使用して、条件なしで識別子の名前をランダムに生成します。
  3. 一意の名前を生成すると、プログラムのロジックを壊す可能性のある重複した名前がランダムに取得されないことが保証されます。

プラグインの実行の結果、ランダム変数の名前と関数を含む次のコードが得られます。

{"gpu":["ANGLE (NVIDIA, NVIDIA GeForce GTX 980 Direct3D11 vs_5_0 ps_5_0), or similar","Mozilla"],"langs":["en-US","en"]}

コンソールでコードを実行して確認できます。操作後も、まだ動作しています。そして、これが優れた難読化ツールの主な品質です ✨.

しかし、難読化の質はどうでしょうか?私の場合、その悪はまだそれほど強くありません。名前を置き換えるだけでも、経験豊富なプログラマーであればこのコードの目的を簡単に理解できるでしょう。そして、JS ミニファイアーがこのタスクを処理できるとしたら、何の意味があるでしょうか。リバースにとって、より実用的で面倒なことを行うことは可能でしょうか?もう一つ呪文があります...

Here

2.隠す?すべて!

「すべて」と書いたときは少し自信があったかもしれませんが、これから行うことは、コードのアクションを可能な限り隠すことです。このセクションでは、静的分析を複雑にし、「クライアント」がコードに侵入するのを潜在的に防ぐために、文字列とさまざまなオブジェクト プロパティを非表示にします!

前の段階で取得した非表示の名前を持つコードを取得し、次のプラグインをそれに適用しましょう:

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);

このプラグインの動作についてはコード コメントですでに少し説明しましたが、その動作をステップごとに簡単に説明しましょう。

  1. コード内で置き換えられるすべてのプロパティと文字列を格納する配列データを作成します。この配列は、データを返す getData 関数で使用されます。
  2. 次に、AST を走査してルート ノード プログラムを見つけます。これを使用して、getData 関数 (指定されたインデックスのプロパティと文字列を返す) がコードの先頭に挿入されます。
  3. 次に、MemberExpression タイプのノードをバイパスします。プロパティを getData 関数の呼び出しに置き換えます。この場合、計算されたプロパティ のおかげで、document.createElement のような構造は document[getData(0)] に変換されます。その過程で、プロパティの名前をデータ配列に入力します。
  4. 最後に、StringLiteral 型のノードをバイパスし、目的のインデックスを持つ getData の呼び出しで文字列も置き換えます。

解析操作は順番に実行されるのではなく、AST 処理中に必要なノードが見つかるためであることに注意してください。

このプラグインを実行した結果、次のコードが得られます:

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();

結果のコードからわかるように、すべてのプロパティは、指定されたインデックスを持つ getData 関数呼び出しによって置き換えられています。文字列に対しても同じことを行い、関数呼び出しを通じて文字列を取得し始めました。プロパティ名と文字列自体は、気づきにくくするために、base64 でエンコードされています...

Here

もうお気づきかと思いますが、このプラグインとコード全般には、現段階では欠陥があります。たとえば、次の点は修正できる可能性があります:

  • プロパティと文字列を返す関数は、その目的である getData について叫びます。しかし、良いことに、識別子の名前を変更する最初のプラグインを適用することで、この点を修正できるということです。
  • getData 関数内の文字列自体は確実に保護されていませんが、base64 のみであるため、初期値を見つけるのは非常に簡単です。この問題を解決するのはさらに困難です。たとえば、getData 関数を作り直して、よく知られたエンコーディングの代わりに暗号化を適用することができます。
  • getData 関数は唯一の関数であり、関数自体をプルして実行することで、すべての呼び出しを元の値に置き換えるスクリプトを作成するのは難しくありません。

この単純さと欠点にもかかわらず、これはすでに難読化と呼ばれる可能性があると思います。しかし、繰り返しになりますが、オープンソースの難読化ツールは同様のことを行うため、それらとどう違うのでしょうか?

私たちは元の問題を思い出さなければなりません。これらの難読化は、公的難読化解除者にとって簡単な作業でした。では、取得したコードを WebCrack で難読化を解除してみましょう。 (うまくいけば、まだ私たちの呪文に対処できないでしょうか?)。実質的な重要性は達成されたと言えるでしょう。「保護された」コードは、公開された難読化解除ツールを介してワンクリックで元に戻せなくなりました

ボーナス。難読化解除

さあ、新しい呪文を学びましょう。パブリックの難読化解除ツールはプラグインを処理できませんが、難読化の実際の概念を研究すると、ソース コードを復元するために使用できるいくつかのパターンに気づくことができます。

それでは、具体的に次のことを活用してみましょう。

  • プロパティと文字列を保存する単一の呼び出される関数があります。
  • この関数の呼び出しはマスクされません。

これらの欠点を考慮して、次のプラグインを実装できます:

let w = screen.width, h = screen.height;
// Let's say there's a logic with some check. 
console.info(w, h);

この難読化解除プラグインの機能について説明しましょう:

  1. 難読化されたコードから getData 関数をコピーしました。必要な引数 (インデックス) を指定して実行することで、必要な文字列を取得できます。
  2. すべての getData 関数呼び出しを調べて、その実行結果に置き換えました。
  3. 最後に、AST で getData 関数を見つけ、不要になったのでコードから削除しました。

結果として、次のコードが得られます:

l=~[];l={___:++l,$$$$:(![]+"")[l],__$:++l,$_$_:(![]+"")[l],_$_:++l,$_$$:({}+"")[l],$$_$:(l[l]+"")[l],_$$:++l,$$$_:(!""+"")[l],$__:++l,$_$:++l,$$__:({}+"")[l],$$_:++l,$$$:++l,$___:++l,$__$:++l};l.$_=(l.$_=l+"")[l.$_$]+(l._$=l.$_[l.__$])+(l.$$=(l.$+"")[l.__$])+((!l)+"")[l._$$]+(l.__=l.$_[l.$$_])+(l.$=(!""+"")[l.__$])+(l._=(!""+"")[l._$_])+l.$_[l.$_$]+l.__+l._$+l.$;l.$$=l.$+(!""+"")[l._$$]+l.__+l._+l.$+l.$$;l.$=(l.___)[l.$_][l.$_];l.$(l.$(l.$$+"\""+(![]+"")[l._$_]+l.$$$_+l.__+"\"+l.$__+l.___+"\"+l.__$+l.$$_+l.$$$+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$$_+l.$$$+"\"+l.__$+l.$_$+l.__$+l.$$_$+l.__+"\"+l.__$+l.$_$+l.___+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+"\"+l.$__+l.___+"=\"+l.$__+l.___+"\"+l.__$+l.$$_+l._$$+l.$$__+"\"+l.__$+l.$$_+l._$_+l.$$$_+l.$$$_+"\"+l.__$+l.$_$+l.$$_+".\"+l.__$+l.$_$+l.___+l.$$$_+"\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$__+l.$$$+"\"+l.__$+l.$_$+l.___+l.__+";\"+l.__$+l._$_+l.$$__+l._$+"\"+l.__$+l.$_$+l.$$_+"\"+l.__$+l.$$_+l._$$+l._$+(![]+"")[l._$_]+l.$$$_+".\"+l.__$+l.$_$+l.__$+"\"+l.__$+l.$_$+l.$$_+l.$$$$+l._$+"(\"+l.__$+l.$$_+l.$$$+",\"+l.$__+l.___+"\"+l.__$+l.$_$+l.___+");"+"\"")())();

Here

したがって、示された欠点を使用して babel の単純なプラグインを作成することで、プロパティと文字列を隠す難読化を取り除くことができました。

この小さな例で、babel の助けを借りてそのような迷惑行為と戦う方法を説明できたと思います。これらのアプローチを使用すると、より複雑な難読化を解決することもできます。主なことは、コード内のパターンを見つけて、AST を巧みに操作することです。

結論

私たちは、コードのリバース エンジニアリングを複雑にする技術である難読化と、それを実装するツールについて学びました。 JavaScript コードを難読化する公開ソリューションはありますが、この保護を瞬時に削除できる公開ソリューションも同じくらい多くあります。

したがって、パブリックの難読化解除ツールで削除できないコードを保護するには、独自のソリューションを作成する必要があります。 JS で難読化を実装する信頼できる方法の 1 つは、目的のコードの AST と対話して、コードを読みにくい形式に変換するカスタム Babel プラグインを作成することです。

もちろん、この分野には難読化に対する既知の技術やアプローチがありますが、それでもなお、コードの学習をより困難にする可能性がある創造性や新しい「トリック」の余地は残されています。このような手法は多数ありますが、コードは常にクライアントの「手の中にある」ため、アルゴリズムの機密性はまったく保証されません。さらに、デバッグの可能性もあり、コードの研究が容易になります。難読化により、意欲の低い研究者を却下できるため、リバース エンジニアリングのコストが増加します。

高度なアプローチがいくつかあります。たとえば、難読化の 1 つは コードの仮想化、または簡単に言えば、カスタム バイトコードを実行する仮想マシンを JS で作成することです。このアプローチでは、静的解析の可能性がほぼ完全に排除され、デバッグが可能な限り困難になります。ただし、これは別の議論の主題です?....

このトピックに関する情報が皆さんのお役に立てば幸いです。これで、最初は難読化されたコードについて自分自身やプログラマを責めることがなくなります。これらのウィザードに感謝します ??‍♀️!ここでマジックの最新トレンドについて喜んでお話しさせていただきます?

以上がここでは、AST、Babel、プラグインを使用して、ラボを無駄にすることなく JavaScript で難読化を作成する方法を説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。