c语言References添加dll,c – 如何修改运行时加载的DLL的导入地址表

我想在运行时挂钩从加载的DLL中调用的函数,我使用了“

Windows Via C/C++”一书中的CAPIHook类(通过安装系统范围挂钩完成的DLL注入和通过修改IAT挂钩)但是这个只有在可执行文件的IAT中存在DLL名称/符号时,代码才有效. (即用于隐式DLL链接)

这是DLL代码:

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(),pszFuncName);

OutputDebugString(sz);

return;

}

// Hook this function in all currently loaded modules

ReplaceIATEntryInAllMods(m_pszCalleeModName,m_pfnOrig,m_pfnHook);

}

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,DWORD dwFlags) {

HMODULE hmod = ::LoadLibraryExW(pszModulePath,dwFlags);

return(hmod);

}

替换IAT的方法:

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,PAGE_WRITECOPY,&dwOldProtect)) {

WriteProcessMemory(GetCurrentProcess(),NULL);

VirtualProtect(ppfn,dwOldProtect,&dwOldProtect);

}

}

return; // We did it,get out

}

}

} // Each import section is parsed until the right entry is found and patched

}

}

作者添加了评论来添加此功能,但我不知道该怎么做

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

他也在书上写了这个,但我又不知道该怎么做

A possible solution is to use the hooked LoadLibrary* functions to

detect when a module is exporting an unpatched hooked function and

then execute two actions:

Hook again the import table of the module already loaded because it is

now possible to call GetProcAddress and get a pointer to the original

implementation of the function to hook. Notice that the name of the

function needs to be stored as a class member and set in the

constructor.

Directly update this hooked function in the Export Address Table of

the exporting module as shown by the implementation of the

ReplaceEATEntryInOneMod function. That way,all new modules calling

the hooked function will call our handler

我尝试在加载DLL后修改IAT,但我的钩子函数没有被调用

HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) {

HMODULE hmod = ::LoadLibraryW(pszModulePath);

if (StrCmpIW(pszModulePath,myDLLUnicodeName.c_str()) == 0 ) {

PROC proc = GetProcAddressRaw(GetModuleHandleA(myDLLName.c_str()),myFunctionName.c_str());

if ( proc != NULL ) {

for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext) {

if (StrCmpIA(p->m_pszCalleeModName,myDLLName.c_str()) == 0) {

MessageBox(NULL,L"This is the New Dynamic DLL",L"Test!",0);

ReplaceIATEntryInAllMods(p->m_pszCalleeModName,proc,p->m_pfnHook);

}

}

}

}

FixupNewlyLoadedModule(hmod,0);

return(hmod);

}

那么,如何修改此代码来处理动态加载情况?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值