21 特权级与内核安全示例

参考

https://blog.51cto.com/13475106/category6.html及狄泰软件相关课程

 

Q:通常情况下选择子中的RPL与对应描述符中的DPL相同,那么是否可以取缔RPL?
RPL是保证内核数据安全的关键要素之一;在内核代码中有决定性作用,绝对不能取缔

A.获取操作系统的内核

操作系统-特权级与内核安全示例
该实验主要通过调用门调用将内核数据进行打印
操作系统-特权级与内核安全示例操作系统-特权级与内核安全示例
具体的实现代码如下

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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
%include "inc.asm"
 
org 0x9000
 
jmp ENTRY_SEGMENT
 
[section .gdt]
; GDT definition
;                                      段基址,       段界限,             段属性
GDT_ENTRY            :     Descriptor    0,            0,                0
CODE32_DESC          :     Descriptor    0,    Code32SegLen - 1,         DA_C + DA_32 + DA_DPL3
VIDEO_DESC           :     Descriptor 0xB8000,     0x07FFF,              DA_DRWA + DA_32 + DA_DPL3
DATA32_KERNEL_DESC   :     Descriptor    0,    Data32KernelSegLen - 1,   DA_DRW + DA_32 + DA_DPL0 
DATA32_USER_DESC     :     Descriptor    0,    Data32UserSegLen - 1,     DA_DRW + DA_32 + DA_DPL3 
STACK32_KERNEL_DESC  :     Descriptor    0,     TopOfKernelStack32,      DA_DRW + DA_32 + DA_DPL0
STACK32_USER_DESC    :     Descriptor    0,     TopOfUserStack32,        DA_DRW + DA_32 + DA_DPL3
TSS_DESC             :     Descriptor    0,       TSSLen - 1,            DA_386TSS + DA_DPL0
FUNCTION_DESC        :     Descriptor    0,   FunctionSegLen - 1,        DA_C + DA_32 + DA_DPL0;内核函数段
; Call Gate
;                                                  选择子,                 偏移,          参数个数,      属性
FUNC_GETKERNELDATA_DESC :    Gate             FunctionSelector,       GetKernelData,       0,         DA_386CGate + DA_DPL3
; GDT end
 
GdtLen    equ   $ - GDT_ENTRY
 
GdtPtr:
          dw   GdtLen - 1
          dd   0
 
; GDT Selector
Code32Selector         equ (0x0001 << 3) + SA_TIG + SA_RPL3
VideoSelector          equ (0x0002 << 3) + SA_TIG + SA_RPL3
KernelData32Selector   equ (0x0003 << 3) + SA_TIG + SA_RPL0
UserData32Selector     equ (0x0004 << 3) + SA_TIG + SA_RPL3
KernelStack32Selector  equ (0x0005 << 3) + SA_TIG + SA_RPL0
UserStack32Selector    equ (0x0006 << 3) + SA_TIG + SA_RPL3
TSSSelector            equ (0x0007 << 3) + SA_TIG + SA_RPL0
FunctionSelector       equ (0x0008 << 3) + SA_TIG + SA_RPL0
; Gate Selector
GetKernelDataSelector  equ (0x0009 << 3) + SA_TIG + SA_RPL3
; end of [section .gdt]
 
TopOfStack16    equ 0x7c00
 
[section .s16]
[bits 16]
ENTRY_SEGMENT:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, TopOfStack16
 
    ; initialize GDT for 32 bits code segment
    mov esi, CODE32_SEGMENT
    mov edi, CODE32_DESC
 
    call InitDescItem
 
    mov esi, DATA32_KERNEL_SEGMENT
    mov edi, DATA32_KERNEL_DESC
 
    call InitDescItem
 
    mov esi, DATA32_USER_SEGMENT
    mov edi, DATA32_USER_DESC
 
    call InitDescItem
 
    mov esi, STACK32_KERNEL_SEGMENT
    mov edi, STACK32_KERNEL_DESC
 
    call InitDescItem
 
    mov esi, STACK32_USER_SEGMENT
    mov edi, STACK32_USER_DESC
 
    call InitDescItem
 
    mov esi, FUNCTION_SEGMENT
    mov edi, FUNCTION_DESC
 
    call InitDescItem
 
    mov esi, TSS_SEGMENT
    mov edi, TSS_DESC
 
    call InitDescItem
 
    ; initialize GDT pointer struct
    mov eax, 0
    mov ax, ds
    shl eax, 4
    add eax, GDT_ENTRY
    mov dword [GdtPtr + 2], eax
 
    ; 1. load GDT
    lgdt [GdtPtr]
 
    ; 2. close interrupt
    cli
 
    ; 3. open A20
    in al, 0x92
    or al, 00000010b
    out 0x92, al
 
    ; 4. enter protect mode
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax
 
    ; 5. load TSS
    mov ax, TSSSelector
    ltr ax
 
    ; 6. jump to 32 bits code
    ;jmp word Code32Selector : 0
    push UserStack32Selector
    push TopOfUserStack32
    push Code32Selector   
    push 0                
    retf
 
; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:
    push eax
 
    mov eax, 0
    mov ax, cs
    shl eax, 4
    add eax, esi
    mov word [edi + 2], ax
    shr eax, 16
    mov byte [edi + 4], al
    mov byte [edi + 7], ah
 
    pop eax
 
    ret
 
[section .kdat]
[bits 32]
DATA32_KERNEL_SEGMENT:
    KDAT               db  "Kernel Data", 0
    KDAT_LEN           equ $ - KDAT
    KDAT_OFFSET        equ KDAT - $$
 
Data32KernelSegLen equ $ - DATA32_KERNEL_SEGMENT
 
[section .udat]
[bits 32]
DATA32_USER_SEGMENT:
    UDAT               times 16 db 0
    UDAT_LEN           equ $ - UDAT
    UDAT_OFFSET        equ UDAT - $$
 
Data32UserSegLen equ $ - DATA32_USER_SEGMENT
 
[section .tss]
[bits 32]
TSS_SEGMENT:
        dd    0
        dd    TopOfKernelStack32      ; 0
        dd    KernelStack32Selector   ;
        dd    0                       ; 1
        dd    0                       ;
        dd    0                       ; 2
        dd    0                       ;
        times 4 * 18 dd 0
        dw    0
        dw    $ - TSS_SEGMENT + 2
        db    0xFF
 
TSSLen    equ    $ - TSS_SEGMENT
 
[section .s32]
[bits 32]
CODE32_SEGMENT:
    mov ax, VideoSelector
    mov gs, ax
 
    mov ax, UserData32Selector
    mov es, ax
 
    mov di, UDAT_OFFSET
 
    call GetKernelDataSelector : 0
 
    mov ax, UserData32Selector   ; eip ==> 0x17
    mov ds, ax
 
    mov ebp, UDAT_OFFSET
    mov bx, 0x0C
    mov dh, 12
    mov dl, 33
 
    call PrintString
 
    jmp $
 
; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:
    push ebp
    push eax
    push edi
    push cx
    push dx
 
print:
    mov cl, [ds:ebp]
    cmp cl, 0
    je end
    mov eax, 80
    mul dh
    add al, dl
    shl eax, 1
    mov edi, eax
    mov ah, bl
    mov al, cl
    mov [gs:edi], ax
    inc ebp
    inc dl
    jmp print
 
end:
    pop dx
    pop cx
    pop edi
    pop eax
    pop ebp
 
    ret
 
Code32SegLen    equ    $ - CODE32_SEGMENT
 
[section .func]
[bits 32]
FUNCTION_SEGMENT:
 
; es:di --> data buffer
GetKernelDataFunc: 
    mov ax, KernelData32Selector
    mov ds, ax
 
    mov si, KDAT_OFFSET
 
    mov cx, KDAT_LEN
 
    call KMemCpy
 
    retf
 
; ds:si --> source
; es:di --> destination
; cx    --> length
KMemCpy:
    cmp si, di
    ja btoe
    add si, cx
    add di, cx
    dec si
    dec di
    jmp etob
btoe:
    cmp cx, 0
    jz done
    mov al, [ds:si]
    mov byte [es:di], al
    inc si
    inc di
    dec cx
    jmp btoe
etob:
    cmp cx, 0
    jz done
    mov al, [ds:si]
    mov byte [es:di], al
    dec si
    dec di
    dec cx
    jmp etob
done:  
    ret  
 
GetKernelData    equ   GetKernelDataFunc - $$
FunctionSegLen    equ   $ - FUNCTION_SEGMENT
 
[section .kgs]
[bits 32]
STACK32_KERNEL_SEGMENT:
    times 256 db 0
 
