系统调用笔记(1)

编程知识 更新时间:2023-04-17 11:03:17

API函数的调用过程(3环部分)

Windows API

  1. Application Programming Interface,简称 API 函数。
  2. Windows有多少个API?
    主要是存放在 C:\WINDOWS\system32 下面所有的dll,dll里面函数都是API

  3. 几个重要的DLL
    Kernel32.dll:最核心的功能模块,比如管理内存、进程和线程相关的函数等.
    User32.dll:是Windows用户界面相关应用程序接口,如创建窗口和发送消息等.
    GDI32.dll:全称是Graphical Device Interface(图形设备接口),包含用于画图和显示文本的函数.比如要显示一个程序窗口,就调用了其中的函数来画这个窗口.
    Ntdll.dll:大多数API都会通过这个DLL进入内核(0环).

做实验找 ReadProcessMemory
首先打开IDA,打开kernelBase.dll(XP是kernel32.dll),按ATL+T,如下图

图1

然后就打开了ReadProcessMemory,如下图

图二


发现是调用了NtReadVirtualMemory。
再去import里面找这个函数就知道谁调用了他

3

发现时ntdll,然后去找ntdll,的这个函数
NtReadVirtualMemory

4


真正读取进程内存的函数在0环,在这里的114h是一个编号,这个编号,对应的是真正的操作系统内核中某个函数,所以我们的API进内核都需要一个编号,这个编号就是真正执行的函数。下面的

1
mov edx,7FFE0300h

这是一个内存地址,存了一个函数,这个函数觉得了用什么方式进0环,也就是这段代码就是找到一个编号通过一个函数(edx)进入0环。
所以3环的API函数都是提供一个进入0环的接口而已。

API函数的调用过程(3环进0环 上)

下面我们说一下上面的7FFE0300h函数是什么,所以先了解下0x7ffe0000这页内存是什么。

_KUSER_SHARED_DATA(Kernel和Use共享了一块数据)

这块任何一个3环的程序都可以访问,他的地址是确定的。地址如下

  1. 在 User 层和 Kernel 层分别定义了一个 _KUSER_SHARED_DATA 结构区域,用于 User 层和 Kernel 层共享某些数据
  2. 它们使用固定的地址值映射,_KUSER_SHARED_DATA 结构区域在 User 和 Kernel 层地址分别为:
    1. User 层地址为:0x7ffe0000
    2. Kernnel 层地址为:0xffdf0000

这两个不同的线性地址,指向的是同一个物理页,区别就是0环通过这个线性地址对这块内存可读可写,但是3环是只读,虽然指向的是同一个物理页,但在User 层是只读的,在Kernnel层是可写的.

5

如上图,查看下内容一样

0x7FFE0300到底存储的是什么?

然后查看下_KUSER_SHARED_DATA这个内存

6

查看到300处偏移就是一个叫SystemCall,这个位置存储的函数有两种情况:

实验:是否支持快速调用

当通过eax=1来执行cpuid指令时,处理器的特征信息被放在ecx和edx寄存器中,其中edx包含了一个SEP位(11位),该位指明了当前处理器知否支持sysenter/sysexit指令

支持:
ntdll.dll!KiFastSystemCall()//这个不是内核函数,是ntdll的

不支持:
ntdll.dll!KiIntSystemCall()
实验如下,改eax=1,ecx,edx清0,命令改成CPUID

7


edx=0F8BFBFF,2进制是

1
‭1111100010111111101111111111‬

 

第11位是1,支持,支持时把KiFastSystemCall()写到300偏移处的地址上,不支持KiIntSystemCall()写过去

进0环需要更改哪些寄存器?

  1. CS的权限由3变为0 意味着需要新的CS

2) SS与CS的权限永远一致 需要新的SS

3) 权限发生切换的时候,堆栈也一定会切换,需要新的ESP

4) 进0环后代码的位置,需要EIP

不支持快速调用时候,中断门进0环:

1
2
3
4
5
6
7
8
9
10
.text:77F070C0                 public KiIntSystemCall
.text:77F070C0 KiIntSystemCall proc near               ; DATA XREF: .text:off_77EF61B8o
.text:77F070C0
.text:77F070C0 arg_4           = byte ptr  8
.text:77F070C0
.text:77F070C0                 lea     edx, [esp+arg_4]//edx是参数指针,系统调用号在eax寄存器
.text:77F070C4                 int     2Eh             ; DOS 2+ internal - EXECUTE COMMAND
.text:77F070C4                                         ; DS:SI -> counted CR-terminated command string
.text:77F070C6                 retn
.text:77F070C6 KiIntSystemCall endp

就2行,把当前函数参数地址存到edx,我们之前往eax存了个内核函数编号,直接通过中断门进入内核。

当CPU支持快速调用时候

1
2
3
text:77F070B0 KiFastSystemCall proc near              ; DATA XREF: .text:off_77EF61B8o
.text:77F070B0                 mov     edx, esp
.text:77F070B2                 sysenter

edx是参数,eax还是编号,没用中断门了,用的sysenter

为什么叫快速调用?

中断门进0环,需要的CS、EIP在IDT表中,需要查内存(SS与ESP由TSS提供),比较慢
而CPU如果支持sysenter指令时,操作系统会提前将CS/SS/ESP/EIP的值存储在MSR寄存器中,sysenter指令执行时,CPU会将MSR寄存器中的值直接写入相关
寄存器,没有读内存的过程,所以叫快速调用,本质是一样的!

中断门 INT 0x2E进0环

步骤一:在IDT表中找到0x2E号门描述符

步骤二:分析CS/SS/ESP/EIP的来源

步骤三:分析EIP是什么

所以做如下实验:

