与C++一起使用GetProcAddress
的常见“解决方案”是“extern”C“,但是它打破了重载。名称修改允许多个函数共存,只要它们的签名不同。但是有没有办法找到这些错误为GetProcAddress
?有没有办法找到在GetProcAddress中使用的C++ mangled名称?
4
A
回答
1
使用dumpbin /exports 'file.dll'
名来获取所有符号的装饰/未修饰的名。
4
的VC++编译器知道自己的名字重整方案,那么为什么不使用呢?里面template<typename T> T GetProcAddress(HMODULE h, const char* name)
,宏__FUNCDNAME__
包含这个包括T
部分,所以在GetProcAddress<void(*)(int)
里面,我们有一个subs与损坏的名称void(*)(int)
。由此,我们可以简单地推导出void foo(int);
的错位名称。此代码依赖于VC++宏__FUNCDNAME__
。
对于MinGW,您需要将其作为
。__PRETTY_FUNCTION__
而不是
FARPROC GetProcAddress_CppImpl(HMODULE h, const char* name, std::string const& Signature)
{
// The signature of T appears twice in the signature of T GetProcAddress<T>(HMODULE, const char*)
size_t len = Signature.find("@@YA");
std::string templateParam = Signature.substr(0, len);
std::string returnType = Signature.substr(len+4);
returnType.resize(templateParam.size()); // Strip off our own arguments (HMODULE and const char*)
assert(templateParam == returnType);
// templateParam and returnType are _pointers_ to functions (P6), so adjust to function type (Y)
std::string funName = "?" + std::string(name) + "@@Y" + templateParam.substr(2);
return ::GetProcAddress(h, funName.c_str());
}
template <typename T>
T GetProcAddress(HMODULE h, const char* name)
{
// Get our own signature. We use `const char* name` to keep it simple.
std::string Signature = __FUNCDNAME__ + 18; // Ignore prefix "[email protected]"
return reinterpret_cast<T>(GetProcAddress_CppImpl(h, name, Signature));
}
// Showing the result
struct Dummy { };
__declspec(dllexport) void foo(const char* s)
{
std::cout << s;
}
__declspec(dllexport) void foo(int i, Dummy)
{
std::cout << "Overloaded foo(), got " << i << std::endl;
}
__declspec(dllexport) void foo(std::string const& s)
{
std::cout << "Overloaded foo(), got " << s << std::endl;
}
__declspec(dllexport) int foo(std::map<std::string, double> volatile&)
{
std::cout << "Overloaded foo(), complex type\n";
return 42;
}
int main()
{
HMODULE h = GetModuleHandleW(0);
foo("Hello, ");
auto pFoo1 = GetProcAddress<void (*)(const char*)>(h, "foo");
// This templated version of GetProcAddress is typesafe: You can't pass
// a float to pFoo1. That is a compile-time error.
pFoo1(" world\n");
auto pFoo2 = GetProcAddress<void (*)(int, Dummy)>(h, "foo");
pFoo2(42, Dummy()); // Again, typesafe.
auto pFoo3 = GetProcAddress<void (*)(std::string const&)>(h, "foo");
pFoo3("std::string overload\n");
auto pFoo4 = GetProcAddress<int (*)(std::map<std::string, double> volatile&)>(h, "foo");
// pFoo4 != NULL, this overload exists.
auto pFoo5 = GetProcAddress<void (*)(float)>(h, "foo");
// pFoo5==NULL - no such overload.
}
0
这是不可能的,只需使用GetProcAddress
即可。但是,一种方法是枚举该特定模块的所有导出函数,然后执行模式匹配以查找所有重名的名称。
更具体地说,参考this answer here。您需要进行的唯一更改是将TRUE
中的MappedAsImage
参数和返回值GetModuleHandle
中的Base
参数传递给ImageDirectoryEntryToData
函数调用。
void EnumerateExportedFunctions(HMODULE hModule, vector<string>& slListOfDllFunctions)
{
DWORD *dNameRVAs(0);
_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory;
unsigned long cDirSize;
_LOADED_IMAGE LoadedImage;
string sName;
slListOfDllFunctions.clear();
ImageExportDirectory = (_IMAGE_EXPORT_DIRECTORY*)
ImageDirectoryEntryToData(hModule,
TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &cDirSize);
if (ImageExportDirectory != NULL)
{
dNameRVAs = (DWORD *)ImageRvaToVa(LoadedImage.FileHeader,
LoadedImage.MappedAddress,
ImageExportDirectory->AddressOfNames, NULL);
for(size_t i = 0; i < ImageExportDirectory->NumberOfNames; i++)
{
sName = (char *)ImageRvaToVa(LoadedImage.FileHeader,
LoadedImage.MappedAddress,
dNameRVAs[i], NULL);
slListOfDllFunctions.push_back(sName);
}
}
}
相关问题
- 1. 有没有办法在Wordpress中使用名称找到主题文件?
- 2. 有没有办法找到Nokogiri :: XML :: Element的根标签名称?
- 3. 库名称mangled
- 4. 有没有办法在actionscript2中找到调用函数的名称?
- 5. 没有找到函数使用GetProcAddress()C++ VBexpress 13
- 6. 有没有办法从位置(x,y线)找到div名称
- 7. 有没有办法在AQL中使用动态集合名称?
- 8. 有没有办法在对象名称中使用变量?
- 9. 有没有办法在vm中找到vm的主机名?
- 10. 有没有办法在AngularJS中得到子类名称?
- 11. 有没有办法在查询中使表名称动态化?
- 12. 有没有办法在C#中通过它的名字找到文件?
- 13. 有没有办法在c#中找到Teamviewer ID?
- 14. C#:有没有办法访问当前字段的名称?
- 15. 有没有办法在java中获取数组的名称?
- 16. 有没有办法在openpyxl中获取工作簿的名称
- 17. 有没有办法在windows Azure中更改cloudapp.net的DNS名称
- 18. 有没有办法使用VersionOne API获取当前sprint名称?
- 19. 有没有办法找出文件stdout的名称被重定向到Python
- 20. 有没有办法在django模板中使用变量设置块的名称?
- 21. 有没有办法使用循环检查java中的所有组件名称?
- 22. 有没有办法在grunt任务名称中指定变量?
- 23. 有没有办法在VB中转义根名称空间?
- 24. 有没有办法在irb中获取屏幕会话名称?
- 25. 有没有办法在EF中按名称指定字段?
- 26. 使用XPath找到没有在C#
- 27. 有没有办法在WinDbg中找到完全合格的方法名?
- 28. 有没有办法在c#中动态获取方法名?
- 29. 有没有办法在Firebird中引用带有变量的字段名称
- 30. 有没有办法看到名称空间参考?
注意'__PRETTY_FUNCTION__'将不是这样的,因为它不是缺胳膊少腿,它看起来像'T GetProcAddress的(HMODULE,为const char *)与T = blahblah]'。我不确定在GCC下是否存在任何这样的东西,如mangled函数名称宏(不这么认为)。 – Damon
@Damon:你说得对,我误解了文档。确实没有这样的宏,并且''头只提供了一个解压缩函数。 –
MSalters
@MSalters有趣,但它没有在函数上工作我尝试了它,因为在dll中,但在你的函数中的错位名称中的反向引用;因为该函数位于命名空间中,并且在相同的命名空间中返回一个类的对象;在返回类型中,命名空间名称get用@ 1 ... –