Stack32KernelSegLen equ $ - STACK32_KERNEL_SEGMENT
TopOfKernelStack32  equ Stack32KernelSegLen - 1
 
[section .ugs]
[bits 32]
STACK32_USER_SEGMENT:
    times 256 db 0c
 
Stack32UserSegLen equ $ - STACK32_USER_SEGMENT
TopOfUserStack32  equ Stack32UserSegLen - 1

实现结果
操作系统-特权级与内核安全示例
从结果中可以看到内核数据被用户进行了拷贝,导致内核数据不安全

B.对上述出现的错误进行改进

初步的解决方法-提出一个检查函数
1.获取段寄存器中RPL的值
2.判断RPL的值是否为SA_RPL0;true则为检查通过,可以继续访问数据,如果为false,特权级较低,出发异常
具体实现是在[section .func] [bits 32]中定义一个检查函数,并在拷贝之前将其进行调用,对RPL的值进行判断
代码如下:

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
[section .func]
[bits 32]
FUNCTION_SEGMENT:
 
; es:di --> data buffer
GetKernelDataFunc: 
    mov cx, [esp + 4]
    and cx, 0x0003
    mov ax, es
    and ax, 0xFFFC
    or  ax, cx
    mov es, ax
 
    mov ax, KernelData32Selector
    mov ds, ax
 
    mov si, KDAT_OFFSET
 
    mov cx, KDAT_LEN
 
    call KMemCpy
 
    retf
 
; ds:si --> source
; es:di --> destination
; cx    --> length
KMemCpy:
    mov ax, es
 
    call CheckRPL;进行调用
 
    cmp si, di
    ja btoe
    add si, cx
    add di, cx
    dec si
    dec di
    jmp etob
btoe:
    cmp cx, 0
    jz done
    mov al, [ds:si]
    mov byte [es:di], al
    inc si
    inc di
    dec cx
    jmp btoe
etob:
    cmp cx, 0
    jz done
    mov al, [ds:si]
    mov byte [es:di], al
    dec si
    dec di
    dec cx
    jmp etob
done:  
    ret  
 
; ax --> selector value
;检查函数
CheckRPL:
    and ax, 0x0003;进行与操作
    cmp ax, SA_RPL0;进行比较操作
    jz valid;进行判断跳转
 
    mov ax, 0
    mov fs, ax
    mov byte [fs:0], 0;触发异常

代码运行结果
操作系统-特权级与内核安全示例
从运行结果可以看出,代码没有对内核数据进行拷贝,同时检查函数起到作用, 对RPL的值进行判断,并触发异常进行打印。但是对用户的选择子RPL的值进行修改伪造,将其改为0,又可以将内核数据进行拷贝。

C.用户程序可以通过伪造的选择子中的RPL的值,从而绕开安全检查的机制,在这里需要提出新的解决方案

1.在栈中获取函数远调用前CS寄存器的值(请求者)
2.从之前CS寄存器的值获取RPL
3.用RPL更新到数据缓冲区对应的段寄存器中
4.实验检查函数CheckRPL对段寄存器进行安全检查
操作系统-特权级与内核安全示例
代码:

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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
%include "inc.asm"
 
org 0x9000
 
jmp ENTRY_SEGMENT
 
[section .gdt]
; GDT definition
;                                      段基址,       段界限,             段属性
GDT_ENTRY            :     Descriptor    0,            0,                0
CODE32_DESC          :     Descriptor    0,    Code32SegLen - 1,         DA_C + DA_32 + DA_DPL3
VIDEO_DESC           :     Descriptor 0xB8000,     0x07FFF,              DA_DRWA + DA_32 + DA_DPL3
DATA32_KERNEL_DESC   :     Descriptor    0,    Data32KernelSegLen - 1,   DA_DRW + DA_32 + DA_DPL0 
DATA32_USER_DESC     :     Descriptor    0,    Data32UserSegLen - 1,     DA_DRW + DA_32 + DA_DPL3 
STACK32_KERNEL_DESC  :     Descriptor    0,     TopOfKernelStack32,      DA_DRW + DA_32 + DA_DPL0
STACK32_USER_DESC    :     Descriptor    0,     TopOfUserStack32,        DA_DRW + DA_32 + DA_DPL3
TSS_DESC             :     Descriptor    0,       TSSLen - 1,            DA_386TSS + DA_DPL0
FUNCTION_DESC        :     Descriptor    0,   FunctionSegLen - 1,        DA_C + DA_32 + DA_DPL0;内核函数段
; Call Gate
;                                                  选择子,                 偏移,          参数个数,      属性
FUNC_GETKERNELDATA_DESC :    Gate             FunctionSelector,       GetKernelData,       0,         DA_386CGate + DA_DPL3
; GDT end
 
