通过DEF文件的DLL导出符号修改似乎得到修改

时间:2013-04-09 16:30:24

标签: c++ dll visual-studio-2012

我使用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导出定义的片段?

我尝试使用许多编译器和链接器选项,但完全没能更接近我的目标。

2 个答案:

答案 0 :(得分:2)

我终于明白了。

正如Hans Passant所指出的那样,链接器以某种我难以掌握的方式处理导出定义中的@ -signs ...


我的观察:

  • Mangled C ++函数(??0FooBar@@QAE@ABV0@@Z)转发给未编组的(extern "C")函数(__E__0__
  • => C ++函数修改在第一个@ -sign(??0FooBar

  • 被裁剪
  • Mangled C ++函数(??0FooBar@@QAE@ABV0@@Z)转发给受损(extern "C" __declspec(dllexport))函数(___E__0__@4

  • => C ++函数重整保持不变

这将是我最初的测试用例,现在已经足够接近我的初始目标了。

从包装器的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);