【发布时间】:2016-10-24 14:43:20
【问题描述】:
DLL 具有一组导出的函数,其他应用程序可以调用这些函数。通常要调用这些函数,你要么有一个函数名,要么有一个序号。
在MSO.dll中,大部分导出到DLL的入口点都没有名字,所以我无法通过正常的方式务实地调用我想要的函数。
通过 Google 搜索,我遇到了一位博主,他声称找到了我想要调用的函数的稳定地址(不会更改的地址)。
这些地址的问题在于,不能指望它们从一个 Office 版本到另一个版本,甚至从一个更新到下一个更新都相同。所以我需要了解 Lee Benfield 在写blog post 时是如何在MSO.dll 中找到这些稳定地址的。你可以在他的博客上找到源代码。
我想要理解的 Lee 的代码部分:
这是我为找到这些地址而编写的一些代码:
#include <Windows.h>
#include <stdint.h>
#include <iostream>
#include <map>
int main()
{
HMODULE hGetProcIDDLL = LoadLibrary("C:\\Program Files\\Microsoft Office 15\\root\\vfs\\ProgramFilesCommonX86\\Microsoft Shared\\OFFICE15\\mso.dll");
PIMAGE_NT_HEADERS header = (PIMAGE_NT_HEADERS)((char *)hGetProcIDDLL + ((PIMAGE_DOS_HEADER)hGetProcIDDLL)->e_lfanew);
PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)((char *)hGetProcIDDLL + header->
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
char** names = (char**)((int)hGetProcIDDLL + exports->AddressOfNames);
std::cout << "Total # of functions: " << exports->NumberOfFunctions << std::endl;
std::cout << "Total # of named functions: " << exports->NumberOfNames << std::endl;
std::map<uintptr_t, char*> addressToName;
for (uint16_t i = 0; i < exports->NumberOfNames; i++)
{
char* name = (char*)hGetProcIDDLL + (int)names[i];
void* fn = GetProcAddress(hGetProcIDDLL, name);
addressToName[(uintptr_t)fn] = name;
//std::cout << "Export: Name: " << name << " Address: " << fn << "\n";
}
for (uint16_t i = 1; i < exports->NumberOfFunctions; i++)
{
void* fn = GetProcAddress(hGetProcIDDLL, MAKEINTRESOURCE(i));
std::map<uintptr_t, char*>::iterator it;
it = addressToName.find((uintptr_t)fn);
std::cout << "oridinal #: " << i << " address: " << fn << " Name: " << (it != addressToName.end() ? it->second : "N\\A") << "\n";
}
// Free the DLL module.
if (!FreeLibrary(hGetProcIDDLL))
{
return E_FAIL;
}
return 0;
}
它本质上与Dumpbin.exe/Export 做同样的事情,但也会打印出procAddress、名称和序数值。您可以在下面看到两次运行差异的图片。高位字的两个字节是稳定的。
参见bin dump 1 和bin dump 2。
我的问题有几个部分:
是什么让高位词稳定,低位词变化?
如何获取 Lee 在 MSO.dll 中找到的稳定地址?
如何知道
clearclipboard和getClipboardCount函数是哪一个,应该找到稳定的地址?
【问题讨论】:
-
您为什么希望能够调用未记录的私有接口?你为什么要这样黑客攻击?
-
如果您想在您拥有的未记录的私有逆向工程接口之上构建您的程序。但是你不应该期望任何稳定性。如果 MS 不想为您提供 API,那完全是他们的特权。
-
“我怀疑 MS 会在意。”我们关心,因为这意味着用户安装了新版本的 Office,而您的应用程序停止工作。然后用户说“新版本的 Office 不起作用。它使这个应用程序崩溃。我依靠这个应用程序进行日常工作。这是 Office 中的一个严重错误。”
-
剪贴板已经有自己的一套API函数。为什么需要 Office 中的任何内容?
-
不仅函数的地址会发生变化,而且函数签名或行为也会发生变化。由于它们没有公开曝光,微软可以随心所欲地改变事情——他们只需要在自己的团队内部协调这些改变。我希望我能在这里提供更多帮助,但我不能。
标签: c++ winapi dll reverse-engineering