GdtLen    equ   $ - GDT_ENTRY
 
GdtPtr:
          dw   GdtLen - 1
          dd   0
 
; GDT Selector
Code32Selector         equ (0x0001 << 3) + SA_TIG + SA_RPL3
VideoSelector          equ (0x0002 << 3) + SA_TIG + SA_RPL3
KernelData32Selector   equ (0x0003 << 3) + SA_TIG + SA_RPL0
UserData32Selector     equ (0x0004 << 3) + SA_TIG + SA_RPL3
KernelStack32Selector  equ (0x0005 << 3) + SA_TIG + SA_RPL0
UserStack32Selector    equ (0x0006 << 3) + SA_TIG + SA_RPL3
TSSSelector            equ (0x0007 << 3) + SA_TIG + SA_RPL0
FunctionSelector       equ (0x0008 << 3) + SA_TIG + SA_RPL0
; Gate Selector
GetKernelDataSelector  equ (0x0009 << 3) + SA_TIG + SA_RPL3
; end of [section .gdt]
 
TopOfStack16    equ 0x7c00
 
[section .s16]
[bits 16]
ENTRY_SEGMENT:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, TopOfStack16
 
    ; initialize GDT for 32 bits code segment
    mov esi, CODE32_SEGMENT
    mov edi, CODE32_DESC
 
    call InitDescItem
 
    mov esi, DATA32_KERNEL_SEGMENT
    mov edi, DATA32_KERNEL_DESC
 
    call InitDescItem
 
    mov esi, DATA32_USER_SEGMENT
    mov edi, DATA32_USER_DESC
 
    call InitDescItem
 
    mov esi, STACK32_KERNEL_SEGMENT
    mov edi, STACK32_KERNEL_DESC
 
    call InitDescItem
 
    mov esi, STACK32_USER_SEGMENT
    mov edi, STACK32_USER_DESC
 
    call InitDescItem
 
    mov esi, FUNCTION_SEGMENT
    mov edi, FUNCTION_DESC
 
    call InitDescItem
 
    mov esi, TSS_SEGMENT
    mov edi, TSS_DESC
 
    call InitDescItem
 
    ; initialize GDT pointer struct
    mov eax, 0
    mov ax, ds
    shl eax, 4
    add eax, GDT_ENTRY
    mov dword [GdtPtr + 2], eax
 
    ; 1. load GDT
    lgdt [GdtPtr]
 
    ; 2. close interrupt
    cli
 
    ; 3. open A20
    in al, 0x92
    or al, 00000010b
    out 0x92, al
 
    ; 4. enter protect mode
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax
 
    ; 5. load TSS
    mov ax, TSSSelector
    ltr ax
 
    ; 6. jump to 32 bits code
    ;jmp word Code32Selector : 0
    push UserStack32Selector
    push TopOfUserStack32
    push Code32Selector   
    push 0                
    retf
 
; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:
    push eax
 
    mov eax, 0
    mov ax, cs
    shl eax, 4
    add eax, esi
    mov word [edi + 2], ax
    shr eax, 16
    mov byte [edi + 4], al
    mov byte [edi + 7], ah
 
    pop eax
 
    ret
 
[section .kdat]
[bits 32]
DATA32_KERNEL_SEGMENT:
    KDAT               db  "Kernel Data", 0
    KDAT_LEN           equ $ - KDAT
    KDAT_OFFSET        equ KDAT - $$
 
Data32KernelSegLen equ $ - DATA32_KERNEL_SEGMENT
 
[section .udat]
[bits 32]
DATA32_USER_SEGMENT:
    UDAT               times 16 db 0
    UDAT_LEN           equ $ - UDAT
    UDAT_OFFSET        equ UDAT - $$
 
Data32UserSegLen equ $ - DATA32_USER_SEGMENT
 
[section .tss]
[bits 32]
TSS_SEGMENT:
        dd    0
        dd    TopOfKernelStack32      ; 0
        dd    KernelStack32Selector   ;
        dd    0                       ; 1
        dd    0                       ;
        dd    0                       ; 2
        dd    0                       ;
        times 4 * 18 dd 0
        dw    0
        dw    $ - TSS_SEGMENT + 2
        db    0xFF
 
