Hi Burkhard,
You are lucky that I'm deep in XP kernel asm code analysis at the moment.
Forget analyzing XP code without at least symbols present.
Let us use following code for analysis: (This is Checked XP SP2 kernel with symbols present) this code in NMI handler forget about
registers, etc
Find this:
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
As you can see if you can make it to pass trough this there is iretd available at the end.
Best regards,
Slobodan
nt!KiTrap02:
80ad6af8 fa cli
80ad6af9 64ff3540000000 push dword ptr fs:[00000040]
80ad6b00 64a13c000000 mov eax,fs:[0000003c]
80ad6b06 8a685f mov ch,[eax+0x5f]
80ad6b09 8a485c mov cl,[eax+0x5c]
80ad6b0c c1e110 shl ecx,0x10
80ad6b0f 668b485a mov cx,[eax+0x5a]
80ad6b13 64890d40000000 mov fs:[00000040],ecx
80ad6b1a 9c pushfd
80ad6b1b 812424ffbfffff and dword ptr [esp],0xffffbfff
80ad6b22 9d popfd
80ad6b23 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6b2a 8d4158 lea eax,[ecx+0x58]
80ad6b2d c6400589 mov byte ptr [eax+0x5],0x89
80ad6b31 8b0424 mov eax,[esp]
80ad6b34 6a00 push 0x0
80ad6b36 6a00 push 0x0
80ad6b38 6a00 push 0x0
80ad6b3a 6a00 push 0x0
80ad6b3c ff7050 push dword ptr [eax+0x50]
80ad6b3f ff7038 push dword ptr [eax+0x38]
80ad6b42 ff7024 push dword ptr [eax+0x24]
80ad6b45 ff704c push dword ptr [eax+0x4c]
80ad6b48 ff7020 push dword ptr [eax+0x20]
80ad6b4b 6a00 push 0x0
80ad6b4d ff703c push dword ptr [eax+0x3c]
80ad6b50 ff7034 push dword ptr [eax+0x34]
80ad6b53 ff7040 push dword ptr [eax+0x40]
80ad6b56 ff7044 push dword ptr [eax+0x44]
80ad6b59 ff7058 push dword ptr [eax+0x58]
80ad6b5c 64ff3500000000 push dword ptr fs:[00000000]
80ad6b63 6aff push 0xff
80ad6b65 ff7028 push dword ptr [eax+0x28]
80ad6b68 ff702c push dword ptr [eax+0x2c]
80ad6b6b ff7030 push dword ptr [eax+0x30]
80ad6b6e ff7054 push dword ptr [eax+0x54]
80ad6b71 ff7048 push dword ptr [eax+0x48]
80ad6b74 ff705c push dword ptr [eax+0x5c]
80ad6b77 6a00 push 0x0
80ad6b79 6a00 push 0x0
80ad6b7b 6a00 push 0x0
80ad6b7d 6a00 push 0x0
80ad6b7f 6a00 push 0x0
80ad6b81 6a00 push 0x0
80ad6b83 6a00 push 0x0
80ad6b85 6a00 push 0x0
80ad6b87 6a00 push 0x0
80ad6b89 6a00 push 0x0
80ad6b8b ff7020 push dword ptr [eax+0x20]
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
80ad6b93 33db xor ebx,ebx
80ad6b95 648a1d51000000 mov bl,fs:[00000051]
80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
80ad6baa 50 push eax
80ad6bab 6a00 push 0x0
80ad6bad 8bcc mov ecx,esp
80ad6baf 8bd5 mov edx,ebp
80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)],0x8
80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b (80ae995c)],0xffffffff
80ad6c02 8bcc mov ecx,esp
80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
80ad6c09 83c408 add esp,0x8
80ad6c0c 64a140000000 mov eax,fs:[00000040]
80ad6c12 66833858 cmp word ptr [eax],0x58
80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
80ad6c18 81c48c000000 add esp,0x8c
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd
80ad6c3d e9b6feffff jmp nt!KiTrap02 (80ad6af8)
80ad6c42 b802000000 mov eax,0x2
80ad6c47 e9a02a0000 jmp nt!KiSystemFatalException (80ad96ec)
bcpauli said:
Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.
The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).
When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):
mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx
For me it looks a little bit like XP is not intended to continue after an
NMI ?
At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard
Slobodan Brcin (eMVP) said:
Hi Burkhard,
nt!KiTrap02
nt!_imp__HalHandleNMI
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it might work.
Please let us know.
If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.
Regards,
Slobodan
I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?
With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.
On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.
thanks
Burkhard