JavaScript のリバースとアンチリバース
popunderjs は元々 github 上にオープン ソース コードを持っていましたが、後に作者がこの需要の巨大な商業的価値を発見したため、単純にオープン ソースを停止し、直接課金したのだと思います。そのため、実装計画を検討したい場合は、公式 Web サイトにアクセスしてソース コードを入手するしかありません。
ファイル構造
script.jsは、ポップアンダーのすべての機能を実装し、複数のAPIメソッドを定義するメイン関数です
license.demo.jsは、このファイルでのみ許可ファイルです。スムーズに呼び出します script.js のメソッド
逆転を防ぐ
このような商業的価値のあるコードは非常に公開されているため、逆転の問題を考慮する必要があります。リバースエンジニアリングに対してどのように機能するかを見てみましょう。
まず、コンソールを開いて 2 つの問題を見つけます:
コンソールの内容はすべて繰り返しクリアされ、次の文のみが出力されます: Console was Clear script.js?0.5309098417125133:1
ブレークポイント デバッグ機能が有効になると、匿名関数 (function() {debugger}) にリダイレクトされるため、ブレークポイント デバッグはできません
つまり、一般的に使用されるブレークポイントデバッグ方法は利用できなくなりました。使用後は、ソース コードを見て、そのロジックを理解できるかどうかを確認することしかできません。ただし、そのソースコードは次のようになります:
<span style="font-size: 16px;">var a = typeof window === S[0] && typeof window[S[1]] !== S[2] ? window : global;<br> try {<br> a[S[3]](S[4]);<br> return function() {}<br> ;<br> } catch (a) {<br> try {<br> (function() {}<br> [S[11]](S[12])());<br> return function() {}<br> ;<br> } catch (a) {<br> if (/TypeError/[S[15]](a + S[16])) {<br> return function() {}<br> ;<br> }<br> }<br> }<br></span>
ソースコードを読み取ることが不可能であることがわかりますので、そのリバース防止対策を破る方法を見つける必要があります。
ツールを使ってアンチリバースエンジニアリングを賢く解読しましょう
まず、ブレークポイントデバッグモードでどのような操作が実行されたかを段階的に確認すると、突然次のコードが見つかりました:
<span style="font-size: 16px;">(function() {<br> (function a() {<br> try {<br> (function b(i) {<br> if (('' + (i / i)).length !== 1 || i % 20 === 0) {<br> (function() {}<br> ).constructor('debugger')();<br> } else {<br> debugger ;<br> }<br> b(++i);<br> }<br> )(0);<br> } catch (e) {<br> setTimeout(a, 5000);<br> }<br> }<br> )()<br>}<br>)();<br></span>
このコードは主に 2 つの部分で構成されています。1 つは、try {} ブロックで b() 関数を使用して、コンソールが開いているかどうかを判断し、開いている場合は、それ自体を呼び出し、繰り返しデバッガー ブレークポイントに入り、干渉を実現します。デバッグの目的で。コンソールが開かれていない場合、デバッガーを呼び出すと例外がスローされます。このとき、catch {} ブロックにタイマーを設定し、5 秒後に b() 関数を再度呼び出します。
実際、すべては setTimeout 関数から始まります (b() 関数はすべてクロージャ呼び出しであり、外部から中断できないため)。したがって、setTimeout が呼び出されている限り、これを実行させないでください。無限のサイクルは断ち切れるかもしれない。
したがって、単純に setTimeout をオーバーライドするだけです...例:
<span style="font-size: 16px;">window._setTimeout = window.setTimeout;<br>window.setTimeout = function () {};<br></span>
でも!この操作はコンソールでは実行できません。コンソールを開くと、必然的に b() 関数の無限ループに引き込まれてしまうからです。現時点では setTimeout をオーバーライドする意味はありません。
この時点で、私たちのツール TamperMonkey が機能します。コードを TM スクリプトに書き込むと、コンソールを開かなくても実行できます。
TM スクリプトを作成したら、ページを更新し、完全にロードされるまで待ってから、コンソールを開きます。この時点では、デバッガーは表示されなくなります。
次に、コンソールがコードを更新する番です
コンソールの右側にあるリンクをクリックして特定のコードを見つけ、{} をクリックして圧縮コードを美しくすると、実際に使用していることがわかりますsetInterval console.clear() を繰り返し呼び出すと、コンソールがクリアされ、「 Console was Clear
そのため、console.clear() 関数をオーバーライドし、ログ情報をフィルタリングすることで、画面のクリア動作を防ぐことができます。
は TamperMonkey のスクリプトにも書き込まれます。コード:
<span style="font-size: 16px;">window.console.clear = function() {};<br>window.console._log = window.console.log;<br>window.console.log = function (e) {<br> if (e['nodeName'] && e['nodeName'] == 'p') {<br> return ;<br> }<br> return window.console.error.apply(window.console._log, arguments);<br>};<br></span>
エラーを情報の出力に使用する理由は、プログラムのロジックを理解するのに役立つコールスタックを表示するためです。
基本的に、これらのタスクを完了した後、このコードは通常のプログラムと同様にデバッグできます。しかし、そのメインコードは難読化され暗号化されていることが多いため、デバッグが非常に困難です。プロセスについて簡単に説明しましょう。
難読化暗号化方法 1: メソッド呼び出しを非表示にして可読性を低下させる
license.demo.js から、最初に次のようなコード部分があることがわかります:
<span style="font-size: 16px;">var zBCa = function T(f) {<br> for (var U = 0, V = 0, W, X, Y = (X = decodeURI("+TR4W%17%7F@%17.....省略若干"),<br> W = '',<br> 'D68Q4cYfvoqAveD2D8Kb0jTsQCf2uvgs'); U < X.length; U++,<br/> V++) {<br/> if (V === Y.length) {<br/> V = 0;<br/> }<br/> W += String["fromCharCode"](X["charCodeAt"](U) ^ Y["charCodeAt"](V));<br/> }<br/> var S = W.split("&&");<br/></span>
通过跟踪执行,可以发现 S 变量的内容其实是本程序所有要用到的类名、函数名的集合,类似于 var S = ['console', 'clear', 'console', 'log'] 。如果要调用 console.clear() 和 console.log() 函数的话,就这样
<span style="font-size: 16px;">var a = window;<br/>a[S[0]][S[1]]();<br/>a[S[2]][S[3]]();<br/></span>
混淆加密方法二:将函数定义加入到证书验证流程
license.demo.js 中有多处这样的代码:
<span style="font-size: 16px;">a['RegExp']('/R[\S]{4}p.c\wn[\D]{5}t\wr/','g')['test'](T + '')<br/></span>
这里的 a 代表 window,T 代表某个函数, T + '' 的作用是把 T 函数的定义转成字符串,所以这段代码的意思其实是,验证 T 函数的定义中是否包含某些字符。
每次成功的验证,都会返回一个特定的值,这些个特定的值就是解密核心证书的参数。
可能是因为我重新整理了代码格式,所以在重新运行的时候,这个证书一直运行不成功,所以后来就放弃了通过证书来突破的方案。
逆向思路:输出所有函数调用和参数
通过断点调试,我们可以发现,想一步一步深入地搞清楚这整个程序的逻辑,是十分困难,因为它大部分函数之间都是相互调用的关系,只是参数的不同,结果就不同。
所以我后来想了个办法,就是只查看它的系统函数的调用,通过对调用顺序的研究,也可以大致知道它执行了哪些操作。
要想输出所有系统函数的调用,需要解决以下问题:
覆盖所有内置变量及类的函数,我们既要覆盖 window.console.clear() 这样的依附在实例上的函数,也要覆盖依附在类定义上的函数,如 window.HTMLAnchorElement.__proto__.click()
需要正确区分内置函数和自定义函数
经过搜索后,找到了区分内置函数的代码:
<span style="font-size: 16px;">// Used to resolve the internal `[[Class]]` of values<br/> var toString = Object.prototype.toString;<br/><br/> // Used to resolve the decompiled source of functions<br/> var fnToString = Function.prototype.toString;<br/><br/> // Used to detect host constructors (Safari > 4; really typed array specific)<br> var reHostCtor = /^\[object .+?Constructor\]$/;<br><br> // Compile a regexp using a common native method as a template.<br> // We chose `Object#toString` because there's a good chance it is not being mucked with.<br> var reNative = RegExp('^' +<br> // Coerce `Object#toString` to a string<br> String(toString)<br> // Escape any special regexp characters<br> .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')<br> // Replace mentions of `toString` with `.*?` to keep the template generic.<br> // Replace thing like `for ...` to support environments like Rhino which add extra info<br> // such as method arity.<br> .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'<br> );<br><br> function isNative(value) {<br> var type = typeof value;<br> return type == 'function'<br> // Use `Function#toString` to bypass the value's own `toString` method<br> // and avoid being faked out.<br> ? reNative.test(fnToString.call(value))<br> // Fallback to a host object check because some environments will represent<br> // things like typed arrays as DOM methods which may not conform to the<br> // normal native pattern.<br> : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;<br> }<br></span>
然后结合网上的资料,写出了递归覆盖内置函数的代码:
<span style="font-size: 16px;">function wrapit(e) {<br> if (e.__proto__) {<br> wrapit(e.__proto__);<br> }<br> for (var a in e) {<br> try {<br> e[a];<br> } catch (e) {<br> // pass<br> continue;<br> }<br> var prop = e[a];<br> if (!prop || prop._w) continue;<br><br> prop = e[a];<br> if (typeof prop == 'function' && isNative(prop)) {<br> e[a] = (function (name, func) {<br> return function () {<br> var args = [].splice.call(arguments,0); // convert arguments to array<br> if (false && name == 'getElementsByTagName' && args[0] == 'iframe') {<br> } else {<br> console.error((new Date).toISOString(), [this], name, args);<br> }<br> if (name == 'querySelectorAll') {<br> //alert('querySelectorAll');<br> }<br> return func.apply(this, args);<br> };<br> })(a, prop);<br> e[a]._w = true;<br> };<br> }<br>}<br></span>
使用的时候只需要:
<span style="font-size: 16px;">wrapit(window);<br>wrapit(document);<br></span>
然后模拟一下正常的操作,触发 PopUnder 就可以看到它的调用过程了。
参考资料:
A Beginners’ Guide to Obfuscation Detect if function is native to browser Detect if a Function is Native Code with JavaScript
以上内容就是Javascript逆向与反逆向的教程,希望能帮助到大家。
相关推荐:
JavaScript中undefined与null的区别详解
以上がJavaScript のリバースとアンチリバースの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

顔の検出および認識テクノロジーは、すでに比較的成熟しており、広く使用されているテクノロジーです。現在、最も広く使用されているインターネット アプリケーション言語は JS ですが、Web フロントエンドでの顔検出と認識の実装には、バックエンドの顔認識と比較して利点と欠点があります。利点としては、ネットワーク インタラクションの削減とリアルタイム認識により、ユーザーの待ち時間が大幅に短縮され、ユーザー エクスペリエンスが向上することが挙げられます。欠点としては、モデル サイズによって制限されるため、精度も制限されることが挙げられます。 js を使用して Web 上に顔検出を実装するにはどうすればよいですか? Web 上で顔認識を実装するには、JavaScript、HTML、CSS、WebRTC など、関連するプログラミング言語とテクノロジに精通している必要があります。同時に、関連するコンピューター ビジョンと人工知能テクノロジーを習得する必要もあります。 Web 側の設計により、次の点に注意してください。

株式分析に必須のツール: PHP および JS でローソク足チャートを描画する手順を学びます。特定のコード例が必要です。インターネットとテクノロジーの急速な発展に伴い、株式取引は多くの投資家にとって重要な方法の 1 つになりました。株価分析は投資家の意思決定の重要な部分であり、ローソク足チャートはテクニカル分析で広く使用されています。 PHP と JS を使用してローソク足チャートを描画する方法を学ぶと、投資家がより適切な意思決定を行うのに役立つ、より直感的な情報が得られます。ローソク足チャートとは、株価をローソク足の形で表示するテクニカルチャートです。株価を示しています

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

逆崩壊ベーカリー作戦は3月22日にリリースされます.多くのプレイヤーは逆崩壊ベーカリーの運営にどれくらいの費用がかかるのか知りたいと思っています.最初の週は割引があります.価格はベーシックバージョンが80.36元、デラックス版が178.76元ですversion. 詳しくはこの記事を見てみましょう. 逆崩壊ベーカリーアクションの価格紹介。逆崩壊ベーカリーアクションの価格 回答: 最初の割引価格は、ベーシックバージョンが 80.36 元、デラックスバージョンが 178.76 元です。 1. 「逆崩壊ベーカリー作戦」は3月22日にリリースされることが決定しており、初週は割引があり、価格はベーシック版80.36元、デラックス版178.76元です。 2. これは、Mica Group の初期の作品 Bakery Girl のリメイクであり、グラフィックス、プロット、ゲームプレイに大きな革新が加えられています。 3. 物語の舞台は近未来、崩壊液の汚染により、

インターネット金融の急速な発展に伴い、株式投資を選択する人がますます増えています。株式取引では、ローソク足チャートは一般的に使用されるテクニカル分析手法であり、株価の変化傾向を示し、投資家がより正確な意思決定を行うのに役立ちます。この記事では、PHP と JS の開発スキルを紹介し、株価ローソク足チャートの描画方法を読者に理解してもらい、具体的なコード例を示します。 1. 株のローソク足チャートを理解する 株のローソク足チャートの描き方を紹介する前に、まずローソク足チャートとは何かを理解する必要があります。ローソク足チャートは日本人が開発した
