220 likes | 503 Views
Chapter 7b – Assembly Debugging. Mithun Shanbhag. Advanced Breakpoints for Native Applications. Advanced Breakpoint Syntax Viewing Register Contents Pseudo – Registers Thread Information Block Debugging Injected Code Exception Monitoring Hardware Breakpoints. Advanced Breakpoint Syntax.
E N D
Chapter 7b – Assembly Debugging Mithun Shanbhag
Advanced Breakpoints for Native Applications • Advanced Breakpoint Syntax • Viewing Register Contents • Pseudo – Registers • Thread Information Block • Debugging Injected Code • Exception Monitoring • Hardware Breakpoints
Advanced Breakpoint Syntax • The advanced breakpoint syntax is composed of two parts – • Context (think SCOPE). • Location. • Context -> • {[function],[source file],[binary module]} • Location -> • Expressed as source lines or function names.
Advanced Breakpoint Syntax (cont’d) • Simple Example – • In VS .NET, to set a breakpoint on line 20 of a file ‘TEST.CPP’, the CONTEXT & LOCATION would be specified as – {, TEST.CPP, }@20
Viewing Register Contents • The VS .NET debugger groups the Register Sets as follows ->
Pseudo – Registers • Pseudo-Registers are not actual hardware registers. • Can be used in the ‘Watch’ window. • Can be used to set conditional breakpoints.
Pseudo – Registers (cont’d) • $ERR is a Pseudo-Register, which displays the last error code for current thread. • Works like the Win32 API call GetLastError(). • Can be used with “, hr” modifier to display error message corresponding to the error code.
Pseudo – Registers (cont’d) • Example -> • Suppose that an error of type ERROR_DRIVE_LOCKED occurs……….. $ERR = 108 $ERR , hr = ERROR_DRIVE_LOCKED • If no error occurs………. $ERR = 0 $ERR , hr = S_OK
Pseudo – Registers (cont’d) • $CLK is another undocumented Pseudo Register. • $CLK can be used to measure time between two location/conditional breakpoints in debug mode. • Rudimentary Timer……the time includes debugger overhead.
Pseudo – Registers (cont’d) • No built-in way of setting a location breakpoint that fires only in a specific thread. • Use $TIB in the watch window to extract the location of desired thread’s Thread Information Block (TIB). • Set up a conditional breakpoint using this value of $TIB. • E.g. - $TIB == 0x00fa2345 • Now debugger will only break execution for the thread whose TIB has been specified.
Pseudo – Registers (cont’d) • $HANDLES shows the numbers of open handles in the current process. • Useful for detecting leaks. • $VFRAME is a virtual frame pointer. • $VFRAME points to the previous item’s EBP value. Hence can be used to manually walk the stack back.
Thread Information Block • FS Register (General Purpose Segment Register) contains a pointer to the Thread Information Block (TIB). • FS:[0x00000018] • TIB is also called as the Thread Environment Block (TEB). • TIB contains all thread-specific data like • Structured Exception Handling (SEH) chains. • Thread Local Storage. • Thread Stack.
Thread Information Block (cont’d) • Whenever an instruction is accessing the FS register, one of the following occurs………… • An SEH frame is created, • An SEH frame is destroyed, • The TIB is accessed or • Thread local storage is being accessed.
Thread Information Block (cont’d) • Accessing the TIB • The linear address of the TIB is FS:[0x00000018] • Retrieving the Thread ID • At an offset of 0x24 from the TIB lies the thread ID • Implementation of GetCurrentThreadId() GetCurrentThreadId: MOV EAX, FS:[00000018h] MOV EAX, DWORD PTR [EAX+024h] RET
Thread Information Block (cont’d) • Accessing the Thread Local Storage • The Thread Local Storage is located at an offset of 0x2C in the TIB structure. • The following disassembly shows how to access the Thread Local Storage Pointer… MOV EAX, FS:[00000018h] MOV ECX, DWORD PTR FS:[0x2C] MOV EDX, DWORD PTR [ECX+EAX*4]
Thread Information Block (cont’d) • Set the Thread Name in Native Code typedef struct tagTHREADNAME_INFO { DWORD dwType; // must be 0x1000 LPCSTR szName; // pointer to name (in user addr space) DWORD dwThreadID; // thread ID (-1=caller thread) DWORD dwFlags; // reserved for future use, must be zero } THREADNAME_INFO; void SetThreadName( DWORD dwThreadID, LPCSTR szThreadName) { THREADNAME_INFO info; info.dwType = 0x1000; info.szName = szThreadName; info.dwThreadID = dwThreadID; info.dwFlags = 0; __try {RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info ); } except (EXCEPTION_CONTINUE_EXECUTION) {} }
Debugging Injected Code` • Attributed Programming – • Some attributes are interpreted by compiler. • Other attributes inject code into the source. • A bug may cause a program to fail while it is executing injected code. • Injected code can be viewed in the DISASSEMBLY window. • You can create a merged source file that contains original and injected code
Debugging Injected Code • Project Properties • C / C++ • Output Files • Expand Attributed Source -> /FX • This allows you to combine IDL attributes with your source file to generate a single file to make a COM object.
Exception Monitoring • When an exception occurs……… • OS suspends process (all threads stop) • Notifies the debugger about exception (First Chance Exception). • If Debugger did not cause the exception • Then, exception passed to debuggee. • Debugger outputs message in Output Window • If debuggee has exception handler • Then, exception is processed • Else, Exception propogates to final handler in NTDLL.DLL • Then, OS suspends debuggee • Notifies debugger about exception (2nd Chance Exception) • Process dies from unhandled exception.
Exception Monitoring (cont’d) • Break -> Stop at point where exception occurred. • Continue -> Pass exception to debuggee and continue execution. • Ignore -> For CPU exceptions………………………… • Re-execute offending instructions • Raises the First Chance Exception again ! For exception generated by ‘RaiseException’ (e.g. C++ exceptions) • Execution will continue as if exception never occurred.