Added some x86 emu (just a few instructions) and dissambly using Zydis

This commit is contained in:
ptitSeb 2018-12-16 21:03:20 +01:00
parent 9cce7008cf
commit 9690d9cdf6
16 changed files with 7348 additions and 64 deletions

View File

@ -34,6 +34,9 @@ SET(ELFLOADER_SRC
src/elfload_dump.c
src/stack.c
src/x86emu.c
src/x86run.c
src/x86primop.c
src/x86trace.c
)
add_executable(box86 ${ELFLOADER_SRC})

View File

@ -5,6 +5,7 @@
#include "box86context.h"
#include "elfloader.h"
#include "debug.h"
#include "x86trace.h"
box86context_t *NewBox86Context(int argc)
{
@ -40,6 +41,8 @@ void FreeBox86Context(box86context_t** context)
FreeCollection(&(*context)->box86_path);
FreeCollection(&(*context)->box86_ld_lib);
if((*context)->zydis)
DeleteX86Trace(*context);
for(int i=0; i<(*context)->argc; ++i)
free((*context)->argv[i]);

View File

@ -6,11 +6,15 @@
typedef struct elfheader_s elfheader_t;
typedef struct x86emu_s x86emu_t;
typedef struct zydis_s zydis_t;
typedef struct box86context_s {
path_collection_t box86_path; // PATH env. variable
path_collection_t box86_ld_lib; // LD_LIBRARY_PATH env. variable
int x86trace;
zydis_t *zydis; // dlopen the zydis dissasembler
int argc;
char** argv;

View File

@ -9,6 +9,7 @@
#include "elfloader.h"
#include "stack.h"
#include "x86emu.h"
#include "x86trace.h"
int box86_debug = DEBUG_INFO;//DEBUG_NONE;
@ -80,6 +81,19 @@ int main(int argc, const char **argv) {
// check BOX86_PATH and load it
LoadEnvPath(&context->box86_path, ".:bin", "BOX86_PATH");
p = getenv("BOX86_TRACE");
if(p) {
if (strcmp(p, "1")==0)
context->x86trace = 1;
}
if(context->x86trace) {
printf_debug(DEBUG_INFO, "Initializing Zydis lib\n", p);
if(InitX86Trace(context)) {
printf_debug(DEBUG_INFO, "Zydis init failed, no x86 trace activated\n", p);
context->x86trace = 0;
}
}
// lets build argc/argv stuff
p=argv[1];
printf_debug(DEBUG_INFO, "Looking for %s\n", p);
@ -153,15 +167,19 @@ int main(int argc, const char **argv) {
// set entrypoint
context->ep = GetEntryPoint(elf_header);
// init x86 emu
context->emu = NewX86Emu(context->ep, (uintptr_t)context->stack, context->stacksz);
context->emu = NewX86Emu(context, context->ep, (uintptr_t)context->stack, context->stacksz);
SetEAX(context->emu, context->argc);
SetEBX(context->emu, (uint32_t)context->argv);
// emulate!
printf_debug(DEBUG_DEBUG, "Start x86emu on Main\n");
Run(context->emu);
// Get EAX
int ret = GetEAX(context->emu);
printf_debug(DEBUG_DEBUG, "Emulation finished, EAX=%d\n", ret);
// all done, free context
FreeBox86Context(&context);
return 0;
return ret;
}

View File

@ -4,38 +4,42 @@
enum SegNames { es=0,cs,ss,ds,fs,gs};
enum {
REGI_AX, REGI_CX, REGI_DX, REGI_BX,
REGI_SP, REGI_BP, REGI_SI, REGI_DI
_AX, _CX, _DX, _BX,
_SP, _BP, _SI, _DI
};
enum {
_CS, _DS, _SS, _ES, _FS, _GS
};
typedef union {
uint32_t x32;
struct {
int CF:1;
int PF:1;
int AF:1;
int ZF:1;
int SF:1;
int TF:1;
int IF:1;
int DF:1;
int OF:1;
unsigned int IOPL:2;
int NT:1;
int F_CF:1;
int F_PF:1;
int F_AF:1;
int F_ZF:1;
int F_SF:1;
int F_TF:1;
int F_IF:1;
int F_DF:1;
int F_OF:1;
unsigned int F_IOPL:2;
int F_NT:1;
int dummy:1;
int RF:1;
int VM:1;
int AC:1;
int VIF:1;
int VIP:1;
int ID:1;
int F_RF:1;
int F_VM:1;
int F_AC:1;
int F_VIF:1;
int F_VIP:1;
int F_ID:1;
} f;
} x86flags_t;
typedef struct {
/*typedef struct {
uint16_t val[8];
uintptr_t phys[8];
} x86segment_t;
} x86segment_t;*/
typedef union {
uint32_t dword[1];
@ -106,32 +110,29 @@ typedef union {
} sb;
} mmx_regs_t;
typedef struct {
// cpu
reg32_t regs[8],ip;
x86flags_t eflags;
// segments
x86segment_t segs[6];
// fpu
fpu_reg_t fpu[9];
fpu_p_reg_t p_regs[9];
fpu_tag_t tags[9];
uint16_t cw,cw_mask_all;
uint16_t sw;
uint32_t top;
fpu_round_t round;
// mmx
mmx_regs_t mmx[8];
} x86regs_t;
#define R_EIP emu->ip.dword[0]
#define R_EAX emu->regs[_AX].dword[0]
#define R_EBX emu->regs[_BX].dword[0]
#define R_ECX emu->regs[_CX].dword[0]
#define R_EDX emu->regs[_DX].dword[0]
#define R_EDI emu->regs[_DI].dword[0]
#define R_ESI emu->regs[_SI].dword[0]
#define R_ESP emu->regs[_SP].dword[0]
#define R_EBP emu->regs[_BP].dword[0]
#define R_AX emu->regs[_AX].word[0]
#define R_DX emu->regs[_DX].word[0]
#define R_AL emu->regs[_AX].byte[0]
#define R_AH emu->regs[_AX].byte[1]
#define R_CS emu->segs[_CS]
#define R_DS emu->segs[_DS]
#define R_SS emu->segs[_SS]
#define R_ES emu->segs[_ES]
#define R_FS emu->segs[_FS]
#define R_GS emu->segs[_GS]
#define _EIP(reg) reg.ip.dword[0]
#define _EAX(reg) reg.regs[REGI_AX].dword[0]
#define _EBX(reg) reg.regs[REGI_BX].dword[0]
#define _ECX(reg) reg.regs[REGI_CX].dword[0]
#define _EDX(reg) reg.regs[REGI_DX].dword[0]
#define _EDI(reg) reg.regs[REGI_DI].dword[0]
#define _ESI(reg) reg.regs[REGI_SI].dword[0]
#define _ESP(reg) reg.regs[REGI_SP].dword[0]
#define _EBP(reg) reg.regs[REGI_BP].dword[0]
#define ACCESS_FLAG(F) emu->eflags.f.F
#define SET_FLAG(F) emu->eflags.f.F = 1
#define CLEAR_FLAG(F) emu->eflags.f.F = 0
#define CONDITIONAL_SET_FLAG(COND, F) emu->eflags.f.F = (COND)?1:0
#endif //__REGS_H_

View File

@ -26,12 +26,25 @@ int CalcStackSize(box86context_t *context)
uint32_t Pop(x86emu_t *emu)
{
uint32_t* st = ((uint32_t*)_ESP(emu->regs));
_ESP(emu->regs) += 4;
uint32_t* st = ((uint32_t*)(R_ESP));
R_ESP += 4;
}
void Push(x86emu_t *emu, uint32_t v)
{
_ESP(emu->regs) -= 4;
*((uint32_t*)_ESP(emu->regs)) = v;
R_ESP -= 4;
*((uint32_t*)R_ESP) = v;
}
uint16_t Pop16(x86emu_t *emu)
{
uint16_t* st = ((uint16_t*)(R_ESP));
R_ESP += 2;
}
void Push16(x86emu_t *emu, uint16_t v)
{
R_ESP -= 2;
*((uint16_t*)R_ESP) = v;
}

View File

@ -10,5 +10,7 @@ int CalcStackSize(box86context_t *context);
uint32_t Pop(x86emu_t *emu);
void Push(x86emu_t *emu, uint32_t v);
uint16_t Pop16(x86emu_t *emu);
void Push16(x86emu_t *emu, uint16_t v);
#endif //__STACK_H_

View File

@ -1,24 +1,38 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "stack.h"
#include "x86emu.h"
#include "x86emu_private.h"
#include "box86context.h"
#include "x86trace.h"
static uint8_t EndEmuMarker[] = {0xcc, 'S', 'C', 0, 0, 0, 0};
x86emu_t *NewX86Emu(uintptr_t start, uintptr_t stack, int stacksize)
x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize)
{
printf_debug(DEBUG_DEBUG, "Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", start, stack, stacksize);
x86emu_t *emu = (x86emu_t*)calloc(1, sizeof(x86emu_t));
// setup cpu helpers
for (int i=0; i<8; ++i)
emu->sbiidx[i] = &emu->regs[i];
emu->sbiidx[4] = &emu->zero;
// set default value
_EIP(emu->regs) = start;
_ESP(emu->regs) = stack + stacksize - 4;
R_EIP = start;
R_ESP = stack + stacksize;
// push "end emu" marker address
Push(emu, (uint32_t)&EndEmuMarker);
// if trace is activated
if(context->x86trace) {
emu->dec = InitX86TraceDecoder(context);
if(!emu->dec)
printf_debug(DEBUG_INFO, "Failed to initialize Zydis decoder and formater, no trace activated\n");
}
return emu;
}
@ -28,28 +42,42 @@ void FreeX86Emu(x86emu_t **x86emu)
if(!x86emu)
return;
printf_debug(DEBUG_DEBUG, "Free a X86 Emu (%p)\n", *x86emu);
if((*x86emu)->dec)
DeleteX86TraceDecoder(&(*x86emu)->dec);
free(*x86emu);
*x86emu = NULL;
}
uint32_t GetEAX(x86emu_t *emu)
{
return _EAX(emu->regs);
return R_EAX;
}
void SetEAX(x86emu_t *emu, uint32_t v)
{
_EAX(emu->regs) = v;
R_EAX = v;
}
void SetEBX(x86emu_t *emu, uint32_t v)
{
_EBX(emu->regs) = v;
R_EBX = v;
}
void SetECX(x86emu_t *emu, uint32_t v)
{
_ECX(emu->regs) = v;
R_ECX = v;
}
void SetEDX(x86emu_t *emu, uint32_t v)
{
_EDX(emu->regs) = v;
R_EDX = v;
}
const char* DumpCPURegs(x86emu_t* emu)
{
static char buff[500];
char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
char tmp[50];
sprintf(buff, "EIP=%08X ", R_EIP);
for (int i=_AX; i<=_DI; ++i) {
sprintf(tmp, "%s=%08X ", regname[i], emu->regs[i].dword[0]);
strcat(buff, tmp);
}
return buff;
}

View File

@ -2,8 +2,9 @@
#define __X86EMU_H_
typedef struct x86emu_s x86emu_t;
typedef struct box86context_s box86context_t;
x86emu_t *NewX86Emu(uintptr_t start, uintptr_t stack, int stacksize);
x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize);
void FreeX86Emu(x86emu_t **x86emu);
uint32_t GetEAX(x86emu_t *emu);
@ -11,5 +12,8 @@ void SetEAX(x86emu_t *emu, uint32_t v);
void SetEBX(x86emu_t *emu, uint32_t v);
void SetECX(x86emu_t *emu, uint32_t v);
void SetEDX(x86emu_t *emu, uint32_t v);
const char* DumpCPURegs(x86emu_t* emu);
int Run(x86emu_t *emu); // 0 if run was successfull, 1 if error in x86 world
#endif //__X86EMU_H_

View File

@ -3,8 +3,34 @@
#include "regs.h"
typedef struct zydis_dec_s zydis_dec_t;
typedef struct x86emu_s {
x86regs_t regs;
// cpu
reg32_t regs[8],ip;
x86flags_t eflags;
// segments
uint32_t segs[6]; // only 32bits value?
// fpu
fpu_reg_t fpu[9];
fpu_p_reg_t p_regs[9];
fpu_tag_t tags[9];
uint16_t cw,cw_mask_all;
uint16_t sw;
uint32_t top;
fpu_round_t round;
// mmx
mmx_regs_t mmx[8];
// cpu helpers
reg32_t zero;
reg32_t *sbiidx[8];
// emu control
int quit;
int divby0;
// trace
zydis_dec_t *dec;
} x86emu_t;
#define INTR_RAISE_DIV0(emu) {emu->divby0 = 1; emu->quit=1;}
#endif //__X86EMU_PRIVATE_H_

2324
src/x86primop.c Executable file

File diff suppressed because it is too large Load Diff

99
src/x86primop.h Executable file
View File

@ -0,0 +1,99 @@
#ifndef __X86PRIMOP_H_
#define __X86PRIMOP_H_
typedef struct x86emu_s x86emu_t;
// Based on libx86emu
uint16_t aaa16 (x86emu_t *emu, uint16_t d);
uint16_t aas16 (x86emu_t *emu, uint16_t d);
uint16_t aad16 (x86emu_t *emu, uint16_t d, uint8_t base);
uint16_t aam16 (x86emu_t *emu, uint8_t d, uint8_t base);
uint8_t adc8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t adc16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t adc32 (x86emu_t *emu, uint32_t d, uint32_t s);
uint8_t add8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t add16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t add32 (x86emu_t *emu, uint32_t d, uint32_t s);
uint8_t and8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t and16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t and32 (x86emu_t *emu, uint32_t d, uint32_t s);
uint8_t cmp8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t cmp16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t cmp32 (x86emu_t *emu, uint32_t d, uint32_t s);
uint8_t daa8 (x86emu_t *emu, uint8_t d);
uint8_t das8 (x86emu_t *emu, uint8_t d);
uint8_t dec8 (x86emu_t *emu, uint8_t d);
uint16_t dec16 (x86emu_t *emu, uint16_t d);
uint32_t dec32 (x86emu_t *emu, uint32_t d);
uint8_t inc8 (x86emu_t *emu, uint8_t d);
uint16_t inc16 (x86emu_t *emu, uint16_t d);
uint32_t inc32 (x86emu_t *emu, uint32_t d);
uint8_t or8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t or16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t or32 (x86emu_t *emu, uint32_t d, uint32_t s);
uint8_t neg8 (x86emu_t *emu, uint8_t s);
uint16_t neg16 (x86emu_t *emu, uint16_t s);
uint32_t neg32 (x86emu_t *emu, uint32_t s);
uint8_t not8 (x86emu_t *emu, uint8_t s);
uint16_t not16 (x86emu_t *emu, uint16_t s);
uint32_t not32 (x86emu_t *emu, uint32_t s);
uint8_t rcl8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t rcl16 (x86emu_t *emu, uint16_t d, uint8_t s);
uint32_t rcl32 (x86emu_t *emu, uint32_t d, uint8_t s);
uint8_t rcr8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t rcr16 (x86emu_t *emu, uint16_t d, uint8_t s);
uint32_t rcr32 (x86emu_t *emu, uint32_t d, uint8_t s);
uint8_t rol8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t rol16 (x86emu_t *emu, uint16_t d, uint8_t s);
uint32_t rol32 (x86emu_t *emu, uint32_t d, uint8_t s);
uint8_t ror8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t ror16 (x86emu_t *emu, uint16_t d, uint8_t s);
uint32_t ror32 (x86emu_t *emu, uint32_t d, uint8_t s);
uint8_t shl8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t shl16 (x86emu_t *emu, uint16_t d, uint8_t s);
uint32_t shl32 (x86emu_t *emu, uint32_t d, uint8_t s);
uint8_t shr8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t shr16 (x86emu_t *emu, uint16_t d, uint8_t s);
uint32_t shr32 (x86emu_t *emu, uint32_t d, uint8_t s);
uint8_t sar8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t sar16 (x86emu_t *emu, uint16_t d, uint8_t s);
uint32_t sar32 (x86emu_t *emu, uint32_t d, uint8_t s);
uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s);
uint32_t shld32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s);
uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s);
uint32_t shrd32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s);
uint8_t sbb8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t sbb16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t sbb32 (x86emu_t *emu, uint32_t d, uint32_t s);
uint8_t sub8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t sub16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t sub32 (x86emu_t *emu, uint32_t d, uint32_t s);
void test8 (x86emu_t *emu, uint8_t d, uint8_t s);
void test16 (x86emu_t *emu, uint16_t d, uint16_t s);
void test32 (x86emu_t *emu, uint32_t d, uint32_t s);
uint8_t xor8 (x86emu_t *emu, uint8_t d, uint8_t s);
uint16_t xor16 (x86emu_t *emu, uint16_t d, uint16_t s);
uint32_t xor32 (x86emu_t *emu, uint32_t d, uint32_t s);
void imul8 (x86emu_t *emu, uint8_t s);
void imul16 (x86emu_t *emu, uint16_t s);
void imul32 (x86emu_t *emu, uint32_t s);
void imul32_direct(uint32_t *res_lo, uint32_t* res_hi, uint32_t d, uint32_t s);
void mul8 (x86emu_t *emu, uint8_t s);
void mul16 (x86emu_t *emu, uint16_t s);
void mul32 (x86emu_t *emu, uint32_t s);
void idiv8 (x86emu_t *emu, uint8_t s);
void idiv16 (x86emu_t *emu, uint16_t s);
void idiv32 (x86emu_t *emu, uint32_t s);
void div8 (x86emu_t *emu, uint8_t s);
void div16 (x86emu_t *emu, uint16_t s);
void div32 (x86emu_t *emu, uint32_t s);
//void ins (x86emu_t *emu, int size);
//void outs (x86emu_t *emu, int size);
/*void push16 (x86emu_t *emu, uint16_t w);
void push32 (x86emu_t *emu, uint32_t w);
uint16_t pop16 (x86emu_t *emu);
uint32_t pop32 (x86emu_t *emu);*/
int eval_condition(x86emu_t *emu, unsigned type);
#endif //__X86PRIMOP_H_

