"Undocumented windows 2000 secrets" translation - Chapter 2 (2)

xiaoxiao2021-03-06  42

Chapter II The Windows 2000 Native API

Translation: kendiv (fcczj@263.net)

Update:

Friday, February 04, 2005

Disclaimer: Please indicate the source and guarantee the integrity of the article, and all rights to the translation.

Windows 2000 Runtime Library

The NT * () and ZW * () functions constitute the basic part of the Native API, but not the main part, and some of the code is located in NTDLL.DLL. The DLL exports to at least 1179 symbols. Among them, 249 and 248 belong to NT * () and ZW * () function sets, and the remaining 682 functions do not call via the INT 2EH interruption. Obviously, this large group function does not rely on the Windows 2000 kernel. What is the purpose of providing them? Let us continue to look down.

C Operation time library

If you study the symbols of the NTDLL.DLL Export section, you will find a lot of lowercase that is very familiar in the C programmer. These are well known, such as memcpy (), sprintf (), and QSort (), which are merged into NTDLL.DLL in these C running libraries. The same is true for NToskrnl.exe, which also provides a function of a group of phases with C rules, although the two group functions are different. Table B-3 of Appendix B lists the two sets of functions and points out which module is partially belonging to each function.

You can easily add NTDLL.LIB (from Windows 2000 DDK) to the Import Library list (the linker will be scanned during the resolution symbol) to link to these functions. If you prefer the dialog box, you can choose the Settings submenu in the Visual C / C Engineering menu, then click the Linke page, select Category General, and add NTDLL.DLL to the Object / Library module list. There is also a way: in the source file, add the following:

#pragma comment (Linker, "/ Defaultlib: NTDLL.LIB")

This is equally effective, beneficial is that other developers can use the default settings of Visual C / C to Rebuild your project.

Reverse compiling these functions similar to C run function (from NTDLL.DLL and NTOSKRNL.EXE), which will find NTDLL.DLL does not depend on ntoskrnl.exe, which is different from NATIVE API in ndll.dll. In fact, these two modules have implemented these functions. The other functions appeared in this section. Note that some of the functions in Table B-3 do not use their exported names. For example, if a 64-bit Large_integer is used in the driver of the kernel mode, the compiler and the linker will automatically import NTOSKRNL.EXE_allshr () and _allshl ().

Extended runtime function

The Windows 2000 also provides a set of extended runtime functions as the standard C rule function. At the time, NTDLL.DLL and NTOSKRNL.EXE realize them. And some of them are overlapping. The names of these extended functions have a common prefix RTL (for runtime library). Table B-4 of Appendix B lists all of these extensions. These runtime functions provided by Windows 2000 also include helper functions for normal tasks, which exceed the ability of C rules function. For example, some of them are used to manage security, and others are used to operate the Windows 2000-specific data structure, and some support for memory management. It is difficult to understand why Microsoft provides documents of 115 functions in Windows 2000 DDK, and throws away 406 very useful functions. Floating-Point Emulator

Let me end this API function exchange with another group of functions provided by NTDLL.DLL. Table 2-1 lists the names of these functions, which may be somewhat familiar with assembly programmers. Go to the __e prefix before the name, you will get the FPU (FLOATING-POINT Unit) compiler of the i386 series CPU. In fact, from the functions listed in Table 2-1, NTDLL.DLL contains a complete floating-point simulator. This once again proves this DLL is a huge code repository, which attracts numerous SYSTEM SPELunker to compile it.

Table 2-1. Floating point simulator interface for NTDLL.DLL

Function name

