Penulis Topik: [Delphi] Simple Code Virtualization (Virtual Machine / Emulator)  (Dibaca 8110 kali)

Offline meong

  • Pro100
  • ****
  • Tulisan: 121
  • Reputation: 203
    • Lihat Profil
[Delphi] Simple Code Virtualization (Virtual Machine / Emulator)
« pada: September 18, 2011, 03:23:23 AM »
Code Virtualization apayah ? masa gak tau sih :(.. Ituloh teknologi digunakan packer (program proteksi) agar kode kita sulit dianalisa. Konsepnya code virtualization simple sih, cukup translate code ke virtualmachine code dan mengeksekusinya pada virtualmachine, heheh simple kan ? Tentu saja tidak karena virtualmachine sendiri itu saya tidak tau bentuk-nya bagaimana :p.

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

Kode: [Pilih]
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.


silahkan comment kalau ada yang kurang dimengerti or ada saran buat kodenya.. kan lumayan tuh kalau di diskusiin ;)..

directlink : http://cybercoding.wordpress.com/2011/09/17/delphi-simple-code-virtualization-virtual-machine-emulator/