invoke setthreadcontext,pi.hthread, addr context
invoke continuedebugevent, dbevent.dwprocessid, dbevent.dwthreadid,dbg_continue
.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
analysis:
the program shows the openfile dialog box. when the user chooses an executable file, it executes the program in single-step mode, couting the number of instructions executed until the debuggee exits.
.elseif dbevent.dwdebugeventcode==exception_debug_event .if dbevent.u.exception.pexceptionrecord.exceptioncode==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 context.contextflags, context_control
invoke getthreadcontext, pi.hthread, addr 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 context.regflag,100h
we set the trap bit (8th bit) in the flag register image.
invoke setthreadcontext,pi.hthread, addr context
invoke continuedebugevent, dbevent.dwprocessid, dbevent.dwthreadid, dbg_continue
.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 dbevent.u.exception.pexceptionrecord.exceptioncode==exception_single_step
inc 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.
invoke getthreadcontext,pi.hthread,addr context or context.regflag,100h
invoke setthreadcontext,pi.hthread, addr context
invoke continuedebugevent, dbevent.dwprocessid, dbevent.dwthreadid,dbg_continue
.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.