2011.6.13
调用门:
对应的结构体是:
typedef struct
{
unsigned short offset_0_15; //偏移
unsigned short selector; //选择子,此门要调用哪个代码段的对应选择子
unsigned char param_count : 4;
unsigned char some_bits : 4;
unsigned char type : 4;
unsigned char app_system : 1;
unsigned char dpl : 2;
unsigned char present : 1;
unsigned short offset_16_31;
} CALLGATE_DESCRIPTOR;
call SelectorCode32:0
call SelectorGate:0 ;门的选择子为Selector32
则他们实质是调用同一块代码,实现跳转,主要用来完成低权限代码调用搞权限代码操作
调用门可以理解为其他代码段描述符的经纪人,代码段都很拽,我们没发直接和他进行操作,但是通过它的代理人Gate来传达我们的需求。
下面的代码主要实现的功能为:在3E0处构造一个调用门调用3E8处描述符对应的代码,3E8描述符的代码范围:0-0xFFFF,从内存的0执行,在0地址是retn指令
0 : retn
3E0 调用门 Select 3E8
3E8 BaseLimit 0-0xFFFF
别人给的学习代码:
.586p
.model flat,stdcall
option casemap:none
CALLGATE struct
OffsetL dw ?
Selector dw ?
DCount db ?
Gtype db ?
OffsetH dw ?
CALLGATE ends
DESCRIPTOR struct
LimitL dw ?
BaseL dw ?
BaseM db ?
Attributes dw ?
BaseH db ?
DESCRIPTOR ends
CODES_SEL equ 3e8h
CODE_TYPE equ 0cf9ah
GATE_TYPE equ 0ech
.code
DriverEntry proc pDriverObject,pRegisterPath
pushfd
pushad
push eax
sgdt [esp-2] ;获取GDTR,edx是描述符的BaseAddr
pop edx
mov eax,edx
mov byte ptr[edx],0c3h ;retn的机器码
mov ecx,3e0h ;eE0/8 = 7C
add edx,ecx
assume edx:ptr CALLGATE
cmp [edx].Selector,CODES_SEL;判断是否已处理
jz _end
mov [edx].OffsetL,ax
mov [edx].Selector,CODES_SEL
mov [edx].DCount,0
mov [edx].Gtype,GATE_TYPE ;这个调用门来调用下面段描述符对应的代码
shr eax,16
mov [edx].OffsetH,ax
add edx,8
assume edx:ptr DESCRIPTOR
mov [edx].LimitL,0ffffh
mov [edx].BaseL,0
mov [edx].BaseM,0
mov [edx].Attributes,CODE_TYPE
mov [edx].BaseH,0
_end:
popad
popfd
mov eax,0c0000182h ;错误代码
ret
DriverEntry endp
end DriverEntry
http://bbs.pediy.com/showthread.php?t=62263 关于调用门的讲解这里引用下方便以后查询
!PCR (Processor Control Region)
kd> !pcr
KPCR for Processor 0 at ffdff000:
Major 1 Minor 1
NtTib.ExceptionList: b276d654
NtTib.StackBase: b276ddf0
NtTib.StackLimit: b276b000
NtTib.SubSystemTib: 00000000
NtTib.Version: 00000000
NtTib.UserPointer: 00000000
NtTib.SelfTib: 7ff7d000
SelfPcr: ffdff000
Prcb: ffdff120
Irql: 00000000
IRR: 00000000
IDR: ffffffff
InterruptMode: 00000000
IDT: 8003f400
GDT: 8003f000 //GDT地址
TSS: 80042000
CurrentThread: 8267cc30
NextThread: 00000000
IdleThread: 80552920
kd> r gdtr
gdtr=8003f000
kd> dw /c4 8003f000
8003f000 0000 0000 0000 0000
8003f008 ffff 0000 9a00 00cf
8003f010 ffff 0000 9200 00cf
选择子8的描述符为 00 CF9A 000000 FFFF
段基址为:0
CF9A ==》 1100 1111 1001 1010
段界限为0xFFFFF
DPL:0
P:1
G:1
S:1 数据描述符,0是系统描述符
TYPE:1010 执行/读
关键代码
push esi
sgdt [esp-2]
pop esi
mov eax,8
.while eax < GDT_LIMIT ; GDT_LIMIT :03ffh
lea edx,[esi+eax]
assume edx:ptr CALLGATE
test [edx].GTYPE,80h ;通过判断present 是否为1来判断是否是空闲
.if ZERO?
mov ebx,FuncAddr
mov [edx].OFFSETL,bx
mov [edx].SELECTOR,08h
mov [edx].DCOUNT,0
mov [edx].GTYPE,GATE_TYPE
shr ebx,16
mov [edx].OFFSETH,bx
.break
.endif
assume edx:nothing
add eax,8
.endw
目标是一致代码段 CPL <= DPL(门), RPL <= DPL(门) DPL(目标) <= CPL
非一致 CALL CPL <= DPL(门), RPL<= DPL(门), DPL(目标) <= CPL
JMP CPL <= DPL(门), RPL <= DPL(门), DPL(目标) = CPL