如何在DLL的PE头中区分导入的函数与导入的全局变量?

时间:2017-12-20 08:39:26

标签: c winapi reverse-engineering portable-executable trampolines

我正在编写一个小工具,应该能够检查任意感兴趣的过程,并检查其中任何静态链接的函数是否为 trampolined 。 (example of a trampoline可以是Microsoft Detours对流程的处理方式。)

为此,我解析了目标进程的PE header并检索了所有导入的DLL及其中包含所有导入函数的DLL。然后我可以比较磁盘上的DLL和目标进程内存中加载的DLL之间的以下内容:

一个。每个导入函数的Import Address Table中的条目。

B中。每个函数的机器码的前N个字节。

如果上述任何一个不匹配,这肯定意味着trampoline应用于特定功能(或WinAPI)。

这种方法很有效,除了目标进程可以导入全局变量而不是函数的一种情况。例如_acmdln就是这样的全局变量。您仍然可以在msvcrt.dll中找到它并使用它:

//I'm not sure why you'd want to do it this way,
//but it will give you the current command line.
//So just to prove the concept ...
HMODULE hMod = ::GetModuleHandle(L"msvcrt.dll");
char* pVar = (char*)::GetProcAddress(hMod, "_acmdln");
char* pCmdLine = pVar ? *(char**)pVar : NULL;

那么,这对我的蹦床检查工具意味着我需要区分导入的函数(WinAPI)和全局变量。知道怎么样?

PS。如果我不这样做,我上面描述的算法将比较全局变量"代码字节"好像它是一个函数,它只是一个命令行的指针,它肯定会有所不同,然后将其标记为一个蹦床函数。

PS2。不完全是我的代码,但解析PE头的类似方法可以是found here。 (搜索DumpImports函数以提取DLL导入。)

1 个答案:

答案 0 :(得分:0)

全局变量将位于.data部分而不是.text部分,此外,如果该部分不是函数,则该部分将没有执行权限。因此,您可以同时使用这两个特征进行过滤。