通过windbg先查看IDT表,然后找到2Eh也就是第46项

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
kd> dq 80b95400 l40
80b95400  83e48e00`00080fc0 83e48e00`00081150
80b95410  00008500`00580000 83e4ee00`000815c0
80b95420  83e4ee00`00081748 83e48e00`000818a8
80b95430  83e48e00`00081a1c 83e48e00`00082018
80b95440  00008500`00500000 83e48e00`00082478
80b95450  83e48e00`0008259c 83e48e00`000826dc
80b95460  83e48e00`0008293c 83e48e00`00082c2c
80b95470  83e48e00`000832fc 83e48e00`000836b0
80b95480  83e48e00`000837d4 83e48e00`00083914
80b95490  00008500`00a00000 83e48e00`00083a80
80b954a0  83e48e00`000836b0 83e48e00`000836b0
80b954b0  83e48e00`000836b0 83e48e00`000836b0
80b954c0  83e48e00`000836b0 83e48e00`000836b0
80b954d0  83e48e00`000836b0 83e48e00`000836b0
80b954e0  83e48e00`000836b0 83e48e00`000836b0
80b954f0  83e48e00`000836b0 84228e00`0008eaf8
80b95500  00000000`00080000 00000000`00080000
80b95510  00000000`00080000 00000000`00080000
80b95520  00000000`00080000 00000000`00080000
80b95530  00000000`00080000 00000000`00080000
80b95540  00000000`00080000 00000000`00080000
80b95550  83e4ee00`0008063a 83e4ee00`000807c0
80b95560  83e4ee00`000808fc 83e4ee00`00081498
80b95570  83e3ee00`0008ffee 83e48e00`000836b0
80b95580  83e38e00`0008f6b0 83e38e00`0008f6ba
80b95590  83e38e00`0008f6c4 83e38e00`0008f6ce
80b955a0  83e38e00`0008f6d8 83e38e00`0008f6e2
80b955b0  83e38e00`0008f6ec 84228e00`0008e104
80b955c0  83e38e00`0008f700 83e38e00`0008f70a
80b955d0  83e38e00`0008f714 83e38e00`0008f71e
80b955e0  83e38e00`0008f728 83e38e00`0008f732
80b955f0  83e38e00`0008f73c 83e38e00`0008f746

 

所以通过中断门进入0环就是83e3ee00`0008ffee,

根据描述符,是中断门,代码段选择子cs是0008,要执行的EIP是前后2字节83e3ffee,ss,esp由TSS得的,下面分析进入0环时候,代码从哪开始执行,用U可以对地址反汇编。
所以通过中断门进入0环要执行的函数是

1
2
3
4
5
6
7
8
9
10
kd> u 83e3ffee
nt!KiSystemService://nt,所以是真正的内核模块了
83e3ffee 6a00            push    0
83e3fff0 55              push    ebp
83e3fff1 53              push    ebx
83e3fff2 56              push    esi
83e3fff3 57              push    edi
83e3fff4 0fa0            push    fs
83e3fff6 bb30000000      mov     ebx,30h
83e3fffb 668ee3          mov     fs,bx

sysenter进0环

因为通过sysenter进0环省略查找IDT,TSS表的步骤,所以快,所以这些信息在执行sysenter指令之前,操作系统必须指定0环的CS段、SS段、EIP以及ESP,存在MSR寄存器里
MSR | 地址
—|—
IA32_SYSENTER_CS | 174H
IA32_SYSENTER_ESP | 175H
IA32_SYSENTER_EIP|176H

可以通过RDMSR/WRMST来进行读写(操作系统使用WRMST写该寄存器):

kd> rdmsr 174 //查看CS,cs+8就是ss选择子
kd> rdmsr 175 //查看ESP
kd> rdmsr 176 //查看EIP

参考:Intel白皮书第二卷(搜索sysenter)
这些都是硬件CPU做的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kd> rdmsr 174
msr[174] = 00000000`00000008
kd> rdmst 175
        ^ Bad register error in 'rdmst 175'
kd> rdmsr 175
msr[175] = 00000000`80792000
kd> rdmsr 176
msr[176] = 00000000`83e400c0
kd> u 83e400c0
nt!KiFastCallEntry:
83e400c0 b923000000      mov     ecx,23h
83e400c5 6a30            push    30h
83e400c7 0fa1            pop     fs
83e400c9 8ed9            mov     ds,cx
83e400cb 8ec1            mov     es,cx
83e400cd 648b0d40000000  mov     ecx,dword ptr fs:[40h]
83e400d4 8b6104          mov     esp,dword ptr [ecx+4]
83e400d7 6a23            push    23h

根据查看通过sysenter进入0环,用的函数是KiFastCallEntry

总结:

API通过中断门进0环:

1)  固定中断号为0x2E
2)  CS/EIP由门描述符提供   ESP/SS由TSS提供
3)  进入0环后执行的内核函数:NT!KiSystemService

API通过sysenter指令进0环:

1)  CS/ESP/EIP由MSR寄存器提供(SS是算出来的)
2)  进入0环后执行的内核函数:NT!KiFastCallEntry

内核模块:ntoskrnl.exe/ntkrnlpa.exe

1、自己实现通过中断门直接调用内核函数。

Call XXXXEE000008XXXX//xxxx是内核函数地址偏移,让Eax等于调用号,然后调KiSystemService和KiFastCallEntry,E是构造了个1110,是p位有效,11是3环就能访问我,0是系统段。

进0环后,原来的寄存器存在哪里?

拿KiSystemService举例。
首先要认识几个结构体:
Trap_Frame结构:
不论通过中断门和快速调用进入0环,所有寄存器都存这。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
kd> dt _Ktrap_frame
ntdll!_KTRAP_FRAME
   +0x000 DbgEbp           : Uint4B
   +0x004 DbgEip           : Uint4B
   +0x008 DbgArgMark       : Uint4B
   +0x00c DbgArgPointer    : Uint4B
   +0x010 TempSegCs        : Uint2B
   +0x012 Logging          : UChar
   +0x013 Reserved         : UChar
   +0x014 TempEsp          : Uint4B
   +0x018 Dr0              : Uint4B
   +0x01c Dr1              : Uint4B
   +0x020 Dr2              : Uint4B
   +0x024 Dr3              : Uint4B
   +0x028 Dr6              : Uint4B
   +0x02c Dr7              : Uint4B
   +0x030 SegGs            : Uint4B
   +0x034 SegEs            : Uint4B
   +0x038 SegDs            : Uint4B
   +0x03c Edx              : Uint4B
   +0x040 Ecx              : Uint4B
   +0x044 Eax              : Uint4B
   +0x048 PreviousPreviousMode : Uint4B
   +0x04c ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x050 SegFs            : Uint4B
   +0x054 Edi              : Uint4B
   +0x058 Esi              : Uint4B
   +0x05c Ebx              : Uint4B
   +0x060 Ebp              : Uint4B
   +0x064 ErrCode          : Uint4B
   +0x068 Eip              : Uint4B
   +0x06c SegCs            : Uint4B
   +0x070 EFlags           : Uint4B
   +0x074 HardwareEsp      : Uint4B
   +0x078 HardwareSegSs    : Uint4B
   +0x07c V86Es            : Uint4B
   +0x080 V86Ds            : Uint4B
   +0x084 V86Fs            : Uint4B
   +0x088 V86Gs            : Uint4B

