home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1999 October
/
PCWorld_1999-10_cd1.bin
/
Hardware
/
Drivers
/
APISpy
/
Injlib.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-07-19
|
7KB
|
225 lines
/*************************************************************
Module name: InjLib.C
Notices: Copyright (c) 1995-1997 Jeffrey Richter
*************************************************************/
#include "CmnHdr.H" /* See Appendix C. */
#include <windows.h>
#include "ProcMem.H"
#include "InjLib.H"
//////////////////////////////////////////////////////////////
typedef HINSTANCE (WINAPI *PROCLOADLIBRARY)(LPBYTE);
typedef BOOL (WINAPI *PROCFREELIBRARY)(HINSTANCE);
typedef HMODULE (WINAPI *PROCGETMODULEHANDLE)(LPBYTE);
typedef struct {
PROCLOADLIBRARY fnLoadLibrary;
PROCFREELIBRARY fnFreeLibrary;
PROCGETMODULEHANDLE fnGetModuleHandle;
BOOL ActionFlag;
BYTE pbLibFile[MAX_PATH * sizeof(WCHAR)];
} INJLIBINFO, *PINJLIBINFO;
//////////////////////////////////////////////////////////////
// Calls to the stack checking routine must be disabled.
#pragma check_stack (off)
static DWORD WINAPI ThreadFunc (PINJLIBINFO pInjLibInfo) {
// There must be less than a page worth of local
// variables used in this function.
HINSTANCE hinstDll;
hinstDll = pInjLibInfo->fnGetModuleHandle(pInjLibInfo->pbLibFile);
if (pInjLibInfo->ActionFlag == LOAD_DLL)
{
if (hinstDll == NULL)
hinstDll = pInjLibInfo->fnLoadLibrary(pInjLibInfo->pbLibFile);
}
else if (pInjLibInfo->ActionFlag == FREE_DLL)
pInjLibInfo->fnFreeLibrary(hinstDll);
// The thread's exit code is the handle of the DLL.
return((DWORD) hinstDll);
}
//////////////////////////////////////////////////////////////
// This function marks the memory address after ThreadFunc.
// ThreadFuncCodeSizeInBytes =
// (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.
static void AfterThreadFunc (void) {
}
#pragma check_stack
//////////////////////////////////////////////////////////////
static BOOL InjectLibWorA (HANDLE hProcess,
const BYTE * const pbLibFile, BOOL fUnicode, BOOL ActionFlag)
{
// Kernel32.DLL's HINSTANCE is used to get the
// address of LoadLibraryA or LoadLibraryW and
// FreeLibrary.
HINSTANCE hinstKrnl = GetModuleHandle(__TEXT("Kernel32"));
INJLIBINFO InjLibInfo;
// The address to which code will be copied in the
// remote process
PDWORD pdwCodeRemote = NULL;
// Calculate the number of bytes in the ThreadFunc
// function.
#ifndef _PPC_
const int cbCodeSize = ((LPBYTE) (DWORD)
AfterThreadFunc - (LPBYTE) (DWORD) ThreadFunc);
#else
// Note: The PowerPC does not support 32-bit immediate
// values. So, the VC++ PowerPC compiler implements 32-bit
// immediates using an offset into a table and grabbing
// the 32-bit value from the table. The references to
// the functions below, are actually offsets into this
// table. So, we have to subtract the contents of these
// offsets to get the actual code size.
const int cbCodeSize = ((LPBYTE) *(PDWORD)
AfterThreadFunc - (LPBYTE) *(PDWORD) ThreadFunc);
#endif
// The address to which INJLIBINFO will be copied in
// the remote process
PINJLIBINFO pInjLibInfoRemote = NULL;
// The number of bytes written to the remote process
DWORD dwNumBytesXferred = 0;
// The handle and ID of the thread executing the
// remote copy of ThreadFunc
DWORD dwThreadId = 0;
const DWORD cbMemSize =
cbCodeSize + sizeof(InjLibInfo) + 3;
HANDLE hThread = NULL;
HINSTANCE hinstDllRemote = NULL;
BOOL fOk = FALSE;
DWORD dwOldProtect;
// Initialize the INJLIBINFO structure here, and
// then copy it to memory in the remote process.
InjLibInfo.fnLoadLibrary = (PROCLOADLIBRARY)
GetProcAddress(hinstKrnl,
(fUnicode ? "LoadLibraryW" : "LoadLibraryA"));
InjLibInfo.fnFreeLibrary = (PROCFREELIBRARY)
GetProcAddress(hinstKrnl, "FreeLibrary");
InjLibInfo.fnGetModuleHandle = (PROCGETMODULEHANDLE)
GetProcAddress(hinstKrnl,
(fUnicode ? "GetModuleHandleW" : "GetModuleHandleA"));
InjLibInfo.ActionFlag = ActionFlag;
InjLibInfo.pbLibFile[0] = 0; // Initialized later
__try {
// Finish initializing the INJLIBINFO structure
// by copying the desired DLL's pathname.
if (fUnicode)
wcscpy((LPWSTR) InjLibInfo.pbLibFile,
(LPCWSTR) pbLibFile);
else
strcpy((LPSTR) InjLibInfo.pbLibFile,
(LPCSTR) pbLibFile);
// Allocate enough memory in the remote process's
// address space to hold our ThreadFunc function
// and an INJLIBINFO structure.
pdwCodeRemote = (PDWORD)
AllocProcessMemory(hProcess, cbMemSize);
if (pdwCodeRemote == NULL)
__leave;
// Change the page protection of the allocated memory
// to executable, read, and write.
fOk = VirtualProtectEx(hProcess, pdwCodeRemote,
cbMemSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
if (!fOk)
__leave;
// Write a copy of ThreadFunc to the remote process.
fOk = WriteProcessMemory(hProcess, pdwCodeRemote,
(LPVOID)(DWORD) ThreadFunc, cbCodeSize,
&dwNumBytesXferred);
if (!fOk)
__leave;
// Write a copy of INJLIBINFO to the remote process.
// (The structure MUST start on an even 32-bit boundary.)
pInjLibInfoRemote = (PINJLIBINFO)
((PBYTE) pdwCodeRemote + ((cbCodeSize + 4) & ~3));
// Put InjLibInfo in the remote thread's memory block.
fOk = WriteProcessMemory(hProcess, pInjLibInfoRemote,
&InjLibInfo, sizeof(InjLibInfo), &dwNumBytesXferred);
if (!fOk)
__leave;
hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)(DWORD) pdwCodeRemote,
pInjLibInfoRemote, 0, &dwThreadId);
if (hThread == NULL)
__leave;
WaitForSingleObject(hThread, INFINITE);
} // __try
__finally {
if (hThread != NULL) {
GetExitCodeThread(hThread, (PDWORD) &hinstDllRemote);
CloseHandle(hThread);
}
// Let the remote thread start executing the remote
// ThreadFunc function using our modified stack, which
// now contains an initialized INJLIBINFO structure.
FreeProcessMemory(hProcess, pdwCodeRemote);
} //__finally
// Return TRUE if the DLL loaded successfully.
return(hinstDllRemote != NULL);
}
//////////////////////////////////////////////////////////////
BOOL InjectLibA (HANDLE hProcess, LPCSTR lpszLibFile, BOOL ActionFlag)
{
return(InjectLibWorA(hProcess, (LPBYTE) lpszLibFile, FALSE, ActionFlag));
}
//////////////////////////////////////////////////////////////
BOOL InjectLibW (HANDLE hProcess, LPCWSTR lpszLibFile, BOOL ActionFlag)
{
return(InjectLibWorA(hProcess, (LPBYTE) lpszLibFile, TRUE, ActionFlag));
}
//////////////////////// End Of File /////////////////////////