シェル時点VMP前に書面に従事したいと考えていますが、この事のオンラインブログを説明することだけを見つけるために、何度も繰り返し、比較的小さいます。https://www.cnblogs.com/LittleHann/p/3344261.html
兄の足跡をたどって、彼はいくつかの試み、マークそれを作りました。
ギャングスター私は、自分自身を記述するための関数で実行をシミュレートstrcmpのを書いて、呼び出し規約WINAPI、呼び出された関数のスタック自身のバランスを設定し、それとは異なります。
呼び出し後のように、元のテキストECXを変更しない、問題を見つけましたが、私ではありません。スタートは、スタックフレームを開いた後、機能のECXの戻り値は、ECXを保存呼び出すために使用されています。
書式#include <iostreamの> の#include "WINDOWS.H" / *ここでダミー命令、2 * /シミュレートされた命令 // 0x12345678のプッシュプッシュの4バイト に#define vPushData 0x10を 呼び出す// 4バイト0x12345678のコールアドレス の#define vcall 0x12を //ターミネーター 、販売0xFFでは、の#define / * この仮想命令の構成である STRオフセットプッシュ STRオフセット押すと、文字列スタックのアドレス コールのstrcmp; * / BYTE bVmData [] = {vPushData、 0x00で、0x00に、0x00で、0x00に、 vPushData、0x00で、0x00に、0x00で、0x00に、 vcall、0x00で、0x00に、0x00で、0x00に、 自動販売機販売}; //単純な仮想化エンジン _declspec(裸の)無効VM(PVOID pvmData) { __asm { //この関数はスタックフレームを開きます EBPプッシュ MOVのEBP、ESP サブESP、0x64は // ECXでvCodeアドレス取る MOV ECX、DWORD PTR SS:[EBPの+ 8] __vstart: //らの第1バイトを取る 、MOVのBLバイトのPTR DS: [ECX] //比較はvPushDataない vPushData、CMP BL です// __vPushDataブロックがジャンプ JE __vPushData //比較がvcallされていない CMP BLを、vcall //が__vcallとにジャンプしている __vcallとJE //比較ではありませんVEND CMP BL、VENDは // __vEndにジャンプしている JE __vEndの int型3。 __vPushData: // ECX + 1、4バイトの背中を指し、vPushDataをスキップ ECXである株式会社 データの// 4つのバイトがEDXに入れ(すなわち、アドレス) MOV EDX、DWORD PTR DS:[ECX] //プッシュアドレス EDXは、プッシュ // ECX + 4、次のデータポイント。 追加ECX ,. 4 ブロック__vstartへ//ジャンプを JMPの__vstart __vcallと: // ECXの+ 1、オフセットアドレス incはECXです //関数アドレス削除 [ECX]:MOV EDX、DWORD PTR DS //はECXを保存します値 MOV DWORD PTR DS:[EBP-20がある]、ECX //コール機能アドレスは EDXを呼び出し ECXのの//戻り値 のMOV ECX、DWORD PTR DS: - [EBP 20である] 。// + ECX 1、4つのアドレスは、オフセット ECXは,. 4追加 __vstartする//ジャンプを JMP __vstart __vEnd: 均衡//スタックを ESPを追加し、0x64 POPのEBPの RETは } }は 、文字列比較関数独自の実装// int型をWINAPI MyStrCmp(のchar *のSRC、 char型* DST) { INT NNUM = 0。 一方、(!(NNUM = *(のchar *)SRC - *(のchar *)DST)&& * DST) //取得関数の戻り値 SRC ++、++ DST; IF(NNUM <0) { NNUM = -1; } そうIF(NNUM> 0) { NNUM = 1; } ; NNUMを返す } int型のmain() { 購入チャーstr1が[] =」利用可能! "; のchar str2には、[] ="「購入可能!; _asm PUSHAD //は、関数ポインタを取得 int型(* WINAPI pMyStrCmp)(SRCチャー*、CHAR * DST); pMyStrCmp = MyStrCmp; //仮想命令データ変更 *を(DWORD *)(bVmData + 1)=(DWORD)STR1; *(DWORD *)(bVmData + 5 + 1)=(DWORD)STR2;。。 。*(DWORD *)(bVmData + 10 + 1)=(DWORD)pMyStrCmp; / /ダミー命令実行 VM(bVmData)を、 { MOV nRet、EAX INT nRet = 0; _asmの popad } のprintf( "%dの"、nRet)。 0を返します。 }