Analysis of Windows NT/2000 environment switching (http://webcrazy.yeah.net)

Source: Internet
Author: User
Analysis on Windows NT/2000 environment Switch
WebSphere (tsu00@263.net)
Note: This article was initially found at www.nsfocus.com

This article assumes that you have already understood the Windows NT/2000 system, and have some concepts about the data structures and kernel working methods such as kpeb/kteb in Windows NT/2000, and the 80 x protection mode, I have learned how to use SoftICE for Windows NT, Microsoft Visual Studio, and other tools, and read the Linux kernel code, if you do not know much about these aspects, please read relevant books on your own.

Context switch involves many aspects. This article only discusses several data related to it in detail and provides some program sections for obtaining the data, it also lists a small amount of Environment switching code for Windows 2000. In addition, the internal system data discussed in this article is not from the Microsoft official documentation. There may be differences between the next versions of Windows NT/2000 and even the current versions, therefore, I try to list the software and hardware involved in this article in detail below. Please adjust the differences caused by factors such as different hardware systems and software versions according to your situation.

⊙ X86 single-processor Windows 2000 Server build 2195
⊙ Numbench SoftICE 4.05 for Windows NT/2000 build 334
⊙ Linux 2.0.30 Kernel
⊙ Datarescue Ida 4.0.4.20.
⊙ Microsoft Visual Studio 6.0 sp3
⊙ Windows 2000 DDK

The following scenarios may be involved in environment switching during the 80x86 operating system:
1. The current task executes a far call or JMP command, and the selector points to a TSS descriptor or a job gate.
2. The current task executes the iret command and returns the previous task. iret only switches when the NT position in the eflags register is 1.
3. An interruption or exception occurs, and the IDT is a task.

The Linux kernel has the following code:

/*
/Usr/src/Linux/include/asm-i386/system. h
List single-processor implementation code only
*/

# Define switch_to (prev, next) do {/
_ ASM _ ("movl % 2," symbol_name_str (current_set) "/n/t "/
"Ljmp % 0/n/t "/
"CMPL % 1," symbol_name_str (last_task_used_math) "/n/t "/
"JNE 1f/n/t "/
"Clts/N "/
"1 :"/
:/* No outputs *//
: "M" (* (char *) & next-> TSS. tr)-4 )),/
"R" (prev), "R" (next ));/
/* Now maybe reload the Debug Registers *//
.
.
.
}/
} While (0)

This Code uses the first case discussed above.

