Jump to content
Nytro

[C++] Simple Code Virtualization (Virtual Machine / Emulator)

Recommended Posts

Posted

[C++] Simple Code Virtualization (Virtual Machine / Emulator)

Original code by: abhe

Ported by: steve10120 at ic0de.org

Thanks to Edi for help with inst_table

Original: ic0de.org

/* Original code by: abhe
Ported by: steve10120@ic0de.org
Thanks to Edi for help with inst_table
*/

#include <Windows.h>
#include <iostream>

int const REGISTER_EAX = 0;
int const REGISTER_ECX = 1;
int const REGISTER_EDX = 2;
int const REGISTER_EBX = 3;
int const REGISTER_ESP = 4;
int const REGISTER_EBP = 5;
int const REGISTER_ESI = 6;
int const REGISTER_EDI = 7;
int const REGISTER_NOP = 8;

typedef struct _VMCONTEXT
{
DWORD EIP;
DWORD Reg[8];
} VMCONTEXT, *PVMCONTEXT;

typedef void (VM_FUNCTION_CALL)(PVMCONTEXT c);

typedef struct _INST
{
VM_FUNCTION_CALL* FunctionCall;
} INST, *PINST;

void AddCode(PVMCONTEXT c, BYTE n)
{
c->EIP += n;
}

void VRetn(PVMCONTEXT c)
{
}

void VJmp(PVMCONTEXT c)
{
DWORD imm32;

c->EIP++;
imm32 = *(PDWORD)c->EIP;
c->EIP = imm32;
}

void VPUSHImm(PVMCONTEXT c)
{
DWORD imm32;

c->EIP++;
imm32 = *(PDWORD)c->EIP;
AddCode(c, 4);
*(PDWORD)c->Reg[REGISTER_ESP] = imm32;
c->Reg[REGISTER_ESP] += 4;
}

void VPUSHReg(PVMCONTEXT c)
{
BYTE regflag;
DWORD imm32;

c->EIP++;
regflag = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( regflag < 8 )
{
imm32 = c->Reg[regflag];
*(PDWORD)c->Reg[REGISTER_ESP] = imm32;
c->Reg[REGISTER_ESP] += 4;
}
}

void VPUSHMem(PVMCONTEXT c)
{
DWORD mem32;
DWORD imm32;

c->EIP++;
mem32 = *(PDWORD)c->EIP;
imm32 = *(PDWORD)mem32;
AddCode(c, 4);
*(PDWORD)c->Reg[REGISTER_ESP] = imm32;
c->Reg[REGISTER_ESP] += 4;
}

void VPOPReg(PVMCONTEXT c)
{
BYTE regflag;
DWORD imm32;

c->EIP++;
regflag = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( regflag < 8 )
{
imm32 = *(PDWORD)c->Reg[REGISTER_ESP];
c->Reg[REGISTER_ESP] -= 4;
c->Reg[regflag] = imm32;
}
}

void VPOPMem(PVMCONTEXT c)
{
DWORD imm32;
DWORD mem32;

imm32 = *(PDWORD)c->Reg[REGISTER_ESP];
c->Reg[REGISTER_ESP] -= 4;
mem32 = *(PDWORD)c->EIP;
AddCode(c, 4);
*(PDWORD)mem32 = imm32;
}

void VMovRegReg(PVMCONTEXT c)
{
BYTE DestReg, SrcReg;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
SrcReg = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
c->Reg[DestReg] = c->Reg[SrcReg];
}

void VMovRegImm(PVMCONTEXT c)
{
BYTE DestReg;
DWORD imm32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
imm32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if ( DestReg < 8 )
c->Reg[DestReg] = imm32;
}

void VMovRegMem(PVMCONTEXT c)
{
BYTE DestReg;
DWORD mem32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
mem32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if ( DestReg < 8 )
c->Reg[DestReg] = *(PDWORD)mem32;
}

void VADDRegReg(PVMCONTEXT c)
{
BYTE DestReg, SrcReg;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
SrcReg = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
c->Reg[DestReg] += c->Reg[SrcReg];
}

void VADDRegImm(PVMCONTEXT c)
{
BYTE DestReg;
DWORD imm32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
imm32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if ( DestReg < 8 )
c->Reg[DestReg] += imm32;
}

void VADDRegMem(PVMCONTEXT c)
{
BYTE DestReg;
DWORD mem32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
mem32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if ( DestReg < 8 )
c->Reg[DestReg] += *(PDWORD)mem32;
}