ETHREAD线程相关的结构体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
ntdll!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   +0x200 CreateTime       : _LARGE_INTEGER
   +0x208 ExitTime         : _LARGE_INTEGER
   +0x208 KeyedWaitChain   : _LIST_ENTRY
   +0x210 ExitStatus       : Int4B
   +0x214 PostBlockList    : _LIST_ENTRY
   +0x214 ForwardLinkShadow : Ptr32 Void
   +0x218 StartAddress     : Ptr32 Void
   +0x21c TerminationPort  : Ptr32 _TERMINATION_PORT
   +0x21c ReaperLink       : Ptr32 _ETHREAD
   +0x21c KeyedWaitValue   : Ptr32 Void
   +0x220 ActiveTimerListLock : Uint4B
   +0x224 ActiveTimerListHead : _LIST_ENTRY
   +0x22c Cid              : _CLIENT_ID
   +0x234 KeyedWaitSemaphore : _KSEMAPHORE
   +0x234 AlpcWaitSemaphore : _KSEMAPHORE
   +0x248 ClientSecurity   : _PS_CLIENT_SECURITY_CONTEXT
   +0x24c IrpList          : _LIST_ENTRY
   +0x254 TopLevelIrp      : Uint4B
   +0x258 DeviceToVerify   : Ptr32 _DEVICE_OBJECT
   +0x25c CpuQuotaApc      : Ptr32 _PSP_CPU_QUOTA_APC
   +0x260 Win32StartAddress : Ptr32 Void
   +0x264 LegacyPowerObject : Ptr32 Void
   +0x268 ThreadListEntry  : _LIST_ENTRY
   +0x270 RundownProtect   : _EX_RUNDOWN_REF
   +0x274 ThreadLock       : _EX_PUSH_LOCK
   +0x278 ReadClusterSize  : Uint4B
   +0x27c MmLockOrdering   : Int4B
   +0x280 CrossThreadFlags : Uint4B
   +0x280 Terminated       : Pos 0, 1 Bit
   +0x280 ThreadInserted   : Pos 1, 1 Bit
   +0x280 HideFromDebugger : Pos 2, 1 Bit
   +0x280 ActiveImpersonationInfo : Pos 3, 1 Bit
   +0x280 Reserved         : Pos 4, 1 Bit
   +0x280 HardErrorsAreDisabled : Pos 5, 1 Bit
   +0x280 BreakOnTermination : Pos 6, 1 Bit
   +0x280 SkipCreationMsg  : Pos 7, 1 Bit
   +0x280 SkipTerminationMsg : Pos 8, 1 Bit
   +0x280 CopyTokenOnOpen  : Pos 9, 1 Bit
   +0x280 ThreadIoPriority : Pos 10, 3 Bits
   +0x280 ThreadPagePriority : Pos 13, 3 Bits
   +0x280 RundownFail      : Pos 16, 1 Bit
   +0x280 NeedsWorkingSetAging : Pos 17, 1 Bit
   +0x284 SameThreadPassiveFlags : Uint4B
   +0x284 ActiveExWorker   : Pos 0, 1 Bit
   +0x284 ExWorkerCanWaitUser : Pos 1, 1 Bit
   +0x284 MemoryMaker      : Pos 2, 1 Bit
   +0x284 ClonedThread     : Pos 3, 1 Bit
   +0x284 KeyedEventInUse  : Pos 4, 1 Bit
   +0x284 RateApcState     : Pos 5, 2 Bits
   +0x284 SelfTerminate    : Pos 7, 1 Bit
   +0x288 SameThreadApcFlags : Uint4B
   +0x288 Spare            : Pos 0, 1 Bit
   +0x288 StartAddressInvalid : Pos 1, 1 Bit
   +0x288 EtwPageFaultCalloutActive : Pos 2, 1 Bit
   +0x288 OwnsProcessWorkingSetExclusive : Pos 3, 1 Bit
   +0x288 OwnsProcessWorkingSetShared : Pos 4, 1 Bit
   +0x288 OwnsSystemCacheWorkingSetExclusive : Pos 5, 1 Bit
   +0x288 OwnsSystemCacheWorkingSetShared : Pos 6, 1 Bit
   +0x288 OwnsSessionWorkingSetExclusive : Pos 7, 1 Bit
   +0x289 OwnsSessionWorkingSetShared : Pos 0, 1 Bit
   +0x289 OwnsProcessAddressSpaceExclusive : Pos 1, 1 Bit
   +0x289 OwnsProcessAddressSpaceShared : Pos 2, 1 Bit
   +0x289 SuppressSymbolLoad : Pos 3, 1 Bit
   +0x289 Prefetching      : Pos 4, 1 Bit
   +0x289 OwnsDynamicMemoryShared : Pos 5, 1 Bit
   +0x289 OwnsChangeControlAreaExclusive : Pos 6, 1 Bit
   +0x289 OwnsChangeControlAreaShared : Pos 7, 1 Bit
   +0x28a OwnsPagedPoolWorkingSetExclusive : Pos 0, 1 Bit
   +0x28a OwnsPagedPoolWorkingSetShared : Pos 1, 1 Bit
   +0x28a OwnsSystemPtesWorkingSetExclusive : Pos 2, 1 Bit
   +0x28a OwnsSystemPtesWorkingSetShared : Pos 3, 1 Bit
   +0x28a TrimTrigger      : Pos 4, 2 Bits
   +0x28a Spare1           : Pos 6, 2 Bits
   +0x28b PriorityRegionActive : UChar
   +0x28c CacheManagerActive : UChar
   +0x28d DisablePageFaultClustering : UChar
   +0x28e ActiveFaultCount : UChar
   +0x28f LockOrderState   : UChar
   +0x290 AlpcMessageId    : Uint4B
   +0x294 AlpcMessage      : Ptr32 Void
   +0x294 AlpcReceiveAttributeSet : Uint4B
   +0x298 AlpcWaitListEntry : _LIST_ENTRY
   +0x2a0 CacheManagerCount : Uint4B
   +0x2a4 IoBoostCount     : Uint4B
   +0x2a8 IrpListLock      : Uint4B
   +0x2ac ReservedForSynchTracking : Ptr32 Void
   +0x2b0 CmCallbackListHead : _SINGLE_LIST_ENTRY

上面的结构体有个相对比较重要的结构体,KTHREAD如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
kd> dt _KTHREAD
ntdll!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   上面这个可以拆解会用到03DebugActive
   
   kd> dt _DISPATCHER_HEADER
