API函数的调用过程(SystemServiceTable)

在上中,讲到进0环后,3环的各种寄存器都会保留到
_Trap_Frame结构体中,这篇我讲解

如何根据系统服务号(eax中存储)找到要执行的内核函数?
调用时参数是存储到3环的堆栈,如何传递给内核函数?

SystemServiceTable 系统服务表

系统调用笔记(2)

系统服务表


ServiceTable存了系统服务表里函数地址表(4字节)
Count是当前系统服务表被调用了几次
serviceLimit存了有多少个函数
ArgmentTable存了有多少个参数(以字节为单位,比如穿了2个参数,每个参数4字节,所以这里存8,一个单元1字节)
绿色的是导出的函数

黄色结构是一样的,区别就是绿色的是Ntoskrl.exe的,黄色的是Win32k.sys(图形显示之类的模块)的。

那么程序执行的时候去哪找系统服务表,是_KTHREAD的偏移0xE0处。

下面系统服务号eax怎么找这个对应的函数呢,虽然eax32位,真正使用的只有13位,如下

判断要调用的函数在哪个表

系统调用笔记(2)

系统服务号


低12位找对应偏移的函数,相同维序的参数表就是这个函数的参数。
下面来分析代码,2种调用除了开始寄存器保存不一样(KiSystemServer多做了一些读取内存寄存器的操作),后来都执行相同的代码所以直接开始分析KiSystemServer执行完跳转到KiFastCallEntry里的代码

下面先列一下不同于KiSystemServer,KiFastCallEntry多用到的结构体

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
kd> dt _KTSS
nt!_KTSS
   +0x000 Backlink         : Uint2B
   +0x002 Reserved0        : Uint2B
   +0x004 Esp0             : Uint4B
   +0x008 Ss0              : Uint2B
   +0x00a Reserved1        : Uint2B
   +0x00c NotUsed1         : [4] Uint4B
   +0x01c CR3              : Uint4B
   +0x020 Eip              : Uint4B
   +0x024 EFlags           : Uint4B
   +0x028 Eax              : Uint4B
   +0x02c Ecx              : Uint4B
   +0x030 Edx              : Uint4B
   +0x034 Ebx              : Uint4B
   +0x038 Esp              : Uint4B
   +0x03c Ebp              : Uint4B
   +0x040 Esi              : Uint4B
   +0x044 Edi              : Uint4B
   +0x048 Es               : Uint2B
   +0x04a Reserved2        : Uint2B
   +0x04c Cs               : Uint2B
   +0x04e Reserved3        : Uint2B
   +0x050 Ss               : Uint2B
   +0x052 Reserved4        : Uint2B
   +0x054 Ds               : Uint2B
   +0x056 Reserved5        : Uint2B
   +0x058 Fs               : Uint2B
   +0x05a Reserved6        : Uint2B
   +0x05c Gs               : Uint2B
   +0x05e Reserved7        : Uint2B
   +0x060 LDT              : Uint2B
   +0x062 Reserved8        : Uint2B
   +0x064 Flags            : Uint2B
   +0x066 IoMapBase        : Uint2B
   +0x068 IoMaps           : [1] _KiIoAccessMap
   +0x208c IntDirectionMap  : [32] UChar

