您的位置:首页 > 其它

方式四:修改模块导入段来拦截API

2015-02-28 17:20 260 查看
一个模块的导入段包含一组DLL,导入段还包含一个符号表,其中列出了该模块从各DLL中导入的符号,

当该模块调用一个导入函数的时候,线程实际上会先从模块的导入表中得到相应的导入函数的地址,然后再跳转到那个地址。

模块的导入段中所有的字符串都是以ANSI格式保存的,有的编译器会生成多个导入段。

//hook dll
/******************************************************************************
Module:  APIHook.h
Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre
******************************************************************************/

#pragma once

///////////////////////////////////////////////////////////////////////////////

class CAPIHook {
public:
// Hook a function in all modules
CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook);

// Unhook a function from all modules
~CAPIHook();

// Returns the original address of the hooked function
operator PROC() { return(m_pfnOrig); }

// Hook module w/CAPIHook implementation?
// I have to make it static because I need to use it
// in ReplaceIATEntryInAllMods
static BOOL ExcludeAPIHookMod;

public:
// Calls the real GetProcAddress
static FARPROC WINAPI GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName);

private:
static PVOID sm_pvMaxAppAddr; // Maximum private memory address
static CAPIHook* sm_pHead;    // Address of first object
CAPIHook* m_pNext;            // Address of next  object

PCSTR m_pszCalleeModName;     // Module containing the function (ANSI)
PCSTR m_pszFuncName;          // Function name in callee (ANSI)
PROC  m_pfnOrig;              // Original function address in callee
PROC  m_pfnHook;              // Hook function address

private:
// Replaces a symbol's address in a module's import section
static void WINAPI ReplaceIATEntryInAllMods(PCSTR pszCalleeModName,
PROC pfnOrig, PROC pfnHook);

// Replaces a symbol's address in all modules' import sections
static void WINAPI ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
PROC pfnOrig, PROC pfnHook, HMODULE hmodCaller);

// Replaces a symbol's address in a module's export sections
static void ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, PROC pfnNew);

private:
// Used when a DLL is newly loaded after hooking a function
static void    WINAPI FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags);

// Used to trap when DLLs are newly loaded
static HMODULE WINAPI LoadLibraryA(PCSTR pszModulePath);
static HMODULE WINAPI LoadLibraryW(PCWSTR pszModulePath);
static HMODULE WINAPI LoadLibraryExA(PCSTR pszModulePath,
HANDLE hFile, DWORD dwFlags);
static HMODULE WINAPI LoadLibraryExW(PCWSTR pszModulePath,
HANDLE hFile, DWORD dwFlags);

// Returns address of replacement function if hooked function is requested
static FARPROC WINAPI GetProcAddress(HMODULE hmod, PCSTR pszProcName);

private:
// Instantiates hooks on these functions
static CAPIHook sm_LoadLibraryA;
static CAPIHook sm_LoadLibraryW;
static CAPIHook sm_LoadLibraryExA;
static CAPIHook sm_LoadLibraryExW;
static CAPIHook sm_GetProcAddress;
};

//////////////////////////////// End of File //////////////////////////////////

/******************************************************************************
Module:  APIHook.cpp
Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre
******************************************************************************/

#include <Windows.h>
#include <CommCtrl.h>
#include <process.h>

#include <ImageHlp.h>
#pragma comment(lib, "ImageHlp")

#include "APIHook.h"
#include <tlhelp32.h>
#include <tchar.h>
#include <StrSafe.h>

/////////////////////////////////////////////////////////////////////////////////

// The head of the linked-list of CAPIHook objects
CAPIHook* CAPIHook::sm_pHead = NULL;

// By default, the module containing the CAPIHook() is not hooked
BOOL CAPIHook::ExcludeAPIHookMod = TRUE;

///////////////////////////////////////////////////////////////////////////////