As we all know, Linux is an open-source operating system, while Microsoft is not so "generous", but we can still reverse engineer it, good news is that there are already many people on the Internet who have studied this, and are extracting some of the results of Mark russinovich (http://www.sysinternals.com/tips.htm ):

//
// NT's main
// Ntoskrnl main
//
Int main (boot parameters)
{
//
// Fire up nt!
//
Kisystemstartup ();
Return 0;
}

From the context, it can be seen that ntoskrnl.exe (PE format, which can be easily analyzed using the Disassembly tool) is the start of NT osloader's true call to the kernel) process, thread, fiber, filemapping, event, mutex), semaphore, and many other kernel objects are managed. They are also responsible for thread scheduling, memory management, inter-process communication, and other operating system functions to coordinate their work, the thread switching code we want to discuss is also in this module.

I am afraid you can imagine the amount of work it will take to analyze the results produced by decompiling ntoskrnl.exe using IDA. Before discussing detailed code for Windows 2000 environment switchover, let's take a look at the following important system data related to environment switchover:

1 process context
Process context refers to the physical address of the page Directory of the current process in the memory paging mechanism under the protection mode of X86, which is stored in the system's register, in Windows 2000, the position is the 18h after the kpeb offset. Let's take a look at SoftICE's output results (Due to space limitations, I deleted the output results, but still annotated the important data, it should be noted that it is closely related to the system environment such as the program you are currently running and has a strong randomness, the same below ):

: CPU // display the current CPU register value

Processor 00 registers
----------------------
CS: EIP = 0008: 80069582 SS: ESP = 0010: 8046fd98
Eax = 8046bdf0 EBX = ffdff000 ECx = ffdff878 edX = 20.ba5a
ESI = 8046bdf0 EDI = 8046bb60 EBP = ffdff800 EFL = 00000213
DS = 0023 es = 0023 FS = 0030 GS = 0000

Cr0 = 8000003b pe mp ts et ne PG
Cr2 = 76ee18ec
32a = 00030000
|
| _ Current process
CR4 = 000002d1 VME PSE MCE PGE
.
.
.

: Proc idle

Process kpeb PID threads pri user time krnl time status
* Idle 8046bb60 0 1 0 00000000 running ba5a running
|
| _ Idle process's kpeb
| _ Current process in the system (different colors are used in SoftICE, and there is a * above *)

: Dd 8046bb60 + 18 L 4 // dd idle's kpeb + 18 h
0010: 8046bb78 00030000 00000000 00000000 00000000 ................
|
| _ Idle process context
: ADDR
32a LDT base: Limit kpeb addr pid name
00030000 fe4e1600008 System
02d59000 ff8e6540 0090 SMSs
01d41000 ff8e17e0 00ac CSRSS
00686000 fe51bae0 00c0 Winlogon
0095d000 ff8a7ae0 00dc services
0276e000 ff8a5d60 00e8 LSASS
00394000 ff881020 0180 svchost
02cae000 ff884020 01a4 spoolsv
00882000 ff85b560 01d0 MSDTC
02993000 ff83f020 0238 svchost
00d2f000 ff83d760 024c llssrv
0063a000 ff8000060 0274 regsvc
02efa000 ff6ecd60 0318 dfssvc
00a5e000 ff823a20 0328 inetinfo
03612000 ff6af860 0384 Explorer
003a2000 ff68e460 03b4 internat
003a7000 ff68cd60 0130 OSA
008c1000 ff6769a0 03e8 svchost
01baa000 ff65a020 01c0 cmd
00822000 ff86c960 038c conime
03362000 ff6b3540 0388 notepad
* 00030000 8046bb60 0000 idle
|
|__ Whether the context of the current process is consistent with the output result of the previous command.

You can use the same method for verification again.

2. Number of times the context switches times thread has been scheduled by the operating system
This value is added to the call thread of the operating system each time. The tool spy ++ attached to Visual Studio, in the thread window, context switches indicates the number of times the thread has been scheduled in the system (SPY ++ displays this value only when running in Windows NT/2000, in 9x ). The switch times position in the system is at the 4ch offset of kteb.

: Thread idle
TID krnl Teb stackbtm stktop stackptr user Teb process (ID)
0000 8046bdf0 8046d040 80470040 8046fd90 00000000 idle (00)
: Dd 8046bdf0 + 4C L 4
0010: 8046be3c %e778 00000000 00000002 00000000 x ...............
|
| _ Indicates that the current idle thread has been called for 0e778h (decimal 59256) times. Use the e command to modify and check the output result of spy ++!

3. kpeb and process name of the process to which the thread belongs are located at kteb + 44h and kpeb + 1fch respectively.
For details, refer to the document nsfocus magazine 11.

It should be pointed out that the above discussion is only for Windows 2000 Server build 2195. If your system is not, or you want to know how to obtain the specific location of these values, refer to the methods described below:

Find a breakthrough, just as the context switches times shown in spy ++ above, and then use reverse engineering, I also use this method to obtain the specific position.

For example! I have been troubled by the ADDR command output result (including the process context) in SoftICE for NT, and I have asked some famous news groups outside China, however, no one has answered the question so far (it may be because my English level is too poor and people cannot understand what it means !)

The ADDR command output result is displayed.

Later, in desperation, I still thought that the physical address register (which stores the physical address of the Process page Directory) should be related to a specific process. It should be stored in the kpeb structure (which is actually true ). If this is the case, instead of enumerating (Enum) All the kpeb in the system, you can get all the records (the premise is to find the offset value relative to kpeb ), can I use the nsfocus magazine 11 method to retrieve the process names of all processes? (PID is the same ).

The address indicated by psinitialsystemprocess exported by worker, and each kpeb in the system is linked by a linked list. The linked list is defined in ntdef. h of Windows 2000 DDK as follows:

Typedef struct _ list_entry {
Struct _ list_entry * flink;
Struct _ list_entry * blink;
} List_entry, * plist_entry, * restricted_pointer prlist_entry;

With kpeb, you can trace the corresponding code (this disassembly code will be listed below) to find the value of at the 18 h offset address.

In Windows 9x, the preceding operations can be performed by the unmarshented function (noname, ord_0001 in the SoftICE export list) with the serial number 1 in kernel32.dll, however, because of the differences between Windows 9x and NT/2000 kernels, the output formats of SoftICE for 9x and nt addr commands are also completely different. In Windows NT/2000, I don't know if there are ready-made functions to get the results. At least I haven't found them yet.

Because the above description is abstract, I still list the output result of SoftICE, which is more conducive to understanding:

: Dd psinitialsystemprocess L 4
0008: 8046a844 fe4e160e1000968 00000000 '. N. H ...........
|
| _ System process kpeb

: Dd @ psinitialsystemprocess + 18 L 4
0008: fe4e1c78 00030000 00000000 00000000 00000000 ................
|
| _ System process context

: Dd @ psinitialsystemprocess + 9C L 4 // 9ch is the position of PID relative to kpeb
0008: fe4e1cfc 00000008 ff8e65e0 8046a180 00000000 ...... e ...... f .....
|
| _ System process PID

: Dd @ psinitialsystemprocess + 1fc L 10 // 1fch is the position of process name relative to kpeb
0008: fe4e1e5c 74737953 running 6d65 00000000 00000000 system ..........
|
System process name _ |
@ (@ Psinitialsystemprocess + a0)-A0
// Calculate the kpeb of the next Process pointed to by the system. 0a0h is the offset of the chain structure to kpeb.
Ff8e6540 4287522112 (-7445184) "Reply @"
|
| _ System process kpeb points to the next kpeb, which can be known as smss.exe from process name( see below)

: Dd @ (@ psinitialsystemprocess + a0)-A0 + 18 L 4
0008: ff8e6558 02d59000 02d5a000 00000000 00000000 ................
|
| _ Smss.exe process context

: Dd @ (@ psinitialsystemprocess + a0)-A0 + 9C L 4
0008: ff8e65dc 00000090 ff8e1880 fe4e1d00 00000518 .....
|
| _Smss.exe PID

: Dd @ (@ psinitialsystemprocess + a0)-A0 + 1fc L 10
0008: ff8e673c 73736d73 6578652e 00000000 00000000 smss.exe ........
|
Smss.exe process name _ |
: Dd @ (@ psinitialsystemprocess + a0)-A0 + 18 L 4

.
. (You can use SoftICE to keep track of the end of the linked list in the same way)
.

The implementation code snippet is as follows:

/*
The following code snippet requires that the system data structure be obtained, that is, running in the ring 0 state.
Must be in the NT/2000 device driver. The length of the Code depends on the architecture of the device driver.
Long degree. Here, only key code segments are listed. You can find this WDM book and place this program segment in your code,
Or contact me directly (tsu00@263.net ).
*/

.
.
.
Plist_entry kpeblisthead, kpeblistptr; // For the plist_entry definition, see
Ulong kpeblistoffset = 0xa0; // defines the Offset Value of the linked list relative to kpeb.
Ulong processnameoffset = 0x1fc; // defines the Offset Value of processname relative to kpeb.
Ulong processcontextoffset = 0x18; // defines the offset between process context and kpeb.
Ulong pidoffset = 0x9c; // defines the offset between the PID and kpeb.

If (ushort) ntbuildnumber )! = 2195 ){
Dbuplint ("only test on Windows 2000 Server build 2195! /N ");
Return;
}