ntdll!_DISPATCHER_HEADER
   +0x000 Type             : UChar
   +0x001 TimerControlFlags : UChar
   +0x001 Absolute         : Pos 0, 1 Bit
   +0x001 Coalescable      : Pos 1, 1 Bit
   +0x001 KeepShifting     : Pos 2, 1 Bit
   +0x001 EncodedTolerableDelay : Pos 3, 5 Bits
   +0x001 Abandoned        : UChar
   +0x001 Signalling       : UChar
   +0x002 ThreadControlFlags : UChar
   +0x002 CpuThrottled     : Pos 0, 1 Bit
   +0x002 CycleProfiling   : Pos 1, 1 Bit
   +0x002 CounterProfiling : Pos 2, 1 Bit
   +0x002 Reserved         : Pos 3, 5 Bits
   +0x002 Hand             : UChar
   +0x002 Size             : UChar
   +0x003 TimerMiscFlags   : UChar
   +0x003 Index            : Pos 0, 1 Bit
   +0x003 Processor        : Pos 1, 5 Bits
   +0x003 Inserted         : Pos 6, 1 Bit
   +0x003 Expired          : Pos 7, 1 Bit
   +0x003 DebugActive      : UChar
   +0x003 ActiveDR7        : Pos 0, 1 Bit
   +0x003 Instrumented     : Pos 1, 1 Bit
   +0x003 Reserved2        : Pos 2, 4 Bits
   +0x003 UmsScheduled     : Pos 6, 1 Bit
   +0x003 UmsPrimary       : Pos 7, 1 Bit
   +0x003 DpcActive        : UChar
   +0x000 Lock             : Int4B
   +0x004 SignalState      : Int4B
   +0x008 WaitListHead     : _LIST_ENTRY

   
   
   
   +0x010 CycleTime        : Uint8B
   +0x018 HighCycleTime    : Uint4B
   +0x020 QuantumTarget    : Uint8B
   +0x028 InitialStack     : Ptr32 Void
   +0x02c StackLimit       : Ptr32 Void
   +0x030 KernelStack      : Ptr32 Void
   +0x034 ThreadLock       : Uint4B
   +0x038 WaitRegister     : _KWAIT_STATUS_REGISTER
   +0x039 Running          : UChar
   +0x03a Alerted          : [2] UChar
   +0x03c KernelStackResident : Pos 0, 1 Bit
   +0x03c ReadyTransition  : Pos 1, 1 Bit
   +0x03c ProcessReadyQueue : Pos 2, 1 Bit
   +0x03c WaitNext         : Pos 3, 1 Bit
   +0x03c SystemAffinityActive : Pos 4, 1 Bit
   +0x03c Alertable        : Pos 5, 1 Bit
   +0x03c GdiFlushActive   : Pos 6, 1 Bit
   +0x03c UserStackWalkActive : Pos 7, 1 Bit
   +0x03c ApcInterruptRequest : Pos 8, 1 Bit
   +0x03c ForceDeferSchedule : Pos 9, 1 Bit
   +0x03c QuantumEndMigrate : Pos 10, 1 Bit
   +0x03c UmsDirectedSwitchEnable : Pos 11, 1 Bit
   +0x03c TimerActive      : Pos 12, 1 Bit
   +0x03c SystemThread     : Pos 13, 1 Bit
   +0x03c Reserved         : Pos 14, 18 Bits
   +0x03c MiscFlags        : Int4B
   +0x040 ApcState         : _KAPC_STATE
   +0x040 ApcStateFill     : [23] UChar
   +0x057 Priority         : Char
   +0x058 NextProcessor    : Uint4B
   +0x05c DeferredProcessor : Uint4B
   +0x060 ApcQueueLock     : Uint4B
   +0x064 ContextSwitches  : Uint4B
   +0x068 State            : UChar
   +0x069 NpxState         : Char
   +0x06a WaitIrql         : UChar
   +0x06b WaitMode         : Char
   +0x06c WaitStatus       : Int4B
   +0x070 WaitBlockList    : Ptr32 _KWAIT_BLOCK
   +0x074 WaitListEntry    : _LIST_ENTRY
   +0x074 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x07c Queue            : Ptr32 _KQUEUE
   +0x080 WaitTime         : Uint4B
   +0x084 KernelApcDisable : Int2B
   +0x086 SpecialApcDisable : Int2B
   +0x084 CombinedApcDisable : Uint4B
   +0x088 Teb              : Ptr32 Void
   +0x090 Timer            : _KTIMER
   +0x0b8 AutoAlignment    : Pos 0, 1 Bit
   +0x0b8 DisableBoost     : Pos 1, 1 Bit
   +0x0b8 EtwStackTraceApc1Inserted : Pos 2, 1 Bit
   +0x0b8 EtwStackTraceApc2Inserted : Pos 3, 1 Bit
   +0x0b8 CalloutActive    : Pos 4, 1 Bit
   +0x0b8 ApcQueueable     : Pos 5, 1 Bit
   +0x0b8 EnableStackSwap  : Pos 6, 1 Bit
   +0x0b8 GuiThread        : Pos 7, 1 Bit
   +0x0b8 UmsPerformingSyscall : Pos 8, 1 Bit
   +0x0b8 VdmSafe          : Pos 9, 1 Bit
   +0x0b8 UmsDispatched    : Pos 10, 1 Bit
   +0x0b8 ReservedFlags    : Pos 11, 21 Bits
   +0x0b8 ThreadFlags      : Int4B
   +0x0bc ServiceTable     : Ptr32 Void
   +0x0c0 WaitBlock        : [4] _KWAIT_BLOCK
   +0x120 QueueListEntry   : _LIST_ENTRY
   +0x128 TrapFrame        : Ptr32 _KTRAP_FRAME
   +0x12c FirstArgument    : Ptr32 Void
   +0x130 CallbackStack    : Ptr32 Void
   +0x130 CallbackDepth    : Uint4B
   +0x134 ApcStateIndex    : UChar
   +0x135 BasePriority     : Char
   +0x136 PriorityDecrement : Char
   +0x136 ForegroundBoost  : Pos 0, 4 Bits
   +0x136 UnusualBoost     : Pos 4, 4 Bits
   +0x137 Preempted        : UChar
   +0x138 AdjustReason     : UChar
   +0x139 AdjustIncrement  : Char
   +0x13a PreviousMode     : Char
   +0x13b Saturation       : Char
   +0x13c SystemCallNumber : Uint4B
   +0x140 FreezeCount      : Uint4B
   +0x144 UserAffinity     : _GROUP_AFFINITY
   +0x150 Process          : Ptr32 _KPROCESS
   +0x154 Affinity         : _GROUP_AFFINITY
   +0x160 IdealProcessor   : Uint4B
   +0x164 UserIdealProcessor : Uint4B
   +0x168 ApcStatePointer  : [2] Ptr32 _KAPC_STATE
   +0x170 SavedApcState    : _KAPC_STATE
   +0x170 SavedApcStateFill : [23] UChar
   +0x187 WaitReason       : UChar
   +0x188 SuspendCount     : Char
   +0x189 Spare1           : Char
   +0x18a OtherPlatformFill : UChar
   +0x18c Win32Thread      : Ptr32 Void
   +0x190 StackBase        : Ptr32 Void
   +0x194 SuspendApc       : _KAPC
   +0x194 SuspendApcFill0  : [1] UChar
   +0x195 ResourceIndex    : UChar
   +0x194 SuspendApcFill1  : [3] UChar
   +0x197 QuantumReset     : UChar
   +0x194 SuspendApcFill2  : [4] UChar
   +0x198 KernelTime       : Uint4B
   +0x194 SuspendApcFill3  : [36] UChar
   +0x1b8 WaitPrcb         : Ptr32 _KPRCB
   +0x194 SuspendApcFill4  : [40] UChar
   +0x1bc LegoData         : Ptr32 Void
   +0x194 SuspendApcFill5  : [47] UChar
   +0x1c3 LargeStack       : UChar
   +0x1c4 UserTime         : Uint4B
   +0x1c8 SuspendSemaphore : _KSEMAPHORE
   +0x1c8 SuspendSemaphorefill : [20] UChar
   +0x1dc SListFaultCount  : Uint4B
   +0x1e0 ThreadListEntry  : _LIST_ENTRY
   +0x1e8 MutantListHead   : _LIST_ENTRY
   +0x1f0 SListFaultAddress : Ptr32 Void
   +0x1f4 ThreadCounters   : Ptr32 _KTHREAD_COUNTERS
   +0x1f8 XStateSave       : Ptr32 _XSTATE_SAVE

线程有一个结构体描述他的状态如上,CPU也有是PCR
即CPU控制区(Process Control Region)
CPU也有自己的控制块,每一个CPU有一个,叫KPCR,有几个核就几个
查看CPU数量:

1
2
3
4
5
6
7
8
9
kd> dd KeNumberProcessors
83f6c96c  00000001 83ef8f33 00000002 00000001
83f6c97c  00000000 00000000 00000020 1fc10000
83f6c98c  00110006 00003c03 77ab7058 77ab6f58
83f6c99c  77ab6fc0 77ab7008 77aa5a8f 77aa5a8d
83f6c9ac  77aa5a64 00000000 00c671e3 841c55b0
83f6c9bc  8412f4f2 83e80d9c 00000000 00000191
83f6c9cc  83e813e4 00000000 00000000 00000000
83f6c9dc  00000000 83edf6af 00000000 025355a9

还可以通过下面命令查看当前的KPCR存在哪,有几核就几个

1
2
3
kd> dd KiProcessorBlock L8//显示一个说明单核
83f6c8c0  83f2dd20 00000000 00000000 00000000
83f6c8d0  00000000 00000000 00000000 00000000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
dt _KPCR
ntdll!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 Used_StackBase   : Ptr32 Void
   +0x008 Spare2           : Ptr32 Void
   +0x00c TssCopy          : Ptr32 Void
   +0x010 ContextSwitches  : Uint4B
   +0x014 SetMemberCopy    : Uint4B
   +0x018 Used_Self        : Ptr32 Void
   +0x01c SelfPcr          : Ptr32 _KPCR
   +0x020 Prcb             : Ptr32 _KPRCB
   +0x024 Irql             : UChar
   +0x028 IRR              : Uint4B
   +0x02c IrrActive        : Uint4B
   +0x030 IDR              : Uint4B
   +0x034 KdVersionBlock   : Ptr32 Void
   +0x038 IDT              : Ptr32 _KIDTENTRY
   +0x03c GDT              : Ptr32 _KGDTENTRY
   +0x040 TSS              : Ptr32 _KTSS
   +0x044 MajorVersion     : Uint2B
   +0x046 MinorVersion     : Uint2B
   +0x048 SetMember        : Uint4B
   +0x04c StallScaleFactor : Uint4B
   +0x050 SpareUnused      : UChar
   +0x051 Number           : UChar
   +0x052 Spare0           : UChar
   +0x053 SecondLevelCacheAssociativity : UChar
   +0x054 VdmAlert         : Uint4B
   +0x058 KernelReserved   : [14] Uint4B
   +0x090 SecondLevelCacheSize : Uint4B
   +0x094 HalReserved      : [16] Uint4B
   +0x0d4 InterruptMode    : Uint4B
   +0x0d8 Spare1           : UChar
   +0x0dc KernelReserved2  : [17] Uint4B
   +0x120 PrcbData         : _KPRCB