_eCommonExceptions _eFIST32 _eFLD64 _eFSTP32 _eEnulatorInit _eFISTP16 _eFLD80 _eFSTp64 _eF2XM1 _eFISTP32 _eFLDCW _eFSTP80 _eFABS _eFISTP64 _eFLDENV _eFSTSW _eFADD32 _eFISUB16 _eFLDL2E _eFSUB32 _eFADD64 _eFISUB32 _eFLDLN2 _eFSUB64 _eFADDPreg _eFISUBR16 _eFLDPI _eFSUBPreg _eFADDreg _eFISUBR32 _eFLDZ _eFSUBR32 _eFADDtop _eFLDI _eFMUL32 _eFSUBR64 _eFCHS _eFIDIVR16 _eFMUL64 _eFSUBreg _eFCOM _eFIDIVR32 _eFMULPreg _eFSUBRPreg _eFCOM32 _eFILD16 _eFMULreg _eFSUBRreg _eCOM64 _eFILD32 _eFMULtop _eFSUBRtop _eFCOMP _eFILD64 _eFPATAN _eFSUBtop _eFCOMP32 _eFIMUL16 _eFPREm _eFTST _eFCOMP64 _eFIMUL32 _eFPREM1 _eFUCOM _eFCOMPP _eFINCSTP _eFPTAN _eFUCOMP _eFCOS _eFINIT _eFRNDINT _eFUCOMPP _eFDECSTP _eFIST16 _eFRSTOR _eFXAM _eFIDIVR16 _eFIST32 _eFSAVE _eFXCH _eFIDIVR32 _eFISTP16 _eFSCALE _eFXTRACT _eFILD16 _eFISTP32 _eFSIN _eFYL2X _eFILD32 _eFISTP64 _eFSQRT _eFYL2XP1 _eFILD64 _eFISUB16 _eFST

_eGetStatusWord _eFIMUL16 _eFISUB32 _eFST32 NPXEMULATORTABLE _eFIMUL32 _eFISUBR16 _eFST64 RestoreEm87Context _eFINCSTP _eFISUBR32 _eFSTCW SaveEm87Context _eFINIT _eFLD16 _eFSTENV_eFIST16 _eFLD32 _eFSTP

For more information on floating point instruction sets, please refer to the original document of Intel 80386 CPU. You can download the Pentium manual from Intel's official website: http://developer.intel.com/design/pentium/manuals/. The manual of these machine code instructions is: Intel Architecture Software Developer's Manual. Volume 2: Instruction Set Reference (Intel 1999b).

Other API functions

NTDLL.DLL and NTOSKRNL.EXE export NTDLL.DLL and NTOSKRNL.EXE also export numerous functions for multiple core components. In order to avoid longer forms, I only list the name prefixes of the available functions and their belongings (Table 2-2).

Table 2-2 Function name prefix and its classification

Prefix

NTDLL.DLL

Ntoskrnl.exe

classification

_e

N / A floating point simulator CC

N / a cache manager CSR

Client-Server runtime library DBG N / A

Debug support EX N / A

Executive Support FSRTL N / A

File system runtime library HAL N / A

Hardware abstraction layer scheduler INBV N / A

System Initialization / VGA Startup Drive (Bootvid.dll) Init N / A

System initialization interlocked N / A

Treat thread secure variables IO N / A

I / O Manager KD N / A

Core debug support Ke N / A

Nuclear routine ki

Kernel interrupt routine LDR

Image loader LPC N / A

Local Process Call (LPC) Equipment LSA N / A

Local security authorization MM N / A

Memory Manager NLS

National Language Support (NLS) NT

NT Native API

OB

N / a

Object Manager PFX

Prefix processing

PO

N / a

Power Manager PS N / A

Process support Read_Register_ N / A

Read RTL from the register address

Windows 2000 Runtime Library SE N / A

Safety processing WRITE_REGISTER_ N / A

Write ZW to the register address

Another group of Native API

Help function and C running time library

Many kernel functions use unified naming rules - PrefixOperationObject (). For example, the ntqueryinformationFile () function belongs to the Native API because its NT prefix, and the function obviously performs QueryInformation operations for a file object. But not all functions follow this rule, but most of them are. Therefore, it can be easily guessing its function through the name of the function.

Used data type

When writing software related to the Windows 2000 kernel --- Whether you are NTDLL.DLL or with user mode, you must process several basic data types, and these data types are in Win32. Very rare. Most of them will repeatedly appear in this book. The following sections will introduce the data type with the highest frequency.

Integrity