FS寄存器,在用户层的时候,指向的是TEB,在内核层的时候,指向的是KPC
下面是通过IDA观察的_KiSystemService函数

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
248
.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环的EPB给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
.text:004356FD
.text:00435702
.text:00435702 ; =============== S U B R O U T I N E =======================================
.text:00435702
.text:00435702
.text:00435702 _KiFastCallEntry2 proc near             ; DATA XREF: _KiTrap01:loc_436724o
.text:00435702                 mov     ecx, 30h
.text:00435707                 mov     fs, ecx
.text:00435709                 mov     ecx, 23h
.text:0043570E                 mov     ds, ecx
.text:00435710                 mov     es, ecx
.text:00435712                 mov     ecx, large fs:40h
.text:00435719                 mov     esp, [ecx+4]
.text:0043571C                 push    23h
.text:0043571E                 push    edx
.text:0043571F                 pushf
.text:00435720                 or      byte ptr [esp+1], 1
.text:00435725                 jmp     short loc_43576B ; Sanitize eflags, clear direction, NT etc;设置eflags为2,,表示所有标志位都是0(中断被关闭),就是清除所有标志位
.text:00435725 _KiFastCallEntry2 endp
.text:00435725
.text:00435727 ; ---------------------------------------------------------------------------
.text:00435727 ; START OF FUNCTION CHUNK FOR _KiFastCallEntry
.text:00435727
.text:00435727 loc_435727:                             ; CODE XREF: _KiFastCallEntry:loc_43574Bj
.text:00435727                 mov     ecx, large fs:40h
.text:0043572E                 mov     esp, [ecx+4]
.text:00435731                 push    0
.text:00435733                 push    0
.text:00435735                 push    0
.text:00435737                 push    0
.text:00435739                 push    23h
.text:0043573B                 push    0
.text:0043573D                 push    20202h
.text:00435742                 push    1Bh
.text:00435744                 push    0
.text:00435746                 jmp     _KiTrap06
.text:0043574B ; ---------------------------------------------------------------------------
.text:0043574B
.text:0043574B loc_43574B:                             ; CODE XREF: _KiFastCallEntry+62j
.text:0043574B                 jmp     short loc_435727
.text:0043574B ; END OF FUNCTION CHUNK FOR _KiFastCallEntry
.text:0043574B ; ---------------------------------------------------------------------------
.text:0043574D                 align 10h
.text:00435750
.text:00435750 ; =============== S U B R O U T I N E =======================================
.text:00435750
.text:00435750 ; ;此时:
.text:00435750 ; ;eax指向服务编号
.text:00435750 ; ;edx指向当前用户栈,edx+8为参数列表
.text:00435750 ;
.text:00435750 ; KGDT_R3_DATA OR RPL_MASK  给ecx
.text:00435750
.text:00435750 _KiFastCallEntry proc near              ; DATA XREF: KiLoadFastSyscallMachineSpecificRegisters(x)+21o
.text:00435750                                         ; _KiTrap01+71o
.text:00435750
.text:00435750 var_7C          = dword ptr -7Ch
.text:00435750 var_B           = byte ptr -0Bh
.text:00435750
.text:00435750 ; FUNCTION CHUNK AT .text:00435727 SIZE 00000026 BYTES
.text:00435750 ; FUNCTION CHUNK AT .text:00435A75 SIZE 00000014 BYTES
.text:00435750 ; FUNCTION CHUNK AT .text:00435BCB SIZE 00000038 BYTES
.text:00435750 ; FUNCTION CHUNK AT .text:00435C04 SIZE 0000001A BYTES
.text:00435750
.text:00435750                 mov     ecx, 23h
.text:00435755                 push    30h             ; 这里的30是KGDT_R0_PCR,也就是0环的GDT的PCR,要给fs,使fs指向KPCR
.text:00435757                 pop     fs              ; 为FS寄存器赋值,30就是段选择子,在GDTR找到相应的段描述符,加载到,FS,指向KPCR结构体
.text:00435759                 mov     ds, ecx         ; ds指向用户数据段
.text:0043575B                 mov     es, ecx         ; es指向用户数据段
.text:0043575D                 mov     ecx, large fs:40h ; 传说中的TSS,保存了一大堆寄存器的值
.text:00435764                 mov     esp, [ecx+4]    ; tts中获得当前线程堆栈的esp,0环ESP给ESP
.text:00435767                 push    23h             ; 23是 KGDT_R3_DATA OR RPL_MASK   ; Push user SS(压入用户态线程的堆栈段寄存器ss)
.text:00435769                 push    edx             ; edx,参数入栈,
.text:00435769                                         ; edx保存的是用户层的堆栈,也就是Push ESP(压入esp)
.text:0043576A                 pushf                   ; 压入标志寄存器
.text:0043576B
.text:0043576B loc_43576B:                             ; CODE XREF: _KiFastCallEntry2+23j
.text:0043576B                 push    2               ; Sanitize eflags, clear direction, NT etc;设置eflags为2,,表示所有标志位都是0(中断被关闭),就是清除所有标志位
.text:0043576D                 add     edx, 8          ; edx+8就是dex移动到了参数位置
.text:00435770                 popf                    ; .errnz(EFLAGS_INTERRUPT_MASK AND 0FFFF00FFh)
.text:00435771                 or      [esp+0Ch+var_B], 2 ; or byte ptr [esp+1], EFLAGS_INTERRUPT_MASK/0100h ; Enable interrupts in eflags(打开用户态eflags的中断)
.text:00435776                 push    1Bh             ; Push user CS
.text:00435778                 push    dword ptr ds:0FFDF0304h ; push return address(使其返回时指向用户空间
.text:00435778                                         ; push dword ptr ds:[USER_SHARED_DATA+UsSystemCallReturn] ;
.text:0043577E                 push    0               ; put pad dword for error on stack
.text:00435780                 push    ebp             ;  save the non-volatile registers
.text:00435781                 push    ebx
.text:00435782                 push    esi
.text:00435783                 push    edi             ; 保存现场
.text:00435784                 mov     ebx, large fs:1Ch ; Ptr32 _KPCR     指向KPCR自己
.text:0043578B                 push    3Bh             ; Push user mode FS
.text:0043578B                                         ; push KGDT_R3_TEB OR RPL_MASK
.text:0043578D                 mov     esi, [ebx+124h] ; esi为指向当前线程的结构体KTHREAD
.text:00435793                 push    dword ptr [ebx] ; 吧KPCR入栈
.text:00435795                 mov     dword ptr [ebx], 0FFFFFFFFh ; ebx等于-1
.text:0043579B                 mov     ebp, [esi+28h]  ; 这个位置是InitialStack
.text:0043579B                                         ; 使ebp指向当前线程堆栈的栈顶
.text:0043579E                 push    1               ; Save previous mode as user(保存先前模式)
.text:004357A0                 sub     esp, 48h        ; 给ESP分配48h字节, 也就是DbgEbp到Eax所占据的空间
.text:004357A0                                         ; allocate remainder of trap frame
.text:004357A3                 sub     ebp, 29Ch       ; sub ebp, NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH
.text:004357A3                                         ; 就是ebp指向了 _Ktrap_frame
.text:004357A9                 mov     byte ptr [esi+13Ah], 1 ; esi+0x13Ah这个位置的偏移,就是新的"先前模式"为1,就是之前是从3环调用的这个代码
.text:004357B0                 cmp     ebp, esp        ; 判断堆栈内压入的值是否正确(这些堆栈内压入的东西,就好比一个trap框架)
.text:004357B2                 jnz     short loc_43574B ; 不正确重新来一遍
.text:004357B4                 and     dword ptr [ebp+2Ch], 0 ; sDr7置0
.text:004357B8                 test    byte ptr [esi+3], 0DFh ; 检查是否被调试
.text:004357BC                 mov     [esi+128h], ebp ; 重新把修改过的TrapFrame设置回_KTHREAD的相应参数位置
.text:004357C2                 jnz     Dr_FastCallDrSave ; 处于调试则保存那些寄存器
.text:004357C8
.text:004357C8 loc_4357C8:                             ; CODE XREF: Dr_FastCallDrSave+Dj
.text:004357C8                                         ; Dr_FastCallDrSave+79j
.text:004357C8                 mov     ebx, [ebp+60h]  ; Ebp给ebx
.text:004357CB                 mov     edi, [ebp+68h]  ; eip给Edi
.text:004357CE                 mov     [ebp+0Ch], edx  ; 参数地址给DbgArgPointer
.text:004357D1                 mov     dword ptr [ebp+8], 0BADB0D00h
.text:004357D8                 mov     [ebp+0], ebx    ; 3环ebp给调试DbgEbp
.text:004357DB                 mov     [ebp+4], edi    ; 3环Eip给DbgEip
.text:004357DE                 sti                     ; 开中断,允许硬件中断
.text:004357DF
.text:004357DF loc_4357DF:                             ; CODE XREF: _KiBBTUnexpectedRange+18j
.text:004357DF                                         ; _KiSystemService+7Fj
.text:004357DF                 mov     edi, eax        ; 取出系统调用号,给edi
.text:004357E1                 shr     edi, 8          ; 系统调用号右移8位
.text:004357E4                 and     edi, 10h        ; 将第12位;与1与,得到的数,看看是哪个的系统服务表,是Ntoskrl的还是Win32k.sys的
.text:004357E7                 mov     ecx, edi        ; 调用号给ecx
.text:004357E9                 add     edi, [esi+0BCh] ; edi的值加上ServiceTable,如果0就是第一个表,1就是第二个表
.text:004357E9                                         ; 就是SSDT表
.text:004357EF                 mov     ebx, eax        ; 调用序号给ebx
.text:004357F1                 and     eax, 0FFFh      ; 系统调用号,只要后面12位
.text:004357F6                 cmp     eax, [edi+8]    ; 调用号跟系统表函数总数作比较
.text:004357F9                 jnb     _KiBBTUnexpectedRange ; 大于等于说明越界,到处理越界的地方去
.text:004357FF                 cmp     ecx, 10h        ; 看看是1还是0,就是说看看是哪一张表
.text:00435802                 jnz     short loc_43581E ; 是0,第一张表往上面跳转
.text:00435804                 mov     ecx, [esi+88h]  ; Teb给ecx
.text:0043580A                 xor     esi, esi        ; esi清0
.text:0043580C
.text:0043580C loc_43580C:                             ; DATA XREF: _KiTrap0E+156o
.text:0043580C                 or      esi, [ecx+0F70h]
.text:00435812                 jz      short loc_43581E
.text:00435814                 push    edx
.text:00435815                 push    eax
.text:00435816                 call    ds:_KeGdiFlushUserBatch ; 是第二张表跳转到的函数,一般都是图像相关,动态加载的
.text:0043581C                 pop     eax
.text:0043581D                 pop     edx
.text:0043581E
.text:0043581E loc_43581E:                             ; CODE XREF: _KiFastCallEntry+B2j
.text:0043581E                                         ; _KiFastCallEntry+C2j
.text:0043581E                 inc     large dword ptr fs:6B0h
.text:00435825                 mov     esi, edx        ; edx存储着3环传入函数的指针
.text:00435827                 xor     ecx, ecx
.text:00435829                 mov     edx, [edi+0Ch]  ; edi存的SSDT表,所以这里+0x0Ch是SSDT参数表起始的的地址
.text:0043582C                 mov     edi, [edi]      ; 指向函数表的地址
.text:0043582E                 mov     cl, [eax+edx]   ; eax系统调用号 参数表+调用号得到参数个数
.text:00435831                 mov     edx, [edi+eax*4] ; 0环函数的地址,函数地址表参数4字节
.text:00435834                 sub     esp, ecx        ; 提升堆栈,提高为Cl,因为参数是3环的,要把3环参数存到0环,所以是抬高这么高的栈针
.text:00435836                 shr     ecx, 2          ; 为了下面rep movsd,一次复制4字节,复制ecx次,ecx保存参数个数单位是一字节,所以这里要除以4
.text:00435839                 mov     edi, esp        ; 设置要复制的地址
.text:0043583B                 cmp     esi, ds:_MmUserProbeAddress ; 判断用户函数地址范围有没有越界
.text:00435841                 jnb     loc_435A75
.text:00435847
.text:00435847 loc_435847:                             ; CODE XREF: _KiFastCallEntry+329j
.text:00435847                                         ; DATA XREF: _KiTrap0E:loc_438AD8o
.text:00435847                 rep movsd               ; 开始复制参数
.text:00435849                 test    byte ptr [ebp+6Ch], 1 ; SegCs
.text:0043584D                 jz      short loc_435865
.text:0043584F                 mov     ecx, large fs:124h
.text:00435856                 mov     edi, [esp+7Ch+var_7C]
.text:00435859                 mov     [ecx+13Ch], ebx
.text:0043585F                 mov     [ecx+12Ch], edi
.text:00435865
.text:00435865 loc_435865:                             ; CODE XREF: _KiFastCallEntry+FDj
.text:00435865                 mov     ebx, edx
.text:00435867                 test    byte ptr ds:dword_52E0C8, 40h
.text:0043586E                 setnz   byte ptr [ebp+12h]
.text:00435872                 jnz     loc_435C04
.text:00435878
.text:00435878 loc_435878:                             ; CODE XREF: _KiFastCallEntry+4BBj
.text:00435878                 call    ebx             ; 调用函数

API函数的调用过程(SSDT)

在上一节课中,我们讲到系统服务表的结构,以及如何找到系统服务
表(KTHREAD 0xbc偏移).

也可以通过SSDT访问
SSDT 的全称是 System Services Descriptor Table,系统服务描述符表
kd> dd KeServiceDescriptorTable(SSDT)ntosKrl是内核导出的
导出的 声明一下就可以使用了
kd> dd KeServiceDescriptorTableShadow(SSDT Shadow)
未导出 需要用其他的方式来查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kd> dd KeServiceDescriptorTable
83f789c0  83e8cd9c 00000000 00000191 83e8d3e4
83f789d0  00000000 00000000 00000000 00000000
83f789e0  83eeb6af 00000000 025355a9 000000bb
83f789f0  00000011 00000100 5385d2ba d717548f
83f78a00  83e8cd9c 00000000 00000191 83e8d3e4
83f78a10  95d46000 00000000 00000339 95d4702c
83f78a20  00000000 00000000 83f78a24 00000340
83f78a30  00000340 865fab00 00000007 00000000


kd> dd KeServiceDescriptorTableShadow
83f78a00  83e8cd9c 00000000 00000191 83e8d3e4
83f78a10  95d46000 00000000 00000339 95d4702c
83f78a20  00000000 00000000 83f78a24 00000340
83f78a30  00000340 865fab00 00000007 00000000
83f78a40  865faa38 865fa7e0 865fa970 865fa8a8
83f78a50  00000000 865fa718 00000000 00000000
83f78a60  83e86809 83e93eed 83ea23a5 00000003
83f78a70  80783000 80784000 00000120 ffffffff

因为KeServiceDescriptorTableShadow没有导出,所以一般采用内存搜索获取这张表

参考资料:

[1]:毛德操,《Windows内核情景分析》
[2]:滴水视频
[3]: 一大堆的别人的博客,重点博客https://blog.csdn.net/Sunny_wwc/article/details/5939848

相关文章:

  • 2022-12-23
  • 2021-06-13
  • 2021-07-19
  • 2021-06-24
  • 2021-10-15
  • 2021-09-04
  • 2021-09-08
  • 2022-01-06
猜你喜欢
  • 2021-07-07
  • 2022-12-23
  • 2021-10-09
  • 2021-08-14
  • 2021-12-20
  • 2021-11-29
  • 2021-05-24
相关资源
相似解决方案