最后一个_KPRCB结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
kd> dt _KPRCB
ntdll!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD
   +0x008 NextThread       : Ptr32 _KTHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD
   +0x010 LegacyNumber     : UChar
   +0x011 NestingLevel     : UChar
   +0x012 BuildType        : Uint2B
   +0x014 CpuType          : Char
   +0x015 CpuID            : Char
   +0x016 CpuStep          : Uint2B
   +0x016 CpuStepping      : UChar
   +0x017 CpuModel         : UChar
   +0x018 ProcessorState   : _KPROCESSOR_STATE
   +0x338 KernelReserved   : [16] Uint4B
   +0x378 HalReserved      : [16] Uint4B
   +0x3b8 CFlushSize       : Uint4B
   +0x3bc CoresPerPhysicalProcessor : UChar
   +0x3bd LogicalProcessorsPerCore : UChar
   +0x3be PrcbPad0         : [2] UChar
   +0x3c0 MHz              : Uint4B
   +0x3c4 CpuVendor        : UChar
   +0x3c5 GroupIndex       : UChar
   +0x3c6 Group            : Uint2B
   +0x3c8 GroupSetMember   : Uint4B
   +0x3cc Number           : Uint4B
   +0x3d0 PrcbPad1         : [72] UChar
   +0x418 LockQueue        : [17] _KSPIN_LOCK_QUEUE
   +0x4a0 NpxThread        : Ptr32 _KTHREAD
   +0x4a4 InterruptCount   : Uint4B
   +0x4a8 KernelTime       : Uint4B
   +0x4ac UserTime         : Uint4B
   +0x4b0 DpcTime          : Uint4B
   +0x4b4 DpcTimeCount     : Uint4B
   +0x4b8 InterruptTime    : Uint4B
   +0x4bc AdjustDpcThreshold : Uint4B
   +0x4c0 PageColor        : Uint4B
   +0x4c4 DebuggerSavedIRQL : UChar
   +0x4c5 NodeColor        : UChar
   +0x4c6 PrcbPad20        : [2] UChar
   +0x4c8 NodeShiftedColor : Uint4B
   +0x4cc ParentNode       : Ptr32 _KNODE
   +0x4d0 SecondaryColorMask : Uint4B
   +0x4d4 DpcTimeLimit     : Uint4B
   +0x4d8 PrcbPad21        : [2] Uint4B
   +0x4e0 CcFastReadNoWait : Uint4B
   +0x4e4 CcFastReadWait   : Uint4B
   +0x4e8 CcFastReadNotPossible : Uint4B
   +0x4ec CcCopyReadNoWait : Uint4B
   +0x4f0 CcCopyReadWait   : Uint4B
   +0x4f4 CcCopyReadNoWaitMiss : Uint4B
   +0x4f8 MmSpinLockOrdering : Int4B
   +0x4fc IoReadOperationCount : Int4B
   +0x500 IoWriteOperationCount : Int4B
   +0x504 IoOtherOperationCount : Int4B
   +0x508 IoReadTransferCount : _LARGE_INTEGER
   +0x510 IoWriteTransferCount : _LARGE_INTEGER
   +0x518 IoOtherTransferCount : _LARGE_INTEGER
   +0x520 CcFastMdlReadNoWait : Uint4B
   +0x524 CcFastMdlReadWait : Uint4B
   +0x528 CcFastMdlReadNotPossible : Uint4B
   +0x52c CcMapDataNoWait  : Uint4B
   +0x530 CcMapDataWait    : Uint4B
   +0x534 CcPinMappedDataCount : Uint4B
   +0x538 CcPinReadNoWait  : Uint4B
   +0x53c CcPinReadWait    : Uint4B
   +0x540 CcMdlReadNoWait  : Uint4B
   +0x544 CcMdlReadWait    : Uint4B
   +0x548 CcLazyWriteHotSpots : Uint4B
   +0x54c CcLazyWriteIos   : Uint4B
   +0x550 CcLazyWritePages : Uint4B
   +0x554 CcDataFlushes    : Uint4B
   +0x558 CcDataPages      : Uint4B
   +0x55c CcLostDelayedWrites : Uint4B
   +0x560 CcFastReadResourceMiss : Uint4B
   +0x564 CcCopyReadWaitMiss : Uint4B
   +0x568 CcFastMdlReadResourceMiss : Uint4B
   +0x56c CcMapDataNoWaitMiss : Uint4B
   +0x570 CcMapDataWaitMiss : Uint4B
   +0x574 CcPinReadNoWaitMiss : Uint4B
   +0x578 CcPinReadWaitMiss : Uint4B
   +0x57c CcMdlReadNoWaitMiss : Uint4B
   +0x580 CcMdlReadWaitMiss : Uint4B
   +0x584 CcReadAheadIos   : Uint4B
   +0x588 KeAlignmentFixupCount : Uint4B
   +0x58c KeExceptionDispatchCount : Uint4B
   +0x590 KeSystemCalls    : Uint4B
   +0x594 AvailableTime    : Uint4B
   +0x598 PrcbPad22        : [2] Uint4B
   +0x5a0 PPLookasideList  : [16] _PP_LOOKASIDE_LIST
   +0x620 PPNPagedLookasideList : [32] _GENERAL_LOOKASIDE_POOL
   +0xf20 PPPagedLookasideList : [32] _GENERAL_LOOKASIDE_POOL
   +0x1820 PacketBarrier    : Uint4B
   +0x1824 ReverseStall     : Int4B
   +0x1828 IpiFrame         : Ptr32 Void
   +0x182c PrcbPad3         : [52] UChar
   +0x1860 CurrentPacket    : [3] Ptr32 Void
   +0x186c TargetSet        : Uint4B
   +0x1870 WorkerRoutine    : Ptr32     void 
   +0x1874 IpiFrozen        : Uint4B
   +0x1878 PrcbPad4         : [40] UChar
   +0x18a0 RequestSummary   : Uint4B
   +0x18a4 SignalDone       : Ptr32 _KPRCB
   +0x18a8 PrcbPad50        : [56] UChar
   +0x18e0 DpcData          : [2] _KDPC_DATA
   +0x1908 DpcStack         : Ptr32 Void
   +0x190c MaximumDpcQueueDepth : Int4B
   +0x1910 DpcRequestRate   : Uint4B
   +0x1914 MinimumDpcRate   : Uint4B
   +0x1918 DpcLastCount     : Uint4B
   +0x191c PrcbLock         : Uint4B
   +0x1920 DpcGate          : _KGATE
   +0x1930 ThreadDpcEnable  : UChar
   +0x1931 QuantumEnd       : UChar
   +0x1932 DpcRoutineActive : UChar
   +0x1933 IdleSchedule     : UChar
   +0x1934 DpcRequestSummary : Int4B
   +0x1934 DpcRequestSlot   : [2] Int2B
   +0x1934 NormalDpcState   : Int2B
   +0x1936 DpcThreadActive  : Pos 0, 1 Bit
   +0x1936 ThreadDpcState   : Int2B
   +0x1938 TimerHand        : Uint4B
   +0x193c LastTick         : Uint4B
   +0x1940 MasterOffset     : Int4B
   +0x1944 PrcbPad41        : [2] Uint4B
   +0x194c PeriodicCount    : Uint4B
   +0x1950 PeriodicBias     : Uint4B
   +0x1958 TickOffset       : Uint8B
   +0x1960 TimerTable       : _KTIMER_TABLE
   +0x31a0 CallDpc          : _KDPC
   +0x31c0 ClockKeepAlive   : Int4B
   +0x31c4 ClockCheckSlot   : UChar
   +0x31c5 ClockPollCycle   : UChar
   +0x31c6 PrcbPad6         : [2] UChar
   +0x31c8 DpcWatchdogPeriod : Int4B
   +0x31cc DpcWatchdogCount : Int4B
   +0x31d0 ThreadWatchdogPeriod : Int4B
   +0x31d4 ThreadWatchdogCount : Int4B
   +0x31d8 KeSpinLockOrdering : Int4B
   +0x31dc PrcbPad70        : [1] Uint4B
   +0x31e0 WaitListHead     : _LIST_ENTRY
   +0x31e8 WaitLock         : Uint4B
   +0x31ec ReadySummary     : Uint4B
   +0x31f0 QueueIndex       : Uint4B
   +0x31f4 DeferredReadyListHead : _SINGLE_LIST_ENTRY
   +0x31f8 StartCycles      : Uint8B
   +0x3200 CycleTime        : Uint8B
   +0x3208 HighCycleTime    : Uint4B
   +0x320c PrcbPad71        : Uint4B
   +0x3210 PrcbPad72        : [2] Uint8B
   +0x3220 DispatcherReadyListHead : [32] _LIST_ENTRY
   +0x3320 ChainedInterruptList : Ptr32 Void
   +0x3324 LookasideIrpFloat : Int4B
   +0x3328 MmPageFaultCount : Int4B
   +0x332c MmCopyOnWriteCount : Int4B
   +0x3330 MmTransitionCount : Int4B
   +0x3334 MmCacheTransitionCount : Int4B
   +0x3338 MmDemandZeroCount : Int4B
   +0x333c MmPageReadCount  : Int4B
   +0x3340 MmPageReadIoCount : Int4B
   +0x3344 MmCacheReadCount : Int4B
   +0x3348 MmCacheIoCount   : Int4B
   +0x334c MmDirtyPagesWriteCount : Int4B
   +0x3350 MmDirtyWriteIoCount : Int4B
   +0x3354 MmMappedPagesWriteCount : Int4B
   +0x3358 MmMappedWriteIoCount : Int4B
   +0x335c CachedCommit     : Uint4B
   +0x3360 CachedResidentAvailable : Uint4B
   +0x3364 HyperPte         : Ptr32 Void
   +0x3368 PrcbPad8         : [4] UChar
   +0x336c VendorString     : [13] UChar
   +0x3379 InitialApicId    : UChar
   +0x337a LogicalProcessorsPerPhysicalProcessor : UChar
   +0x337b PrcbPad9         : [5] UChar
   +0x3380 FeatureBits      : Uint4B
   +0x3388 UpdateSignature  : _LARGE_INTEGER
   +0x3390 IsrTime          : Uint8B
   +0x3398 RuntimeAccumulation : Uint8B
   +0x33a0 PowerState       : _PROCESSOR_POWER_STATE
   +0x3468 DpcWatchdogDpc   : _KDPC
   +0x3488 DpcWatchdogTimer : _KTIMER
   +0x34b0 WheaInfo         : Ptr32 Void
   +0x34b4 EtwSupport       : Ptr32 Void
   +0x34b8 InterruptObjectPool : _SLIST_HEADER
   +0x34c0 HypercallPageList : _SLIST_HEADER
   +0x34c8 HypercallPageVirtual : Ptr32 Void
   +0x34cc VirtualApicAssist : Ptr32 Void
   +0x34d0 StatisticsPage   : Ptr32 Uint8B
   +0x34d4 RateControl      : Ptr32 Void
   +0x34d8 Cache            : [5] _CACHE_DESCRIPTOR
   +0x3514 CacheCount       : Uint4B
   +0x3518 CacheProcessorMask : [5] Uint4B
   +0x352c PackageProcessorSet : _KAFFINITY_EX
   +0x3538 PrcbPad91        : [1] Uint4B
   +0x353c CoreProcessorSet : Uint4B
   +0x3540 TimerExpirationDpc : _KDPC
   +0x3560 SpinLockAcquireCount : Uint4B
   +0x3564 SpinLockContentionCount : Uint4B
   +0x3568 SpinLockSpinCount : Uint4B
   +0x356c IpiSendRequestBroadcastCount : Uint4B
   +0x3570 IpiSendRequestRoutineCount : Uint4B
   +0x3574 IpiSendSoftwareInterruptCount : Uint4B
   +0x3578 ExInitializeResourceCount : Uint4B
   +0x357c ExReInitializeResourceCount : Uint4B
   +0x3580 ExDeleteResourceCount : Uint4B
   +0x3584 ExecutiveResourceAcquiresCount : Uint4B
   +0x3588 ExecutiveResourceContentionsCount : Uint4B
   +0x358c ExecutiveResourceReleaseExclusiveCount : Uint4B
   +0x3590 ExecutiveResourceReleaseSharedCount : Uint4B
   +0x3594 ExecutiveResourceConvertsCount : Uint4B
   +0x3598 ExAcqResExclusiveAttempts : Uint4B
   +0x359c ExAcqResExclusiveAcquiresExclusive : Uint4B
   +0x35a0 ExAcqResExclusiveAcquiresExclusiveRecursive : Uint4B
   +0x35a4 ExAcqResExclusiveWaits : Uint4B
   +0x35a8 ExAcqResExclusiveNotAcquires : Uint4B
   +0x35ac ExAcqResSharedAttempts : Uint4B
   +0x35b0 ExAcqResSharedAcquiresExclusive : Uint4B
   +0x35b4 ExAcqResSharedAcquiresShared : Uint4B
   +0x35b8 ExAcqResSharedAcquiresSharedRecursive : Uint4B
   +0x35bc ExAcqResSharedWaits : Uint4B
   +0x35c0 ExAcqResSharedNotAcquires : Uint4B
   +0x35c4 ExAcqResSharedStarveExclusiveAttempts : Uint4B
   +0x35c8 ExAcqResSharedStarveExclusiveAcquiresExclusive : Uint4B
   +0x35cc ExAcqResSharedStarveExclusiveAcquiresShared : Uint4B
   +0x35d0 ExAcqResSharedStarveExclusiveAcquiresSharedRecursive : Uint4B
   +0x35d4 ExAcqResSharedStarveExclusiveWaits : Uint4B
   +0x35d8 ExAcqResSharedStarveExclusiveNotAcquires : Uint4B
   +0x35dc ExAcqResSharedWaitForExclusiveAttempts : Uint4B
   +0x35e0 ExAcqResSharedWaitForExclusiveAcquiresExclusive : Uint4B
   +0x35e4 ExAcqResSharedWaitForExclusiveAcquiresShared : Uint4B
   +0x35e8 ExAcqResSharedWaitForExclusiveAcquiresSharedRecursive : Uint4B
   +0x35ec ExAcqResSharedWaitForExclusiveWaits : Uint4B
   +0x35f0 ExAcqResSharedWaitForExclusiveNotAcquires : Uint4B
   +0x35f4 ExSetResOwnerPointerExclusive : Uint4B
   +0x35f8 ExSetResOwnerPointerSharedNew : Uint4B
   +0x35fc ExSetResOwnerPointerSharedOld : Uint4B
   +0x3600 ExTryToAcqExclusiveAttempts : Uint4B
   +0x3604 ExTryToAcqExclusiveAcquires : Uint4B
   +0x3608 ExBoostExclusiveOwner : Uint4B
   +0x360c ExBoostSharedOwners : Uint4B
   +0x3610 ExEtwSynchTrackingNotificationsCount : Uint4B
   +0x3614 ExEtwSynchTrackingNotificationsAccountedCount : Uint4B
   +0x3618 Context          : Ptr32 _CONTEXT
   +0x361c ContextFlags     : Uint4B
   +0x3620 ExtendedState    : Ptr32 _XSAVE_AREA