TSSLen    equ    $ - TSS_SEGMENT
 
[section .s32]
[bits 32]
CODE32_SEGMENT:
    mov ax, VideoSelector
    mov gs, ax
 
    mov ax, UserData32Selector
    mov es, ax
 
    mov di, UDAT_OFFSET
 
    call GetKernelDataSelector : 0
 
    mov ax, UserData32Selector   ; eip ==> 0x17
    mov ds, ax
 
    mov ebp, UDAT_OFFSET
    mov bx, 0x0C
    mov dh, 12
    mov dl, 33
 
    call PrintString
 
    jmp $
 
; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:
    push ebp
    push eax
    push edi
    push cx
    push dx
 
print:
    mov cl, [ds:ebp]
    cmp cl, 0
    je end
    mov eax, 80
    mul dh
    add al, dl
    shl eax, 1
    mov edi, eax
    mov ah, bl
    mov al, cl
    mov [gs:edi], ax
    inc ebp
    inc dl
    jmp print
 
end:
    pop dx
    pop cx
    pop edi
    pop eax
    pop ebp
 
    ret
 
Code32SegLen    equ    $ - CODE32_SEGMENT
 
[section .func]
[bits 32]
FUNCTION_SEGMENT:
 
; es:di --> data buffer
GetKernelDataFunc: 
    mov cx, [esp + 4]
    and cx, 0x0003
    mov ax, es
    and ax, 0xFFFC
    or  ax, cx
    mov es, ax
 
    mov ax, KernelData32Selector
    mov ds, ax
 
    mov si, KDAT_OFFSET
 
    mov cx, KDAT_LEN
 
    call KMemCpy
 
    retf
 
; ds:si --> source
; es:di --> destination
; cx    --> length
KMemCpy:
    mov ax, es
 
    call CheckRPL;进行调用
 
    cmp si, di
    ja btoe
    add si, cx
    add di, cx
    dec si
    dec di
    jmp etob
btoe:
    cmp cx, 0
    jz done
    mov al, [ds:si]
    mov byte [es:di], al
    inc si
    inc di
    dec cx
    jmp btoe
etob:
    cmp cx, 0
    jz done
    mov al, [ds:si]
    mov byte [es:di], al
    dec si
    dec di
    dec cx
    jmp etob
done:  
    ret  
 
; ax --> selector value
;检查函数
CheckRPL:
    and ax, 0x0003;进行与操作
    cmp ax, SA_RPL0;进行比较操作
    jz valid;进行判断跳转
 
    mov ax, 0
    mov fs, ax
    mov byte [fs:0], 0;触发异常
 
valid:
    ret   
GetKernelData    equ   GetKernelDataFunc - $$
FunctionSegLen    equ   $ - FUNCTION_SEGMENT
 
[section .kgs]
[bits 32]
STACK32_KERNEL_SEGMENT:
    times 256 db 0
 
Stack32KernelSegLen equ $ - STACK32_KERNEL_SEGMENT
TopOfKernelStack32  equ Stack32KernelSegLen - 1
 
[section .ugs]
[bits 32]
STACK32_USER_SEGMENT:
    times 256 db 0
 
Stack32UserSegLen equ $ - STACK32_USER_SEGMENT
TopOfUserStack32  equ Stack32UserSegLen - 1

首先通过反编译在call GetKernelDataSelector : 0跳转处设置断点,接下来对通用寄存器eip寄存器进行查看,由92a8到92af之间的差值为7,可以推断mov ax, UserData32Selector ; eip ==> 0x17,该处是返回地址。同时0x17会入栈,cs也会入栈,对寄存器进行查看,此时cs寄存器为0x0b,接下来对栈顶的6个字节进行查看,发现0x17与cs寄存器都入栈,再继续操作,触发异常,过程如图所示
操作系统-特权级与内核安全示例操作系统-特权级与内核安全示例操作系统-特权级与内核安全示例操作系统-特权级与内核安全示例

小结

1.RPL是保证内核数据安全的关键要素之一
2.内核代码可通过追踪真实请求者特权级判断操作合法性
3.进行函数远调用时,真实请求者的选择子就会存储于栈中
4.通过提取真实特权级能够保证内核数据安全

  

  

  

posted on   lh03061238  阅读(71)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示