難読化とは、プログラムのソースコードを、機能を保持する形式に縮小することですが、逆コンパイル時の分析、作業アルゴリズムの理解、および変更を複雑にします。 JavaScriptに適用されるこの技術は、ダウンロード(iframe)、スパム、SEOなどの種類のシャドウオンラインビジネスで使用されます。 今日の私たちの仕事は、JSコードを隠すすべての方法を学ぶことです。これは、あなたが善のためだけに使うことを望んでいます。
難読化されたスクリプト
理論
まず、いくつかの質問に答えます。
1.何を隠しますか?Webアプリケーションのクライアント部分、つまり一般ユーザーが最終的に自分のコンピューターにダウンロードする部分のみを非表示にします。
次のテクノロジーは、このタイプに起因します。
- ページのHTMLコード。
- JavaScriptコード/ JSページファイル。
- ページのCSSコード/ CSSファイル。
- 画像およびその他の情報(「データ」プロトコルをサポートするブラウザーのみ)。
2.誰から隠す? この情報をすべて非表示にすることは、以下から合理的です
- アンチウイルス(iframeまたはその他の悪意のあるスクリプトの場合);
- 他の人(たとえば、すばらしいJavaScriptスクリプトを書いたが、誰かにそれをはぎ取られたくない場合)。
3.隠された情報のセキュリティをどのように確認できますか?
わかりません。
なんで? ユーザーがダウンロードするすべての情報は引き続きブラウザーによって実行されるためです。 つまり、情報を非常に複雑な方法で暗号化/非表示にしても、コードを読み取れないということにはなりません。 どんな場合でも読むことが可能になります、あなたはこの読書を複雑にすることができるだけです。 これらの困難な方法についてお話します。
4.暗号化/難読化プロセスは原則としてどのように行われますか?
2つの異なる段階があります。難読化/暗号化されたコードを作成し、通常のブラウザー実行のために解読します。 PHPスクリプトを使用して難読化されたコードを生成しますが、これは何でも使用できます。 ただし、コード実行の復号化はJavaScriptで記述する必要があります。この場合、スクリプトは本質的に復号化して実行されます。
JJEncode作品
基本的なHTML / CSS暗号化
HTMLまたはCSSコードを暗号化する必要がある場合はどうなりますか? すべてが単純です。JavaScriptで暗号化し、復号化後にHTMLコードとして貼り付けます。
挿入例(暗号化/暗号化/難読化なし):
<html> <script> var html = '<center><h3> -</h3></center>'; // "html" , document.getElementsByTagName('html')[0].innerHTML = html; // <html> </html> </script> </html>
CSSスタイルでも同じことを行います。
<html><script> var css = 'body{margin:0px;}.subcl{padding:5px;}'; // "css" , document.getElementsByTagName('html')[0].innerHTML = '<style>'+css+'</style>'; // <html> </html> </script> </html>
次に、HTMLとCSSを無視して、本質のみを説明します。最初に非表示にし、次にJavaScriptを暗号化します。
誰かが私たちのコードを見て解読する前に、彼はそれを見つけようとします。 以下に、好奇心の強いユーザーの目からコードを隠す効果的な方法をいくつか紹介します。
ドキュメントの本文に「] [akep」という単語を非表示にします
<script>タグの属性を置き換える
すべてが非常に単純ですが、ユーザーの不注意に焦点を合わせているため、これは良い保護または平均的な保護とは見なされません。
原理自体は非常に単純です。 ページ( "index.html")と、コードを非表示にするJavaScriptファイル( "script.js")があります。 「index.html」ページで、次のことを示しました。
<script type="text/javascript" src="./script.js"></script>
次に、「text」フォルダを作成します。このフォルダに「javascript」という名前でスクリプト(「script.js」)を入れ、属性を交換します。 次のようになります。
<script src="text/javascript" type="./script.js"></script>
最良の効果を得るには、すぐにユーザーの注意をパスに向けてください。 たとえば、次のように:
<script src="text/javascript" type="http://host.com/////////script.js"></script>
個人的な経験でテストされた:素晴らしい作品! このようにして、JavaScriptでチートエンジンを使用する必要があったため、私はクリック用のアフィリエイトプログラムを作成しました。 アフィリエイト管理者は彼を見ませんでした:)。
Javascriptハンドラー
このメソッドは、JSコードを隠すための普遍的なツールでもありませんが、それについては引き続き説明します。 主なアイデアは、onLoad、onClickなどのイベントハンドラー内のコードを非表示にすることです。 つまり、おおよそ次の設計で:
<body onLoad="alert(1);"></body> <textarea onClick="alert(1);"></textarea>
たとえば、bodyタグとframesetタグには、ページ/フレームの読み込み後に所定のコードを実行するonLoadハンドラーがあります。
ハンドラーはすべてのオブジェクトで同じではないことに注意してください。
Cookie、リファラー、アドレス
JavaScriptは、Cookie(document.cookie)、リファラー(document.referrer)、ページアドレス(location.href)などの非標準の場所で非表示にすることもできます。 この場合、コードはプレーンテキストとして保存され、eval()関数を使用して実行されます。この関数は、テキストを引数として受け取り、JavaScriptコードとして実行します。
例として、次のタイプのCookieがすでにあるという仮定を考えてみましょう。
cookievalue=||alert(1);||
このアラートを次のように実行します。
<script>eval(unescape(document.cookie).split("||")[1]);</script>
ここでは、ホストのすべてのCookieのテキストを取得し、「||」が立っている場所で部分に分割します。 次に、2番目の要素([1])を取得し、eval()で実行します。
実行したいコードがページ自体に表示されず、コードを強制的に削除できるため、このメソッドはそれほど悪くありません! 実装例:
<?php
同様に、location.hrefやdocument.referrerなど、JavaScriptを介して利用可能な他の行を使用できます。
Ajaxコードの非表示
この場合、コードは別のファイルにあり、このファイルを読み取り、その内容をeval()関数で実行することにより、コードが起動されます。
非表示のコードを含むページと、このコードを実行する関数を含むページを作成する必要があります。
- 非表示にするコードのあるページ(「l」という名前):
alert(1);
- コード呼び出しのあるページ:
<script>function x(){try{return new XMLHttpRequest();}catch(e){try{return new ActiveXObject('Msxml2.XMLHTTP');}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP');}catch(e){return null;}}}};function y(){var z=x();if(z){z.open('get','./l');z.onreadystatechange=function(){if(z.readyState==4){ eval(z.responseText);}};z.send(null);}};y();</script>
このメソッドは、コードを別のファイル(この例では「l」)に隠します。 もちろん、ファイルパスを見つけて開くことはできますが、そのようなコードを難読化する場合、ファイル名を見つけることは非常に困難です。
ヌルバイトがOperaを攻撃
この方法はシンプルで非常に効果的ですが、残念ながらOperaブラウザ専用に設計されています。 このメソッドの本質は、非表示にするコードの前にいわゆるヌルバイトを置くことです(ヌルバイトまたはヌルバイトは、ASCIIコード「0」の文字です)。 なんで? その場合、Operaは、この記号の後に、ビルトインビューアーにコードを表示しません。 例:
<html> - </html> <?php echo(chr(0)); ?> <script>alert(1); </script>
この例では、最初に通常のコードが表示されますが、非表示にする必要はありません。 次に、PHPを使用してnullバイトを挿入し、その後に非表示のコードを挿入します。
HTMLコードとコメントの非表示
コードをHTMLで簡単に非表示にしてから、処理して実行できます。 たとえば、次のように:
<body><img src="./pict.jpg" a="al" b="er" c="t(1);"></body> <script>a = document.body.innerHTML; eval(a.split('a="')[1].split('"')[0]+a.split('b="')[1].split('"')[0]+a.split(' c="')[1].split('"')[0]);</script>
この場合、imgタグの属性にコードを隠し、その後、ページ全体のコードを処理して、散在する断片を収集しました。 同様に、HTML / JavaScriptコメント内のテキストを非表示にできます。
HTML: JavaScript: // alert(1); /* alert(1); */
それとは別に、jQuery、mooToolsなどの一般的なフレームワーク内のコードを非常に効果的に非表示にできることに注意してください。 これらのファイルは疑わしくなく、調査には多くの時間がかかります(ただし、元のファイルと変更されたファイルを自動的に比較する可能性は常にあります)。
これで、最終的に、セキュリティの専門家が見ているもの、およびウイルス対策が研究していることについて話すことができると思います。 JSコードを暗号化および難読化する最も一般的な方法については、以下をお読みください。
標準のJavaScript関数/メソッドの置換
このメソッドは、標準のJavaScript関数またはメソッドの代わりに変数を置換することに焦点を当てています。
: <script>document.getElementsByTagName("html")[0].innerHTML = document.getElementsByTagName("body")[0].length;</script> : <script>a=document;c='getElementsByTagName';a[c]("html").innerHTML = a[c]("body")[0].innerHTML.length;</script>
この場合、「document」オブジェクトを変数「a」に、getElementsByTagNameメソッドを変数「c」に置き換えました。 メソッド(ポイント、たとえば.lengthまたは.getElementsByTagNameで始まる)は、配列内のキーを定義することによって置き換えることもできます(オブジェクトを配列と見なす場合)。 「ドキュメント」オブジェクトがあり、その中にgetElementsByTagName要素がある場合、これは次の2つの方法で呼び出すことができることを意味します。
document.getElementsByTagName
document['getElementsByTagName']
2番目のメソッドでは、文字列データ( "getElementsByTagName")を使用するため、文字列(メソッドの名前)を含む変数に置き換えることができます。
置換は、同じ標準オブジェクト/関数/変数を頻繁に使用する場合に役立ちます。 これにより、コードが大幅に変更され、圧縮されます。
洪水のコメントとコード
このメソッドは、難読化されたコード、つまりスクリプトコードのセマンティックロードを持たないコードにフラッドを挿入するように設計されています。 コードとコメントの両方をあふれさせることができます:
: <script> a = 'hahaha' ; alert ( a ) ; </script> : <script> weoibog = 'gwrobgoerh'; a = 'hahaha'; bfionb = 'wgeogioweg'; alert(a);
この場合、コメントスレッドは密度が高すぎますが、実際にはコードは非常に単純でした。「
a = "hahaha"; alert(a);
a = "hahaha"; alert(a);
「。
フラッドコードはフラッドコメントにも干渉する可能性があります。 必要に応じて、JavaScriptコードにフラッドを追加するPHP関数を作成できます。 個人的に、私は英語のブログからいくつかの記事を取り、単語を解析し、関数はこれらの単語をランダムにコメントに追加しました。
ところで、「偽の閉鎖」の形で複数行のコメントを使用することもお勧めします。
alert(2);
どの数字がアラートを表示しますか? :)
難読化されたアラート作業
テキストを16進コードに置き換える
この点については、テキストを変換する他の方法を参照したかったのですが、復号化にヘルパー関数を必要としない唯一の暗号化方法であるため、この方法のみを残しました。
<script> alert(document["\x63\x6F\x6F\x6B\x69\x65"]); </script>
この場合、最初に、ドキュメントオブジェクトの内部Cookie変数を配列の要素として使用しました。 次に、彼女の名前を16進数に変換しました。 ドットを介して、つまりdocument.cookieとしてcookie変数を使用した場合、16進形式で呼び出しを変換することはできません。これは文字列(配列内のキーは文字列)にのみ適用されますが、ドキュメントに適用されるためです。 Cookieなし。
16進形式に変換するPHP関数:
<?php function cescape($s) { foreach (str_split($s,1) as $sym) { $d = dechex(ord($sym)); $c[] = (strlen($d) == 1) ? '0'.$d : $d; } return (''.'\\'.implode(''.'\\',$c)); } ?>
存在しない機能を使用したトリック
上記の説明からすでにわかっているように、JavaScriptでオブジェクトの要素としてメソッドを呼び出すことができます:document.getElementByIdおよびdocument ['getElementById']。 両方のオプションは実質的に同じです。違いはレコードのみです-2番目のオプションでは文字列を使用します。
ある夜、これらの行を取得する非常に興味深い方法を思いつきました。 たとえば、上記の「getElementById」を暗号化する必要があります。 この例を使用して、この方法の簡単な説明を避けましょう。
<script> a = b(c(d())); </script>
関数b、c、dは以前に宣言されていないため、このスクリプトは機能しません。 それでは、このコードを機能させてみましょう。このため、try {} catch(){}コンストラクトのサンドボックスを使用します。
<script> try{a = b(c(d()))}catch(e){alert(e);} </script>
開始後、エラーが表示されます。つまり、コードは機能していませんが、残りの正しい部分の実行は停止していません。
そして今、私たちはそのようなスキームが文字列「getElementById」の暗号化にどのように関連付けられるかを自問しますか? など:
<script>try{(getE(leme(ntB(yId()))))}catch(e){x = (e+'').split('(').slice(1,5).join('');}</script>
このコードを実行した後、変数「x」に含まれる文字列「getElementById」を取得します。
この方法の塩は何ですか? 事実は、機能を見つけるときのアンチウイルスの発見的分析は、それらが存在しないことを誓うことです。 したがって、さまざまな方法で文字列を暗号化するレベルではなく、JavaScript自体からこれらの文字列を受信するレベルでコードを難読化します。
〜演算子を使用した数値
演算子「〜」(チルダ)はビット否定であり、「alert(〜13);」のように使用されます。 このコードは「-14」を出力します。 この演算子は、「-(number + 1)」の原則に基づいて動作します。
変数「a」に何らかの番号を割り当て、この番号をどこにも書かないことを想像してください。「a =〜[]」;
このコードは、変数「a」に番号「-1」を割り当てます。 なんで? 配列は数値「0」のニュートラル要素であるため、〜0は「-(0 + 1)」、つまり-1と同等です。
他の変換の例:
a = ~[];
文字列データのない文字と文字列
文字/記号またはテキストをつづりなく明示的に取得する必要がある場合があります。 これは、1つのJavaScript機能で実行できます。 この言語には、テキストに変換して処理できるさまざまなシステム内メッセージがあります。
たとえば、「コード」というテキストを取得する必要があるとします。 この行は、charCodeAt()、fromCharCode()などのメソッドの名前に含まれています。 次のようにテキストを取得できます。
a = (alert+'').split("ive ")[1].substr(0,4);
この例では、変数「a」にはテキスト「code」が含まれます。 さらに詳細に分析します。 次のコードを実行してみてください:「alert(alert + '');」。 「関数アラート(){[ネイティブコード]}」のようなものが表示されます。 したがって、alert()関数のみを2回使用すると、まったく異なる文字が得られました。
それでは、すべての仕組みを理解してみましょう。 JavaScriptのすべてのオブジェクト、関数、その他すべてに特定の「説明」があると想像してください。 これにアクセスするには、このオブジェクトまたは関数のタイプを明示的に文字列に変更し、たとえば空の文字列(+ "")を追加する必要があります。
文字列暗号化
JavaScriptで文字列を暗号化/復号化するための便利な機能がいくつかあります。 それらのいくつかを分析しましょう:
escape();
文字をASCIIコードに、またはその逆に変換することで機能するStringオブジェクトの2つのメソッドもあります。
a = String.fromCharCode(97); b = "b".charCodeAt();
文字列は、.matchおよび.replaceメソッドと組み合わせて正規表現で変換することもできます。 他のメソッドは、むしろ、文字列で検索することに起因します。
オブジェクト/変数の変換
オブジェクトと変数の名前を文字列に変換することもできます(たとえば、この文字列を後で暗号化するため)。 変換は、メソッド名の変換と同じ原理に従って、つまり、「。Method」から「[Method]」への移行によって行われます。 正しい変換を行うには、オブジェクトの階層で「ドキュメント」という単語が含まれるさらに上位の要素を見つける必要があります。 彼にこれを名前を付けます。 JavaScript標準によると、これはオブジェクトではなく、オブジェクトへの参照を返す演算子です。 その結果、getElementByIdを次のように安全に使用できるようになりました: "this [" document "] [" getElementById”]。
コードバインディング
特定の条件が満たされた後にのみ実行されるようにコードを記述することが必要になる場合があります。 たとえば、JavaScriptコードを作成して販売したいのですが、他のサイトで実行できないようにドメインへのバインディングで販売したいと考えています。
繰り返しますが、絶対的な保護を考え出すことはできません。原則として、コピー/アンテザープロセスを困難にする方法はいくつかあります。
そのようなバインディング+依存するデータのいくつかのタイプを以下に示します。
- ドメインへのバインド// location.href.split( '/')[2];
- パラメーターへのバインド(#?の後にページに渡されます)// location.href.split( '#')[1]またはlocation.href.split( '?')。slice(1);
- 日付へのバインド// a = new Date();
- JavaScriptコードへのバインド//;
- ページ全体のコードへのバインド// a = document.getElementsByTagName( 'html')[0] .innerHTML;
- ブラウザバインディング// a = navigator.userAgent;
- Cookieへのバインド// document.cookie;
- あなたが考えることができる他のバインディング。
疑わしい機能の回避
また、関数eval()、document.write()などの明示的な使用を避けることをお勧めします。 実際のコードを検索するとき、多くの場合、人々はこれらの関数の代わりにalert()置換メソッドを使用します。その後、暗号化を開始した方法ですぐにコードを読み取ることができるため、難読化のポイントがすべて消えます。 eval()を使用せずにコードを実行する方法は?
これの先頭にthis演算子があることを思い出してください。 これを使用して、eval()関数を次のコードに変換できます。
a = this["\x65\x76\x61\x6C"];
このような変換後、「eval()」の代わりに「a()」を安全に使用できます。
読めない行に変更する
難読化されたコードでは、識別子を示すために次の文字とその組み合わせを使用する必要があります。
"o", "O", "0"
"i", "I", "l", "1"
"_"
(およびバリアント"__"
、 "___"
...)"$"
(および"$$"
、 "$$$"
変形...)
このような文字を使用した後、特に圧縮して余分なスペースや改行を削除すると、コードが非常に読みにくくなります。
コード暗号化
テキストを暗号化する方法は無制限にありますが、それらはすべてテキスト/数値関数の使用に基づいています。 多くの場合、コンストラクトは機能します:eval()+ encryption_function()+ encrypted_string。 これらの方法のいずれかを余分な水なしで見せようとします。
文字列「alert(1);」を暗号化する必要があるとします。 それから2文字を取り出して数字に変換し(ASCIIコード)、それらを読み、その隣の最初の文字をきれいな(翻訳なしの)形式にすることに思いつきました。 コードをそのような2文字の部分に分割すると、元のコードの約2から2.5倍のコードが得られることを考慮してください。そのようなブロックを何らかの方法で(配列要素として、またはセパレーターを介して)分離する方が良いことを忘れてはなりません。 区切り文字には、暗号化された文字列がURL文字列のように見えるため、「%」記号を使用します。 簡単なPHPスクリプトを作成しましょう。
<?php $a = "alert(1);"; $a = str_split($a, 2); $e = ''; foreach ($a as $v) { $e .= '%' . $v[0] . (ord($v[0])+ord($v[1])); } echo($e); ?>
取得したものは次のとおりです。「
%a205%e215%t156%190%;59
」。
そして、このコードのデコーダーをJavaScriptで記述します。
function d(s) { s = s.split('%').slice(1); c = ''; for (i = 0; i < s.length; i++) { c += s[0] + String.fromCharCode(s.substr(1)-s[0].charCodeAt()); } return c; }
この場合のコード呼び出しは、「eval(d( '%a205%e215%t156%190%; 59'));」のようになります。
このスクリプト全体を少し難読化するだけです。 記載されているすべての方法を使用するわけではありませんが、そのうちのいくつかにのみ触れます。
z = '73706C697421736C696365216C656E6774682166726F6D43686172436F6465217375627374722163686172436F64654174'; _=''; for(__=0;__<z.length/2;__++){_+=unescape('%'+z[__*2]+z[__*2+1]);} _=_[_[0]+_[1]+_[2]+_[3]+_[4]]('!');function ___(__){__ = __[_[0]]('\x25')[_[1]](-~[]); _I='';for (_l=0;_l<__[_[2]];_l++){_I+=__[_l][0]+String[_[3]](__[_l][_[4]](1)-__[_l][0][_[5]]());}return _I;} this['\x65\x76\x61\x6C'](___('%a205%e215%t156%190%;59'));
この一見読めないコードを処理するプロセスをさらに詳しく考えてみましょう。
z = '....'
ここでは、変数に文字列split!slice!length!fromCharCode!substr!charCodeAtを16進数形式(\ x73 \ x70 \ x6C \ x69 \ x74 ...)で変換したテキストが割り当てられます。 x ";_='';for(...}
ここでは、split!slice!length!fromCharCode!substr!charCodeAtを変数 "_"に逆変換します。_=_...('!');
記号「!」がある場所で行を分割します。function ___(__){...}
上記の難読化された形式の関数d()。this['\x65\x76\x61\x6C'](....);
文字列のデコードとコードの実行。
最後に
要約すると、 これらすべての方法を組み合わせることで、単純なユーザーでも普通のユーザーでもコードを読み取ったり、自分にコピーしたりすることはできなくなります。 しかし、コンピューターセキュリティの専門家はこれらのトリックの大部分をよく知っているので、この情報を公開するので、これらの方法がより一般的になり、よく知られるようになると思います。 提供された情報を適切な目的に使用できることを願っています。
スクリプトを読みやすくする
ハッカーマガジン、 9月(09)152
| qbz | (lopuxin.iv @ yandex.ru、 http: //essenzo.net) 。
ハッカーを購読する