Dbuplint ("/n H6/T/tkpeb ADDR/tpid/T name ");
Dbuplint ("/N ---/T --------/t ---/T ----/N ");

Kpeblisthead = kpeblistptr = (plist_entry) (char *) psinitialsystemprocess) + kpeblistoffset );
While (kpeblistptr-> flink! = Kpeblisthead ){
Void * kpeb;
Char processname [16];
Ulong processcontext;
Ulong PID;

// Obtain kpeb
Kpeb = (void *) (char *) kpeblistptr)-kpeblistoffset );

// Obtain processname
Memset (processname, 0, sizeof (processname ));
Memcpy (processname, (char *) kpeb) + processnameoffset, 16 );

// Obtain the process context
Processcontext = * (ulong *) (char *) kpeb) + processcontextoffset );

// Obtain the PID
PID = * (ulong *) (char *) kpeb) + pidoffset );

// Output the result to the debugger
Dbuplint ("% 08x/T % 08x/T % 04x/T % s/n", processcontext, kpeb, PID, processname );

// Point to the next linked list
Kpeblistptr = kpeblistptr-> flink;
}

.
.
.

The following figure shows the output result of the debugger after compiling and running in checked mode (which is the underlying implementation method of enumprocesses ):

32a kpeb addr pid name
------------------
00030000 fe4e1600008 System
02d59000 ff8e7920 0090 smss.exe
003c1000 fe520520 00ac csrss.exe
026c6000 fe51a020 00a8 winlogon.exe
03209000 ff8a8d60 00dc services.exe
.
. Omitted
.

The reason why I spent so much time describing the process context acquisition seems to be different from the Environment switching topic, mainly because of the closed nature of Windows NT/2000, I think it is easier to understand the Linux platform if you really need to understand the environment switch. In NT, you should know how to obtain important data structures related to this, then we can connect with the X86 platform architecture to help you better understand it. Using the similar method described above, you can also find a lot of important information about kpeb/kteb, such as process priority (kpeb + 62 h) time used by the process in the kernel and user States (kpeb + 38h and kpeb + 3ch), thread ID (kteb + 1e4h), etc, it can be compared with the task_struct structure in Linux.

After talking about this, let me briefly talk about the environment switching code in Windows 2000.

In Windows NT/2000, when will the environment switch take place? I have seen a description in the DDK FAQ as follows:

Q: What are the causes of a context switch in Windows NT?
A: There are only two ways that a thread context is switched.
1. The thread yields It's quantum by blocking on something (event, semaphore, etc .).
2. The time period is up. This is caused by a timer interrupt.

Kidispatchinterrupt is a scheduled environment switching routine in NT/2000. Some of its codes are listed below:

Code that implements similar functions in Linux is located in/usr/src/Linux/kernel/sched. c
00403a58 kidispatchinterrupt proc near
00403a58
00403a58 var_c = dword ptr-0ch
00403a58 var_8 = dword ptr-8
00403a58 var_4 = dword ptr-4
00403a58
00403a58 mov EBX, DS: 0ffdff01ch
00403a5e Lea eax, [EBX + 800 H]
00403a64 CLI
00403a65 CMP eax, [eax]
00403a67 JZ short loc_403a86
00403a69 push EBP
00403a6a push dword ptr [EBX]
00403a6c mov dword ptr [EBX], 0 ffffffffh
00403a72 mov edX, ESP
00403a74 mov ESP, [EBX + 81ch]
00403a7a push edX
00403a7b mov EBP, eax
00403a7d call sub_460ba4
00403a82 pop ESP
00403a83 pop dword ptr [EBX]
00403a85 pop EBP

.
. (For limited space, skip the section here and follow up step by step if you are interested)
.

The other code for switching to the third layer is as follows:

The code for implementing this function in Linux is located in/usr/src/Linux/include/asm-i386/pgtable. h
; Implemented by the macro definition set_page_dir. For details, refer.

In this case, EDI stores kpeb (using SoftICE and heel), and after execution, eax is the process context
In combination with mov, can eax trace the specific location of the object in kpeb? I tracked it from here.
00403b87 mov eax, [EDI + 18 h]
00403b8a mov EBP, [EBX + 40 h]
00403b8d mov ECx, [EDI + 30 h]
00403b90 mov [EBP + 1ch], eax
00403b93 mov convention, eax; eax-> Convention 3
00403b96 mov [EBP + 66 h], CX
00403b9a XOR eax, eax
00403b9c CMP [EDI + 20 h], ax
; Transfer error handling. If necessary, kebugcheck will be called, and a terrible blue screen will crash.
00403ba0 jnz short loc_403bce
; Ldtr null Selector
00403ba2 lldt ax
00403ba5 Lea ECx, [ECx]
00403ba7
00403ba7 loc_403ba7:; Code xref:. Text: 00403b7dj
00403ba7;. Text: 00403 bfaj
; Add context switches times
00403ba7 Inc dword ptr [ESI + 4ch]
00403baa Inc dword ptr [EBX + 5c0h]
00403bb0 pop ECx
00403bb1 mov [EBX], ECx
00403bb3 CMP byte PTR [ESI + 49 H], 0
00403bb7 jnz short loc_403bbd
00403bb9 popf
00403bba XOR eax, eax
00403bbc retn
00403bbd loc_403bbd:; Code xref:. Text: 00403bb7j
00403bbd popf
00403bbe jnz short loc_403bc3
00403bc0 mov Al, 1
00403bc2 retn
00403bc3 loc_403bc3:; Code xref:. Text: 00403 bbej
00403bc3 mov Cl, 1
00403bc5 call DS: halrequestsoftwareinterrupt
00403bcb XOR eax, eax
00403bcd retn

.
. (Omitted)
.

I have not commented on some code, mainly because some code is related to the Code runtime environment, such as handling the error check of the NT execution body (including validity and security ), I have not listed the code here. If you are interested, you can use SoftICE to trace the code step by step and find many internal nt mechanisms.

Windows 2000 is a preemptible multi-threaded operating system, and does not involve the specific method of thread scheduling. I cannot list the details of the worker module here. This article only discusses how to obtain this information, but if you want to know more, you can further analyze it based on the discussion in this article.

I have been familiar with single-chip microcomputer, and I have never understood how to design an OS from the ground up (it may be just a few instructions, so don't laugh at single-chip microcomputer experts, however, I thought I was so ridiculous when I had access to the NT kernel. However, when dealing with the NT kernel, a lot of Linux code can be referenced. After all, they should have the same principle. Although Linux is not a microkernel OS, NT/2000 is. I personally think that Linux's task_struct and NT's kpeb, Linux's bottom half mechanism and NT's DPC (delayed process call) and so on (although the implementation methods on the mechanism are still quite different ). Microsoft does not provide any official documentation and the complexity of the NT kernel (some people have criticized that the NT microkernel is larger than Linux). As mentioned in this article, I cannot guarantee its absolute correctness. If you find any errors or have any suggestions, please let me know. Thank you!

References:
1. Jeffrey Richter
<Programming applications for Microsoft Windows, Fourth Edition>
2. Linux documents
3. Mark russinovich documents
4. Intel Corp <intel architecture software developer's manual, Volume 3>

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.