CAPIHook::CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook) {

// Note: the function can be hooked only if the exporting module
//       is already loaded. A solution could be to store the function
//       name as a member; then, in the hooked LoadLibrary* handlers, parse
//       the list of CAPIHook instances, check if pszCalleeModName
//       is the name of the loaded module to hook its export table and
//       re-hook the import tables of all loaded modules.

m_pNext  = sm_pHead;    // The next node was at the head
sm_pHead = this;        // This node is now at the head

// Save information about this hooked function
m_pszCalleeModName   = pszCalleeModName;
m_pszFuncName        = pszFuncName;
m_pfnHook            = pfnHook;
m_pfnOrig            =
GetProcAddressRaw(GetModuleHandleA(pszCalleeModName), m_pszFuncName);

// If function does not exit,... bye bye
// This happens when the module is not already loaded
if (m_pfnOrig == NULL)
{
wchar_t szPathname[MAX_PATH];
GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
wchar_t sz[1024];
StringCchPrintfW(sz, _countof(sz),
TEXT("[%4u - %s] impossible to find %S\r\n"),
GetCurrentProcessId(), szPathname, pszFuncName);
OutputDebugString(sz);
return;
}

#ifdef _DEBUG
// This section was used for debugging sessions when Explorer died as
// a folder content was requested
//
//static BOOL s_bFirstTime = TRUE;
//if (s_bFirstTime)
//{
//   s_bFirstTime = FALSE;

//   wchar_t szPathname[MAX_PATH];
//   GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
//   wchar_t* pszExeFile = wcsrchr(szPathname, L'\\') + 1;
//   OutputDebugStringW(L"Injected in ");
//   OutputDebugStringW(pszExeFile);
//   if (_wcsicmp(pszExeFile, L"Explorer.EXE") == 0)
//   {
//      DebugBreak();
//   }
//   OutputDebugStringW(L"\n   --> ");
//   StringCchPrintfW(szPathname, _countof(szPathname), L"%S", pszFuncName);
//   OutputDebugStringW(szPathname);
//   OutputDebugStringW(L"\n");
//}
#endif

// Hook this function in all currently loaded modules
ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook);
}

///////////////////////////////////////////////////////////////////////////////

CAPIHook::~CAPIHook() {

// Unhook this function from all modules
ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnHook, m_pfnOrig);

// Remove this object from the linked list
CAPIHook* p = sm_pHead;
if (p == this) {     // Removing the head node
sm_pHead = p->m_pNext;
} else {

BOOL bFound = FALSE;

// Walk list from head and fix pointers
for (; !bFound && (p->m_pNext != NULL); p = p->m_pNext) {
if (p->m_pNext == this) {
// Make the node that points to us point to our next node
p->m_pNext = p->m_pNext->m_pNext;
bFound = TRUE;
}
}
}
}

///////////////////////////////////////////////////////////////////////////////

// NOTE: This function must NOT be inlined
FARPROC CAPIHook::GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName) {

return(::GetProcAddress(hmod, pszProcName));
}

///////////////////////////////////////////////////////////////////////////////

// Returns the HMODULE that contains the specified memory address
static HMODULE ModuleFromAddress(PVOID pv) {

MEMORY_BASIC_INFORMATION mbi;
return((VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
? (HMODULE) mbi.AllocationBase : NULL);
}

///////////////////////////////////////////////////////////////////////////////

void CAPIHook::ReplaceIATEntryInAllMods(PCSTR pszCalleeModName,
PROC pfnCurrent, PROC pfnNew) {

HMODULE hmodThisMod = ExcludeAPIHookMod
? ModuleFromAddress(ReplaceIATEntryInAllMods) : NULL;

// Get the list of modules in this process
//CToolhelp th(TH32CS_SNAPMODULE, GetCurrentProcessId());
HANDLE m_hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
//if(m_hSnapshot == INVALID_HANDLE_VALUE)
MODULEENTRY32 me = { sizeof(me) };
for (BOOL bOk = Module32First(m_hSnapshot, &me); bOk; bOk = Module32Next(m_hSnapshot, &me)) {

// NOTE: We don't hook functions in our own module
if (me.hModule != hmodThisMod) {

// Hook this function in this module
ReplaceIATEntryInOneMod(
pszCalleeModName, pfnCurrent, pfnNew, me.hModule);
}
}
if (m_hSnapshot != INVALID_HANDLE_VALUE)
CloseHandle(m_hSnapshot);
}

///////////////////////////////////////////////////////////////////////////////

// Handle unexpected exceptions if the module is unloaded
LONG WINAPI InvalidReadExceptionFilter(PEXCEPTION_POINTERS pep) {

// handle all unexpected exceptions because we simply don't patch
// any module in that case
LONG lDisposition = EXCEPTION_EXECUTE_HANDLER;

// Note: pep->ExceptionRecord->ExceptionCode has 0xc0000005 as a value

return(lDisposition);
}

void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) {

// Get the address of the module's import section
ULONG ulSize;

// An exception was triggered by Explorer (when browsing the content of
// a folder) into imagehlp.dll. It looks like one module was unloaded...
// Maybe some threading problem: the list of modules from Toolhelp might
// not be accurate if FreeLibrary is called during the enumeration.
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
__try {
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
}
__except (InvalidReadExceptionFilter(GetExceptionInformation())) {
// Nothing to do in here, thread continues to run normally
// with NULL for pImportDesc
}

if (pImportDesc == NULL)
return;  // This module has no import section or is no longer loaded

// Find the import descriptor containing references to callee's functions
for (; pImportDesc->Name; pImportDesc++) {
PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
if (lstrcmpiA(pszModName, pszCalleeModName) == 0) {

// Get caller's import address table (IAT) for the callee's functions
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
((PBYTE) hmodCaller + pImportDesc->FirstThunk);

// Replace current function address with new function address
for (; pThunk->u1.Function; pThunk++) {

// 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) {
if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) {
DWORD dwOldProtect;
if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY,
&dwOldProtect)) {

WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
sizeof(pfnNew), NULL);
VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect,
&dwOldProtect);
}
}
return;  // We did it, get out
}
}
}  // Each import section is parsed until the right entry is found and patched
}
}

