|
API monitoring unleashed IV
Tech Forum - Dr. Nitin Paranjpe & Parag
Paithankar
Now
that we have sharedmodule.dll ready and have understood the code,
let’s move on to the "action application": the Injector
Application. Here’s where all the "remote" magic is taken
care of. The Injector Application is the application to which is
passed the process id of the application we want to monitor. As
explained earlier, this application will open the process and load
our DLL into the process space. Here is the code to do that.
The Injector Application is an
EXE file, so please follow the steps shown below to create one such
EXE file. We will create the EXE in VC++ as we created a DLL in
VC++. The steps are very simple. Please DO NOT modify any of the
checkboxes or settings when following the steps given below:
- Start VC++ IDE. Select the Project template
(from the Projects Tab) as "Win32 Console Application".
Please remember not to tamper with any other settings or checkboxes.
Enter the Project Name as "Injector" as shown below:
- Now, select the Project type as ‘A "Hello,
World!" application.’
- Now, the wizard will create the files for you
and inject the basic code. Open the file view from the Workspace
View. If workspace view is not visible, press ALT+0.
- From the file view, double click on the Injector.cpp
file. This file will be visible under the "Source Files"
tree.
- Add the code provided on the Express Computer
website just below the #include "stdafx.h" line.
The code is is available at HERE
Please compile sharedmodule.dll
and Injector.exe. Now go to the command prompt and run Injector.exe.
Pass the process id of the application you wish to monitor. This
process id has to be passed to injector.exe at the command prompt.
Say, the process id of Explorer.exe is 1676, then you need to run
Injector.exe as follows:
C:\work\vc6\injector\injector.exe
1676
After running, your application
will list out all the modules loaded by Explorer.exe. It will then
hook into Explorer.exe and wait for you to press a key, after which
it will unhook from Explorer.exe.
If you have any problems compiling
Injector.exe, please send an e-mail to paragp@mediline.co.in or
parag_pp@yahoo.com.
Let us now understand what happens
in the code.
The working
The Injector Application works
in the following steps:
- Get the process id of the application from
the command line (argv[1]).
- Call the DoHook function with the UnHook parameter
set to false.
- Enumerate all the modules for that particular
process, and during the process store the handle of our "sharedmodule.dll"
module.
- Call DoHook with UnHook set to true and module
handle set to the stored module handle.
So, as you would have understood
so far, the heart of the application lies inside two main functions
DoHook & EnumModules.
DoHook–the process hooker
This function is called with three
parameters:
a. pid – the Process
id of the process which we are going to hook/monitor.
b. UnHook – Boolean
flag indicating whether we are going to Hook or UnHook the process.
c. hFreeModule – Handle
to the module which will host our Remote Thread. This is neglected
when hooking into the process.
DoHook itself works in
the following steps:
1. Open the process with all
possible access (PROCESS_ALL_ACCESS) with the OpenProcess
API.
2. Allocate memory into the
remote process using the VirtualAllocEx API. We will require
this memory to store the path to our module. When our thread is
called, this path will be used by the remote process to load the
module.
3. Copy the path to the module
into the memory we allocated inside the remote process. The API
used to do this is WriteProcessMemory.
4. Now, if the operation is
a hooking operation (which means UnHook is false), get an address
to the FreeLibrary function from Kernel32.dll, or if it is the other
way around, then get an address to the LoadLibraryA function from
Kernel32.dll.
5. If the operation is a hooking
operation, call LoadLibraryA with a path to the module to be loaded.
This is the magic call, which actually loads our DLL into the
remote processes address space! The moment our DLL is loaded,
the respective DllMain code is called from sharedmodule and things
start rolling! If the operation is an Un-hooking operation, FreeLibrary
is called with handle to our module. This forces a DLL_PROCESS_DETACH
being called.
6. In both cases, whether hooking
or un-hooking, we have to wait for LoadLibraryA or FreeLibrary to
finish. This is achieved with a WaitForSingleObject API call.
7. After completion, free the
memory allocated inside the remote process. This is achieved by
the VirtualFreeEx API.
8. Now, close the respective
handles, freeing the memory.
So, as you must have understood,
it is this function which actually opens the remote process and
pushes in a thread into that process. Then our module is loaded
by calling the subsequent thread and the action begins.
In order to free or un-hook the
application from our module, it is important that we store the handle
to our module once it’s loaded into the remote process. To achieve
this, we have the EnumModules function, explained next.
EnumModules
This is a very simple function
and works in the following steps:
1. Open the process, whose
process id (pid) is passed to this function. This is achieved by
calling OpenProcess API with PROCESS_ALL_ACCESS.
2. As we are going to call
API from a library called PSAPI.dll, it happens at times that the
appropriate header file is missing. Considering that, let’s load
PSAPI.dll in order to be able to call the function from this module.
3. The two functions we are
going to call from PSAPI.dll are:
- i. EnumProcessModules – This function
enumerates all a modules for a particular process and stores their
handles in a one-dimensional array.
- ii. GetModuleFileNameEx – This function
gets the path to the loaded module.
4. Now, call EnumProcessModules
using the handle to the opened process.
5. Iterate through all the
loaded modules and make subsequent calls to GetModuleFileNameEx.
6. During iteration, compare
the retrieved module to our module path.
7. If found, free this module
and return the handle to the module, to the caller.
You have to understand that we
will require this function only when we are unloading our DLL and
require the module handle to our DLL.
That’s it! See how simple that
was? With respect to all the APIs provided throughout the articles,
try hunting for them in MSDN. When found, forget about implementing
them, even understanding how they work would look difficult. We
hope this exercise provides a fairly good understanding of how all
these APIs are used. You can go ahead and modify the overridden
MyCopyFileA function to do whatever you wish! In this way, all subsequent
calls to MyCopyFileA from within the remote application will call
your code!!!
In the first article of this series
you might remember that we had mentioned something about a device
driver. Well, here’s a short introduction to that: All applications
running on the Windows operating system work in two modes—user mode
and kernel mode. As far as we know, there is no way of knowing when
a process was created or deleted in user mode. Although you can
know which window was created or destroyed by setting the system-wide
CBT (Computer-Based Training) Hook, you still can’t know which process
was created or destroyed in user mode. To be notified of this, Windows
OS provides a kernel mode API called PsSetCreateProcessNotifyRoutine.
Using this, you can be notified of a creation/deletion of a process.
Now, you must be thinking how can a kernel mode application talk
to a user mode application? Well, it’s simple: by setting a kernel
mode event and acknowledging the same in user mode! Send an e-mail
to the aforementioned addresses if you are interested in obtaining
the source code demonstrating this.
(Note: Please Add "imagehlp.lib"
to your library linking list.)
 |
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 |
|