我正在编写一个C ++内存分析器。
众所周知,可执行程序可能包含许多全局对象, 它的DLL模块可能包含全局对象 好。这些全局对象将使用CRT进行初始化 初始化 - 在入口点之后和WinMain之前;对于DLL, 在你进入DllMain之前,入口点是_DllMainCRTStartup, DLL的所有全局对象都被初始化。
全局对象可以分配内存。所以一个内存分析器 必须在任何全局对象初始化之前初始化。后 做了很多研究,我发现这不是一件容易的事。
一个想法是使用带有CREATE_SUSPENDED标志的CreateProcess - 尝试 获得第一次机会。之后,使用CreateRemoteThread进行调用 LoadLibrary在目标进程中加载一个注入DLL,和 初始化该DLL。但它不起作用because this will load all the implicit-linking DLLs of the executable program first.也许CreateRemoteThread触发了这种行为?
那么,我们如何获得第一次机会?
答案 0 :(得分:0)
除非使用特定于平台的方式,否则可能有一种方法可以做到这一点,但解决问题的一种方法是将延迟初始化与dylib加载相结合。
例如,假设你的内存分配器函数是这样导出的:
attribute disable
...在名为API void* exported_alloc();
API void exported_free(void* mem);
的dylib内。
在这种情况下,为了确保所有其他dylib在加载时都可以访问它,我们可以创建一个中央静态链接的库(例如:sdk.lib)您的dylib链接与标题如下:
mem.dll
......我们可以像这样实施:
#ifndef MEMORY_H
#define MEMORY_H
// Memory.h
void* my_alloc();
void my_free(void* mem);
#endif
..然后在完成DLL后的适当时间调用static void* (exported_alloc)() = 0;
static void (exported_free)(void* mem) = 0;
static void initialize()
{
if (!exported_alloc)
{
// Load 'mem.dll' (ex: 'LoadLibrary') and look up
// symbols for `exported_alloc` and `exported_free`
// (ex: GetProcAddress).
}
}
void* my_alloc()
{
initialize();
return exported_alloc();
}
void my_free(void* mem)
{
initialize();
exported_free(mem);
}
。这会产生一些运行时开销(类似于访问单例的开销),但它是一个跨平台的解决方案(前提是您有一个跨平台的方法在运行时加载/卸载dylibs /共享库)。 / p>
使用此解决方案,所有在全局范围内分配内存的DLL将在以惰性初始化方式执行任何内存分配之前加载FreeLibrary
,确保它们都可以访问您的内存函数在适当的时候。