///////////////////////////////////////////////////////////////////////////////

void CAPIHook::ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName,
PROC pfnNew) {

// Get the address of the module's export section
ULONG ulSize;

PIMAGE_EXPORT_DIRECTORY pExportDir = NULL;
__try {
pExportDir = (PIMAGE_EXPORT_DIRECTORY) ImageDirectoryEntryToData(
hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ulSize);
}
__except (InvalidReadExceptionFilter(GetExceptionInformation())) {
// Nothing to do in here, thread continues to run normally
// with NULL for pExportDir
}

if (pExportDir == NULL)
return;  // This module has no export section or is unloaded

PDWORD pdwNamesRvas = (PDWORD) ((PBYTE) hmod + pExportDir->AddressOfNames);
PWORD pdwNameOrdinals = (PWORD)
((PBYTE) hmod + pExportDir->AddressOfNameOrdinals);
PDWORD pdwFunctionAddresses = (PDWORD)
((PBYTE) hmod + pExportDir->AddressOfFunctions);

// Walk the array of this module's function names
for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
// Get the function name
PSTR pszFuncName = (PSTR) ((PBYTE) hmod + pdwNamesRvas
);

// If not the specified function, try the next function
if (lstrcmpiA(pszFuncName, pszFunctionName) != 0) continue;

// We found the specified function
// --> Get this function's ordinal value
WORD ordinal = pdwNameOrdinals
;

// Get the address of this function's address
PROC* ppfn = (PROC*) &pdwFunctionAddresses[ordinal];

// Turn the new address into an RVA
pfnNew = (PROC) ((PBYTE) pfnNew - (PBYTE) hmod);

// Replace current function address with new function address
if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) {
DWORD dwOldProtect;
if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY,
&dwOldProtect)) {

WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
sizeof(pfnNew), NULL);
VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, &dwOldProtect);
}
}
break;  // We did it, get out
}
}

///////////////////////////////////////////////////////////////////////////////
// Hook LoadLibrary functions and GetProcAddress so that hooked functions
// are handled correctly if these functions are called.

CAPIHook CAPIHook::sm_LoadLibraryA  ("Kernel32.dll", "LoadLibraryA",
(PROC) CAPIHook::LoadLibraryA);

CAPIHook CAPIHook::sm_LoadLibraryW  ("Kernel32.dll", "LoadLibraryW",
(PROC) CAPIHook::LoadLibraryW);

CAPIHook CAPIHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA",
(PROC) CAPIHook::LoadLibraryExA);

CAPIHook CAPIHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW",
(PROC) CAPIHook::LoadLibraryExW);

CAPIHook CAPIHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress",
(PROC) CAPIHook::GetProcAddress);

///////////////////////////////////////////////////////////////////////////////

