V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB,
V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP,
V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS,
- V3_OP_SETZ, V3_OP_MOVS, V3_OP_MOVZX, V3_OP_MOVSX} v3_op_type_t;
+ V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX} v3_op_type_t;
typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t;
+#define MAKE_1OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \
+ addr_t * src, \
+ addr_t * ecx, addr_t * flags) { \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushfq; " \
+ "pushq %4; " \
+ "popfq; " \
+ "rep; " \
+ #iname"q; " \
+ "pushfq; " \
+ "popq %0; " \
+ "popfq; " \
+ : "=q"(*flags) \
+ : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags) \
+ ); \
+ \
+ *flags |= flags_rsvd; \
+ }
+
+
+#define MAKE_1OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \
+ addr_t * src, \
+ addr_t * ecx, addr_t * flags) { \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %4; " \
+ "popf; " \
+ "rep; " \
+ #iname"l; " \
+ "pushf; " \
+ "pop %0; " \
+ "popf; " \
+ : "=q"(*flags) \
+ : "D"(*(uint32_t *)dst),"a"(*(uint32_t *)src),"c"(*(uint32_t *)ecx),"q"(*flags) \
+ ); \
+ \
+ *flags |= flags_rsvd; \
+ }
+
+#define MAKE_1OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \
+ addr_t * src, \
+ addr_t * ecx, addr_t * flags) { \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %4; " \
+ "popf; " \
+ "rep; " \
+ #iname"w; " \
+ "pushf; " \
+ "pop %0; " \
+ "popf; " \
+ : "=q"(*flags) \
+ : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags) \
+ ); \
+ *flags |= flags_rsvd; \
+ }
+
+
+
+#define MAKE_1OP_8STR_INST(iname) static inline void iname##8(addr_t * dst, \
+ addr_t * src, \
+ addr_t * ecx, addr_t * flags) { \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %4; " \
+ "popf; " \
+ "rep; " \
+ #iname"b; " \
+ "pushf; " \
+ "pop %0; " \
+ "popf; " \
+ : "=q"(*flags) \
+ : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags) \
+ ); \
+ *flags |= flags_rsvd; \
+ }
+
+
+
+
#define MAKE_2OP_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \
uint64_t tmp_dst = *dst, tmp_src = *src; \
\
+#define MAKE_2OUT_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \
+ asm volatile ( \
+ #iname"q %1, %0; " \
+ : "=q"(*(uint64_t *)dst), "=q"(*(uint64_t *)src) \
+ : "0"(*(uint64_t *)dst), "1"(*(uint64_t *)src) \
+ ); \
+ }
+
+#define MAKE_2OUT_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \
+ asm volatile ( \
+ #iname"l %1, %0; " \
+ : "=q"(*(uint32_t *)dst), "=q"(*(uint32_t *)src) \
+ : "0"(*(uint32_t *)dst), "1"(*(uint32_t *)src) \
+ ); \
+ }
+
+#define MAKE_2OUT_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \
+ asm volatile ( \
+ #iname"w %1, %0; " \
+ : "=q"(*(uint16_t *)dst), "=q"(*(uint16_t *)src) \
+ : "0"(*(uint16_t *)dst), "1"(*(uint16_t *)src) \
+ ); \
+ }
+
+#define MAKE_2OUT_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \
+ asm volatile ( \
+ #iname"b %1, %0; " \
+ : "=q"(*(uint8_t *)dst), "=q"(*(uint8_t *)src) \
+ : "0"(*(uint8_t *)dst), "1"(*(uint8_t *)src) \
+ ); \
+ }
+
+
+
+
/****************************/
MAKE_2OP_8EXT_INST(movzx);
MAKE_2OP_8EXT_INST(movsx);
-MAKE_2OP_8_INST(xchg);
+MAKE_2OUT_8_INST(xchg);
MAKE_2OP_8STR_INST(movs);
+MAKE_1OP_8STR_INST(stos);
+MAKE_1OP_8STR_INST(scas);
/****************************/
MAKE_2OP_16_INST(mov);
MAKE_2OP_16EXT_INST(movzx);
MAKE_2OP_16EXT_INST(movsx);
-MAKE_2OP_16_INST(xchg);
+MAKE_2OUT_16_INST(xchg);
MAKE_2OP_16STR_INST(movs);
+MAKE_1OP_16STR_INST(stos);
+MAKE_1OP_16STR_INST(scas);
+
/****************************/
/* 32 Bit instruction forms */
MAKE_2OP_32_INST(mov);
-MAKE_2OP_32_INST(xchg);
+MAKE_2OUT_32_INST(xchg);
MAKE_2OP_32STR_INST(movs);
+MAKE_1OP_32STR_INST(stos);
+MAKE_1OP_32STR_INST(scas);
+
+
#ifdef __V3_64BIT__
MAKE_2OP_64_INST(mov);
+MAKE_2OP_64STR_INST(movs);
+MAKE_1OP_64STR_INST(stos);
+MAKE_1OP_64STR_INST(scas);
-
-MAKE_2OP_64_INST(xchg);
+MAKE_2OUT_64_INST(xchg);
#endif
#define ROMBIOS_START 0x000f0000
// VGA frame buffer
- if (1) {
+ if (0) {
if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
PrintError("Could not map VGA framebuffer\n");
return -1;
addr_t tmp_rcx = 0;
addr_t src_addr = 0;
- if (dec_instr->op_type == V3_OP_MOVS) {
- // PrintError("MOVS emulation\n");
-
- if (dec_instr->dst_operand.operand != write_gva) {
- PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
- (void *)dec_instr->dst_operand.operand, (void *)write_gva);
- return -1;
- }
-
- emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
- dec_instr->str_op_length :
- (0x1000 - PAGE_OFFSET_4KB(write_gva)));
- /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
+ if (dec_instr->dst_operand.operand != write_gva) {
+ PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
+ (void *)dec_instr->dst_operand.operand, (void *)write_gva);
+ return -1;
+ }
+
+ emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
+ dec_instr->str_op_length :
+ (0x1000 - PAGE_OFFSET_4KB(write_gva)));
+
+ /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
+ tmp_rcx = emulation_length;
+
- PrintDebug("STR_OP_LEN: %d, Page Len: %d\n",
- (uint_t)dec_instr->str_op_length,
- (uint_t)(0x1000 - PAGE_OFFSET_4KB(write_gva)));
- PrintDebug("Emulation length: %d\n", emulation_length);
- tmp_rcx = emulation_length;
-
+ if (dec_instr->op_type == V3_OP_MOVS) {
- // figure out addresses here....
- if (info->mem_mode == PHYSICAL_MEM) {
- if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
- PrintError("Could not translate write Source (Physical) to host VA\n");
- return -1;
- }
- } else {
- if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
- PrintError("Could not translate write Source (Virtual) to host VA\n");
- return -1;
- }
+ // figure out addresses here....
+ if (info->mem_mode == PHYSICAL_MEM) {
+ if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
+ PrintError("Could not translate write Source (Physical) to host VA\n");
+ return -1;
}
-
-
- PrintDebug("Dst Operand: %p (size=%d), Src Operand: %p\n",
- (void *)dec_instr->dst_operand.operand,
- dec_instr->dst_operand.size,
- (void *)dec_instr->src_operand.operand);
- PrintDebug("Dst Addr: %p, Src Addr: %p\n", (void *)dst_addr, (void *)src_addr);
-
- //return -1;
-
-
-
-
+ } else {
+ if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
+ PrintError("Could not translate write Source (Virtual) to host VA\n");
+ return -1;
+ }
+ }
if (dec_instr->dst_operand.size == 1) {
movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
} else if (dec_instr->dst_operand.size == 2) {
movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
} else if (dec_instr->dst_operand.size == 4) {
- movs32((addr_t*)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+ movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+#ifdef __V3_64BIT__
+ } else if (dec_instr->dst_operand.size == 8) {
+ movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+#endif
} else {
PrintError("Invalid operand length\n");
return -1;
}
- PrintDebug("Calling Write function\n");
+ info->vm_regs.rdi += emulation_length;
+ info->vm_regs.rsi += emulation_length;
- if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
- PrintError("Did not fully read hooked data\n");
- return -1;
+ // RCX is only modified if the rep prefix is present
+ if (dec_instr->prefixes.rep == 1) {
+ info->vm_regs.rcx -= emulation_length;
}
+ } else if (dec_instr->op_type == V3_OP_STOS) {
- PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
- (void *)*(addr_t *)&(info->vm_regs.rdi),
- (void *)*(addr_t *)&(info->vm_regs.rsi),
- (void *)*(addr_t *)&(info->vm_regs.rcx));
+ if (dec_instr->dst_operand.size == 1) {
+ stos8((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+ } else if (dec_instr->dst_operand.size == 2) {
+ stos16((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+ } else if (dec_instr->dst_operand.size == 4) {
+ stos32((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+#ifdef __V3_64BIT__
+ } else if (dec_instr->dst_operand.size == 8) {
+ stos64((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+#endif
+ } else {
+ PrintError("Invalid operand length\n");
+ return -1;
+ }
info->vm_regs.rdi += emulation_length;
- info->vm_regs.rsi += emulation_length;
- info->vm_regs.rcx -= emulation_length;
- PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
- (void *)*(addr_t *)&(info->vm_regs.rdi),
- (void *)*(addr_t *)&(info->vm_regs.rsi),
- (void *)*(addr_t *)&(info->vm_regs.rcx));
-
- if (emulation_length == dec_instr->str_op_length) {
- info->rip += dec_instr->instr_length;
+ // RCX is only modified if the rep prefix is present
+ if (dec_instr->prefixes.rep == 1) {
+ info->vm_regs.rcx -= emulation_length;
}
- return emulation_length;
+ } else {
+ PrintError("Unimplemented String operation\n");
+ return -1;
+ }
+
+ if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
+ PrintError("Did not fully read hooked data\n");
+ return -1;
}
+ if (emulation_length == dec_instr->str_op_length) {
+ info->rip += dec_instr->instr_length;
+ }
+
+ return emulation_length;
+
+
- return -1;
}
instr->str_op_length = 1;
}
+ } else if (instr->op_type == V3_OP_STOS) {
+ instr->num_operands = 2;
+
+ if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) {
+ PrintError("Could not get Destination memory operand\n");
+ return -1;
+ }
+
+ // STOS reads from rax
+ xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG0),
+ &(instr->src_operand.operand),
+ &(instr->src_operand.size));
+ instr->src_operand.type = REG_OPERAND;
+
+ if (instr->prefixes.rep == 1) {
+ addr_t reg_addr = 0;
+ uint_t reg_length = 0;
+
+ xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG1), ®_addr, ®_length);
+ instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length);
+ } else {
+ instr->str_op_length = 1;
+ }
+
+ } else {
+ PrintError("Unhandled String OP\n");
+ return -1;
}
return 0;
- PrintDebug("Struct: Seg=%p, base=%p, index=%p, scale=%p, displacement=%p (size=%d)\n",
- (void *)mem_op.segment, (void*)mem_op.base, (void *)mem_op.index,
+ PrintDebug("Struct: Seg=%p (size=%d), base=%p, index=%p, scale=%p, displacement=%p (size=%d)\n",
+ (void *)mem_op.segment, mem_op.segment_size, (void*)mem_op.base, (void *)mem_op.index,
(void *)mem_op.scale, (void *)(addr_t)mem_op.displacement, mem_op.displacement_size);
*/
case XED_REG_CS:
*v3_reg = (addr_t)&(info->segments.cs);
+ *reg_len = 8;
return SEGMENT_REGISTER;
case XED_REG_DS:
*v3_reg = (addr_t)&(info->segments.ds);
+ *reg_len = 8;
return SEGMENT_REGISTER;
case XED_REG_ES:
*v3_reg = (addr_t)&(info->segments.es);
+ *reg_len = 8;
return SEGMENT_REGISTER;
case XED_REG_SS:
*v3_reg = (addr_t)&(info->segments.ss);
+ *reg_len = 8;
return SEGMENT_REGISTER;
case XED_REG_FS:
*v3_reg = (addr_t)&(info->segments.fs);
+ *reg_len = 8;
return SEGMENT_REGISTER;
case XED_REG_GS:
*v3_reg = (addr_t)&(info->segments.gs);
+ *reg_len = 8;
return SEGMENT_REGISTER;
return V3_OP_MOVSX;
+
case XED_IFORM_DEC_MEMv:
case XED_IFORM_DEC_MEMb:
return V3_OP_DEC;
case XED_IFORM_SETZ_MEMb:
return V3_OP_SETZ;
-
case XED_IFORM_MOVSB:
case XED_IFORM_MOVSW:
case XED_IFORM_MOVSD:
case XED_IFORM_MOVSQ:
return V3_OP_MOVS;
+ case XED_IFORM_STOSB:
+ case XED_IFORM_STOSW:
+ case XED_IFORM_STOSD:
+ case XED_IFORM_STOSQ:
+ return V3_OP_STOS;
+
+
default:
return V3_INVALID_OP;
}