Breaking back into user from kernel.

Basic idea

Substitute in the trap frame the address of an int 3 instruction. On return from the int 2e system call, this address will be excuted, breaking into the NTSD debugger. Then manipulate eip to restore the original address.

Details

  1. Prepare by attaching to the target process with ntsd. I was debugging termsrv, so I used ntsd -d -p _pid_of_termsrv_.
  2. You will need the address of an int 3 instruction in the user address space. There is one at the entry to ntdll!DbgBreakPoint. Since ntdll.dll loads at a fixed address, for SP4, this byte can always be found at 0x77f76578.
  3. When you get the kd breakpoint, and you want to climb out to ntsd on its return, do a kv and look for the frame pointer listed for KiSystemServices. Using both !trap _x_ and dd _x_ find where the return address is stored. It is 0x68 bytes from the trap frame address.
  4. Note the return address and substitute the address of the int 3 recored above. Go.
  5. You will ntsd trap. Set eip to the correct return address. You can now continue with ntsd as normal.

Example session

kd> kv
Loading symbols for 0x77f60000        ntdll.dll ->   c:\nt_debug\nt40sp4.1\symbols\dll\ntdll.dbg
*** WARNING: symbols checksum is wrong 0x00062f7c 0x000650fd for c:\nt_debug\nt4
0sp4.1\symbols\dll\ntdll.dbg
ChildEBP RetAddr  Args to Child
fd5e9ea0 801aa96e e11d9588 e11d956c 8019589e ntoskrnl!SepDeReferenceLogonSession+0xdb (FPO: [1,0,2])
fd5e9eac 8019589e e11d9570 805e7f48 e11d9558 ntoskrnl!SepTokenDeleteMethod+0xe (FPO: [1,0,1])
fd5e9ec4 8013a65f e11d9570 e11d9558 e11d9570 ntoskrnl!ObpRemoveObjectRoutine+0xcc (FPO: [EBP 0x805e7f48] [1,0,4])
fd5e9edc 8013a852 fd5e9f04 fd5e9f04 02bbfe00 ntoskrnl!ObfDereferenceObject+0xa5(FPO: [0,1,3])
fd5e9ef8 801441c4 0000012c 00000000 00000000 ntoskrnl!NtClose+0x17a (FPO: [EBP 0xfd5e9f04] [1,2,4])
fd5e9ef8 77f6767f 0000012c 00000000 00000000 ntoskrnl!KiSystemService+0xc4 (FPO: [0,0] TrapFrame @ fd5e9f04)
02bbff90 70527e56 70527af4 0014c340 02bbffec NTDLL!NtClose+0xb (FPO: [1,0,0])
02bbff90 70527e56 70527af4 0014c340 02bbffec ntoskrnl!KiCallUserMode+0x4 (FPO: [2,3,4])

kd> !trap  fd5e9f04
eax=00000028 ebx=001eef70 ecx=02bbf78c edx=00000000 esi=001eeef0 edi=001eef0c
eip=77f6767f esp=02bbfdf8 ebp=02bbff90 iopl=0         nv up ei ng nz ac pe cy
vip=0    vif=0
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000293
ErrCode = 00000000
77f6767f c20400           ret     0x4

kd> dd  fd5e9f04
fd5e9f04  00000000 00000000 00000000 00000000
fd5e9f14  00000000 00000000 00000000 00000000
fd5e9f24  00000000 00000000 00000000 00000000
fd5e9f34  00000000 00000023 00000023 00000000
fd5e9f44  02bbf78c 00000028 00295401 ffffffff
fd5e9f54  00000038 001eef0c 001eeef0 001eef70
fd5e9f64  02bbff90 00000000 77f6767f 0000001b
fd5e9f74  00000293 02bbfdf8 00000023 00000000

kd> ed fd5e9f6c
fd5e9f6c 77f6767f 77efce09
fd5e9f70 0000001b

kd> !trap  fd5e9f04
eax=00000028 ebx=001eef70 ecx=02bbf78c edx=00000000 esi=001eeef0 edi=001eef0c
eip=77efce09 esp=02bbfdf8 ebp=02bbff90 iopl=0         nv up ei ng nz ac pe cy
vip=0    vif=0
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000293
ErrCode = 00000000
77efce09 cc               int     3

kd> g
eax=00000000 ebx=001eef70 ecx=00295401 edx=ffffffff esi=001eeef0 edi=001eef0c
eip=77efce09 esp=02bbfdf8 ebp=02bbff90 iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000293
kernel32!DebugActiveWinStation+0xbb:
77efce09 cc               int     3

0:021> kv
ChildEBP RetAddr  Args to Child
02bbff90 70527e56 70527af4 0014c340 02bbffec kernel32!DebugActiveWinStation+0xbb(FPO: [Non-Fpo]
02bbffac 70527b27 00160fa0 705655f0 77ef4fa2 rpcrt4!RecvLotsaCallsWrapper+0x9 (FPO: [1,0,0])
02bbffb8 77ef4fa2 00163a08 70560a24 705655f0 rpcrt4!ThreadStartRoutine+0x17 (FPO: [1,0,1])
00003a98 00000003 00163a08 70560a24 705655f0 kernel32!BaseThreadStart+0x51(FPO:[Non-Fpo]

0:021> r eip=77f6767f

0:021> kv
ChildEBP RetAddr  Args to Child
02bbfdf4 77ef13ff 0000012c 70533a95 0000012c ntdll!NtClose+0xb (FPO: [1,0,0])
02bbfdfc 70533a95 0000012c 0014c340 001eeef0 kernel32!CloseHandle+0x4e (FPO: [1,0,0])
02bbfe10 7052850f 00160fa0 00144bbc 00144bc4 rpcrt4!WMSG_SASSOCIATION__~WMSG_SASSOCIATION+0x55 (FPO: [0,0,3])
02bbff90 70527e56 70527af4 0014c340 02bbffec rpcrt4!WMSG_ADDRESS__ReceiveLotsaCalls+0x6b6(FPO: [Non-Fpo]
02bbff94 70527af4 0014c340 02bbffec 70560a24 rpcrt4!RecvLotsaCallsWrapper+0x9 (FPO: [1,0,0])
02bbffac 70527b27 00160fa0 705655f0 77ef4fa2 rpcrt4!BaseCachedThreadRoutine+0x91 (FPO: [EBP 0x02bbffec] [1,0,4])
02bbffb8 77ef4fa2 00163a08 70560a24 705655f0 rpcrt4!ThreadStartRoutine+0x17 (FPO: [1,0,1])
02bbffec 00000000 70527b10 00163a08 00000000 kernel32!BaseThreadStart+0x51(FPO:[Non-Fpo]

0:021> g

CdmCacheFlush: Starting Cache Flush For LogonId 6
CdmCacheFlush: Done with Cache Flush For LogonId 6