[OFN_FLAGS &OFN_FILEMUSTEXIST+&OFN_PATHMUSTEXIST+&OFN_LONGNAMES+&OFN_EXPLORER+&OFN_HIDEREADONLY]
________________________________________________________________________________________
; Data:
[UserFileFilter: 0 # 50] [FullChoosenFile: 0 #50] [ChoosenFile: 0 #20]
[OPENFILENAME: len hwndFileOwner:
0 OF_hInstance: 0 FilterStrings
userFileFilter 200 &NULL FullChoosenFile 200
ChoosenFile
200 &NULL AppName OFN_FLAGS
nFileOffsetinChoosenFile: W§ 0 nFileExtensioninChoosenFile:
0
DefaultExtension: D§ &NULL
HookCustomData: &NULL HookProcPtr: &NULL HookTemplateName:
0]
[AppName: 'Win32 Debug Example no.4' 0
FilterStrings: B§ 'Executable Files'
0 '*.exe' 0
'All Files' 0 '*.*' 0 0
ExitProc:
"The debuggee exits
Total Instructions executed : %lu",0
ProcessInfo: "File Handle: %lx
Process Handle: %lx
Thread Handle: %lx
Image Base: %lx
Start Address: %lx", 0]
[TotalInstruction: 0]
[buffer: B§ 0 #512]
[PROCESS_INFORMATION: PI_hProcess: 0
PI_hThread: 0
PI_dwProcessId: 0 PI_dwThreadId: 0]
[STARTUPINFO: SI_cb: 0
SI_lpReserved: 0 SI_lpDesktop: 0
SI_lpTitle: 0 SI_dwX: 0
SI_dwY: 0
SI_dwXSize: 0 SI_dwYSize:
0 SI_dwXCountChars:
0
SI_dwYCountChars: 0 SI_dwFillAttribute: 0 SI_dwFlags:
0
SI_wShowWindow: W§ 0 SI_cbReserved2: W§ 0 SI_lpReserved2:
D§ 0
SI_hStdInput: 0 SI_hStdOutput: 0
SI_hStdError: 0]
[DEBUG_EVENT: DE_dwDebugEventCode: 0
DE_dwProcessId: 0
DE_dwThreadId: 0
DE_u: CPDI_hFile:
E_pExceptionRecord: 0
CPDI_hProcess: 0
CPDI_hThread: 0
CPDI_lpBaseOfImage: 0
0
0
0
CPDI_lpStartAddress: 0] [DamnedUnionTail: 0 #100]
; CREATE_PROCESS_DEBUG_INFO union Data (available
at 'DE_u'):
;
; HANDLE hFile;
; HANDLE hProcess;
; HANDLE hThread;
; LPVOID lpBaseOfImage;
; DWORD dwDebugInfoFileOffset;
; DWORD nDebugInfoSize;
; LPVOID lpThreadLocalBase;
; LPTHREAD_START_ROUTINE lpStartAddress;
; LPVOID lpImageName;
; WORD fUnicode;
; EXCEPTION_DEBUG_INFO union Data (available at
'DE_u'):
;
; EXCEPTION_RECORD ExceptionRecord;
; DWORD dwFirstChance;
; EXCEPTION_RECORD union Data (available at 'ExceptionRecord' of 'DE_u'):
; DWORD ExceptionCode;
; DWORD ExceptionFlags;
; struct _EXCEPTION_RECORD
*ExceptionRecord;
; PVOID ExceptionAddress;
; DWORD NumberParameters;
; DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
; This is the full structure of CONTEXT with nested structure unfolded:
[CONTEXT: C_ContextFlags: 0
C_iDr0: 0 C_iDr1: 0 C_iDr2: 0 C_iDr3: 0 C_iDr6:
0 C_iDr7: 0
FLOATING_SAVE_AREA: FSA_ControlWord: 0 FSA_StatusWord: 0
FSA_TagWord: 0
FSA_ErrorOffset: 0 FSA_ErrorSelector: 0 FSA_DataOffset: 0
FSA_DataSelector: 0]
[FSA_RegisterArea: B§ 0 #80]
[FSA_Cr0NpxState: 0
C_regGs: 0 C_regFs: 0 C_regEs: 0 C_regDs: 0
C_regEdi: 0 C_regEsi: 0
C_regEbx: 0 C_regEdx: 0 C_regEcx: 0 C_regEax: 0
C_regEbp: 0 C_regEip: 0
C_regCs: 0
C_regFlag: 0
C_regEsp: 0 C_regSs: 0][C_ExtendedRegisters: B§ 0 #512]
________________________________________________________________________________________
____________________________________________________________________________________________
Main:
call 'Comdlg32.GetOpenFileNameA'
OPENFILENAME
...If eax e &TRUE
call
'KERNEL32.GetStartupInfoA' STARTUPINFO
call
'KERNEL32.CreateProcessA' FullChoosenFile &NULL &NULL &NULL
&FALSE,
&DEBUG_PROCESS+&DEBUG_ONLY_THIS_PROCESS,
&NULL &NULL STARTUPINFO PROCESS_INFORMATION
.While
eax e &TRUE
L0:
call 'KERNEL32.WaitForDebugEvent' DEBUG_EVENT &INFINITE
.If D§DE_dwDebugEventCode = &EXIT_PROCESS_DEBUG_EVENT
call 'USER32.wsprintfA' buffer ExitProc D§TotalInstruction
pop eax, eax, eax
call 'USER32.MessageBoxA' 0 Buffer AppName &MB_ICONINFORMATION | jmp
L9>>
.Else_If D§DE_dwDebugEventCode = &EXCEPTION_DEBUG_EVENT
If D§E_pExceptionRecord e &EXCEPTION_BREAKPOINT
mov D§C_ContextFlags &CONTEXT_CONTROL
call 'KERNEL32.GetThreadContext' D§PI_hThread CONTEXT
or D§C_regFlag 0100
call 'KERNEL32.SetThreadContext' D§PI_hThread CONTEXT
call 'KERNEL32.ContinueDebugEvent' D§DE_dwProcessId D§DE_dwThreadId,
&DBG_CONTINUE
jmp L0<<
Elseif D§E_pExceptionRecord e &EXCEPTION_SINGLE_STEP
inc D§TotalInstruction
call 'KERNEL32.GetThreadContext' D§PI_hThread CONTEXT
or D§C_regFlag 0100
call 'KERNEL32.SetThreadContext' D§PI_hThread CONTEXT
call 'KERNEL32.ContinueDebugEvent' D§DE_dwProcessId D§DE_dwThreadId,
&DBG_CONTINUE
jmp L0<<
End_If
.End_If
call 'KERNEL32.ContinueDebugEvent' D§DE_dwProcessId D§DE_dwThreadId,
&DBG_EXCEPTION_NOT_HANDLED
.End_While
...End_If
L9: call 'Kernel32.CloseHandle' D§PI_hProcess
call 'Kernel32.CloseHandle'
D§PI_hThread
call 'KERNEL32.ExitProcess'
0
.Else_If D§DE_dwDebugEventCode = &EXCEPTION_DEBUG_EVENT
If D§E_pExceptionRecord e &EXCEPTION_BREAKPOINT
We take this opportunity to
set the debuggee into single-step mode. Remember that Windows sends an
EXCEPTION_BREAKPOINT just before it executes the first instruction of the
debuggee.
mov D§C_ContextFlags &CONTEXT_CONTROL
call 'KERNEL32.GetThreadContext' D§PI_hThread CONTEXT
We call GetThreadContext to fill the CONTEXT structure with the current values in the registers of the debuggee. More specifically, we need the current value of the flag register.
or D§C_regFlag 0100
We set the trap bit (8th bit)
in the flag register image.
call 'KERNEL32.SetThreadContext' D§PI_hThread CONTEXT
call 'KERNEL32.ContinueDebugEvent' D§DE_dwProcessId D§DE_dwThreadId,
&DBG_CONTINUE
Then we call SetThreadContext
to overwrite the values in the CONTEXT
structure with the new one(s) and call ContinueDebugEvent
with DBG_CONTINUE flag to
resume the debuggee.
Elseif D§E_pExceptionRecord e &EXCEPTION_SINGLE_STEP
inc D§TotalInstruction
When an instruction is executed
in the debuggee, we receive an EXCEPTION_DEBUG_EVENT.
We must examine the value of u.Exception.pExceptionRecord.ExceptionCode.
If the value is EXCEPTION_SINGLE_STEP,
then this debug event is generated because of the single-step mode. In
this case, we can increment the variable TotalInstruction
by one because we know that exactly one instruction was executed in the
debuggee.
call 'KERNEL32.GetThreadContext' D§PI_hThread CONTEXT
or D§C_regFlag 0100
call 'KERNEL32.SetThreadContext' D§PI_hThread CONTEXT
call 'KERNEL32.ContinueDebugEvent' D§DE_dwProcessId D§DE_dwThreadId,
&DBG_CONTINUE
Since the trap flag is cleared
after the debug exception is generated, we must set the trap flag again
if we want to continue in single-step mode.
Warning:
Don't use the example in this tutorial with a large program: tracing is
SLOW. You may have to wait for ten minutes before you can close the debuggee.