仮想マシンの概要 いわゆる仮想マシン保護技術とは、コードを機械や人間が認識できない疑似コード バイト ストリームの文字列に変換することを指します。具体的な実行時には、これらの疑似コードが一つずつ翻訳・解釈され、徐々に元のコードに復元されて実行されます。 疑似コードを変換し、特定の実行を担当するこのサブルーチンは、仮想マシン VM (抽象 CPU のような) と呼ばれます。これは関数の形で存在し、関数のパラメータはバイトコードのメモリ アドレスです。 現在、ビジネスに仮想マシンを適用する保護シェルは、Vmprotect、themida、execrypt の 3 つです。 仮想マシンアーキテクチャ コード内の指示は多様であり、その構成形式も常に変化していることがわかっています。仮想マシンがあらゆる特定の状況を翻訳して処理することは不可能です。考えられるすべての命令は、まず抽象的に分類され、次にいくつかの単純な小さな命令に分割され、その後、処理のためにさまざまな特殊なサブルーチン (ハンドラー) に渡される必要があります。 コンパイラ理論を学んだ学生なら、3 進コード (3 アドレス コードとも呼ばれる) について知っているはずです。つまり、割り当て式がどんなに複雑であっても、いくつかの 3 アドレス コード シーケンスに分解できます。 (3 アドレス コードとは何ですか? 3 アドレス コードは、バイナリ演算、比較、分岐ジャンプ演算など、1 つの演算のみを完了します。) 同様に、命令がいかに複雑であっても、分割できないアトミック命令のシーケンスに分解できます。 仮想マシン (CPU) のアーキテクチャは、スタック ベース、レジスタ ベース、3 アドレス マシンの 3 つのタイプに分けられます。ここでは、スタックベースの仮想マシン アーキテクチャ (スタック ベース) についてのみ説明します。このアーキテクチャの仮想マシンはスタックを頻繁に操作する必要があり、使用する仮想レジスタ (仮想 eax、ebx など) はスタックに保存されます。各アトミック命令のハンドラーはプッシュとポップを行う必要があります。 今日の CPU には多数のレジスタがあり、スタックは一般的に関数にパラメータを渡すときにのみ使用されます (PC で使用される x86 シリーズ CPU など)。しかし、スタックやレジスタを持たず、メモリのみで動作する CPU もいくつかあります。このタイプの CPU を使用するマシンは 3 アドレス マシンと呼ばれます。 スタックベースの CPU または仮想マシンには、一時変数やレジスタの概念はありません。すべてがスタックに置かれます。命令内でオペランドを指定する必要がないため、レジスタベースの命令よりも命令が短くなります。そのため、比較的シンプルで、組み込みシステムで広く使用されています。コードを保護するためにもこれを選択します。 たとえば、add 命令の場合、スタックベースの CPU は最初にスタックから 2 つの数値をポップし、次に 2 つの数値を加算して、その合計をスタックにプッシュします。 Add 命令は 1 バイトのみを占有します。レジスタベースの CPU の場合、対応する命令は add Reg1, Reg2 であり、3 バイトが必要です。レジスタのない CPU の命令がどのようなものになるか、またどれほど簡潔になるかをよく想像してください。もちろん、簡潔な指示の欠点は効率が低いことです。 ここで説明する仮想マシン保護テクノロジは、レジスタベースの CPU コードをスタックベースの CPU 疑似コードに変換することです。その後、疑似コードはスタックベースの仮想マシン (CPU) によって解釈され、実行されます。 コマンドシステム 鍵となるのは、仮想スタックベースの仮想マシン (CPU) 命令システムを設計することです。命令システムが単純で再利用性が高いほど、優れています。 add 命令を例に挙げてみましょう。 X86 シリーズ CPU の add 命令には、add reg,imm、add reg,reg、add reg,mem、add mem,reg など、さまざまな形式があります。スタックベースの仮想マシン CPU には、それほど多くのトリックはありません。加算命令は 1 つだけであり、パラメーターと戻り値はすべてスタック内にあります。 仮想マシンの CPU シミュレーションには、次のような追加コマンドを実装する必要があります。 元の add コマンド パラメータを push コマンドに変換する必要があります。プッシュ オブジェクトに応じて、異なる実装が必要になります。 Push コマンドがあり、Pop コマンドも必要です。 スタックベースの仮想マシン命令システムは、1 バイトのアクション命令 (add、dec など) と、push、pop などのさまざまなスタック操作命令というシンプルなものです。複雑なレジスタやメモリの操作はありません。 x86 CPU 命令を仮想マシン CPU 命令に変換する必要があります。例: Call 命令は、Call 関数が仮想マシンの疑似コードではない可能性があるため、比較的面倒です。したがって、Call 命令に遭遇すると、仮想マシンを終了し、処理を実際の CPU に引き渡す必要があります。コードは次のようになります。 さらに、フラグ、非シミュレート命令、命令の最適化の処理にも注意を払う必要があります。例外処理もありますが、ここでは詳しく説明しません。 VStartVM は仮想マシンのエントリ ポイントであり、動作環境 (各レジスタの値) の保存とスタックの初期化 (仮想マシンが使用するすべての変数がスタック内にある) を担当します。 バイトコードは疑似コードです。 VMDispatcher は疑似コードを 1 つずつ読み取って処理し、次のサブルーチン (Handler) に配布します。 パッカーはまず既知の X86 命令をバイトコードに解釈し、それを PE ファイルに格納し、元のコードを削除して同様のコードに置き換え、仮想マシン実行ループに入ります。 VStartVM が初期化された後、スタックは次のようになります。 edi は VMcontext を指します。 esi は疑似コードのアドレスを指します。 ebp は実際のスタックの先頭を指します。これら 3 つのレジスタは VM 内で変更しないでください。 VMContext は、仮想マシン VM によって使用される仮想環境構造です。 VM がスタックを使用して独自のレジスタ構造を保存する理由は、マルチスレッド プログラムの互換性を考慮するためです。 開梱時のスタックバランスの原則は誰もが知っています。同様に、仮想マシンが変換されたプログラム コードを実行する場合、元のスタック アドレスを任意に変更することはできません。また、スタック内の VMcontext 構造がフラッシュされていないことを頻繁に確認する必要があります。 |
<<: Ready Player Oneの開発元であるDirective GamesはAWS上で稼働しています
あなたのウェブサイトの製品についてもっと多くの人に知ってもらいたい、そして本当に製品マネージャーを人...
Zenlayerはインドネシア/インドネシアに自社インドネシアデータセンターを構え、データセンターは...
中国市場での 10 年以上にわたる発展を経て、クラウド コンピューティングは、単にリソースベースのニ...
要点: 1. 「Open Cloud Native Application Center」(略して ...
9月6日午前、NetEaseは検索方向から電子商取引事業を展開し、独自のドメイン名huihui.cn...
cartika.com の歴史は 1999 年にまで遡ります。つまり、ある程度の資格があるということ...
タイタニック3D版公開からSEOロングテールキーワード選定について語る最近、3D版のタイタニックを観...
[[320833]]この記事では、Kubernetes のセキュリティ メカニズムを中心に、一連の概...
ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス多くの人が新浪微博の調子...
ソフト記事はなぜ存在するのか?星文天下がこの疑問を提起したとき、ソフト記事が存在する根本的な理由、つ...
最近、奇妙な現象に遭遇しました。以前の記事は収集後も保存されていたのですが、先週から、私のウェブサイ...
外部リンクの構築は日常的な問題ですが、私たちの日々の仕事の焦点でもあります。しかし、現在SEOに取り...
クラウド環境での変更管理は、企業が急速に変化する環境に対応し、成功の可能性を高める道筋を作成するのに...
週末、WeChat 公式アカウントを開設したばかりの皆さんは、残業の疲れから目覚めたばかりで、Lin...
2月に「青大根アルゴリズム」がリリースされて以来、多くのウェブマスターがBaiduがリリースしたこの...