Generally speaking, integer types have multiple different variants. Win32 SDK's header file and SDK document uses its proprietary terms that are easily confused with the basic type of C / C and some derived types. Table 2-3 lists these integer types and the equivalent relationship between them. In the "MASM" column, the type name of the Microsoft Macro Assembly Language (MASM) is given. Win32 SDK is the basic data type of C / C defines the corresponding Byte, Word, DWORD alias. "Alias ​​1" and "Alias ​​2" two columns include alias they often use. For example, Wchar represents the base type of Unicode character type. The last column "Symbol" lists the corresponding alias for the corresponding symbol type. Be sure to remember that the ANSI character type char is a symbol, and the Unicode type Wchar is unsigned. This inconsistency will result in unexpected errors when the compiler converts these types in the expression or calculation into an integer type. Table 2-3 The last line of MASM TBYTE type (read "10-Byte") is an 80-bit floating point number for high-precision floating point operations. Microsoft Visual C / C does not provide a corresponding data type for Win32 programmers. It should be noted that the MASM's TBYTE and WIN32 TBYTE (read "Text Byte") does not have any relationship, the latter is just a macro for converting, and corresponds to CHAR or WCHAR according to whether there is #define unicode in the source file.

Table 2-3. Equivalent integer type

Bit number

Masm

basic type

Alias ​​1

Alias ​​2

Symbolic

BTYE UNSIGNED Char Uchar

Char 16 Word Unsigned Short Ushort Wchar Short 32 DWORD UNSIGNED Long Ulong

Long 32 DWORD Unsigned Int uint

INT 64 Qword Unsigned __INT64 ULONGLONG DWORDLONG Longlong 80 TBYTE N / A

Since the 64-bit integer is more difficult in the 32-bit programming environment, Windows 2000 usually does not provide 64-bit basic types, such as __int64 or its derived type. Alternative, DDK header file NTDEF.H defines a fine Union structure, which can interpret one 64-bit number as a pair of 32 digits or a complete 64-bit number. See Large_integer and ularge_integer. Type definition. This type can indicate an integer with symbols and unsigned numerals, respectively. Controls unregistered by using longlong / ulonglong (for 64-bit Quadpart members) or long / ulong (for 32-bit HIGHPART members).

Typedef union _large_integer