void VSUBRegReg(PVMCONTEXT c)
{
BYTE DestReg, SrcReg;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
SrcReg = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
c->Reg[DestReg] -= c->Reg[SrcReg];
}

void VSUBRegImm(PVMCONTEXT c)
{
BYTE DestReg;
DWORD imm32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
imm32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if ( DestReg < 8 )
c->Reg[DestReg] -= imm32;
}

void VSUBRegMem(PVMCONTEXT c)
{
BYTE DestReg;
DWORD mem32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
mem32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if ( DestReg < 8 )
c->Reg[DestReg] -= *(PDWORD)mem32;
}

void VMulEaxReg(PVMCONTEXT c)
{
BYTE SrcReg;

c->EIP++;
SrcReg = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( SrcReg < 8 )
c->Reg[REGISTER_EAX] *= c->Reg[SrcReg];
}

void VDivEaxReg(PVMCONTEXT c)
{
BYTE SrcReg;

c->EIP++;
SrcReg = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( SrcReg < 8 )
{
c->Reg[REGISTER_EAX] /= c->Reg[SrcReg];
c->Reg[REGISTER_EAX] %= c->Reg[SrcReg];
}
}

void VANDRegReg(PVMCONTEXT c)
{
BYTE DestReg, SrcReg;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
SrcReg = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
c->Reg[DestReg] &= c->Reg[SrcReg];
}

void VAndRegImm(PVMCONTEXT c)
{
BYTE DestReg;
DWORD imm32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
imm32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if (DestReg < 8 )
c->Reg[DestReg] &= imm32;
}

void VAndRegMem(PVMCONTEXT c)
{
BYTE DestReg;
DWORD mem32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
mem32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if (DestReg < 8 )
c->Reg[DestReg] &= *(PDWORD)mem32;
}

void VORRegReg(PVMCONTEXT c)
{
BYTE DestReg, SrcReg;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
SrcReg = *(PBYTE)c->EIP;
AddCode(c, 1);
if ( ( DestReg < 8 ) & ( SrcReg < 8 ) )
c->Reg[DestReg] |= c->Reg[SrcReg];
}

void VORRegImm(PVMCONTEXT c)
{
BYTE DestReg;
DWORD imm32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
imm32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if (DestReg < 8 )
c->Reg[DestReg] |= imm32;
}

void VORRegMem(PVMCONTEXT c)
{
BYTE DestReg;
DWORD mem32;

c->EIP++;
DestReg = *(PBYTE)c->EIP;
AddCode(c, 1);
mem32 = *(PDWORD)c->EIP;
AddCode(c, 4);
if (DestReg < 8 )
c->Reg[DestReg] |= *(PDWORD)mem32;
}

const INST inst_table[23] = {{VRetn},{VJmp},{VPUSHImm},{VPUSHReg},{VPUSHMem},{VPOPReg},{VPOPMem},{VMovRegReg},
{VMovRegImm},{VMovRegMem},{VADDRegReg},{VADDRegImm},{VADDRegMem},{VSUBRegReg},{VSUBRegImm},{VSUBRegMem},
{VMulEaxReg},{VDivEaxReg},{VANDRegReg},{VAndRegImm},{VORRegReg},{VORRegImm},{VORRegMem}};

VMCONTEXT ExecuteVM(LPVOID Code, DWORD Size)
{
INST Ins;
BYTE Op;
LPVOID Stack;
VMCONTEXT Context;

for (Op = 0; Op < 7; Op++)
Context.Reg[Op] = 0;

Stack = GlobalAlloc(GMEM_FIXED, 1024 * 1024 * 2);
if (Stack)
{
Context.Reg[REGISTER_ESP] = (DWORD)Stack;
Context.EIP = (DWORD)Code;
while (Context.EIP <= ((DWORD)Code + Size - 1))
{
Op = *(PBYTE)Context.EIP;
Ins = inst_table[Op];
Ins.FunctionCall(&Context);
if (Op == 0)
break;
}
GlobalFree(Stack);
}
return Context;
}

int main(void)
{
BYTE Code[13] = {0x08,0x00,0x05,0x00,0x00,0x00, // mov eax, 5
0x0B,0x00,0x05,0x00,0x00,0x00, // add eax, 5
0x00}; // retn

VMCONTEXT Context = ExecuteVM(&Code, sizeof(Code));

std::cout << Context.Reg[REGISTER_EAX] << std::endl;

return 0;
}

Sursa: ic0de.org

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...