|
API monitoring unleashed — III
Tech Forum - Dr. Nitin Paranjpe
Last
week we worked on the code for the shared module for monitoring
of applications. If you need to refer to it, it’s available on the
Express Computer website at www.expresscomputeronline.com/techforum.shtml.
Let us try and understand the code now. It’s assumed that you are
a C/C++ developer. If you are not, then you can simply skip this
section. Apart from the standard stdio and stdlib, you will see
that imghelp has been included—you require this header file for
the “helper APIs” that we have used. In order to locate the module
handle of our own DLL, we need to store the module handle passed
to our DllMain entry point. This is stored in the g_hModule variable.
You would have guessed by now that we are hooking the CopyFileW
function of the user32.dll library. In order to call the original
function after our work is done, we need to store the function pointer
of the original function. This is stored in the g_OriginalCopyFileW
variable.
Next, as we are using function pointers,
we need to have a typedef that contains the exact prototype declaration
of the function as it exists in the dll. The prototype of CopyFileW
is MyCopyFileW_t. Just below the prototype, you will see our function,
which will be called after the hooking has been done. If you see
the function body, you will notice that the function does not do
anything at the moment. It simply calls the original function, which
is pointed by the g_OriginalCopyFileW pointer. It is at this place
that you can write your implementation code and may or may not call
the original function. In this way, you can override the default
behaviour of the CopyFileW library function.
I am sure you must be wondering why there
is a ‘W’ at the end of the CopyFile API always. This is because
CopyFileW is the Unicode implementation of the CopyFile function.
There is also an ANSI version of the CopyFile API, called CopyFileA.
If you are or have been a Visual Basic developer you might have
been using an A at the end of the API call while declaring the API
using “Declare…. Alias….” etc. But now I guess you know what the
A at the end exactly means.
Let’s move on. Now comes the most important
function that actually does the hooking. This function is called
SetHook. SetHook accepts four parameters. Here are the four parameters
and their significance:
1. hModuleOfCaller
This is the module handle of the caller who is making the call to
this API. Now, say there is a process called “A” that is making
a call to the CopyFile API. But this actual implementation of the
API call may or may not be in the process itself. It could also
reside inside a dll, which the process A refers to.
When we iterate through all such loaded
modules (dlls) for a particular process, we have to make sure that
all these modules/processes call our function instead of the original
library’s function. This parameter is hence the module handle of
one such loaded module.
2. LibraryName
This is the textual name of the library. If the original function
belongs to user32.dll, this parameter will contain “user32.dll”.
3. OldFunctionPointer
This is the pointer to the original function from the base library.
Hence, if we are hooking the CopyFile function of user32.dll, this
parameter will contain the pointer to the original function from
user32.dll. This can be obtained by using the GetProcAddress API.
4. NewFunctionPointer
This is the pointer to our function.
Digging into SetHook
Now let us try and understand the SetHook
function in detail. As mentioned earlier, we need to iterate
through a list of import descriptors and change the function pointers
to point to our function. This is exactly what the SetHook function
does. Let us understand how it does this. In order to understand
this quickly and clearly, consider dividing its tasks into the following
list:
- Get the address of the module’s import
section.
This is done using the ImageDirectoryEntryToData helper API. Please
read up on this API in MSDN for further information. This is a
very powerful and interesting function.
- Loop through all descriptors and find
the import descriptor containing references to functions called.
Once we get an address to the module’s import section we iterate
through the various entries and compare the library name passed
to the function.
- Get pointer to caller’s Import Address
Table (IAT).
Once the library is located, get the pointer to the Import Address
Table that will actually contain the various function pointers.
- Iterate through the import list, locate
the function we want to hook and replace the original function
pointer to our function.
Now iterate through the IAT to locate our function. This function
pointer will be exactly the same as the one obtained by calling
a GetProcAddress. Once located, replace the old function pointer
to point to our function.
SetHook and multiple modules
Now that we have understood how to hook
inside a loaded module using the SetHook function, let us understand
where to apply this knowledge. It is quite possible that a particular
process had loaded multiple modules at a time. In order to apply
a process-wise hook in an efficient manner, we need to set a hook
into each and every module loaded by the process. This is exactly
what the EnumAndSetHooks function does. Let us now try and
understand how this function works.
The following simple steps explain how
EnumAndSetHook works:
- Loads the original library and gets
an address to the original function.
- Depending on the parameter passed, it
decides whether we need to Hook the function or to restore (Unhook)
the function. This is decided by the UnHook flag passed to this
function.
- It then calls the EnumProcessModules
API from PSAPI.DLL. This API gets a list of all the loaded modules
for a process. As the dll is loaded and run inside the hooked
process, GetCurrentProcess returns us the handle to the currently
running process.
- After getting a list of modules inside
hMods, we iterate through the list and pass on every module handle
to a subsequent call of SetHook.
The DllMain
DllMain is the entry point to our dll.
It does the following:
- If the operation requested is of type
“DLL_PROCESS_ATTACH”, store the original Module handle and call
EnumAndSetHooks with UnHook as FALSE indicating that we are hooking
this API. EnumAndSetHooks returns a pointer to the original function;
we will need this when unhooking from the API.
- If the operation requested is of type
“DLL_PROCESS_DETACH”, restore the original function pointer by
calling EnumAndSetHooks with the UnHook set to TRUE.
In the next article we will move on to
understanding the Injector Application.
(Note: Please Add "imagehlp.lib"
to your library linking list.)
Feedback
Your feedback, suggestions, requests for covering specific topics
or issues are welcome. Please send feedback to techforum@mediline.co.in
 |
About the Author:Dr
Nitin Paranjape is the Chairman and MD of Maestros (Mediline).
He is a consultant with many organisations, covering appropriate
technology utilisation, business application of relevant technology,
application architecture and audit as well as knowledge transfer.
He has authored more than 650 articles on various technology-related
subjects. He can be contacted at nitin@mediline.co.in |
|