Re: 如何跟踪windows下中断处理程序?
Windows内核调试
如何跟踪windows下中断处理程序?
dannydeng
2009-06-18, 16:54 下午
问题: windows XP SP2 出现黑屏,最后发现是死在BIOS 的INT10里. (修改BIOS INT10 中断,进去,出来都打印到com口). 说明是windows的中断处理程序最后还是调用了BIOS的INT 10功能. 所以想跟踪一下windows的int 10 中断. windbg 连,发现黑屏时系统并没死,break 后dump IDT:
kd> !IDT -a
Dumping IDT:
00: 80542190 nt!KiTrap00
01: 8054230c nt!KiTrap01
02: Task Selector = 0x0058
03: 80542720 nt!KiTrap03
04: 805428a0 nt!KiTrap04
05: 80542a00 nt!KiTrap05
06: 80542b74 nt!KiTrap06
07: 805431ec nt!KiTrap07
08: Task Selector = 0x0050
09: 805435f0 nt!KiTrap09
0a: 80543710 nt!KiTrap0A
0b: 80543850 nt!KiTrap0B
0c: 80543ab0 nt!KiTrap0C
0d: 80543d9c nt!KiTrap0D
0e: 80544498 nt!KiTrap0E
0f: 805447d0 nt!KiTrap0F
10: 805448f0 nt!KiTrap10
11: 80544a2c nt!KiTrap11
12: 805447d0 nt!KiTrap0F
13: 805447d0 nt!KiTrap0F
14: 805447d0 nt!KiTrap0F
..................................................
设断点 kd> bp nt!KiTrap10 (这样可以吗?我不确定)
但发现即使BOIS 的int 10 跑了, windbg 也并没有停下来.也就是说设的断点不生效.请教各位大虾,该如何跟踪windows的中断处理?
Re: 如何跟踪windows下中断处理程序?
dannydeng
2009-06-18, 17:02 下午
另外,我在BIOS 的hook int10 里 执行一些IO操作,windbg里设io access 的断点,也是没有停下来,是什么原因呢?哪位高人能帮忙答疑呢?在此先谢过了.
Re: 如何跟踪windows下中断处理程序?
格蠹老雷
2009-06-19, 01:43 上午
保护模式下的0x10号异常是用于浮点错误的。通常说的INT 10是指实模式下的显示服务。进了保护模式后,Windows会将必须还要执行的实模式代码翻译为一种字节码,需要时模拟执行,因为切换回实模式的开销太大了。
不知楼主是做什么开发遇到这样的问题?
Re: 如何跟踪windows下中断处理程序?
dannydeng
2009-06-19, 13:12 下午
这是参与XEN下虚拟BIOS项目遇到的问题. 我发现XP在加载dxg.sys 时跑到了我的BIOS INT10 hook里,进去后就没出来了.在没有加载dxg.sys 之前也跑进过好几次INT10,但那时候是可以出来的. BIOS INT10是模式的代码,那么windows是怎么模拟执行的呢?有什么资料可以查询吗?
请问 Raymond 老师,如果在driver的代码里执行INT 10指令,跑到的handle 难道不是IDT里的10: 805448f0 nt!KiTrap10 吗?
Re: 如何跟踪windows下中断处理程序?
格蠹老雷
2009-07-03, 09:01 上午
如果在一个WDM驱动里强行这么写,应该可以转到KiTrap10,不过没有什么驱动会这么做,因为前面说过在保护模式下,KiTrap10是处理浮点错误的(coprocessor error)。
Re: 如何跟踪windows下中断处理程序?
MJ0011
2009-07-03, 13:49 下午
可以用KiI386CallAbios调用BIOS中断的,WINDOWS的显示驱动videoport.sys就使用这种方式调用INT 0X10~
cPublicProc _KiI386CallAbios,4
;
; We're using a 32bit CS:EIP - go to a 16bit CS:IP
; Note the base of KiAbiosCallSelector is the flat address of _KiI386AbiosCall
; routine.
;
push ebp
mov ebp, esp
push ebx
COPY_CALL_FRAME _KiBiosFrame
sub esp,LocalStack ; After C style frame
CurrentIrql ; Local Variable
push eax ; Local Variable
cmp al, DISPATCH_LEVEL ; Is irql > Dispatch_level?
jae short Kac00
; Raise to Dispatch Level
RaiseIrql DISPATCH_LEVEL
mov [esp], al
Kac00:
;
; Set up parameters on stack before remapping stack.
;
push word ptr KGDT_CDA16 ; CDA anchor selector
push KacRequestBlock ; Request Block
push KacFunctionTable ; Func transfer table
push KacDeviceBlock ; Device Block
mov ebx, KacAbiosFunction ; (ebx)-> Abios Entry
;
; Remap current stack to 16:16 stack. The base of the 16bit stack selector is
; the base of current kernel stack.
;
inc _KiInBiosCall ; Set the 'In Bios' flag
if DBG
cmp _KiInBiosCall,2
jb @F
push offset FLAT:KiBiosReenteredAssert
call _dbgPrint
add esp, 4
@@:
endif
STACK32_TO_STACK16 ; Switch to 16bit stack
push word ptr KGDT_CODE16
push word ptr (offset FLAT:Kac40 - offset FLAT:_KiI386CallAbios@16)
push KGDT_CODE16
push offset FLAT:Kac30 - offset FLAT:_KiI386CallAbios@16
retf
Kac30:
;
; Stack switching (from 32 to 16) turns interrupt off. We must turn it
; back on.
;
sti
push bx ; Yes, BX not EBX!
retf
Kac40:
add esp, 14 ; pop out all the parameters
STACK16_TO_STACK32 ; switch back to 32 bit stack
;
; Pull callers flat return address off stack and push the
; flat code selector followed by the return offset, then
; execute a far return and we'll be back in the 32-bit code space.
;
db OPERAND_OVERRIDE
push KGDT_R0_CODE
db OPERAND_OVERRIDE
push offset FLAT:Kac50
db OPERAND_OVERRIDE
retf
Kac50:
pop ecx ; [ecx] = OldIrql
pop ebx ; restore ebx
cmp cl, DISPATCH_LEVEL
jae short Kac60
LowerIrql cl
Kac60:
dec _KiInBiosCall ;Clear 'In Bios' Flag
add esp,LocalStack ; subtract off the scratch space
pop ebp
stdRET _KiI386CallAbios
stdENDP _KiI386CallAbios