[an error occurred while processing this directive]
Issue dated - 14th April 2003

-


Previous Issues

CURRENT ISSUE
INDIA NEWS
INDIA TRENDS
NEWS ANALYSIS
STOCK FILE
OPINION
FOCUS
COMPANY WATCH
E-BUSINESS
OPINION
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 II

TechForum - Dr. Nitin Paranjpe

Continuing from where we left off last week, we will plunge right into the Shared Module. This is a Windows Dynamic Link Library, a very simple DLL that contains the overridden code as well as the actual injection code. Why do we need the Injector Application if this DLL is doing the injection part? We need the application for the simple reason that DLLs can’t run by themselves. Another reason is that the injector application is the one that will create memory, load the DLL, etc, inside the remote processes space.

Now, let us see how to write such a DLL in MS VC++ 6.0:

Just follow the following steps; they are so simple that even if you have never used a VC++ IDE, you can still create the DLL and write the corresponding code very easily:

1. Start VC++ IDE. Select the Project template (from the Projects Tab) as “Win32 Dynamic-Link Library.” DO NOT touch any other settings or checkboxes. Enter the Project Name as “SharedModule” as shown in Figure 1.

2. Now, select the Project type as “A simple DLL project” as shown in Figure 2.

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 SharedModule.cpp file. This file will be visible under the “Source Files” tree.

5. Add the following code just below the #include “stdafx.h” line. There will be a point-by-point explanation of the code after we have finished all the steps.

#include <stdio.h>
#include <imagehlp.h>
#include <stdlib.h>
HANDLE g_hModule = INVALID_HANDLE_VALUE;
PROC g_OriginalCopyFileW;
typedef BOOL WINAPI MyCopyFileW_t(
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
BOOL bFailIfExists
);
BOOL WINAPI MyCopyFileW(
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
BOOL bFailIfExists
)
{
BOOL ReturnValue;
MyCopyFileW_t* fn = (MyCopyFileW_t*)g_OriginalCopyFileW;
ReturnValue = (*fn)(lpExistingFileName,
lpNewFileName,
bFailIfExists);
return ReturnValue;
}
void SetHook(HMODULE hModuleOfCaller, LPSTR LibraryName,
PROC OldFunctionPointer, PROC NewFunctionPointer)
{
if(hModuleOfCaller == g_hModule)
return;
if(hModuleOfCaller == 0)
return;
ULONG ulSize;
// Get the address of the module’s import section
PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
(PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(
hModuleOfCaller,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&ulSize
);
// Does this module have an import section ?
if (pImportDesc == NULL)
return;
// Loop through all descriptors and find the
// import descriptor containing references to callee’s functions
while (pImportDesc->Name)
{
PSTR pszModName = (PSTR)((PBYTE) hModuleOfCaller +
pImportDesc->Name);
if (stricmp(pszModName, LibraryName) == 0)
break; // Found
pImportDesc++;
} // while
if (pImportDesc->Name == 0)
return;

// Get caller’s IAT
PIMAGE_THUNK_DATA pThunk =
(PIMAGE_THUNK_DATA)( (PBYTE) hModuleOfCaller +
pImportDesc->FirstThunk );
PROC pfnCurrent = OldFunctionPointer;
// Replace current function address with new one
while (pThunk->u1.Function)
{
// Get the address of the function address
PROC* ppfn = (PROC*) &pThunk->u1.Function;
// Is this the function we’re looking for?
BOOL bFound = (*ppfn == pfnCurrent);
if (bFound)
{
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(ppfn, &mbi,
sizeof(MEMORY_BASIC_INFORMATION));
// In order to provide writable access to this part of the
// memory we need to change the memory protection
if (FALSE == ::VirtualProtect(
mbi.BaseAddress,
mbi.RegionSize,
PAGE_READWRITE,
&mbi.Protect)

)
return;
*ppfn = *NewFunctionPointer;
BOOL bResult = TRUE;
// Restore the protection back
DWORD dwOldProtect;
::VirtualProtect(
mbi.BaseAddress,
mbi.RegionSize,
mbi.Protect,
&dwOldProtect
);
break;
} // if
pThunk++;
} // while
}
PROC EnumAndSetHooks(LPSTR BaseLibraryName, LPSTR BaseFunctionName, PROC NewFunctionPointer, bool UnHook, PROC Custom)
{
HMODULE hMods[1024];
DWORD cbNeeded;
unsigned int i;
typedef BOOL (WINAPI * PFNENUMPROCESSMODULES)(
HANDLE hProcess,
HMODULE *lphModule,
DWORD cb,
LPDWORD lpcbNeeded
);
HMODULE hBaseLib = LoadLibrary(BaseLibraryName);
PROC hBaseProc;
if(UnHook)
hBaseProc = (PROC) Custom;
else
hBaseProc = GetProcAddress(hBaseLib, BaseFunctionName);
PFNENUMPROCESSMODULES m_pfnEnumProcessModules;
HMODULE m_hModPSAPI = ::LoadLibraryA(“PSAPI.DLL”);
m_pfnEnumProcessModules = (PFNENUMPROCESSMODULES)
::GetProcAddress(m_hModPSAPI, “EnumProcessModules”);
HANDLE hProcess = ::GetCurrentProcess();
if( m_pfnEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
SetHook(hMods[i], BaseLibraryName, hBaseProc, NewFunctionPointer);
}
}
return hBaseProc;
}
6. After you have copy-pasted the code, modify the DllMain function as shown below. If you find that difficult simply remove the DllMain function and copy-paste the function given below directly inside the CPP file:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hModule = hModule;
g_OriginalCopyFileW = EnumAndSetHooks(“KERNEL32.DLL”, “CopyFileW”, (PROC) MyCopyFileW, false, 0);
case DLL_PROCESS_DETACH:
EnumAndSetHooks(“KERNEL32.DLL”, “CopyFileW”, (PROC) GetProcAddress(LoadLibrary(“KERNEL32”),”CopyFileW”), true, (PROC) MyCopyFileW);
break;
}
return TRUE;
}

Now compile the application, it should successfully compile and generate the DLL. If it fails, please feel free to send me a dump of the error log. Please send it to paragp@mediline.co.in

In the next article I will explain the above code and we can then move ahead to writing the code for the injector application.

(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.