Windows内核实验:中断现场(Interrupt Handling)
Windows内核实验:中断现场(Interrupt Handling)
!!!windbg调试器给我们的信息可能是不准确的,中断断下来后,调试子系统需要通过串口发送给调试器,这期间有些寄存器的值就变了,比较准确的方法就是在r0里写汇编,返回给我们数据
|
eax:401040 ebx:7ffd9000 ecx:b2ede300 edx:7c92eb94 esi:419cf0 |
中断前后变得只有,eflags:0x246–>0x46 esp:12ff7c->b2d13dcc cs:1b–>8 ss:23–>10
1b(0001 1011) –> 8(1000)
23(0010 0011) –> 10(0001 0000)
ds为什么还是23,没有提升到内核?
kd> dg 23 |
可以看到ds是一个平坦段,可以访问整个4gb,分段保护机制其实是在弱化,只是提供了进程隔离,具体访问保护是由分页机制来提供的
eflags变化?
第九位变为0了,也就是IF位置零,中断处理过程关中断
cs段选择子为什么会是8?
和我们构造的中断门有关系 他的16-31位为中断处理程序目标代码段选择子 即为下面的0008
eq 8003f500 0040ee00`00081040
dg x命令显示段选择子x所指向的段描述符
ss和sp是怎么来的呢?
从tss段里取出来的,TR寄存器中存放着指向当前任务TSS段的段选择子
str [g_tr] 把当前任务(任务状态段TSS)的选择器存储到指定的位置上看下是0x28 右移3位所以是gdt表第5个即为tss段描述符
TYPE的B是指任务是否处于忙状态(当前正在执行或被挂起等待执行),忙为1
kd> r gdtr |
type为1011
这个基地址就是任务状态段TSS(Task state segment)所在处,即为下面的结构
其中红色的叫做静态字段,在任务创建是设置,一般不会改变
绿色的叫做动态字段,时常更新
|
esp: 0xb29d3dcc ss: 0x10 |
可以验证到,就是从tss里面去取内核栈
为什么esp栈顶提升了0x14,栈里压了5个什么
|
cs: 0x1b eflags: 0x246 esp: 0x12ff78 ss: 0x23 |
栈里第一个是返回地址,后面分别是三环的cs eflags esp ss,和之前理论是一样的(出错码是可选的),iret时会弹出来
栈顶的返回地址怎么来调试验证?
直接在IdtEntry里写上int3 ,
void __declspec(naked) IdtEntry() {
__asm {
int 3
iretd
}
}
void interrupt() {
__asm {
push eax
pop eax
int 0x20
}
}不挂调试器会报错,挂了调试器会在int3处断下来
Break instruction exception - code 80000003 (first chance)
00401040 cc int 3
r esp
esp=b2cf3dcc
dps b2cf3dcc l5
b2cf3dcc 00401061
b2cf3dd0 0000001b
b2cf3dd4 00000246
b2cf3dd8 0012ff78
b2cf3ddc 00000023
ub 00401061 l4
0040105b 756d jne 004010ca
0040105d 50 push eax
0040105e 58 pop eax
0040105f cd20 int 20h返回地址确实是int 20h中断后的下一条指令
cs和ss选择子的RPL(CPL)都变为0,代表当前正在执行的程序或任务的特权级别为内核权限
windbg
r gdtr |
GDT中第一个表项(0号)的描述符保留不用,称为空描述符
按照上图解析