7

最后面4个是保护模式下用不的到的,中断门在发生权限切换时候,会向0环的堆栈压入5个值,就是0x068到0x078,快速调用没有。
代码中push 0 ,就是0x64,errorcode,

下面是KiSystemServer的反汇编加注释,用到了上面的结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
.text:0043567E _KiSystemService proc near              ; CODE XREF: ZwAcceptConnectPort(x,x,x,x,x,x)+Cp
.text:0043567E                                         ; ZwAccessCheck(x,x,x,x,x,x,x,x)+Cp ...
.text:0043567E
.text:0043567E arg_0           = dword ptr  4
.text:0043567E
.text:0043567E                 push    0               ; _KTRAP_FRAME +0x064 ErrCode
.text:00435680                 push    ebp             ; 0x060 Ebp,3环寄存器入栈
.text:00435681                 push    ebx             ; 0x05C,ebx
.text:00435682                 push    esi             ; 0x058 Esi
.text:00435683                 push    edi             ; 0x054 Edi
.text:00435684                 push    fs              ; 0x050 SegFs
.text:00435686                 mov     ebx, 30h        ; 为FS寄存器赋值,30就是段选择子,在GDTR找到相应的段描述符,加载到,FS,指向KPCR结构体
.text:0043568B                 mov     fs, bx          ; Windows内核有个特殊的基本要求,就是只要CPU在内核运行,就得使
.text:0043568B                                         ; mov ebx,30 //0011 0000  所以就是0环GDT索引6
.text:0043568B                                         ; mov fs,bx
.text:0043568B                                         ;
.text:0043568B                                         ; 0环的FS.Base指向CPU自己的KPCR,不是指向当前线程
.text:0043568B                                         ; 选择码,0x30的结构分析如下:
.text:0043568B                                         ; 1.bit0~bit1:RPL,Requested Privilege Level,要求运行的级别,这里是0
.text:0043568B                                         ; 2.bit2:找GDT还是IDT,这里是0,GDT
.text:0043568B                                         ; 3.bit3!bit15,是在GDT或者IDT的下标
.text:0043568B                                         ; windbg查看段描述符:834093f2 dc003748
.text:0043568B                                         ; Base:83f2dc00 指向当前的_KPCR
.text:0043568E                 mov     ebx, 23h
.text:00435693                 mov     ds, ebx
.text:00435695                 mov     es, ebx
.text:00435697                 mov     esi, large fs:124h ; 查看下KPCR偏移124h是什么,查训发现是当前CPU所执行线程的_ETHREAD
.text:0043569E                 push    large dword ptr fs:0 ; 保存老的ExceptionList
.text:0043569E                                         ; _KPCR偏移+0x00->NT_TIB->ExceptionList
.text:004356A5                 mov     large dword ptr fs:0, 0FFFFFFFFh ; 新的ExceptonList为空白,因为3环的异常链表,不能用,要进0环了
.text:004356B0                 push    dword ptr [esi+13Ah] ; 因为Esi存的_KTHREAD,他的偏移13A存的PreviousMode,
.text:004356B0                                         ; 就是保存老的先前模式到堆栈
.text:004356B0                                         ; 先前模式就是当调用这些代码时候,原来是几环的数就是几,比如原来0环,先前模式就是0,原来3环就是1
.text:004356B0                                         ; 因为有些内核代码可以从0和3调用,但是执行内容不一样,通过这个知道执行什么。
.text:004356B6                 sub     esp, 48h        ; ESP 提升到_KTRAP_FRAME结构体第一个成员,也就是这个结构体指针
.text:004356B9                 mov     ebx, [esp+68h+arg_0] ; 查了下这个位置是3环CS
.text:004356B9                                         ; 所以这句是取出3环压入的参数CS _KTRAP_FRAME + 0x6C
.text:004356BD                 and     ebx, 1          ; 上面的CS跟1与运算
.text:004356BD                                         ; 0环最低位是0,3环最低位为1
.text:004356C0                 mov     [esi+13Ah], bl  ; 上面的运算结果存到esi+0x13Ah这个位置的偏移,就是新的"先前模式"
.text:004356C6                 mov     ebp, esp        ; 抬高栈针,ebp=esp=_KTRAP_FRAME指针
.text:004356C8                 mov     ebx, [esi+128h] ; _KTHTEAD中的TrapFrame给ebx
.text:004356CE                 mov     [ebp+3Ch], ebx  ; 将_KTHREAD中的Trap_Frame暂时存在这个位置后面
.text:004356CE                                         ; //会将这个值取出来,重新恢复给_KTHREAD的Trap_Frame
.text:004356CE                                         ;
.text:004356CE                                         ; 零时存在这
.text:004356D1                 and     dword ptr [ebp+2Ch], 0 ; Dr7清0
.text:004356D5                 test    byte ptr [esi+3], 0DFh ; 查看当前线程是否处于调试状态
.text:004356D5                                         ; 看看是不是-1,
.text:004356D9                 mov     [esi+128h], ebp ; 因为有改变堆栈中的_KTRAP_FRAME,将其重新赋值给_KTHREAD中的TRAPFRAME
.text:004356DF                 cld
.text:004356E0                 jnz     Dr_kss_a        ; 处于调试的话跳转,跳转那边的代码是讲调试寄存器都存到Trap_Frame里
.text:004356E6
.text:004356E6 loc_4356E6:                             ; CODE XREF: Dr_kss_a+Dj
.text:004356E6                                         ; Dr_kss_a+79j
.text:004356E6                 mov     ebx, [ebp+60h]  ; 3环的Ebx给ebx
.text:004356E9                 mov     edi, [ebp+68h]  ; 3环的Eip
.text:004356EC                 mov     [ebp+0Ch], edx  ; edx存的3环参数指针:
.text:004356EC                                         ;
.text:004356EC                                         ; _kiFastSystemCall函数
.text:004356EC                                         ;
.text:004356EC                                         ; mov edx,esp
.text:004356EC                                         ;
.text:004356EC                                         ; sysenter
.text:004356EF                 mov     dword ptr [ebp+8], 0BADB0D00h ; 这个是操作系统的标志
.text:004356F6                 mov     [ebp+0], ebx    ; 3环的ebp存储到KTRAP_FRAME+0x000 DbgEbp的位置
.text:004356F9                 mov     [ebp+4], edi    ; 3环的ebp存储到KTRAP_FRAME+0x004 DbgEip的位置
.text:004356FC                 sti
.text:004356FD                 jmp     loc_4357DF      ; 跳到KiFastCallEntry
.text:004356FD _KiSystemService endp

最后还是跳到了KiFastCallEntry,最后发现从两个口进来最后都要执行一样的代码

参考资料:

[1]:毛德操,《Windows内核情景分析》
[2]:滴水视频
[3]: 一大堆的别人的博客

更多推荐

系统调用笔记(1)

本文发布于:2023-04-13 23:08:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/57dc8b2ca3049e5b3fa9295765f666ff.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:笔记   系统

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!

  • 73932文章数
  • 14阅读数
  • 0评论数