Virtual Machine atau Mesin Virtual atau Emulator adalah mesin yang mengeksekusi code sesuai apa yang dilakukan mesin asli (real Cpu). Dalam Pengeksekusian kode pada real cpu yang dilakukan adalah fetching (mengambil/menarik data misal opcode) dan melakukan eksekusi berdasarkan opcode, nah hall inilah yang dilakukan oleh virtual machine. Ada banyak opcode dan tentu saja korelasinya dengan register, flag dan lain2 (silahkan baca2 buku assembly biar jelasnya).
Tujuan dari pembuatan sample itu karena kurangnya contoh dan penjelasan tentang teknologi virtualmachine or emulator, semoga berguna dan memberikan penjelasan tentang dunia virtualization itu sendiri. Oh ya Code dibawah tentu saja tidak bisa dikatakan virtual machine yang bagus, selain belum mencakup semua execution opcode, cpuflag, jump+, juga belum ada virtualmemory (bagi yang ingin buat emulator). Tapi gak papalah namanya juga sample, iya nda sih ?. Oh ya here u go codenya
Code:
program vmtest;
uses
Windows, sysutils, codesitelogging;
const
// Registers
REGISTER_EAX = 0;
REGISTER_ECX = 1;
REGISTER_EDX = 2;
REGISTER_EBX = 3;
REGISTER_ESP = 4;
REGISTER_EBP = 5;
REGISTER_ESI = 6;
REGISTER_EDI = 7;
REGISTER_NOP = 8;
Type
PVMCONTEXT = ^TVMCONTEXT;
TVMCONTEXT = record
_Eip: DWord;
Reg: array [0..7] of DWord; //EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI
end;
TINST = Record
op: string;
Func: Procedure (c: PVMCONTEXT);
end;
procedure Addcode(c: PVMCONTEXT; n : byte);
begin
inc(c^._eip, n);
end;
Procedure VRetN(c: PVMCONTEXT);
begin
codesite.Send('eax', c^.Reg[REGISTER_EAX]);
end;
Procedure VJmp(c: PVMCONTEXT);
var
imm32 : DWord;
begin
inc(c^._eip);
imm32 := PDword(c^._eip)^;
c^._eip := imm32;
end;
Procedure VPUSHImm(c: PVMCONTEXT);
var
imm32 : DWord;
begin
inc(c^._eip);
imm32 := PDword(c^._eip)^;
Addcode(c,4);
PDword(c^.Reg[REGISTER_ESP])^ := imm32;
inc(c^.Reg[REGISTER_ESP], 4);
end;
Procedure VPUSHReg(c: PVMCONTEXT);
var
regflag: Byte;
imm32 : DWord;
begin
inc(c^._eip);
regflag := pByte(c^._eip)^;
Addcode(c,1);
if( regflag < 8 ) then begin
imm32 := c^.Reg[regflag];
PDword(c^.Reg[REGISTER_ESP])^ := imm32;
inc(c^.Reg[REGISTER_ESP], 4);
end else begin
codesite.senderror('VPUSHReg');
end;
end;
Procedure VPUSHMem(c: PVMCONTEXT);
var
mem32 : DWord;
imm32 : DWord;
begin
inc(c^._eip);
mem32 := PDword(c^._eip)^;
imm32 := PDword(mem32)^;
Addcode(c, 4);
PDword(c^.Reg[REGISTER_ESP])^ := imm32;
inc(c^.Reg[REGISTER_ESP], 4);
end;
Procedure VPOPReg(c: PVMCONTEXT);
var
regflag: Byte;
imm32 : DWord;
begin
inc(c^._eip);
regflag := pByte(c^._eip)^;
Addcode(c,1);
if( regflag < 8 ) then begin
imm32 := PDword(c^.Reg[REGISTER_ESP])^;
dec(c^.Reg[REGISTER_ESP], 4);
c^.Reg[regflag] := imm32;
end;
end;
Procedure VPOPMem(c: PVMCONTEXT);
var
imm32 : DWord;
mem32 : DWord;
begin
imm32 := PDword(c^.Reg[REGISTER_ESP])^;
dec(c^.Reg[REGISTER_ESP], 4);
mem32 := PDword(c^._eip)^;
Addcode(c, 4);
PDword(mem32)^ := imm32;
end;
procedure VMovRegReg(c: PVMCONTEXT);
var
DestReg, SrcReg: Byte;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
SrcReg := pByte(c^._eip)^;
Addcode(c,1);
if( DestReg < 8 ) and ( SrcReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[SrcReg];
end else begin
codesite.senderror('VMovRegReg');
end;
end;
procedure VMovRegImm(c: PVMCONTEXT);
var
DestReg: Byte;
imm32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
imm32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := imm32;
end else begin
codesite.senderror('VMovRegImm');
end;
end;
procedure VMovRegMem(c: PVMCONTEXT);
var
DestReg: Byte;
mem32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
mem32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := PDword(mem32)^;
end else begin
codesite.senderror('VMovRegMem');
end;
end;
procedure VADDRegReg(c: PVMCONTEXT);
var
DestReg, SrcReg: Byte;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
SrcReg := pByte(c^._eip)^;
Addcode(c,1);
if( DestReg < 8 ) and ( SrcReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] + c^.Reg[SrcReg];
end else begin
codesite.senderror('VADDRegReg');
end;
end;
procedure VADDRegImm(c: PVMCONTEXT);
var
DestReg: Byte;
imm32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
imm32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] + imm32;
end else begin
codesite.senderror('VADDRegImm');
end;
end;
procedure VADDRegMem(c: PVMCONTEXT);
var
DestReg: Byte;
mem32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
mem32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] + PDword(mem32)^;
end else begin
codesite.senderror('VADDRegMem');
end;
end;
procedure VSUBRegReg(c: PVMCONTEXT);
var
DestReg, SrcReg: Byte;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
SrcReg := pByte(c^._eip)^;
Addcode(c,1);
if( DestReg < 8 ) and ( SrcReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] - c^.Reg[SrcReg];
end else begin
codesite.senderror('VSUBRegReg');
end;
end;
procedure VSUBRegImm(c: PVMCONTEXT);
var
DestReg: Byte;
imm32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
imm32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] - imm32;
end else begin
codesite.senderror('VSUBRegImm');
end;
end;
procedure VSUBRegMem(c: PVMCONTEXT);
var
DestReg: Byte;
mem32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
mem32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] - PDword(mem32)^;
end else begin
codesite.senderror('VSUBRegMem');
end;
end;
procedure VMulEaxReg(c: PVMCONTEXT);
var
SrcReg: Byte;
begin
inc(c^._eip);
SrcReg := pByte(c^._eip)^;
Addcode(c,1);
if ( SrcReg < 8 ) then begin
c^.Reg[REGISTER_EAX] := c^.Reg[REGISTER_EAX] - c^.Reg[SrcReg];
end else begin
codesite.senderror('VMulEaxReg');
end;
end;
procedure VDivEaxReg(c: PVMCONTEXT);
var
SrcReg: Byte;
begin
inc(c^._eip);
SrcReg := pByte(c^._eip)^;
Addcode(c,1);
if ( SrcReg < 8 ) then begin
c^.Reg[REGISTER_EAX] := c^.Reg[REGISTER_EAX] div c^.Reg[SrcReg];
c^.Reg[REGISTER_EDX] := c^.Reg[REGISTER_EAX] mod c^.Reg[SrcReg]
end else begin
codesite.senderror('VDivEaxReg');
end;
end;
procedure VAndRegReg(c: PVMCONTEXT);
var
DestReg, SrcReg: Byte;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
SrcReg := pByte(c^._eip)^;
Addcode(c,1);
if( DestReg < 8 ) and ( SrcReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] and c^.Reg[SrcReg];
end else begin
codesite.senderror('VAndRegReg');
end;
end;
procedure VAndRegImm(c: PVMCONTEXT);
var
DestReg: Byte;
imm32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
imm32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] And imm32;
end else begin
codesite.senderror('VAndRegImm');
end;
end;
procedure VAndRegMem(c: PVMCONTEXT);
var
DestReg: Byte;
mem32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
mem32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] And PDword(mem32)^;
end else begin
codesite.senderror('VAndRegMem');
end;
end;
procedure VORRegReg(c: PVMCONTEXT);
var
DestReg, SrcReg: Byte;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
SrcReg := pByte(c^._eip)^;
Addcode(c,1);
if( DestReg < 8 ) and ( SrcReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] or c^.Reg[SrcReg];
end else begin
codesite.senderror('VORRegReg');
end;
end;
procedure VORRegImm(c: PVMCONTEXT);
var
DestReg: Byte;
imm32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
imm32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] Or imm32;
end else begin
codesite.senderror('VORRegImm');
end;
end;
procedure VORRegMem(c: PVMCONTEXT);
var
DestReg: Byte;
mem32: DWord;
begin
inc(c^._eip);
DestReg := pByte(c^._eip)^;
Addcode(c,1);
mem32 := PDword(c^._eip)^;
Addcode(c,4);
if( DestReg < 8 ) then begin
c^.Reg[DestReg] := c^.Reg[DestReg] or PDword(mem32)^;
end else begin
codesite.senderror('VORRegMem');
end;
end;
const
inst_table1 : array [0..23] of TINST =(
{00}(op: 'Retn'; Func: VRetN),
{01}(op: 'Jump'; Func: VJmp),
{02}(op: 'PUSHIm'; Func: VPUSHImm),
{03}(op: 'PUSHReg'; Func: VPUSHReg),
{04}(op: 'PUSHMem'; Func: VPUSHMem),
{05}(op: 'POPReg'; Func: VPOPReg),
{06}(op: 'POPMem'; Func: VPOPMem),
{07}(op: 'MovRegReg'; Func: VMovRegReg),
{08}(op: 'MovRegImm'; Func: VMovRegImm),
{09}(op: 'MovRegMem'; Func: VMovRegMem),
{10}(op: 'ADDRegReg'; Func: VADDRegReg),
{11}(op: 'ADDRegImm'; Func: VADDRegImm),
{12}(op: 'ADDRegMem'; Func: VADDRegMem),
{13}(op: 'SUBRegReg'; Func: VSUBRegReg),
{14}(op: 'SUBRegImm'; Func: VSUBRegImm),
{15}(op: 'SUBRegMem'; Func: VSUBRegMem),
{16}(op: 'MulEaxReg'; Func: VMulEaxReg),
{17}(op: 'DivEaxReg'; Func: VDivEaxReg),
{18}(op: 'ANDRegReg'; Func: VANDRegReg),
{19}(op: 'ANDRegImm'; Func: VANDRegImm),
{20}(op: 'ANDRegMem'; Func: VANDRegMem),
{21}(op: 'ORRegReg'; Func: VORRegReg),
{22}(op: 'ORRegImm'; Func: VORRegImm),
{23}(op: 'ORRegMem'; Func: VORRegMem)
);
Function ExecuteVM(Code: Pointer; Size: DWord):TVMCONTEXT;
var
Ins: TINST;
Op: Byte;
Stack: Pointer;
begin
with result do begin
{Setup Machine}
for op:= 0 to 7 do Reg[op] := 0;
GetMem(Stack, 1024*1024*2);
Reg[REGISTER_ESP] := DWord(Stack);
_eip := DWord(Code);
{Execute Cycle}
while (_eip <= (DWord(Code)+Size) -1 ) do begin
Op := pByte(_eip)^;
Ins := inst_table1[Op];
codesite.Send('%s / %s', [inttohex(Op, 2), Ins.op]);
Ins.Func(@result);
if (Op = 0) then exit;
end;
FreeMem(Stack, 1024*1024*2);
end;
end;
const
Temp:Array [0..12] of byte =(
$08,$00,$05,$00,$00,$00, //mov eax, 5
$0B,$00,$05,$00,$00,$00, //add eax, 5
$00 //ret
);
begin
ExecuteVM(@temp[0], sizeof(temp));
end.
Tidak Ada Komentar Pada Artikel » [Delphi] Simple Code Virtualization (Virtual Machine / Emulator)
Post a Comment