📄 lrmi.c
字号:
} else { if (size == 4) asm volatile ("cld; outsl" : "=S" (esi) : "d" (edx), "0" (esi)); else if (size == 2) asm volatile ("cld; outsw" : "=S" (esi) : "d" (edx), "0" (esi)); else asm volatile ("cld; outsb" : "=S" (esi) : "d" (edx), "0" (esi)); } esi -= (unsigned int)context.vm.regs.ds << 4; context.vm.regs.esi &= 0xffff0000; context.vm.regs.esi |= esi & 0xffff; }static voidem_rep_outs(int size) { unsigned int ecx, edx, esi; ecx = context.vm.regs.ecx & 0xffff; edx = context.vm.regs.edx & 0xffff; esi = context.vm.regs.esi & 0xffff; esi += (unsigned int)context.vm.regs.ds << 4; if (context.vm.regs.eflags & DIRECTION_FLAG) { if (size == 4) asm volatile ("std; rep; outsl; cld" : "=S" (esi), "=c" (ecx) : "d" (edx), "0" (esi), "1" (ecx)); else if (size == 2) asm volatile ("std; rep; outsw; cld" : "=S" (esi), "=c" (ecx) : "d" (edx), "0" (esi), "1" (ecx)); else asm volatile ("std; rep; outsb; cld" : "=S" (esi), "=c" (ecx) : "d" (edx), "0" (esi), "1" (ecx)); } else { if (size == 4) asm volatile ("cld; rep; outsl" : "=S" (esi), "=c" (ecx) : "d" (edx), "0" (esi), "1" (ecx)); else if (size == 2) asm volatile ("cld; rep; outsw" : "=S" (esi), "=c" (ecx) : "d" (edx), "0" (esi), "1" (ecx)); else asm volatile ("cld; rep; outsb" : "=S" (esi), "=c" (ecx) : "d" (edx), "0" (esi), "1" (ecx)); } esi -= (unsigned int)context.vm.regs.ds << 4; context.vm.regs.esi &= 0xffff0000; context.vm.regs.esi |= esi & 0xffff; context.vm.regs.ecx &= 0xffff0000; context.vm.regs.ecx |= ecx & 0xffff; }static voidem_inb(void) { asm volatile ("inb (%w1), %b0" : "=a" (context.vm.regs.eax) : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax)); }static voidem_inw(void) { asm volatile ("inw (%w1), %w0" : "=a" (context.vm.regs.eax) : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax)); }static voidem_inl(void) { asm volatile ("inl (%w1), %0" : "=a" (context.vm.regs.eax) : "d" (context.vm.regs.edx)); }static voidem_outb(void) { asm volatile ("outb %b0, (%w1)" : : "a" (context.vm.regs.eax), "d" (context.vm.regs.edx)); }static voidem_outw(void) { asm volatile ("outw %w0, (%w1)" : : "a" (context.vm.regs.eax), "d" (context.vm.regs.edx)); }static voidem_outl(void) { asm volatile ("outl %0, (%w1)" : : "a" (context.vm.regs.eax), "d" (context.vm.regs.edx)); }static intemulate(void) { unsigned char *insn; struct { unsigned int size : 1; unsigned int rep : 1; } prefix = { 0, 0 }; int i = 0; insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4); insn += context.vm.regs.eip; while (1) { if (insn[i] == 0x66) { prefix.size = 1 - prefix.size; i++; } else if (insn[i] == 0xf3) { prefix.rep = 1; i++; } else if (insn[i] == 0xf0 || insn[i] == 0xf2 || insn[i] == 0x26 || insn[i] == 0x2e || insn[i] == 0x36 || insn[i] == 0x3e || insn[i] == 0x64 || insn[i] == 0x65 || insn[i] == 0x67) { /* these prefixes are just ignored */ i++; } else if (insn[i] == 0x6c) { if (prefix.rep) em_rep_ins(1); else em_ins(1); i++; break; } else if (insn[i] == 0x6d) { if (prefix.rep) { if (prefix.size) em_rep_ins(4); else em_rep_ins(2); } else { if (prefix.size) em_ins(4); else em_ins(2); } i++; break; } else if (insn[i] == 0x6e) { if (prefix.rep) em_rep_outs(1); else em_outs(1); i++; break; } else if (insn[i] == 0x6f) { if (prefix.rep) { if (prefix.size) em_rep_outs(4); else em_rep_outs(2); } else { if (prefix.size) em_outs(4); else em_outs(2); } i++; break; } else if (insn[i] == 0xec) { em_inb(); i++; break; } else if (insn[i] == 0xed) { if (prefix.size) em_inl(); else em_inw(); i++; break; } else if (insn[i] == 0xee) { em_outb(); i++; break; } else if (insn[i] == 0xef) { if (prefix.size) em_outl(); else em_outw(); i++; break; } else return 0; } context.vm.regs.eip += i; return 1; }/* I don't know how to make sure I get the right vm86() from libc. The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) which should be declared as "int vm86(struct vm86_struct *);" in <sys/vm86.h>. This just does syscall 113 with inline asm, which should work for both libc's (I hope).*/#if !defined(USE_LIBC_VM86)static intlrmi_vm86(struct vm86_struct *vm) { int r;#ifdef __PIC__ asm volatile ( "pushl %%ebx\n\t" "movl %2, %%ebx\n\t" "int $0x80\n\t" "popl %%ebx" : "=a" (r) : "0" (113), "r" (vm));#else asm volatile ( "int $0x80" : "=a" (r) : "0" (113), "b" (vm));#endif return r; }#else#define lrmi_vm86 vm86#endifstatic voiddebug_info(int vret) { int i; unsigned char *p; fputs("vm86() failed\n", stderr); fprintf(stderr, "return = 0x%x\n", vret); fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax); fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx); fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx); fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx); fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi); fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi); fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp); fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip); fprintf(stderr, "cs = 0x%04x\n", context.vm.regs.cs); fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp); fprintf(stderr, "ss = 0x%04x\n", context.vm.regs.ss); fprintf(stderr, "ds = 0x%04x\n", context.vm.regs.ds); fprintf(stderr, "es = 0x%04x\n", context.vm.regs.es); fprintf(stderr, "fs = 0x%04x\n", context.vm.regs.fs); fprintf(stderr, "gs = 0x%04x\n", context.vm.regs.gs); fprintf(stderr, "eflags = 0x%08lx\n", context.vm.regs.eflags); fputs("cs:ip = [ ", stderr); p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff)); for (i = 0; i < 16; ++i) fprintf(stderr, "%02x ", (unsigned int)p[i]); fputs("]\n", stderr); }static intrun_vm86(void) { unsigned int vret; while (1) { vret = lrmi_vm86(&context.vm); if (VM86_TYPE(vret) == VM86_INTx) { unsigned int v = VM86_ARG(vret); if (v == RETURN_TO_32_INT) return 1; pushw(context.vm.regs.eflags); pushw(context.vm.regs.cs); pushw(context.vm.regs.eip); context.vm.regs.cs = get_int_seg(v); context.vm.regs.eip = get_int_off(v); context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK); continue; } if (VM86_TYPE(vret) != VM86_UNKNOWN) break; if (!emulate()) break; } debug_info(vret); return 0; }intLRMI_call(struct LRMI_regs *r) { unsigned int vret; memset(&context.vm.regs, 0, sizeof(context.vm.regs)); set_regs(r); context.vm.regs.cs = r->cs; context.vm.regs.eip = r->ip; if (r->ss == 0 && r->sp == 0) { context.vm.regs.ss = context.stack_seg; context.vm.regs.esp = context.stack_off; } else { context.vm.regs.ss = r->ss; context.vm.regs.esp = r->sp; } pushw(context.ret_seg); pushw(context.ret_off); vret = run_vm86(); get_regs(r); return vret; }intLRMI_int(int i, struct LRMI_regs *r) { unsigned int vret; unsigned int seg, off; seg = get_int_seg(i); off = get_int_off(i); /* If the interrupt is in regular memory, it's probably still pointing at a dos TSR (which is now gone). */ if (seg < 0xa000 || (seg << 4) + off >= 0x100000) { fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); return 0; } memset(&context.vm.regs, 0, sizeof(context.vm.regs)); set_regs(r); context.vm.regs.cs = seg; context.vm.regs.eip = off; if (r->ss == 0 && r->sp == 0) { context.vm.regs.ss = context.stack_seg; context.vm.regs.esp = context.stack_off; } else { context.vm.regs.ss = r->ss; context.vm.regs.esp = r->sp; } pushw(DEFAULT_VM86_FLAGS); pushw(context.ret_seg); pushw(context.ret_off); vret = run_vm86(); get_regs(r); return vret; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -