I'm not the only one to ask this question so I thought I would report my findings. Using the program below which is by no means complete but only to the point of proving what is happening with Win2k. The program is a modification of ICZ's or Hutche's debug tut#30. The program originally counted instructions of a debugee. What happens in Win2K as far as I can see is that a NTDLL loads all programs for extra security monitoring. So consequenty when the "break" exception is executed the DLL resumes control. So what happens is the debuggee never runs and the debugger will count an outragious number of instructions. This will through the user of course thinking that he or she cannot modify the register context. This program has several message boxes that first illustrate that first the Flags are indeed modified and it also illustrates that the Eip did not get loaded after "break exception" as is normally the case. So this program jam loads the Eip so that the debuggee can be executed in single step mode. But what is interesting to note is that when the debuggee exits the program does not end but returns to the NTDLL. For now I inserted an instruction count register variable as an escaped from what would be alot of mouse clicking. Use the simple debuggee called movEbx.exe.

"Debuggee"

.386

.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data

.code

start:
mov ebx,001234abcdh
mov ecx,ebx
mov ebx,ecx
mov edx,ecx
mov ecx,ecx
invoke ExitProcess,NULL
end start


"The Debugger"

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\user32.lib

.data
AppName db "Win32 Debug Example no.4",0
ofn OPENFILENAME <>
FilterString db "Executable Files",0,"*.exe",0
db "All Files",0,"*.*",0,0
ExitProc db "The debuggee exits",0

dispregXXX db "regXXX= : %1x",0

ProcessInfo db "File Handle: %lx ",0dh,0Ah
db "Process Handle: %lx",0Dh,0Ah
db "Thread Handle: %lx",0Dh,0Ah
db "Image Base: %lx",0Dh,0Ah
db "Start Address: %lx",0


regEAX dd 0
regEBX dd 0
regECX dd 0
regEDX dd 0
regXXX dd 0
thread dd 0
Identify db "Event: %x",0
Display2 db "ProcessThread: %08x",0
Display3 db "DBEventThread: %08x",0

membufdisp db "Dump: %1x",20h
db " %1x",0Dh,0Ah
db " ........%1x",20H
db " %1x",0

displayregs db "Reg- CS: %08x",0Dh,0Ah
db "Reg- DS: %08x",0Dh,0Ah
db "Reg- ES: %08x",0Dh,0Ah
db "Reg- SS: %08x",0Dh,0Ah
db "Reg- EAX: %08x",0Dh,0Ah
db "Reg- EBX: %08x",0Dh,0Ah
db "Reg- ECX: %08x",0Dh,0Ah
db "Reg- EDX: %08x",0Dh,0Ah
db "Reg- EIP: %08x",0Dh,0Ah
db "Reg- ESP: %08x",0Dh,0Ah
db "Reg- EBP: %08x",0Dh,0Ah
db "Reg- ESI: %08x",0Dh,0Ah
db "Reg- EDI: %08x",0Dh,0Ah
db "Reg- FS: %08x",0Dh,0Ah
db "Reg- GS: %08x",0Dh,0Ah
db "Reg- EFLAGS: %08x",0

bytesread dd 0
readbuff dd 0
baseaddr dd 0
errorMessage db "Error: %s",0
MsgSrc dd 0
errorMsgbuff dd 0
globlock dd 0
loclock dd 0
count1 dd 0

.data?

buffer db 4096 dup(?)
startinfo STARTUPINFO <>
pi PROCESS_INFORMATION <>
DBEvent DEBUG_EVENT <>
align dword
context CONTEXT <>

.code
start:
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke GetStartupInfo,addr startinfo
invoke CreateProcess, addr buffer,NULL,NULL,NULL, FALSE,
DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS , NULL, NULL, addr startinfo, addr pi
cmp eax,0
jne go5
call DisplayLastError
int 3

go5:

invoke SetDebugErrorLevel,SLE_MINORERROR
.while TRUE

invoke WaitForDebugEvent, addr DBEvent, INFINITE ;*****
.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
invoke wsprintf, addr buffer, addr ExitProc
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION

.break

.elseif DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
invoke wsprintf, addr buffer, addr ProcessInfo, DBEvent.u.CreateProcessInfo.hFile, DBEvent.u.CreateProcessInfo.hProcess, DBEvent.u.CreateProcessInfo.hThread, DBEvent.u.CreateProcessInfo.lpBaseOfImage, DBEvent.u.CreateProcessInfo.lpStartAddress
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION

invoke GlobalAlloc ,GMEM_MOVEABLE or GMEM_ZEROINIT,1000h
mov readbuff,eax
invoke GlobalLock,eax ;**read process memory**
mov globlock,eax
mov eax,0h
mov bytesread,eax ;**and display/Dump**
mov eax,401000h
mov baseaddr,eax
invoke ReadProcessMemory,pi.hProcess,baseaddr,addr readbuff,100h,addr bytesread
push eax
mov eax,bytesread
mov regXXX,eax
call DisplayregXXX ;** no. of bytes read**
pop eax
cmp eax,0
jne go4
call DisplayLastError
int 3

go4:
mov eax,readbuff+0
call Swap
mov readbuff+0,eax
mov eax,readbuff+04h
call Swap
mov readbuff+04h,eax
mov eax,readbuff+08h
call Swap
mov readbuff+08h,eax
mov eax,readbuff+0Ch
call Swap
mov readbuff+0Ch,eax

invoke wsprintf,addr buffer,addr membufdisp,readbuff+00h,readbuff+04h,readbuff+08h,readbuff+0Ch
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
invoke GlobalUnlock,addr globlock
invoke GlobalFree,addr readbuff
cmp eax,0
jne go
call DisplayLastError
.break
go:
mov eax,DBEvent.u.CreateProcessInfo.hFile
mov regEAX,eax
mov ebx,DBEvent.u.CreateProcessInfo.hProcess
mov regEBX,ebx
mov ecx,DBEvent.u.CreateProcessInfo.hThread
mov regECX,ecx
mov edx,DBEvent.u.CreateProcessInfo.lpBaseOfImage
mov regEDX,edx

.elseif DBEvent.dwDebugEventCode==LOAD_DLL_DEBUG_EVENT ;*

call DisplayEvent
call DisplayDBThread ;*
call DisplayProcessThread

.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_INFO ;***A***
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_DATATYPE_MISALIGNMENT

invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE
.endif

.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT

mov eax,010h
mov count1,eax ;**intitialize instructions to count**

mov context.ContextFlags, CONTEXT_FULL

call DisplayProcessThread

invoke SuspendThread,pi.hThread
invoke GetThreadContext,pi.hThread, addr context
cmp eax,0h
jne go1
call DisplayLastError
int 3
go1:

mov eax,context.regFlag ;** Set trap flag and jam load EIP**
call DisplayAllRegs
or context.regFlag,0100h
invoke SetThreadContext,pi.hThread, addr context
mov eax,0401000h
mov context.regEip,eax
invoke SetThreadContext,pi.hThread, addr context
call DisplayAllRegs
invoke ResumeThread,pi.hThread


invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE ;INT 3

cmp eax,0
jne go2
call DisplayregXXX
call DisplayLastError
.break
go2:
.continue



.elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP

call DisplayAllRegs

invoke SuspendThread,pi.hThread
invoke GetThreadContext,pi.hThread,addr context
or context.regFlag,0100h
invoke SetThreadContext,pi.hThread, addr context
invoke ResumeThread,pi.hThread

dec count1 ;**decrement instruction counter**
jnz Continue
.break

DisplayEvent:

invoke wsprintf, addr buffer, addr Identify,DBEvent.u.Exception.pExceptionRecord.ExceptionCode
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION ;*
ret

DisplayDBThread:

invoke wsprintf, addr buffer, addr Display3, DBEvent.u.CreateProcessInfo.hThread
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
ret

DisplayProcessThread:

pushad
invoke wsprintf, addr buffer, addr Display2, pi.hThread
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
popad
ret

DisplayregXXX:

pushad
invoke wsprintf, addr buffer,addr dispregXXX,regXXX
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
popad
ret

DisplayLastError:

push eax
invoke GetLastError
mov regXXX,eax
mov MsgSrc,eax
call DisplayregXXX
invoke LocalAlloc ,LMEM_MOVEABLE or LMEM_ZEROINIT,1000
mov errorMsgbuff,eax
mov loclock,eax
invoke LocalLock,loclock
invoke FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,0,MsgSrc,0,addr errorMsgbuff,0,NULL
invoke wsprintf, addr buffer, addr errorMessage,errorMsgbuff
invoke MessageBox,0,addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
invoke LocalUnlock,addr loclock
invoke LocalFree,addr errorMsgbuff
pop eax
ret

DisplayAllRegs:

pushad
mov context.ContextFlags, CONTEXT_FULL
invoke GetThreadContext,pi.hThread, addr context
invoke wsprintf, addr buffer, addr displayregs,context.regCs,context.regDs,context.regEs,context.regSs,
context.regEax,context.regEbx,context.regEcx,context.regEdx,context.regEip,context.regEsp,context.regEbp,
context.regEsi,context.regEdi,context.regFs,context.regGs,context.regFlag
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
popad
ret

Swap:

xchg ah,al
mov ecx,010h
rol eax,cl
xchg ah,al
ret

Continue:

invoke ResumeThread,pi.hThread


invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,DBG_CONTINUE


.endif
.endif
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED
.endw
.endif
invoke CloseHandle,pi.hProcess
invoke CloseHandle,pi.hThread
invoke ExitProcess, 0
end start
Posted on 2003-02-23 11:24:24 by mrgone
Intel Quote

Nested task (bit 14). Controls the chaining of interrupted and called tasks. The
processor sets this flag on calls to a task initiated with a CALL instruction, an interrupt,or an exception. It examines and modifies this flag on returns from a task initiated with the IRET instruction. The flag can be explicitly set or cleared with the POPF/POPFD instructions; however, changing to the state of this flag can generate unexpected exceptions in application programs. Refer to Section 6.4., ?Task Linking? in Chapter 6, Task Management for more information on nested tasks.
Posted on 2003-02-23 20:15:38 by mrgone
I have also found that Dr Watson virus protection software comes with Win2k and is used in this NT DLL to various checking for what it may consider illegal instructions. The way it gets control must be through NT flag generated exceptions.
Posted on 2003-03-11 14:44:33 by mrgone