Chapter 2: Native API
Gushaow@mails.gscas.ac.cn In addition to the Win32 API, the NT platform is open to another basic interface is the local API. Kernel mode driver and file system driven developers may already be familiar with the native API, as the kernel mode module is at a lower system level, which is invisible at that level. Despite this, do not need the driving level to access this interface, the ordinary Win32 program can call the native API at any time. There is no technical limit, but Microsoft does not support this application development method. User32.dll, advapi32.dll, gdi32.dll, rpcrt4.dll, kernel32.dll represents the basic provider of Win32 API, of course, there are other DLLs, such as Version.dll, Shell32.dll, ComctL32.dll. All Win32 API calls eventually turn to NTDLL.DLL and then forward it to ntoskrnl.exe. NTDLL.DLL is the user mode terminal of this API. The real interface is implemented in ntoskrnl.exe. In fact, the kernel mode drivers call this module most of them if they request system services. The main role of NTDLL.DLL is to make the specific subset of the kernel function can be called by a program running in user mode. NTDLL.DLL enters Ntoskrnl.exe through software interrupts, which is switched through the interrupt gate to switch the CPU privilege level. For example, kernel32.dll derived DeviceIoControl () actually called NTDEviceIOControlFile () exported in NTDLL.DLL, and disassemble this function can be seen, EAX loads the Magic 0x38, which is actually the system call number, then edx points to the stack . The target address is the current stack pointer ESP 4, so EDX points to the return address, which means that the stack is stored in the stack before entering NTDEviceIocontrolFile (). In fact, it is the parameter of the function. The next instruction is int 2eh, and goes to the interrupt handler at the interrupt descriptor table IDT position 0x2e.
NTDeviceLocontrolfile:
Mov Eax, 38h
Lea Edx, [ESP 4]
Int 2eh
Ret 28h
Of course INT 2E interface is more than just a simple API call dispatcher, but it is mainly Main Gate from the user mode into the kernel mode.
The Windows 2000 Native API consists of 248 such dealing functions, 37 more than NT 4.0. It can be easily recognized from the export list of NTDLL.DLL: prefix NT. 249 were exported in NTDLL.DLL because ntcurrentteb () is a pure user mode function, so it is not necessary to pass it to the kernel. Surprisingly, only a subset of Native APIs can be called from kernel mode. On the other hand, Ntoskrnl.exe exports two NT * symbols, which do not exist in NTDLL.DLL: NTBUILDNUMBER, NTGLOBALFLAG. They do not point to functions, in fact, to point to NTOSKRNL.EXE variables, which can be imported using the Drive Module of the C compiler Extern keyword. NTDLL.DLL and NTOSKRNL.EXE have two prefix NT *, ZW *. In fact, both the anti-assembly results in NTDLL.DLL are the same. In ntoskrnl.exe, the NT prefix points to the real code, and ZW is still an int 2eh Stub. That is to say, the ZW * function set passes the user mode to the kernel mode door, and the NT * symbol directs the code after the mode switching. NTCURRENTTEB () in NTDLL.DLL does not have a corresponding ZW function. NtoskRNL does not export paired NT / ZW functions. Some functions appear in one way.
The 2EH interrupt handler puts the value in the EAX as the index in the lookup table to find the final target function. This table is also the system service table SST, C language structure system_service_table as follows: The list also contains the definition of SERVICE_DEScriptor_Table, which is the fourth member of the SST array, and the first two have special purposes. Typedef NTSTATUS (NTAPI * NTPROC) ();
Typedef ntproc * pntproc;
#define ntproc_ sizeof (ntproc)
Typedef struct _system_service_table
{PNTProc serviceable; // Entrance pointer array
PDWORD counterTable; // Call the number count array
DWORD serviceLIMIT; // Service entrance number
PBYTE ARGUMENTTABLE; / / Service parameter byte array
) System_Service_Table,
* Psystem_service_table,
* * Ppsystem_service_table;
/ / _ _ _ _ _ _ _ _ _ _ _ _ _
Typedef struct _service_descriptor_table
{System_service_table ntoskrnl; // ntoskrnl system service, native API}
System_service_table win32k; // Win32k implementation system service, GDI / user support
SYSTEM_SERVICE_TABLE TABLE3; // Not used
System_service_table Table4; // Not used
} Service_descriptor_table,
* PService_Descriptor_table,
* PPService_Descriptor_table;
NTOSKRNL exports a pointer to the primary SDT through a symbol: KeserviceDescriptable. The kernel maintains another SDT, which is KeserviceDescriptAbleshadow. But this symbol has not been exported. To access the main SDT in the kernel mode component is very simple, only two lines C language code:
EXTERN PSERVICE_DESCRIPTOR_TABLE KESERVICEDEScriptable;
PSERVICE_DEScriptor_table psdt = keserviceDescriptable;
Ntproc is a convenient placeholder for this API, similar to the Proc in Win32 programming. Native API usually returns a NTSTATUS code, using NTAPI calls, it and _stdcall synonym. ServiceLimit members have the number of portions found in the ServiceTable array. At 2k, the default value is 248. ArgumentTable is an array of Bytes, each corresponding to the location of the serviceetable and displays the number of parameters in the caller stack. This information and EDX are required to be the kernel from the caller stack Copy parameter to your stack. The CounterTable member is not used in the 2k of Free Buid. In Debug Build, this member points to the DWORDS array representing each function, which can be used for performance analysis. You can use the command: DD kerviceDescriptable to display, the debugger resolves this symbol to 0x8046e0c0. Only the top four is important, corresponding to the four SDT members. Run command: ln 8046e100, the display symbol is KeserviceDescriptableShadow, indicating that the fifth start is indeed the second SDT maintained by the kernel. The main difference is that the next entry containing Win32k.sys, and the former one is not. In both tables, Table3 and Table4 are empty. Ntoskrnl.exe offers a convenient API function name to: KeaddSystemServentable to populate these locations.
2EH interrupt treatment marked as kiSystemService (). This is also the internal symbol that ntoskrnl.exe does not export, but is included in the 2K symbol file. The operation of KisystemService is as follows:
1 Retrieve the SDT pointer from the current thread control block
2 Decide which one of 4 SSTs in the SDT. Decide by testing the 12th and 13 of the delivery ID in Eax. ID in 0x0000-0X0FFF to NTOSKRNL form, ID is
0x1000 and 0x1FFF allocation to the Win32k form. The remaining 0x2000-0x2FFFFF and
0x3000-0X3FFF is reserved for Table3 and Table4.
3 Check 0-11 bits of EAX by selecting the SST's serviceLimit member. Returns the error code status_invalid_system_service if the ID exceeds the range.
4 Check the parameter stack pointer and mmuserProbeAddress in Eax. This is a global variable exported by ntoskrnl. Usually equal to 0x7FFF0000, if the parameter pointer is not in this address, return Status_Access_violation.
5 Find the number of parameter stack bytes in ArgumentTable, from the caller stack Copy all parameters to the current kernel mode stack.
6 Find the service function pointer in ServiceTable and call this function.
7 Control Go to the internal function KiserviceExit, after the service call returns.
From the discussion of the SDT, you can see the second kernel mode interface with the native API. This interface connects the graphics device interface of the Win32 subsystem and the window manager and kernel mode components Win32k. The Win32K interface is also based on INT 2EH. The service number of this machine API ranges from 0x0000 to 0x0FFF, Win32k service number from 0x1000 to 0x1FFF. (DD W32PServentable determines the symbol of Win32k.sys.) Win32K has a total of 639 system services.
2EH treatment procedure does not use global SDT KeserviceDescriptAble
But a thread-related pointer. Obviously, the thread can have different SDTs to be related to itself. KeinitializTREAD () writes KeserviceDescriptable to thread control blocks when thread initial testization. Despite this, this default setting may be changed to other values, such as KeserviceDescriptAbleshadow. Windows 2K runtime library
NTDLL.DLL exports no less than 1179 symbols. The 249/248 belongs to the NT * / ZW * collection. Therefore, 682 functions are not transferred via the INT 2EH gate. Obviously, so many functions do not rely on 2K kernels.
Some of them are almost the same function as the C operation time. In fact, NTOSKRNL has also achieved some functions similar to C operation time. These functions can be linked to NTDLL.LIB in the DDK. The C rule function of NTDLL.DLL and NTOSKRNL.EXE can be found that NTDLL.DLL does not rely on ntoskrnl.exe. Two modules each implement these functions.
In addition to C running time library, 2K also provides an extension runtime function collection. Once again, NTDLL.DLL and NTOSKRNL.EXE each realize them. Similarly, the collection has overlap, but does not match. This set of functions start with RTL. The 2K runtime library includes some auxiliary functions that cannot be completed at C run. For example, some processing of safety transactions, additional data structures for 2K, and some support memory management. Microsoft only records 115 in 406 functions in DDK.
NTDLL.DLL also provides another function set to begin with the __e prefix. In fact they are used for floating point number simulators.
There are still many functions, all of these functions are as follows:
__e (floating point simulation), CC (Cache Management), CSR (C / S Runtime Library), DBG (Debug Support), EX (Performance Support), FSRTL (File System Runtime), HAL (Hardware Abstract Layer), InBV (System initial test / VGA launch driver Bootvid.dll), init (system initial test), interlocked, IO (IO Manager), KD (kernel modulator support), ke (kernel routine ), Ki (kernel interrupt processing), LDR (image loader), LPC (local process call), LSA (local security authorization), MM (memory management), NLS (international language support), NT (NT native machine API), OB (Object Manager), PFX (Prefix Processing), PS (Process Support), READ_REGISTER_ (from Register Address), RTL (2K Runtime Library), SE (Security Processing), Write_register_ (write register address), ZW (replacement method for this API),
When writing software from user mode through NTDLL.DLL or kernel mode through NTOSKRNL.EXE and 2K kernel interaction, there is a need to handle many basic data structures, which are rarely seen in Win32 world.
Common data structure
l integer
ANSI characters are symbolic, and Unicode Wchar is unsigned
MASM's TBYTE is 80-bit floating point numbers for high-precision floating point operation units, pay attention to it is completely different from Win32's TByte (Text Byte).
Table 2-3. Equivalent Integral Data Types
Bits Masm Fundamental Alias # 1 alias # 2 signed
8 Byte unsigned char Uchar Char 16 Word unsigned short ushort wchar short32 dword unsigned long ulong long
32 DWORD UNSIGNED INT uint Int
64 qword unsigned _int64 Ulonglong DWordlong Longlong
80 TBYTE N / A
Typedef union _large_integer
{Struct {
Ulong lowpart;
Long hiHPART;
Longlong quadpart;
}
Large_integer, * pularge_integer;
Typedef union _ularge_integer {
Struct {
Ulong lowpart;
Ulong highpart;
Ulonglong quadpart;
} Ularge_integer, * pularge_integer;
l character
Win32 programming PSTR user char *, PWSTR is used for Wchar *. Depending on whether UNICODE is defined, PTSTR is interpreted as PSTR or PWSTR. In 2K core mode, the common data type is unicode_string, and string is used to represent an ANSI string:
Typedef struct _unicate_string {
Ushort length; // Current byte length, not characters! ! !
Ushort maximumlength; // buffer maximum byte length
Pwstr buffer;} unicode_string, * punicode_string;
Typedef struct _string {
Ushort Length;
Ushort maximumlength;
Pchar buffer;} String, * pstring;
Typedef string ansi_string, * pansi_string;
Typedef string oem_string, * poem_string;
Manipulation function: RTLCREATUNICODESTRING (), RTLINITUNICODESTRING (),
RTLCopyUnicodestring (), etc.
l structure
Many kernel API functions require a fixed size Object_attributes structure, such as NTOPENFILE (). The property of the object is a combination of OBJ_ * values, which can be checked from NTDEF.H.
The IO_STATUS_BLOCK structure provides information about the requested operation results, which is very simple, and the Status member contains a NTSTATUS code, and if the operation successfully Information information provides information about a specific request.
Another structure is LIST_ENTRY, which is a two-way ring list.
Typedef struct _object_attributes
{
Ulong Length;
Handle rootdirectory;
Punicode_String ObjectName;
Ulong attributes;
PVOID SecurityDescriptor;
Pvoid SecurityQualityOfService;
} Object_attribdtes, * POBJECT_ Attributes;
Typedef struct _io_status_block
{
NTSTATDS Status;
Ulong information;} ×_status_block, * pio_status_block;
Typedef struct _list_entry
{
Struct _List_ENTRY * FLINK;
Struct _List_ENTRY * BLINK;
} List_entry, * plist_entry;
A typical example of the two-way linked list is the process and thread chain. The internal variable PSACTIVEPROCESSHEAD is a list_entry structure that specifies the first member of the system process list in the data segment of Ntoskrnl.exe.
The Client_ID structure consists of a process and thread ID.
TypedEf struct _client_id
{Handle UniqueProcess;
Handle uniqueethread;
CLIENT_ID, * PCLIENT_ID;
Want to call an API function in ntdll.dll from the user mode, you must take into account the following four points:
1 SDK header file does not include prototypes of these functions
2 Some basic data types used by these functions are not included in the SDK file
3 SDK and DDK header files are not compatible, and cannot contain NTDDK.H in Win32 C source files.
4 NTDLL.LIB is not included in the default gate list of VCs.
The fourth is easy to resolve: #Progma Comment (Linker, "/ Defaultlib: NTDLL.LIB")
Definition of missing is more difficult to resolve, the easiest way is to write a custom header file, just contain definitions that need to call NTDLL.dll. Fortunately, this work has been made in the W2K_DEF.H file of the disc. Because this header file will be used in user mode and kernel mode, you must be in user mode code, # clude
There are also three good native API data sources:
l Mark Russinovich Inside the Native API
Www.sysinternals.com/ntdll.htm
l 1999, 2011 DDJ contains my article: Inside Windows NT System Data
Www.ddj.com/ftp/1999/1999_11/ntinfo.zip
l Gary Nebbett's Windows NT / 2000 Native API Reference.
The W2K_Call.dll example library that appears in Chapter 6 shows how to use W2K_DEF.H. Chapter 6 also provides another method that calls 2K cores from the user mode, and this method is not limited to the native API collection. In fact, this method is not limited to NTOSKRNL.EXE, but can be used for modules loaded into kernel memory, if the API function is exported, or provides matching .dbg or .pdb symbol file.