A quick post on how to debug injected DLLs through Visual Studio. This is rather straightforward, but it seems like a fair amount of people are unaware that this can be done. It might possibly because programs typically don’t have DLLs injected to them at runtime, so perhaps people think that debugging them can’t be done in a straightforward way. Fortunately, if you attach to the target process beforehand and inject a DLL, the Visual Studio debugger will detect the loaded DLL and allow for an ordinary debugging experience. The steps are rather simple:
1. Choose to attach to a process through the “Debug” menu in Visual Studio.
2. Select the target process from the list and attach.
3. Attach to the process and verify that breakpoints can get hit.
And that’s all there is to it. All of the useful features of the Visual Studio debugger are now available for debugging the injected DLLs.
Like many developers who write code in their free time, I have an overwhelming backlog of side projects. A lot of these projects don’t get finished for the usual variety of reasons: lack of time, loss of interest, another side projects comes up, and so on. As I searched through the folders of these projects, I realized that while I might not be able to complete them now or in the future, that there are certain portions of them that I can carve out and post about. These snippets will typically be short code blocks that I had written to solve a rather particular problem at the time.
The code snippet covered here will be a function I wrote called FindWindowLike. Interestingly enough, while Googling this, there appears to be an MSDN article from 1997 which lists a VB6 function that does the same thing. The one posted here is implemented much differently than that horrible mess though. The purpose of this function is to get a handle to a window while knowing only part of its title. This was useful when I was trying to get a window handle which changed on every instance of the program — for example the process id was part of the title. The code is very straightforward and uses EnumWindows to enumerate all windows on the desktop and perform a substring match.
I’ve finally and painstakingly moved all of the code relating to my previous blogs posts to GitHub. The descriptions in the repositories are not very descriptive (that’s what the actual blog posts are for!), but now the code is available to look at without needing to download and unzip archives. The GitHub site is https://github.com/codereversing/. Going through this also allowed me to see how my programming style (indent, variable/function naming) has evolved. I definitely prefer the more .NET type of style
if(someVariable ==10){
f();}else{
g();}
if(someVariable == 10)
{
f();
}
else
{
g();
}
to the more space conscious, but harder to read, K&R C style
if(some_variable ==10){
f();}else{
g();}
if(some_variable == 10) {
f();
} else {
g();
}
All future code will be posted on GitHub now instead of zipped and linked through the blog post.
Here an implementation of AddVectoredExceptionHandler as it was reverse engineered.
PVOID RtlAddVectoredExceptionHandler(ULONG FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler, int Unknown){
PPEB pPeb = GetPEB();
VECTORED_HANDLER_ENTRY *pVecNewEntry =(VECTORED_HANDLER_ENTRY *)HeapAlloc((HANDLE)pPeb->ProcessHeap, 0, sizeof(VECTORED_HANDLER_ENTRY));if(pVecNewEntry ==nullptr){returnnullptr;}
pVecNewEntry->dwAlwaysOne =1;
PVOID pEncodedHandler = EncodePointer(VectoredHandler);
VECTORED_HANDLER_LIST *pVecHandlerBase =(VECTORED_HANDLER_LIST *)(VectorHandlerListBase);
AcquireSRWLockExclusive(&pVecHandlerBase->srwLock);
pVecNewEntry->pVectoredHandler =(PVECTORED_EXCEPTION_HANDLER)pEncodedHandler;//If the list is empty then set the CrossProcessFlags fieldsif(pVecHandlerBase->pFirstHandler ==(VECTORED_HANDLER_ENTRY *)&pVecHandlerBase->pFirstHandler){
InterlockedBitTestAndSet((LONG *)&pPeb->CrossProcessFlags, 2);}if(FirstHandler){//Insert new node at the head of the VEH list
pVecNewEntry->pNext = pVecHandlerBase->pFirstHandler;
pVecNewEntry->pPrev =(VECTORED_HANDLER_ENTRY *)&pVecHandlerBase->pFirstHandler;
pVecHandlerBase->pFirstHandler->pPrev = pVecNewEntry;
pVecHandlerBase->pFirstHandler = pVecNewEntry;}else{//Insert new node at the end of the VEH list
pVecNewEntry->pNext =(VECTORED_HANDLER_ENTRY *)&pVecHandlerBase->pFirstHandler;
pVecNewEntry->pPrev = pVecHandlerBase->pLastHandler;
pVecHandlerBase->pLastHandler->pNext = pVecNewEntry;
pVecHandlerBase->pLastHandler = pVecNewEntry;}
ReleaseSRWLockExclusive(&pVecHandlerBase->srwLock);return(PVOID)pVecNewEntry;}
PVOID RtlAddVectoredExceptionHandler(ULONG FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler, int Unknown)
{
PPEB pPeb = GetPEB();
VECTORED_HANDLER_ENTRY *pVecNewEntry =
(VECTORED_HANDLER_ENTRY *)HeapAlloc((HANDLE)pPeb->ProcessHeap, 0, sizeof(VECTORED_HANDLER_ENTRY));
if(pVecNewEntry == nullptr)
{
return nullptr;
}
pVecNewEntry->dwAlwaysOne = 1;
PVOID pEncodedHandler = EncodePointer(VectoredHandler);
VECTORED_HANDLER_LIST *pVecHandlerBase = (VECTORED_HANDLER_LIST *)(VectorHandlerListBase);
AcquireSRWLockExclusive(&pVecHandlerBase->srwLock);
pVecNewEntry->pVectoredHandler = (PVECTORED_EXCEPTION_HANDLER)pEncodedHandler;
//If the list is empty then set the CrossProcessFlags fields
if(pVecHandlerBase->pFirstHandler == (VECTORED_HANDLER_ENTRY *)&pVecHandlerBase->pFirstHandler)
{
InterlockedBitTestAndSet((LONG *)&pPeb->CrossProcessFlags, 2);
}
if(FirstHandler)
{
//Insert new node at the head of the VEH list
pVecNewEntry->pNext = pVecHandlerBase->pFirstHandler;
pVecNewEntry->pPrev = (VECTORED_HANDLER_ENTRY *)&pVecHandlerBase->pFirstHandler;
pVecHandlerBase->pFirstHandler->pPrev = pVecNewEntry;
pVecHandlerBase->pFirstHandler = pVecNewEntry;
}
else
{
//Insert new node at the end of the VEH list
pVecNewEntry->pNext = (VECTORED_HANDLER_ENTRY *)&pVecHandlerBase->pFirstHandler;
pVecNewEntry->pPrev = pVecHandlerBase->pLastHandler;
pVecHandlerBase->pLastHandler->pNext = pVecNewEntry;
pVecHandlerBase->pLastHandler = pVecNewEntry;
}
ReleaseSRWLockExclusive(&pVecHandlerBase->srwLock);
return (PVOID)pVecNewEntry;
}
You can download the full Visual Studio 2013 project here. Follow on Twitter for more updates.
This post will continue where the first one left off and explain the operations happening on the doubly linked list of exception handlers. To understand anything in this post, you should read the first one.
Finding the Link Relationships
Given the information from part one, there are two structures at work here: _LdrpVectorHandlerList, which is a non-exported named symbol, and _LdrpVectorHandlerEntry, which is the name given to the struct allocated in _RtlpAddVectoredHandler. Each of these structures has two pointers within them that get moved around.
The best way to find out what is happening is to dynamically trace adding exception handlers. For example, what goes on in the code when three exception handlers are added in series?Each one will be added to the head of the list, so that if an exception occurs then the call order will be VectoredHandler3 -> VectoredHandler2 -> VectoredHandler1 -> Unhandled exception. For the case of a handler being inserted at the head of the list, the following instructions will be executed:
The easiest way to see what is going on is to make a table of the runs. Here let X, Y, Z be the different memory addresses of ESI. Let Base be the base address of _LdrpVectorHandlerList, relative to EAX and EDI. I’ve also reproduced the structures and the mappings of registers to fields below.
Looking at the results of these three adds, you can begin to see a relationship.
[X] = [ESI] Always holds the address of the previous handler
[X+4] = [ESI+0x4] Always holds the address of the base of the table
[*(Base+4)] = [EAX+0x4] Always holds the address of the new handler
[Base] = [EDI] Always holds the address of the new handler
Given that this operation is to insert at the head of the list, it is possible to draw some conclusions. Since [ESI] always contains the address of the previous topmost handler, it can be assumed to be a pointer to the next handler in the chain. [ESI+0x4] can be assumed to be a pointer to the previous handler in the chain, which in the case of inserting a head node, is set as the base of the exception list. Now the struct definition can be completed.
[EAX+0x4] is a bit more difficult to discern. EAX holds the value of the address of the second field in _LdrpVectorHandlerList. This is dereferenced and the second item in the dereferenced struct is set to the address of the new handler. What is happening here is that the pPrev field of the current topmost handler prior to inserting a new one is set to the address of the new handler, thus keeping the list chain intact. This may not seem obvious from looking at the assembly but is what is occurring when actually stepping through the instructions with a debugger. Lastly, EDI, which is the first member of _LdrpVectorHandlerList is set to hold the address of the new handler.
Now for the other case: inserting at the back of the vectored exception list. In that scenario, the following instructions will be executed:
This is a slight variation on the first case. The best way to see what is going on is to step through the assembly code again. Here X, Y, and Z will map to [ESI] like last time. Here Base will be [EDI+0x4], the third member of _LdrpVectorHandlerList — unlike [EDI] in the previous segment, which was the second member. [Base+0x4] will be [EDI + 0x4].
First run
[X]
[X+4]
[Base]
[*(Base+4)]
0x77284728
0x77284728
X
X
Second run
[Y]
[Y+4]
[Base]
[*(Base+4)]
0x77284728
X
Y
Y
Third run
[Z]
[Z+4]
[Base]
[*(Base+4)]
0x77284728
Y
Z
Z
Again,
[X] = [ESI] Always holds the address of the base of the table
[X+4] = [ESI+0x4] Holds the address of the previous handler
[Base] = [EAX] Holds the address to the new handler
[*(Base +4)] = [EDI+0x4] Holds the address of the new handler
Here, the mappings that were established for [X] and [X+4] as pNext and pPrev still make sense. For a node inserted at the back of the exception list, pNext will point to the base of the table (end), and pPrev will point to the address of the previous handler. Here [Base] is the third member of _LdrpVectorHandlerList. Given what is known from the previous run and this one, it is possible to draw a conclusion that the two pointers in _LdrpVectorHandlerList are pointers to the first and last exception handlers. The definition of _LdrpVectorHandlerList can now be completed.
That wraps up the implementation details of vectored exception handlers. The full C implementation will be provided in the next post. Follow on Twitter for more updates.