static void do_test(struct vm86plus_struct *v86, unsigned long eip, const char *text) { long ret; printf("[RUN]\t%s from vm86 mode\n", text); v86->regs.eip = eip; ret = vm86(VM86_ENTER, v86); if (ret == -1 && errno == ENOSYS) { printf("[SKIP]\tvm86 not supported\n"); return; } if (VM86_TYPE(ret) == VM86_INTx) { char trapname[32]; int trapno = VM86_ARG(ret); if (trapno == 13) strcpy(trapname, "GP"); else if (trapno == 5) strcpy(trapname, "BR"); else if (trapno == 14) strcpy(trapname, "PF"); else sprintf(trapname, "%d", trapno); printf("[OK]\tExited vm86 mode due to #%s\n", trapname); } else if (VM86_TYPE(ret) == VM86_UNKNOWN) { printf("[OK]\tExited vm86 mode due to unhandled GP fault\n"); } else { printf("[OK]\tExited vm86 mode due to type %ld, arg %ld\n", VM86_TYPE(ret), VM86_ARG(ret)); } }
static int do_vm86(xf86Int10InfoPtr pInt) { int retval, signo; xf86InterceptSignals(&signo); retval = vm86_rep(VM86S); xf86InterceptSignals(NULL); if (signo >= 0) { xf86DrvMsg(pInt->scrnIndex, X_ERROR, "vm86() syscall generated signal %d.\n", signo); dump_registers(pInt); dump_code(pInt); stack_trace(pInt); return 0; } switch (VM86_TYPE(retval)) { case VM86_UNKNOWN: if (!vm86_GP_fault(pInt)) return 0; break; case VM86_STI: xf86DrvMsg(pInt->scrnIndex, X_ERROR, "vm86_sti :-((\n"); dump_registers(pInt); dump_code(pInt); stack_trace(pInt); return 0; case VM86_INTx: pInt->num = VM86_ARG(retval); if (!int_handler(pInt)) { xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Unknown vm86_int: 0x%X\n\n", VM86_ARG(retval)); dump_registers(pInt); dump_code(pInt); stack_trace(pInt); return 0; } /* I'm not sure yet what to do if we can handle ints */ break; case VM86_SIGNAL: return 1; /* * we used to warn here and bail out - but now the sigio stuff * always fires signals at us. So we just ignore them for now. */ xf86DrvMsg(pInt->scrnIndex, X_WARNING, "received signal\n"); return 0; default: xf86DrvMsg(pInt->scrnIndex, X_ERROR, "unknown type(0x%x)=0x%x\n", VM86_ARG(retval), VM86_TYPE(retval)); dump_registers(pInt); dump_code(pInt); stack_trace(pInt); return 0; } return 1; }
int main(int argc,char **argv) { struct vm86plus_struct vm; struct vm86_regs *regs; u_int8_t *image; int32_t ret,opsize; u_int seg; int32_t i; if(argc < 2) { printf("[+] Welcome to easyHW emulator\n"); printf("Usage : %s <filename>\n",*argv); exit(1); } read_opcodes(*(argv+1),&opsize); for (i=0;i<sizeof(buffer);i++) { buffer[i]^= 0xaa; buffer[i]-=10; buffer[i]&=0xff; } image = mmap((void*)BASE,VM_IMAGE_SIZE,7,0x22,-1,0); if(image == (u_int8_t *)MAP_FAILED) { perror("[error] mmap"); return -1; } memset(image,0x00,VM_IMAGE_SIZE); memcpy(image+0x100,buffer,opsize); memset(&vm,0,sizeof(struct vm86_struct)); vm.regs.eip = (unsigned int)(image+0x100); vm.regs.esp = (unsigned int)(image+0x1000); vm.regs.eax = 0; vm.regs.ebx = 0; vm.regs.ecx = 0; vm.regs.edx = strlen(msg); vm.regs.cs = ((unsigned int)image) >> 4; vm.regs.ss = ((unsigned int)image) >> 4; vm.regs.ds = ((unsigned int)image) >> 4; vm.regs.es = ((unsigned int)image) >> 4; vm.regs.fs = ((unsigned int)image) >> 4;; vm.regs.gs = ((unsigned int)image) >> 4;; vm.regs.eflags = 0; vm.cpu_type = CPU_586; regs = &vm.regs; while(1) { ret = vm86(VM86_ENTER,&vm); if (ret == -1) { perror("[error] vm86"); } #ifdef HW_DEBUG coredump(regs); #endif //printf("return : %08x\n",ret); switch(VM86_TYPE(ret)) { case VM86_INTx: if (VM86_ARG(ret) != 0x80) break; if(regs->eax == __NR_write || regs->eax == __NR_read) regs->ecx += BASE; exec_asm(&vm.regs); break; case VM86_TRAP: exit(0); break; default: printf("[x] Invalid Instruction !\n"); exit(0); } } return 0; }