Windows NT/2000 Internal data structure (http://webcrazy.yeah.net)

Source: Internet
Author: User
Talk about the internal data structure of Windows NT/2000
WebSphere (tsu00@263.net)
Note: This article was initially found at www.nsfocus.com
Now let's talk about the internal data structure of Windows NT/2000 with the implementation of regmon (http://www.sysinternals.com/) in NT.

Regmon is a utility that monitors applications to access the system registry. We all know that winapi regxxx is generally called when the registry is used in applications, and regxxx will eventually call native API zwxxx! (See Windows NT/2000 DDK documentation ). Regmon monitors the Registry by changing these routines. Zwxxx is implemented as follows:

MoV eax, serviceid
Lea edX, parametertable
Int 2EH
RET paramtablebytes

This is the NT system services. Is it a bit similar to Linux (except that Linux is interrupted for 80 h, and it also has serviceid, for example, the fork system calls serviceid 2 ).

System services is defined in DDK documentation as follows:

The set of native, user-mode routines exported by the executive for use only by protected subsystems. Each System Service has a name of the form twolettersxxxyyy where:
Twoletters is the prefix for all system services.
XXX is usually a verb, describing the operation of a given service.
YYY is generally the object type the Service operates on.

System servicesare composed of two groups in the system. One is guided by win32k.sys, and the other is provided by ntoskrnl.exe. The former mainly completes the communication between the Win32, POSIX, and OS/2 subsystems (subsystems) and the kernel in NT and can only be called by user-State applications, such as USER32! Waitmessage. Since regmon only applies to the latter, this article will discuss it. All of the following discussions about system service are suitable for both!

Last time (nsfocus magazine 10) I mentioned keservicedescriptortable and said that its structure is as follows:

Struct _ servicedescriptorentry {
Unsigned int * servicetablebase;
Unsigned int * servicecountertablebase;
Unsigned int numberofservices;
Unsigned char * paramtablebase;
} Servicedescriptortableentry

Ntoskrnl.exe exports the global variable keservicedescriptortable pointing to servicedescriptortableentry (by win32k. the system services exported by sys also has its own servicedescriptortable. in Win2000 Server, its service ID starts from 1000hand is directed by keservicedescriptortableto 50h. its structure is basically the same as that exported by ntosrknl.exe. This article will not discuss it, the ntcall command in SoftICE can list all system services in specific circumstances ).

Next, we will use SoftICE 4.05 for Windows NT/2000 to analyze the situation of Windows 2000 Server build 2195 on the X86 platform (the following is only an excerpt. The data may not be the same for different versions at different times)

: Dd keservicedescriptortable L 4*4
// If you want to view the table exported by win32k. sys, use dd keservicedescriptortable + 50 L 4*4.
// Deploy the keservicedescriptortable at 50 h.
0008: 8046ab80 804704d8 00000000 201700f8 804708bc ...... g.
| _ Servicetablebase value | _ paramtablebase Value
| _ It seems that the total value is 0 |
| _ Keservicedescriptortable address | _ numberofservice

: Dd @ keservicedescriptortable l byte (@ (keservicedescriptortable + 08) * 4
// Dd servicedescriptortableentry-> servicetablebase l numberofservice * 4
0008: 804704d8 804ab3bf 804ae86b 804bdef3 8050b034... J. K. J... k.4.p.
|
| System service entry address of _ serviceid = 0 (and so on)

0008: 804704e8 804c11f4 80459214 8050c2ff 8050c33f... l... e... p .?. P.
0008: 804704f8 804b581c 80508874 8049860a 804fc7e2. XK. T. P... I... O.
0008: 80470508 804955f7 8049c8a6 80448472 804a8d50. ui... I. R. d.p. J.
0008: 80470518 804b6bfb 804f0cef 804fcb95 8040189a. kk ...... o ...@.
0008: 80470528 804d06cb 80418f66 804f69d4 8049e0cc... M. F. A. Io... I.
... (Omitted)

: DB @ (keservicedescriptortable + 0C) l byte (@ (keservicedescriptortable + 08 ))
// DB servicedescriptortableentry-> paramtablebase
0008: 804708bc 18 20 2C 2C 40 2C 40 44-0c 18 08 04 04 0C 10 .., @, @ d ........
|
| Number of system service parameters of _ serviceid = 0x4 (that is, the number of parameters is 18 h/4 = 6)

0008: 804708cc 18 08 08 0C 08 04 04-04 0C 04 20 08 0C 14 0C ...............
... (Omitted)

To obtain the application that has performed operations on the system registry, you only need to inject your own code into the system service that has the operation, that is, to change the execution process of these system services, first, execute your own code (the record in regmon is used for the GUI part), and then return to the original place to continue the execution. Through the above analysis, we know that as long as we modify the data from servicetablebase to servicetablebase + numberofservice * 4, we can change the execution process of the system service, as long as you know the serviceid of the system service, you can change the location of the system service endpoint in this region. How can you get the service ID of the system service! We can use zwopenkey as an example:

: U zwopenkey
Ntoskrnl! Zwopenkey
0008: 80400e2a b867000000 mov eax, 00000067
| _ Serviceid
| _ Machine code (the second byte is the linear address of zwopenkey plus a serviceid)
0008: 80400e2f 8d542404 Lea edX, [esp + 04]
0008: 80400e33 cd2e int 2e
0008: 80400e35 c20c00 RET 000c

So long as we know the zwxxx routine name (that is, the linear address of the System Service in the memory), can we achieve our goal? Let's take a look at the specific implementation code of regmon:
.
.
.
// Save the original zwopenkey entry and use it in hookregopenkey
Realregopenkey = syscall (zwopenkey );

// Modify the zwopenkey process and point to the new entry. That is, when zwopenkey is called, The hookregopenkey is executed.
Syscall (zwopenkey) = (pvoid) hookregopenkey;
.
.
.

Syscall is defined on intel as follows:
# Define syscall (_ function) servicetable-> servicetable [* (Pulong) (puchar) _ FUNCTION + 1)]
Servicetable-> servicetable is the servicedescriptortableentry-> servicetablebase described above (for ease of description ). _ FUNCTION + 1 refers to the address of serviceid. The entire expression gets the position of the system service entry address corresponding to _ function in linear memory. For other definitions, see regsys. C and regsys. H!
You can use SoftICE to compare the changes of the system service entry address in servicetable before and after regsys. sys loading, so as to enhance the understanding of System Service interception.

Now we know the basic implementation method of regmon (of course, many problems need to be considered to implement this function, such as protection of communication between State applications and kernel drivers, thread synchronization, etc ).

Let's take a look at another application of keservicedescriptortable! If we re-allocate the segment memory pool, construct our own servicetable and paramtable arrays (the original system services of the system must be copied, otherwise ...), then, modify servicetablebase and paramtablebase in the structure to point to their own servicetable and paramtable, and then modify numberofservices. Can you add your own system service! For more information, see <unauthenticated ented NT>. I have never seen this book. I only know its reputation on the Internet. Oh, I would also like to thank James shatlyk for providing me with the supporting example code of the book. If you have read this book (I do not know whether it is in Chinese or not), Can you contact me?

After talking about the system service, let's take a look at how regmon obtains the system process name in the driver.
First, let's talk about kteb (kernel thread environment block) and kpeb (kernel process environment block), which are the same as Teb (actually user-Teb, kpeb/kteb records the system kernel process/thread information. To understand kteb and kpeb, you must first know how to obtain their base addresses in the current process/thread. You can first look at native API iogetcurrentprocess. In Windows 2000 DDK document, it is defined as follows:
Peprocess iogetcurrentprocess ();
When Ida proor softiceis used, it is known that ntoskrnl.exe is implemented only by several Assembly commands:

MoV eax, FS: [00000124]
MoV eax, [eax + 00000044] // The value below NT 4.0 should be [eax + 40]
RET

This native API is very typical. Its First Command gets the kteb of the current thread, and the entire API will start with 68 for kteb (I .e., Hex 44) get the kpeb of the current process at the byte and return it to the user. You can use SoftICE for verification.

Let's take a look at how it is implemented:

//----------------------------------------------------------------------
//
// Getprocessnameoffset
//
// In an effort to remain version-independent, rather than using
// Hard-coded into the kpeb (kernel process environment block), we
// Scan the kpeb looking for the name, which shocould match that
// Of the GUI Process
//
//----------------------------------------------------------------------
Ulong getprocessnameoffset ()
{
Peprocess curproc;
Int I;
Dbuplint ("getprocessnameoffset/N "));
Curproc = psgetcurrentprocess ();

//
// Scan for 12kb, hopping the kpeb never grows that big!
//
For (I = 0; I <3 * page_size; I ++ ){

If (! Strncmp (sysname, (pchar) curproc + I, strlen (sysname ))){

Return I;
}
}

//
// Name not found-oh, well
//
Return 0;
}

//----------------------------------------------------------------------
//
// Getprocess
//
// Uses unmarshented Data Structure offsets to obtain the name of
// Currently executing process.
//
//----------------------------------------------------------------------
Filterstatus getprocess (pchar name)
{
Peprocess curproc;
Char * nameptr;
Ulong I;

//
// We only try and get the name if we located the name offset
//
If (processnameoffset ){

Curproc = psgetcurrentprocess ();
Nameptr = (pchar) curproc + processnameoffset;
Strncpy (name, nameptr, 16 );

} Else {

Strcpy (name ,"??? ");
}
.
.
.
}

This code is excerpted from the NT driver section of regmon. For details, see regsys. C.
The two functions are mainly used to obtain the process name for the program. We all know that the driver part cannot simply call Win32 APIs, while the ntquerysysteminformation provided by the NT execution body mainly targets all processes, threads, or other nt internal information, therefore, we must look for other methods (the general method is to follow up the corresponding Win32 API and use debugger to perform a difficult but challenging reverse engineering, then find out the specific implementation process in the NT execution body, you can also use this method to verify the mentioned in this article ).

The two functions in regmon obtain the process name by searching for kpeb. getprocessnameoffset mainly calls psgetcurrentprocess to obtain the kpeb base address, and then searches for kpeb to get the offset of processname to kpeb, which is stored in the global variable processnameoffset. If psgetcurrentprocess is defined in NT/2000 DDK:
# Define psgetcurrentprocess () iogetcurrentprocess ()
Iogetcurrentprocess has been discussed earlier.
The author searches for the three-page memory area (4 kb for one page on x86). The comments in the program show that he does not know whether the range is exceeded. In the program segment, sysname is defined as system, because the DriverEntry entry in the driver is scheduled by the system process (getprocessnameoffset is called in DriverEntry ). You can also use SoftICE to find the processnameoffset value in a specific Windows NT/2000 version. In Windows 2000 Server build 2195 on the X86 platform, it is 1fch (1dch for NT 4.0 and 3.51), and then several processes are checked based on this value.

Getprocess adds the processnameoffset value to the kpeb base address of the current process to obtain the name of the current process (the native API process that calls the Registry in regmon.

For the specific structure of kpeb/kteb, the specific meaning of each byte, due to its so-called undocument, I checked msdn, to various newsgroups, and tracked the NT kernel, I did not find a small part of the article, which is also my intention to write this article. I hope that experts and friends can communicate with each other, and there are some mistakes in this article, I hope you can point it out and talk to me. Thank you!

References:
1. regmon source code 4.22
2. Windows 2000 DDK documentation

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.