{

Struct

{

Ulong lowpart;

Long highpart;

}

Longlong quadpart;

Large_integer, * Plarge_integer;

Typedef union _ularge_integer

{

Struct

{

Ulong lowpart;

Ulong highpat;

}

Ulonglong quadpat;

} Ularge_integer, * pularge_integer;

Listing 2-3. Large_integer and ularge_integer

String

In Win32 programming, PSTR and PWSTR are often used instead of ANSI and Unicode strings, respectively. PSTR is defined as char *, and PWSTR is defined as WCHAR * (see Table 2-3). By the source file, the #define Unicode indicator appears, the additional PTSTR type corresponds to PSTR or PWSTR, so that the ANSI and Unicode versions of the application can be maintained by a single source file. Basically, these strings are simple to point to arrays of CHAR or WCHAR types at zero end. If you often deal with the Windows 2000 kernel, you will have to handle a very different string representation. The most common type is Unicode_String, which is a third-party type, which gives its definition. Typedef struct _unicate_string

{

Ushort Length;

Ushort maximumlength;

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;

Listing 2-4. String Type

Length members give the number of bytes of the current string (note, not the number of characters), and MaxImumLength members indicate the size of the buffer to the memory block, and the actual string data will be saved in the memory block. Note that MaxImumLength is also the number of bytes. Since the Unicode character width is 16 bits, all its length is always twice the number of characters. Typically, the string of buffer points to zero end. However, some kernel modules may only rely on the length values ​​of the string, regardless of the 0 characters ending, this is careful.

The ANSI string of Windows 2000 is called String, as shown in Listing 2-4. For convenience, Nedef.h defines ANSI_STRING and OEM_STRING to represent 8-bit strings using different code pages (ANSI default code page 1252; OEM default code page is 437). However, the main string type used by the Windows 2000 kernel is also unicode_string. You may occasionally touch 8 strings.

In Figure 2-3, I give two typical Unicode_String examples. The on the left contains two separate memory blocks: a Unicode_String structure and a 16-bit PWChar type Unicode character array. This may be the most common string type in the Windows 2000 data type. On the right is a frequently occurring special type, in which the Unicode_String and the PWChar array are located in the same memory block. Some kernel functions, including some of the functions used inside the Native API, saving the structured system information returned in a continuous memory block. If the data contains a string, they are usually stored in embedded Unicode_String, as shown in Figure 2-3. For example, the NTQuerySystemInformation () function frequently uses this special string type.

These string structures do not make hand care, NTDLL.DLL and NTOSKRNL.exe export a rich set of runtime API functions, such as RTLCReateUnicODestring (), RTLinitUnicodestring (), RTLCopyunicodeString (), etc. Typically, string and ANSI_String have corresponding equivalents. Most of these functions have document records in DDK, but some are not. However, it is easy to guess the functionality of these unnocured string functions and the parameters thereof. The advantage of using Unicode_String, String is that the specified buffer can accommodate the size of the string. If you deliver a unicode_string type string, this function needs to appropriately change the value of the string, which may increase the length of the string, which only needs to simply check MaximumLength members can be determined. Is there enough space to store results. Structural body

Individual several kernel API functions are expected to have a suitable Object_attributes structure, and the list 2-5 shows the definition of the structure. For example, the NTOPENFILE () function does not have a PWSTR or PUNICODE_STRING parameter to specify the path to the file to be opened. Alternative, the ObjectName member in the Object_Attributes structure gives the path. Usually, it is easy to set this structure. In addition to ObjectName, you also need to set up Length and Attributes members. Length must be set to: sizeof (object_attributes), Attributes is an OBJ_ * constant from NTDEF.H. For example, if your object name is not case sensitive, Attributes should be set to OBJ_CASE_INSENSITIVE. Of course, the ObjectName member is a Unicode_String pointer and is not the usual PWSTR. The remaining members can be set to NULL as long as they are not used.

Typedef struct _object_attributes

{

Ulong Length;

Handle rootdirectory;

Punicode_String ObjectName;

Ulong attributes;

PVOID SecurityDescriptor;

Pvoid ​​SecurityQualityOfService;

} Object_attributes, * pobject_attribute;

Listing 2-5. Object_attributes structure

Object_attributes structure only describes details of the data used by the function, and the IO_STATUS_BLOCK structure given by the list 2-6 is used to record processing results of the operations submitted by the user. This structure is very simple --- Staus member stores a NTSTATUS type code, which may be Status_Success or define all possible error code in NTSTATUS.H. Information members provide additional data related to the operation in the event of successful operation. For example, if the function returns a block, the member will be set to the size of the data block.

Typedef struct _io_stratus_block

{

NTSTATUS STATUS;

Ulong information;

} }_Status_block, * pio_status_block;

Listing 2-6. IO_STATUS_BLOCK Structure

Another common Windows 2000 data type is a list_entry structure, and the list 2-7 shows the definition of the structure. The kernel uses this structure to maintain all objects in a two-way linked list. A number of object spacers is very common. FLINK members are a forward link, pointing to the next list_entry structure, the BLINK member is a backward link, pointing forward a List_entry structure. Normally, these linked lists are circular, that is, the last FLINK point to the first list_entry structure in the linked list, and the first Blink points to the last one. This is easy to double-way traversed the list. If a program is to traverse the entire list, it needs to save the address of the first list_entry structure to determine if the entire linked list has been traversed. If the list contains only one list_entry structure, the list_entry structure must reference itself, that is, Flink and Blink points to himself. Typedef struct _list_entry

{

Struct _List_ENTRY * FLINK;

Struct _List_ENTRY * BLINK;

} List_entry, * plist_entry;

Listing 2-7. List_entry structure

Figure 2-4 shows the relationship between the members of the object linked list. Objects A1, A2, A3 belong to the same linked list. Note that the FLINK of A3 points to the blink of A1, A1 pointing A3. Only one member is only one member, so Flink and Blink are pointing to the same address - that is, the address of the object B1. An example of a typical two-way linked list is a process and threaded table. The internal variable PSACTIVEPROCESSHEAD is a LIST_ENTRY structure located in the .data section of Ntoskrnl.exe. This variable points to the header of the system process (through its BLINK pointer). You can use DD PSactiveProcesshead in the kernel debugger to get the header of the list, and then traverse the entire linked list through its Flink and Blink pointers (still using the DD command). Of course, this method of detecting Windows processes is very cumbersome, but this allows you to go deep into the basic system structure. The Windows 2000 Native API provides a more convenient way to enumerate the process, such as the ntquerysysteminformation () function.

TypedEf struct _client_id

{

Handle uniqueprocess;

Handle uniqueethread;

} Client_ID, * pClient_ID;

Listing 2-8. Client_ID structure

Processing processes and threads API functions such as NTOpenProcess (), and NTOPENTHREAD (), using the list 2-8 to be associated with specific processes, threads. Although its type is Handle, in fact, from a strict sense, UniqueProcess and UNIQUETHREAD members are not handle, they are integer types of process IDs and thread IDs. That is, the standard WIN32 function getCurrentProcessId () and the value of DWORD type returned by getCurrentThreadId ().

The Windows 2000 Execute (Executive) also uses the Client_ID structure to identify unique threads within the global range. For example, if you use the kernel debugger! Thread command to display the current thread parameters, you will see the display similar to "CID PPP.TTT" in the output of the output, where "PPP" is a uniqueprocess member of Client_ID, and "" " TTT "represents UniqueThread as shown below. Note that I markedly using the black body. KD>! THREAD

Thread 83A51BA8 CID 0A5C.0E64 TEB: 7FFDD000 WIN32THREAD: E14F4EB0 Running on Processor 0

Not impersonating

DeviceMap E20FB208

Owning process 83a14708

Wait Start Tickcount 906512 Elapsed Ticks: 68570

Context Switch Count 266 Largestack

Usertime 00: 00: 00.0312

KernelTime 00: 00: 00.0015

. . . . . . . . . . . . . . . . . . .

Native API interface

For the drivers of the kernel mode, the interfaces using the Native API are very common, just like calling the Win32 API in the program in user mode. The header files and libraries provided by Windows 2000 DDK include information needed when calling ntoskrnl.exe. On the other hand, Win32 SDK has hardly supports the NTDLL.DLL export NTIVE API in the program. I said "I hardly" is because Win32 SDK actually provides an important thing: import library NTDLL.LIB, which is located in the / program files / microsoft platform SDK / lib directory. If this library does not have this library, it will be difficult to call NTDLL.DLL exported functions.

Translation:

You need to install Windows 2000 DDK to get ntdll.lib

You can download the latest SDK to http://www.microsoft.com/msdownload/platformsdk/sdkupdate/

Adding NTDLL.DLL import library to the project

You must consider the following four points before you can successful compilation and links Use NTDLL.DLL Export Functions in User Mode.

1. In the SDK's header file, there is no prototype of these functions.

2. Several basic data types used in these functions are missing in the SDK file.

3. SDK and DDK header files are not compatible, you can't add #include to your Win32 C source code file.

4. NTDLL.LIB does not join the Visual C / C default import library list

The last problem is easy to resolve, just edit the project setting properties, or add your source code, # prgma Comment (Linker, "Defaultlib: NTDLL.LIB"), like Windows 2000 Runtime Library As explained in the section, this will add NTDLL.DLL to the linker / defaultLib settings when compiling. Solving the definition of deletions is more difficult. Because it is not possible to integrate SDK and DDK header files into the C program, the easiest solution is to write a custom header file, which contains all call NTDLL.dll exports must be defined. Fortunately, you don't need to start this work, in this book CD / SRC / Common / Include directory W2K_DEF.H file contains all the basic information you need. The header will play an important role in sixth and seventh chapters. Because it is designed to be an engineering that can be compatible with user mode and kernel mode, in the user mode code, you must insert #define _user_mode_ before #include to join some definitions that appear in DDK. Many details about Native API programming have been published. At present, a good book for Windows 2000 platform is the "Windows NT / 2000 Native API Reference" of Gary Nebblet's. The book provides less sample programs, but it covers all Native APIs on the Windows NT / 2000 platform, as well as data structural definitions required for these functions, and some other structural definitions.

The W2k_Call.dll sample library will be described in Chapter 6, demonstrates a typical usage of W2k_DEF.H. Chapter VI will also discuss another way to enter the Windows 2000 kernel in user mode, which is not limited to Native API. In fact, this technique can also be used in NToskrnl.exe, which can be used for all modules loaded into kernel space, as long as they export function or can be matched with .dbg or .pdb symbol files. This method can be used. As you can see, there are still many interesting information in the remaining chapters of this book. However, before we arrived, we will continue to discuss some basic concepts and technologies.

转载请注明原文地址:https://www.9cbs.com/read-59746.html

New Post(0)