我使用DEF文件创建了一个包装器DLL来描述它的EXPORTS
。
从原始DLL的导出(使用dumpbin生成):
EXPORTS
??0FooBar@@QAE@ABV0@@Z @1
从我为包装器DLL创建的DEF文件:
EXPORTS
??0FooBar@@QAE@ABV0@@Z=__E__0__ @1
使用OllyDbg检查生成的包装器DLL时,我可以看到导出实际上已更改为:
Names in FooBarDLL, item 0
Address=0F085685
Section=.text
Type=Export
Name=??0FooBar
如您所见,缺少通常由Microsoft Visual C ++为此类类/函数/参数组合生成的额外garbledegock(@@QAE@ABV0@@Z
)。
为了确保这不是OllyDbg使用的用户错误,我也检查了原始DLL的导出,看起来就像我期待的东西一样令人惊讶:
Names in FooBarDLLOriginal, item 1
Address=1003A800
Section=.text
Type=Export
Name=??0FooBar@@QAE@ABV0@@Z
因为我需要我的包装器DLL看起来与原始DLL完全一样,所以这个结果显然不好。
如何阻止Visual C ++忽略我的DEF导出定义的片段?
我尝试使用许多编译器和链接器选项,但完全没能更接近我的目标。
答案 0 :(得分:2)
我终于明白了。
正如Hans Passant所指出的那样,链接器以某种我难以掌握的方式处理导出定义中的@ -signs ...
我的观察:
??0FooBar@@QAE@ABV0@@Z
)转发给未编组的(extern "C"
)函数(__E__0__
) => C ++函数修改在第一个@ -sign(??0FooBar
)
Mangled C ++函数(??0FooBar@@QAE@ABV0@@Z
)转发给受损(extern "C" __declspec(dllexport)
)函数(___E__0__@4
)
这将是我最初的测试用例,现在已经足够接近我的初始目标了。
从包装器的DEF文件:
EXPORTS
??0FooBar@@QAE@ABV0@@Z=___E__0__@4 @1
从包装器DLL的导出(使用dumpbin生成):
ordinal hint RVA name
1 0 00001000 ??0FooBar@@QAE@ABV0@@Z = ___E__0__@4
2 1 00001000 ___E__0__@4 = ___E__0__@4
真正令我惊讶的是,当使用OllyDbg读取导出表时,序号1的导出仍然不可见。仍然,当加载DLL(LoadLibrary
)并使用GetProcAddress(hDLL, "??0FooBar@@QAE@ABV0@@Z")
解析该函数的地址时,一切正常。
所以我现在有一个包装原始DLL的DLL,使用功能相同的导出表。它现在显示了我的代理实现的额外导出,但这对我的目的来说没有问题。这样就可以创建一个代理DLL,它可以拦截,如果需要,甚至在涉及C ++修改时也可以增强原始实现。我不知何故觉得我过于复杂化了一些东西但嘿,它有效。
对于我完全通过的函数,我只需在我的DEF文件中创建一个转发导出,如下所示:
??BarFoo@WhoCares@@@Z = OriginalDllName.??BarFoo@WhoCares@@@Z
答案 1 :(得分:1)
这个问题(和其他类似的问题)涉及使用Code Project WRAPPIT工具自动创建代理DLL。使用Till观察的解决方案是:
始终将包装函数声明为__stdcall,以便使用前导_和尾随@ 0进行修饰,然后在.def文件中使用它,以便保留原始函数修饰(如果有)。
(如果/如果用真实函数替换包装器,则需要记住将调用约定从__stdcall更改为所需的调用约定,以及删除__declspec(裸),添加参数声明,更改或删除。 def文件声明匹配等。)
Wrapper .cpp snipet:
// _OriginalFunction@12
extern "C" __declspec(naked) void __stdcall __E__0__()
{
__asm
{
jmp p[0*4];
}
}
.def文件:
EXPORTS
_OriginalFunction@12=___E__0__@0 @1
etc.
我修改了我的WRAPPIT工具版本来自动执行此操作:
165c165
< fprintf(fdef,"%s=%s @%u\r\n",v[i].en,v[i].in,v[i].o);
---
> fprintf(fdef,"%s=_%s@0 @%u\r\n",v[i].en,v[i].in,v[i].o);
167c167
< fprintf(fdef,"%s=%s @%u NONAME\r\n",v[i].en,v[i].in,v[i].o);
---
> fprintf(fdef,"%s=_%s@0 @%u NONAME\r\n",v[i].en,v[i].in,v[i].o);
225c225
< fprintf(fcpp,"// %s\r\nextern \"C\" __declspec(naked) void %s %s()\r\n",v[i].en,argv[3],v[i].in);
---
> fprintf(fcpp,"// %s\r\nextern \"C\" __declspec(naked) void %s %s()\r\n",v[i].en,"__stdcall",v[i].in);