Hi I have been though the masm32 API I don't know how many times and I can't figure out how to get THREAD_GET_CONTEXT and TREAD_SET_CONTEXT access in NT. Does it have to do with GenericMapping function? Thanks, other Frank

This code displays everything down to the error. It show threads of process and threads of Debug events.Debug event codes as well as a dump of the debugee's first four bytes in reverse order. It demonstates that the error is SetThreadContext by returning a null in eax.
I suggest opening this first very simple program which is little more than a skeleton that juggles register contents back and forth. Also easy to disassemble.


"debugee"

.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

"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",0Dh,0Ah
db "regXXX= : %lx",0Dh,0Ah
db "thread : %1x",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: %08x",0
Display2 db "ProcessThread: %08x",0
Display3 db "DBEventThread: %08x",0
membufdisp db "Dump: %08x",0
ReadMem dd 0


.data?


membuf dd 2048 dup(?)
buffer db 2048 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
invoke SetDebugErrorLevel,SLE_MINORERROR
.while TRUE

invoke WaitForDebugEvent, addr DBEvent, INFINITE ;*****
.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
invoke wsprintf, addr buffer, addr ExitProc,regXXX,thread
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

call DisplayEvent
call DisplayDBThread
call DisplayProcessThread


invoke ReadProcessMemory,pi.hProcess,401000h,addr membuf,08h,addr ReadMem
cmp eax,0h
jne go
.break
go:
invoke wsprintf, addr buffer,addr membufdisp,membuf+0,membuf+4
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION



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



call DisplayProcessThread

mov context.ContextFlags, CONTEXT_FULL

invoke SuspendThread,pi.hThread
invoke GetThreadContext,pi.hThread, addr context
cmp eax,0h
jne go1
.break
go1:
push eax
mov eax,context.regFlag
mov regXXX,eax
call DisplayregXXX
pop eax
or context.regFlag,100h
invoke SetThreadContext,pi.hThread, addr context
jne go2
.break
go2:
invoke GetThreadContext,pi.hThread, addr context
push eax
mov eax,context.regFlag
mov regXXX,eax
call DisplayregXXX
pop eax
invoke ResumeThread,pi.hThread



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



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



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


invoke SuspendThread,pi.hThread
invoke GetThreadContext,pi.hThread,addr context
mov edx,context.regEip
and edx,00000ffffh
cmp edx,000001006h
jnb Get
jmp Continue



Get:

cmp edx,00100fh
jnb Continue
mov ebx,context.regEip
mov regXXX,ebx
jmp Continue

DisplayEvent:

pushad

invoke GlobalAlloc,GMEM_MOVEABLE OR GMEM_ZEROINIT,1000h
push eax
push eax
invoke GlobalLock,eax
push eax

invoke wsprintf, addr buffer, addr Identify,DBEvent.u.Exception.pExceptionRecord.ExceptionCode
pop eax
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION ;*
call GlobalUnlock
call GlobalFree
popad
ret

DisplayDBThread:

pushad
invoke wsprintf, addr buffer, addr Display3, DBEvent.u.CreateProcessInfo.hThread
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
popad
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, addr regXXX
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
popad
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-14 21:33:20 by mrgone
have you tried getlasterror? it should give you a pointer in the right direction...
Posted on 2003-02-15 01:38:00 by BubbaFate
Thanks for reminding me bubba. I was going to try it but got distracted with Generic options. Those API's will lead you around in circles sometimes. I do know that somewhere I need to assign the thread THREAD_GET_CONTEXT and THREAD_SET_CONTEXT. I'm just not sure how to do it. I tried in in CreateProcess and in CONTEXT struct but no luck yet. There is a THREAD_ALL_ACCESS but the API file says I should choose the minimal that I need or it will slow down system performance.
Posted on 2003-02-15 02:16:34 by mrgone
I'm not sure, but I think you have to use the thread handle that is given to you during CREATE_PROCESS_DEBUG_EVENT and not the one that is given to you in the PROCESS_INFORMATION structure... so as a quick test try using regECX instead of pi.hThread in your context calls.
Posted on 2003-02-15 02:35:55 by BubbaFate
I already tried using original handle. Let me me reiterate in saying everything works great in Windows98. Yes I did try the other thread handle and got the exact same results. It's crazy aint it? One thing I do know is that if Windows decides you won't get in than you sure won't using their operating system. I remeber when the 286 first came out. I had and still have the users manual "286AIPX". It is a consequence of the processesor design that who ever gets first crack at the Global Descriptor Table and the Local Descriptor Tables rules the memory. There could be a back door as in the 286 BIOS had a SS(Stack Segment) "for those who don't know" SS:SP parameter. The reason the 286 had this parameter in it's BIOS is because the '286 could not switch back to real mode from protected mode once it was in protected mode. The solution was to reset the processor usually by doing a jump to F000:FFF0 which is where the Intel processor starts reading. Usually there will be a intra segment jump right here like jump 1000:1223. Even the Pentium starts off in real mode and it's core processor is just an 8086 capable of addressing only 64K. But when this reset was done. The value in SS:SP pointed to an address that told the processor the current machine state. I other words First parameter would be say, Load the CS register and next would load another until IP which would then jump to execution with all it's registers properly set. I have heard Microsoft@ recently touting that the only protection is hardware protection. They are a day late but not a dollar short. Intel already devised this in the hard ware of the processor. So do they want to keep us out? They can except for a reset and I don't mean int 3. They can get hold of that interrupt vector too. Let me say this. Digital Processors are maxed out in speed. In fact if anyone told me 10 years ago that they would operate into the low SHF range I would not have believed them. I don't care how big the heat sinks are or the advanced stripline techniques of the PCB. Analog is next. Be forwarned you must lean to program in weights. Computer systems made 50 years ago are faster than todays computers if it is a well designed analog computer. Think of a sign wave. The computer is calculating up and down that wave in weight codes. Sure the buss access has some room to grow but soon it will peak. WHAT'S NEXT?????
Posted on 2003-02-15 03:32:58 by mrgone
Whenever I run your code I get bombarded by messageboxes :) But I did step through the code and SetThreadContext is working fine, and I'm running Windows XP. As far as the THREAD_? constants go, those are parameters to the OpenThread API and AFAIK can only be used there. Anyway I just came across this when lookin at the platform sdk entry for CreateProcess so you shouldn't have to worry about it anyway.

When created, the new process and thread handles receive full access rights (PROCESS_ALL_ACCESS and THREAD_ALL_ACCESS).
Posted on 2003-02-15 04:00:05 by BubbaFate
I'm using Win2k here and it don't work. The message boxes are for information leading up to the event failure. You saw where I tested some operations .(the 3 goes) ? Yeah it fails on the last one the set thread context. I don't think it's getting the correct thread but rather a thread value from an NT DLL. The last box displayed is supposed to be a trapped EIP value from the debuggee. I'm getting one in the 7000000 upper segment range. Must be a DLL.
Posted on 2003-02-15 13:24:11 by mrgone
I inserted this code and found I could not even store the thread handle. It gives a bogus value win2k

push eax
mov eax,pi.hThread
call DisplayProcessThread
mov regXXX,eax
call DisplayregXXX
pop eax
Posted on 2003-02-15 19:38:12 by mrgone
DisplayregXXX:


pushad
invoke wsprintf, addr buffer,addr dispregXXX, [color=red]addr regXXX[/color]
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
popad
ret


Its not a bogus value... its the address of the variable 'regXXX', to display the value of regXXX take of addr... remember that dword's are passed by value not by reference
Posted on 2003-02-16 04:41:23 by BubbaFate
Oh that was address of pointer. :o No wonder I kept getting that same value.lol. Ok so does the term "addr" mean or just in that feild? Anyway I sure appreciate you helping me fumble through these basic of MASM. I see I have a long way to go.
Posted on 2003-02-16 12:22:46 by mrgone
Yes addr stands for address... if you know c, its the same as doing &SomeVariable
Posted on 2003-02-16 12:26:38 by BubbaFate
Well I never did any C. I've been in hardware design the last few years but not as lucrative with economic slow down. But I used to program in DOS alot back then but with assembler.
Anyway, I tried what you siad with loading with passing thread handle to function GetThreadContext like this:

invoke SuspendThread,pi.hThread
invoke GetThreadContext,regECX, addr context
cmp eax,0h
jne go1
.break
go1:
push eax
mov eax,context.regFlag
mov regXXX,eax
call DisplayregXXX
pop eax
or context.regFlag,100h
invoke SetThreadContext,regECX, addr context
jne go2
.break

And I get same Flag status. But you did notice that pi.hThread in CONTEXT did give a different value from original create process. Anyway both handles seem to work but I still can't set the thread. I get an error. It really doesn't do me any good at this point to use GetLastError because I don't know what the return codes mean. I need a copy of 2000 DDK. I'll try to order this week. How big is the WINNT.H file header? Do you have info on return codes?
Posted on 2003-02-16 14:10:27 by mrgone
A handle is nothing more than an index of an array... every process has a handle table and when you "get a handle" to some object all windows does is add an entry to the handle table and return the index of the table that it added the information to... so lets say you called openprocess and you get back the value 10, if you call openprocess again you would probably get the value 11... thats why its important to call closehandle when ever you create a handle, so windows can remove the entry in the handle table... thus freeing up memory

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes.asp
Posted on 2003-02-16 14:20:33 by BubbaFate
also that addr keyword is basically a lea instruction
Posted on 2003-02-16 14:23:02 by BubbaFate
Ok you are saying it's a lookup table? I follow you and Lea is similar to assembly statement mov AX, old syntax like: mov BX, .
Well thanks again and thanks for hyperlink. I was reading you explanations on wsprint. Your a heavy hitter. You need to write a book for us masm dummies. I'll buy a copy. Never know when you might get board with the board. We'll be in trouble then.
Posted on 2003-02-16 14:44:04 by mrgone

You need to write a book


I don't know that much... yall just happened to ask questions I know =)
Posted on 2003-02-16 14:46:21 by BubbaFate
Ok not what it means but have a few guesses. here it is:

"The secified resource type cannot be found in the image file"
Posted on 2003-02-17 00:51:32 by mrgone
I think that error is left over from messagebox calls
Posted on 2003-02-17 05:49:00 by BubbaFate
I found out I made a mistake when I did error checking but it was good experience to learn to use MessageFormat to out system generated text strings.
I did another check on the context right after CreateProcess and found the regesters where never right to begin with. Shouldn't Eip be sitting at base address offset 1000h ? I'm not sure but is that address generated by CS:EIP ?
Need some review on that I guess I guess.
Posted on 2003-02-17 10:33:36 by mrgone
When I used NULL with CreateProcess win2k automatically assigned the debugee a security descriptor. The user must default to about priviledge level 2 or 3. Anyway check it out I'm not making this stuff up.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/security_descriptors.asp

Atleast I know I'm not crazy. Well....not completely anyway...lol
Posted on 2003-02-17 12:33:06 by mrgone