291
src/x86run.c Executable file
View File

@ -0,0 +1,291 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "stack.h"
#include "x86emu.h"
#include "x86emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
uint8_t Fetch8(x86emu_t *emu)
{
uint8_t val = *(uint8_t*)R_EIP;
R_EIP++;
return val;
}
int8_t Fetch8s(x86emu_t *emu)
{
int8_t val = *(int8_t*)R_EIP;
R_EIP++;
return val;
}
uint16_t Fetch16(x86emu_t *emu)
{
uint16_t val = *(uint16_t*)R_EIP;
R_EIP+=2;
return val;
}
uint32_t Fetch32(x86emu_t *emu)
{
uint32_t val = *(uint32_t*)R_EIP;
R_EIP+=4;
return val;
}
int32_t Fetch32s(x86emu_t *emu)
{
int32_t val = *(int32_t*)R_EIP;
R_EIP+=4;
return val;
}
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
void GetEb(x86emu_t *emu, reg32_t **op, reg32_t *ea, uint32_t v)
{
uint32_t m = v&0xC7; // filter Eb
if(m>=0xC0) {
int lowhigh = (m&04)>>3;
*op = (reg32_t *)&emu->regs[_AX+(m&0x03)].byte[lowhigh]; //?
return;
} else if (m<=7) {
if(m==0x4) {
uint8_t sib = Fetch8(emu);
uintptr_t base = emu->regs[_AX+(sib&0x7)].dword[0]; // base
if((sib&0x7)==5)
base = Fetch32(emu);
base += emu->sbiidx[(sib>>3)&7]->dword[0] << (sib>>6);
*op = (reg32_t*)base;
return;
} else if (m==0x5) { //disp32
*op = ea;
ea->dword[0] = Fetch32(emu);
return;
}
*op = &emu->regs[_AX+m];
return;
} else if(m>0x40 && m<=0x47) {
uintptr_t base;
if(m==0x44) {
uint8_t sib = Fetch8(emu);
base = emu->regs[_AX+(sib&0x7)].dword[0]; // base
if((sib&0x7)==5)
base = Fetch32(emu);
uint32_t idx = emu->sbiidx[(sib>>3)&7]->dword[0];
/*if(((v>>3)&7)==4)
idx += Fetch8(emu);*/
base += idx << (sib>>6);
} else {
base = emu->regs[_AX+(m&0x7)].dword[0];
}
base+=Fetch8(emu);
*op = (reg32_t*)base;
return;
} else if(m>0x80 && m<0x87) {
uintptr_t base;
if(m==0x84) {
uint8_t sib = Fetch32(emu);
base = emu->regs[_AX+(sib&0x7)].dword[0]; // base
if((sib&0x7)==5)
base = Fetch32(emu);
uint32_t idx = emu->sbiidx[(sib>>3)&7]->dword[0];
/*if(((v>>3)&7)==4)
idx += Fetch32(emu);*/
base += idx << (sib>>6);
} else {
base = emu->regs[_AX+(m&0x7)].dword[0];
}
base+=Fetch32(emu);
*op = (reg32_t*)base;
return;
} else {
ea->word[0] = 0;
*op = ea;
return;
}
}
void GetEd(x86emu_t *emu, reg32_t **op, reg32_t *ea, uint32_t v)
{
uint32_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
*op = &emu->regs[_AX+(m&0x07)];
return;
} else if (m<=7) {
if(m==0x4) {
uint8_t sib = Fetch8(emu);
uintptr_t base = emu->regs[_AX+(sib&0x7)].dword[0]; // base
if((sib&0x7)==5)
base = Fetch32(emu);
base += emu->sbiidx[(sib>>3)&7]->dword[0] << (sib>>6);
*op = (reg32_t*)base;
return;
} else if (m==0x5) { //disp32
*op = ea;
ea->dword[0] = Fetch32(emu);
return;
}
*op = &emu->regs[_AX+m];
return;
} else if(m>0x40 && m<=0x47) {
uintptr_t base;
if(m==0x44) {
uint8_t sib = Fetch8(emu);
base = emu->regs[_AX+(sib&0x7)].dword[0]; // base
if((sib&0x7)==5)
base = Fetch32(emu);
uint32_t idx = emu->sbiidx[(sib>>3)&7]->dword[0];
/*if(((sib>>3)&7)==4)
idx += Fetch8(emu);*/
base += idx << (sib>>6);
} else {
base = emu->regs[_AX+(m&0x7)].dword[0];
}
base+=Fetch8s(emu);
*op = (reg32_t*)base;
return;
} else if(m>0x80 && m<0x87) {
uintptr_t base;
if(m==0x84) {
uint8_t sib = Fetch32(emu);
base = emu->regs[_AX+(sib&0x7)].dword[0]; // base
if((sib&0x7)==5)
base = Fetch32(emu);
uint32_t idx = emu->sbiidx[(sib>>3)&7]->dword[0];
/*if(((sib>>3)&7)==4)
idx += Fetch32(emu);*/
base += idx << (sib>>6);
} else {
base = emu->regs[_AX+(m&0x7)].dword[0];
}
base+=Fetch32s(emu);
*op = (reg32_t*)base;
return;
} else {
ea->word[0] = 0;
*op = ea;
return;
}
}
void GetG(x86emu_t *emu, reg32_t **op, uint32_t v)
{
*op = &emu->regs[_AX+((v&0x38)>>3)];
}
int Run(x86emu_t *emu)
{
emu->quit = 0;
printf("Starting\nCPU Regs: %s\n", DumpCPURegs(emu));
while (!emu->quit)
{
if(emu->dec) {
printf_debug(DEBUG_NONE, "%08p: %s\n", R_EIP, DecodeX86Trace(emu->dec, R_EIP));
}
uint8_t opcode = Fetch8(emu);
uint8_t nextop;
reg32_t *op1, *op2, *op3, *op4;
reg32_t ea1, ea2, ea3, ea4;
uint8_t tmp8u;
int8_t tmp8s;
uint16_t tmp16u;
int16_t tmp16s;
uint32_t tmp32u;
int32_t tmp32s;
uint64_t tmp64u;
int64_t tmp64s;
switch(opcode) {
case 0x00: /* ADD Eb,Gb */
nextop = Fetch8(emu);
GetEb(emu, &op1, &ea2, nextop);
GetG(emu, &op2, nextop);
op2->byte[0] = add8(emu, op1->byte[0], op2->byte[1]);
break;
case 0x83: /* Grpl Ed,Ix */
nextop = Fetch8(emu);
GetEd(emu, &op1, &ea2, nextop);
tmp32s = Fetch8s(emu);
switch((nextop>>3)&7) {
case 0: op1->dword[0] = add32(emu, op1->dword[0], tmp32s); break;
case 1: op1->dword[0] = or32(emu, op1->dword[0], tmp32s); break;
case 2: op1->dword[0] = adc32(emu, op1->dword[0], tmp32s); break;
case 3: op1->dword[0] = sbb32(emu, op1->dword[0], tmp32s); break;
case 4: op1->dword[0] = and32(emu, op1->dword[0], tmp32s); break;
case 5: op1->dword[0] = sub32(emu, op1->dword[0], tmp32s); break;
case 6: op1->dword[0] = xor32(emu, op1->dword[0], tmp32s); break;
case 7: op1->dword[0] = cmp32(emu, op1->dword[0], tmp32s); break;
}
break;
case 0x87: /* XCHG Ed,Gd */
nextop = Fetch8(emu);
GetEd(emu, &op1, &ea2, nextop);
GetG(emu, &op2, nextop);
tmp32u = op1->dword[0];
op1->dword[0] = op2->dword[0];
op2->dword[0] = tmp32u;
break;
case 0x8D: /* LEA Gd, M */
nextop = Fetch8(emu);
GetEd(emu, &op1, &ea2, nextop);
GetG(emu, &op2, nextop);
op2->dword[0] = (uint32_t)&op1->dword[0];
break;
case 0xFF: /* GRP 5 Ed */
nextop = Fetch8(emu);
GetEd(emu, &op1, &ea2, nextop);
switch((nextop>>3)&7) {
case 0: /* INC Ed */
op1->dword[0] = inc32(emu, op1->dword[0]);
break;
case 1: /* DEC Ed */
op1->dword[0] = dec32(emu, op1->dword[0]);
break;
case 2: /* CALL NEAR Ed */
Push(emu, R_EIP);
R_EIP = op1->dword[0];
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
printf("Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
} else {
Push16(emu, R_CS);
Push(emu, R_EIP);
R_EIP = op1->dword[0];
R_CS = (op1+1)->word[0];
}
break;
case 4: /* JMP NEAR Ed */
R_EIP = op1->dword[0];
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
printf("Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
} else {
R_EIP = op1->dword[0];
R_CS = (op1+1)->word[0];
}
break;
case 6: /* Push Ed */
Push(emu, op1->dword[0]);
break;
default:
printf("Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
}
break;
default:
printf("Unimplemented Opcode 0x%02X\n", opcode);
emu->quit=1;
}
printf("CPU Regs: %s\n", DumpCPURegs(emu));
}
}

107
src/x86trace.c Executable file
View File

@ -0,0 +1,107 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "debug.h"
#include "x86trace.h"
#include "box86context.h"
#include "x86zydis.h"
#include "x86emu_private.h"
typedef ZyanStatus (*PFNZydisDecoderInit)(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
ZydisAddressWidth address_width);
typedef ZyanStatus (*PFNZydisFormatterInit)(ZydisFormatter* formatter, ZydisFormatterStyle style);
typedef ZyanStatus (*PFNZydisDecoderDecodeBuffer)(const ZydisDecoder* decoder,
const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction);
typedef ZyanStatus (*PFNZydisFormatterFormatInstruction)(const ZydisFormatter* formatter,
const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length,
ZyanU64 runtime_address);
typedef struct zydis_s {
void* lib;
PFNZydisDecoderInit ZydisDecoderInit;
PFNZydisFormatterInit ZydisFormatterInit;
PFNZydisDecoderDecodeBuffer ZydisDecoderDecodeBuffer;
PFNZydisFormatterFormatInstruction ZydisFormatterFormatInstruction;
} zydis_t;
typedef struct zydis_dec_s {
ZydisDecoder decoder;
ZydisFormatter formatter;
ZydisDecodedInstruction instruction;
PFNZydisDecoderDecodeBuffer ZydisDecoderDecodeBuffer;
PFNZydisFormatterFormatInstruction ZydisFormatterFormatInstruction;
} zydis_dec_t;
int InitX86Trace(box86context_t *context)
{
context->zydis = (zydis_t*)calloc(1, sizeof(zydis_t));
if(!context->zydis)
return 1;
context->zydis->lib = dlopen("libZydis.so", RTLD_LAZY);
if(!context->zydis->lib) {
printf_debug(DEBUG_INFO, "Failed to open libZydis: %s\n", dlerror());
return 1;
}
#define GO(f) context->zydis->f = (PFN##f)dlsym(context->zydis->lib, #f);\
if(!context->zydis->f) {printf_debug(DEBUG_INFO, "Fail to load Zydis function %s\n", #f); dlclose(context->zydis->lib); context->zydis->lib=NULL; return 1;}
GO(ZydisDecoderInit);
GO(ZydisFormatterInit);
GO(ZydisDecoderDecodeBuffer);
GO(ZydisFormatterFormatInstruction);
#undef GO
return 0;
}
void DeleteX86Trace(box86context_t *context)
{
if(!context->zydis)
return;
if(context->zydis->lib)
dlclose(context->zydis->lib);
free(context->zydis);
context->zydis = NULL;
}
zydis_dec_t* InitX86TraceDecoder(box86context_t *context)
{
if(!context->zydis)
return NULL;
zydis_dec_t *dec = (zydis_dec_t*)calloc(1, sizeof(zydis_dec_t));
dec->ZydisDecoderDecodeBuffer = context->zydis->ZydisDecoderDecodeBuffer;
dec->ZydisFormatterFormatInstruction = context->zydis->ZydisFormatterFormatInstruction;
context->zydis->ZydisDecoderInit(&dec->decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_ADDRESS_WIDTH_32);
context->zydis->ZydisFormatterInit(&dec->formatter, ZYDIS_FORMATTER_STYLE_INTEL);
return dec;
}
void DeleteX86TraceDecoder(zydis_dec_t **dec)
{
free(*dec);
*dec = NULL;
}
const char* DecodeX86Trace(zydis_dec_t *dec, uint32_t p)
{
static char buff[256];
if(ZYAN_SUCCESS(dec->ZydisDecoderDecodeBuffer(&dec->decoder, (char*)p, 10,
&dec->instruction))) {
char tmp[255];
buff[0]='\0';
for (int i=0; i<dec->instruction.length; ++i) {
sprintf(tmp, "%02X ", *((unsigned char*)p+i));
strcat(buff, tmp);
}
dec->ZydisFormatterFormatInstruction(&dec->formatter, &dec->instruction, tmp, sizeof(tmp),p);
strcat(buff, tmp);
} else {
sprintf(buff, "Decoder failed @%p", p);
}
return buff;
}

15
src/x86trace.h Executable file
View File

@ -0,0 +1,15 @@
#ifndef __X86TRACE_H_
#define __X86TRACE_H_
#include <stdint.h>
typedef struct box86context_s box86context_t;
typedef struct zydis_dec_s zydis_dec_t;
int InitX86Trace(box86context_t *context);
void DeleteX86Trace(box86context_t *context);
zydis_dec_t* InitX86TraceDecoder(box86context_t *context);
void DeleteX86TraceDecoder(zydis_dec_t **dec);
const char* DecodeX86Trace(zydis_dec_t *dec, uint32_t p);
#endif //__X86TRACE_H_

4346
src/x86zydis.h Executable file

File diff suppressed because it is too large Load Diff