void CAPIHook::FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags) {

// If a new module is loaded, hook the hooked functions
if ((hmod != NULL) &&   // Do not hook our own module
(hmod != ModuleFromAddress(FixupNewlyLoadedModule)) &&
((dwFlags & LOAD_LIBRARY_AS_DATAFILE) == 0) &&
((dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) == 0) &&
((dwFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) == 0)
) {

for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext) {
if (p->m_pfnOrig != NULL) {
ReplaceIATEntryInAllMods(p->m_pszCalleeModName,
p->m_pfnOrig, p->m_pfnHook);
} else {
#ifdef _DEBUG
// We should never end up here
wchar_t szPathname[MAX_PATH];
GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
wchar_t sz[1024];
StringCchPrintfW(sz, _countof(sz),
TEXT("[%4u - %s] impossible to find %S\r\n"),
GetCurrentProcessId(), szPathname, p->m_pszCalleeModName);
OutputDebugString(sz);
#endif
}
}
}
}

///////////////////////////////////////////////////////////////////////////////

HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath) {

HMODULE hmod = ::LoadLibraryA(pszModulePath);
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}

///////////////////////////////////////////////////////////////////////////////

HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) {

HMODULE hmod = ::LoadLibraryW(pszModulePath);
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}

///////////////////////////////////////////////////////////////////////////////

HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath,
HANDLE hFile, DWORD dwFlags) {

HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);
FixupNewlyLoadedModule(hmod, dwFlags);
return(hmod);
}

///////////////////////////////////////////////////////////////////////////////

HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath,
HANDLE hFile, DWORD dwFlags) {

HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);
FixupNewlyLoadedModule(hmod, dwFlags);
return(hmod);
}

///////////////////////////////////////////////////////////////////////////////

FARPROC WINAPI CAPIHook::GetProcAddress(HMODULE hmod, PCSTR pszProcName) {

// Get the true address of the function
FARPROC pfn = GetProcAddressRaw(hmod, pszProcName);

// Is it one of the functions that we want hooked?
CAPIHook* p = sm_pHead;
for (; (pfn != NULL) && (p != NULL); p = p->m_pNext) {

if (pfn == p->m_pfnOrig) {

// The address to return matches an address we want to hook
// Return the hook function address instead
pfn = p->m_pfnHook;
break;
}
}

return(pfn);
}

//////////////////////////////// End of File //////////////////////////////////

// Prototypes for the hooked functions
typedef int (WINAPI *PFNMESSAGEBOXA)(HWND hWnd, PCSTR pszText,
PCSTR pszCaption, UINT uType);

typedef int (WINAPI *PFNMESSAGEBOXW)(HWND hWnd, PCWSTR pszText,
PCWSTR pszCaption, UINT uType);

// We need to reference these variables before we create them.
extern CAPIHook g_MessageBoxA;
extern CAPIHook g_MessageBoxW;

///////////////////////////////////////////////////////////////////////////////

// This function sends the MessageBox info to our main dialog box
void SendLastMsgBoxInfo(BOOL bUnicode,
PVOID pvCaption, PVOID pvText, int nResult) {

// Get the pathname of the process displaying the message box
wchar_t szProcessPathname[MAX_PATH];
GetModuleFileNameW(NULL, szProcessPathname, MAX_PATH);

// Convert the return value into a human-readable string
PCWSTR pszResult = L"(Unknown)";
switch (nResult) {
case IDOK:       pszResult = L"Ok";        break;
case IDCANCEL:   pszResult = L"Cancel";    break;
case IDABORT:    pszResult = L"Abort";     break;
case IDRETRY:    pszResult = L"Retry";     break;
case IDIGNORE:   pszResult = L"Ignore";    break;
case IDYES:      pszResult = L"Yes";       break;
case IDNO:       pszResult = L"No";        break;
case IDCLOSE:    pszResult = L"Close";     break;
case IDHELP:     pszResult = L"Help";      break;
case IDTRYAGAIN: pszResult = L"Try Again"; break;
case IDCONTINUE: pszResult = L"Continue";  break;
}

// Construct the string to send to the main dialog box
wchar_t sz[2048];
StringCchPrintfW(sz, _countof(sz), bUnicode
? L"Process: (%d) %s\r\nCaption: %s\r\nMessage: %s\r\nResult: %s"
: L"Process: (%d) %s\r\nCaption: %S\r\nMessage: %S\r\nResult: %s",
GetCurrentProcessId(), szProcessPathname,
pvCaption, pvText, pszResult);

// Send the string to the main dialog box
//COPYDATASTRUCT cds = { 0, ((DWORD)wcslen(sz) + 1) * sizeof(wchar_t), sz };
//FORWARD_WM_COPYDATA(FindWindow(NULL, TEXT("Last MessageBox Info")),
//   NULL, &cds, SendMessage);
::OutputDebugStringW(sz);
}

