Issue dated - 5th May 2003

-


Previous Issues

CURRENT ISSUE
INDIA NEWS
NEWS ANALYSIS
STOCK FILE
INDIA TREND
E-BUSINESS
OPINION
COMPANY WATCH
IND. COMPUTES
TECHSPACE
TECHNOLOGY
PRODUCTS
EVENTS
COLUMNS
TECH FORUM

THE C# COLUMN

BETWEEN THE BYTES
TECHNOLOGY
SPECIALS <NEW>
HMA BANKBIZ
EC SERVICES
ARCHIVES/SEARCH
IT APPOINTMENTS
WRITE TO US
SUBSCRIBE/RENEW
CUSTOMER SERVICE
ADVERTISE
ABOUT US

 Network Sites
  IT People
  Network Magazine
  Business Traveller
  Exp. Hotelier & Caterer
  Exp. Travel & Tourism
  Exp. Backwaters
  Exp. Pharma Pulse
  Exp. Healthcare Mgmt.
  Express Textile
 Group Sites
  ExpressIndia
  Indian Express
  Financial Express

 
Front Page > TechSpace > Story Print this Page|  Email this page

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:

  1. 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:
  2. Now, select the Project type as ‘A "Hello, World!" application.’
  3. 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.
  4. From the file view, double click on the Injector.cpp file. This file will be visible under the "Source Files" tree.
  5. 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:

  1. Get the process id of the application from the command line (argv[1]).
  2. Call the DoHook function with the UnHook parameter set to false.
  3. Enumerate all the modules for that particular process, and during the process store the handle of our "sharedmodule.dll" module.
  4. 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
<Back to top>


© Copyright 2003: Indian Express Group (Mumbai, India). All rights reserved throughout the world. This entire site is compiled in
Mumbai by The Business Publications Division of the Indian Express Group of Newspapers.
Please contact our Webmaster for any queries on this site.