提问人:Caty 提问时间:6/4/2023 最后编辑:Caty 更新时间:6/5/2023 访问量:135
如何在类中挂钩 Windows 上的 fopen()
How to hook fopen() on Windows inside a class
问:
我需要在 Windows 上挂钩 fopen() 作为类的成员。我测试了这段代码:
void **IATfind(const char *function, HMODULE module);
// Define the function pointer type for the original function
typedef FILE*(__cdecl* popen)(const char* filename, const char* mode);
struct Hook {
// Declare the original function pointer
popen orig_fopen;
// Define the detoured function
FILE* __cdecl hook_fopen(const char* filename, const char* mode) {
printf("Rewrite fopen: %s\n", filename); // need to know here which module make fopen() call
return orig_fopen("hook_test.txt", mode);
}
void DetourIATptr(const char *function, void *newfunction, HMODULE module) {
void **funcptr = IATfind(function, module);
if (funcptr == 0) {
printf("cannot find function address\n");
return;
}
DWORD oldrights, newrights = PAGE_READWRITE;
//Update the protection to READWRITE
VirtualProtect(funcptr, sizeof(LPVOID), newrights, &oldrights);
orig_fopen = (popen)*funcptr;
*funcptr = (void*)&Hook::hook_fopen;
//Restore the old memory protection flags.
VirtualProtect(funcptr, sizeof(LPVOID), oldrights, &newrights);
}
void Do() {
//DetourIATptr("fopen", (void*)hook_fopen, 0);
}
};
int main(int argc, CHAR *argv[]) {
Hook hk;
hk.Do();
printf("main\n");
fopen("myfile.txt", "w");
return 0;
}
void **IATfind(const char *function, HMODULE module) { //Find the IAT (Import Address Table) entry specific to the given function.
if (module == 0)
module = GetModuleHandle(0);
PIMAGE_DOS_HEADER pImgDosHeaders = (PIMAGE_DOS_HEADER)module;
PIMAGE_NT_HEADERS pImgNTHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)pImgDosHeaders + pImgDosHeaders->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR pImgImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)pImgDosHeaders + pImgNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if (pImgDosHeaders->e_magic != IMAGE_DOS_SIGNATURE) {
printf("libPE Error : e_magic is no valid DOS signature\n");
return 0;
}
for (IMAGE_IMPORT_DESCRIPTOR *iid = pImgImportDesc; iid->Name != NULL; iid++) {
for (int funcIdx = 0; *(funcIdx + (LPVOID*)(iid->FirstThunk + (SIZE_T)module)) != NULL; funcIdx++) {
char *modFuncName = (char*)(*(funcIdx + (SIZE_T*)(iid->OriginalFirstThunk + (SIZE_T)module)) + (SIZE_T)module + 2);
const uintptr_t nModFuncName = (uintptr_t)modFuncName;
bool isString = !(nModFuncName & (sizeof(nModFuncName) == 4 ? 0x80000000 : 0x8000000000000000));
if (isString) {
if (!_stricmp(function, modFuncName)) {
printf("address finded\n");
return funcIdx + (LPVOID*)(iid->FirstThunk + (SIZE_T)module);
}
}
}
}
return 0;
}
我得到这个:错误 C2440:“类型转换”:无法从“FILE (__cdecl Hook::)(const char *,const char *)” 转换为“void *”
如果我从 Hook 结构中定义 hook_fopen(),代码工作正常,但我需要使用类才能在多个 dll 模块中挂钩 fopen()。
替代解决方案:可以避免使用类,但需要知道哪个模块进行 fopen() 调用,因此必须在 hook_fopen() 中识别 hmodule,我需要它用于加载更多 dll 模块并检查此模块是否充当恶意软件的应用程序。
答: 暂无答案
评论
hook_fopen
orig_fopen
hook_fopen
hook_fopen
hook_fopen
不能是 member 或 class/struct。 是错误的。必须根本不需要(我已经没有说它是如何实现的)popen orig_fopen;
extern "C" { extern PVOID __imp_fopen;}
IATfind