///////////////////////////////////////////////////////////////////////////////

// This is the MessageBoxW replacement function
int WINAPI Hook_MessageBoxW(HWND hWnd, PCWSTR pszText, LPCWSTR pszCaption,
UINT uType) {

// Call the original MessageBoxW function
int nResult = ((PFNMESSAGEBOXW)(PROC) g_MessageBoxW)
(hWnd, pszText, pszCaption, uType);

// Send the information to the main dialog box
SendLastMsgBoxInfo(TRUE, (PVOID) pszCaption, (PVOID) pszText, nResult);

// Return the result back to the caller
return(nResult);
}

///////////////////////////////////////////////////////////////////////////////

// This is the MessageBoxA replacement function
int WINAPI Hook_MessageBoxA(HWND hWnd, PCSTR pszText, PCSTR pszCaption,
UINT uType) {

// Call the original MessageBoxA function
int nResult = ((PFNMESSAGEBOXA)(PROC) g_MessageBoxA)
(hWnd, pszText, pszCaption, uType);

// Send the information to the main dialog box
SendLastMsgBoxInfo(FALSE, (PVOID) pszCaption, (PVOID) pszText, nResult);

// Return the result back to the caller
return(nResult);
}

// Hook the MessageBoxA and MessageBoxW functions
CAPIHook g_MessageBoxA("User32.dll", "MessageBoxA",
(PROC) Hook_MessageBoxA);

CAPIHook g_MessageBoxW("User32.dll", "MessageBoxW",
(PROC) Hook_MessageBoxW);

//dllmain.cpp

#include <windows.h>

wchar_t log[1024] = { 0 };

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD  ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
wsprintfW(log,L"DLL_PROCESS_ATTACH tid:%d \n",GetCurrentThreadId());
::OutputDebugStringW(log);
break;
case DLL_THREAD_ATTACH:
wsprintfW(log,L"DLL_THREAD_ATTACH tid:%d \n",GetCurrentThreadId());
::OutputDebugStringW(log);
break;
case DLL_THREAD_DETACH:
wsprintfW(log,L"DLL_THREAD_DETACH tid:%d \n",GetCurrentThreadId());
::OutputDebugStringW(log);
break;
case DLL_PROCESS_DETACH:
wsprintfW(log,L"DLL_PROCESS_DETACH tid:%d \n",GetCurrentThreadId());
::OutputDebugStringW(log);
break;
}
return TRUE;
}

hook dll project will generate injectdll.dll

// inject exe project, it will inject hook dll to test project.
#include <Windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <stdio.h>

wchar_t log[1024] = { 0 };

BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {

BOOL bOk = FALSE; // Assume that the function fails
HANDLE hProcess = NULL, hThread = NULL;
PWSTR pszLibFileRemote = NULL;

__try {
// Get a handle for the target process.
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION |   // Required by Alpha
PROCESS_CREATE_THREAD     |   // For CreateRemoteThread
PROCESS_VM_OPERATION      |   // For VirtualAllocEx/VirtualFreeEx
PROCESS_VM_WRITE,             // For WriteProcessMemory
FALSE, dwProcessId);
if (hProcess == NULL) __leave;

// Calculate the number of bytes needed for the DLL's pathname
int cch = 1 + lstrlenW(pszLibFile);
int cb  = cch * sizeof(wchar_t);

// Allocate space in the remote process for the pathname
pszLibFileRemote = (PWSTR)
VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
if (pszLibFileRemote == NULL) __leave;

// Copy the DLL's pathname to the remote process' address space
if (!WriteProcessMemory(hProcess, pszLibFileRemote,
(PVOID) pszLibFile, cb, NULL)) __leave;

// Get the real address of LoadLibraryW in Kernel32.dll
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
if (pfnThreadRtn == NULL) __leave;

// Create a remote thread that calls LoadLibraryW(DLLPathname)
DWORD remoteTID = 0;
hThread = CreateRemoteThread(hProcess, NULL, 0,
pfnThreadRtn, pszLibFileRemote, 0, &remoteTID);
wsprintfW(log,L"CreateRemoteThread tid:%d for inject dll.\n",remoteTID);
::OutputDebugStringW(log);
if (hThread == NULL) __leave;

// Wait for the remote thread to terminate
WaitForSingleObject(hThread, INFINITE);

bOk = TRUE; // Everything executed successfully
}
__finally { // Now, we can clean everything up

// Free the remote memory that contained the DLL's pathname
if (pszLibFileRemote != NULL)
VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

if (hThread  != NULL)
CloseHandle(hThread);

if (hProcess != NULL)
CloseHandle(hProcess);
}

return(bOk);
}

BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {

BOOL bOk = FALSE; // Assume that the function fails
HANDLE hthSnapshot = NULL;
HANDLE hProcess = NULL, hThread = NULL;

__try {
// Grab a new snapshot of the process
hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if (hthSnapshot == INVALID_HANDLE_VALUE) __leave;

// Get the HMODULE of the desired library
MODULEENTRY32W me = { sizeof(me) };
BOOL bFound = FALSE;
BOOL bMoreMods = Module32FirstW(hthSnapshot, &me);
for (; bMoreMods; bMoreMods = Module32NextW(hthSnapshot, &me)) {
bFound = (_wcsicmp(me.szModule,  pszLibFile) == 0) ||
(_wcsicmp(me.szExePath, pszLibFile) == 0);
if (bFound) break;
}
if (!bFound) __leave;

// Get a handle for the target process.
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION |
PROCESS_CREATE_THREAD     |
PROCESS_VM_OPERATION,  // For CreateRemoteThread
FALSE, dwProcessId);
if (hProcess == NULL) __leave;

// Get the real address of FreeLibrary in Kernel32.dll
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
if (pfnThreadRtn == NULL) __leave;

// Create a remote thread that calls FreeLibrary()
//hThread = CreateRemoteThread(hProcess, NULL, 0,
//   pfnThreadRtn, me.modBaseAddr, 0, NULL);
DWORD remoteTID = 0;
hThread = CreateRemoteThread(hProcess, NULL, 0,
pfnThreadRtn, me.hModule, 0, &remoteTID);
wsprintfW(log,L"CreateRemoteThread tid:%d for Eject dll.\n",remoteTID);
::OutputDebugStringW(log);
if (hThread == NULL) __leave;

// Wait for the remote thread to terminate
WaitForSingleObject(hThread, INFINITE);

bOk = TRUE; // Everything executed successfully
}
__finally { // Now we can clean everything up

if (hthSnapshot != NULL)
CloseHandle(hthSnapshot);

if (hThread     != NULL)
CloseHandle(hThread);

if (hProcess    != NULL)
CloseHandle(hProcess);
}

return(bOk);
}

int main()
{
wchar_t szLibFile[MAX_PATH];
GetModuleFileNameW(NULL, szLibFile, _countof(szLibFile));
wchar_t *pFilename = wcsrchr(szLibFile, L'\\') + 1;
wcscpy_s(pFilename, _countof(szLibFile) - (pFilename-szLibFile),L"injectdll.dll");
DWORD pid = 0;
wprintf_s(L"Please put in inject process ID:\n");
wscanf_s(L"%d",&pid);
InjectLibW(pid,szLibFile);
getchar();
EjectLibW(pid,szLibFile);
return 0;
}


//test project, this project will be hooked
#include <Windows.h>
#include <stdio.h>

void main()
{
OutputDebugStringW(L"this process will be inject hook dll.\n");

while(true)
{
MessageBoxA(NULL,"MessageBoxA","MessageBoxA TEST",MB_OKCANCEL);
int ret = MessageBoxW(NULL,L"MessageBoxW",L"MessageBoxW TEST",MB_YESNOCANCEL);
if( ret == IDNO )	break;
}
getchar();
}


the test result:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: