如果我有符号,如何在 DLL 中找到参数签名并调用未导出的方法?

Posted

技术标签:

【中文标题】如果我有符号,如何在 DLL 中找到参数签名并调用未导出的方法?【英文标题】:How do I find the argument signature for and call an unexported method in a DLL if I have the symbol for it? 【发布时间】:2012-08-31 18:38:44 【问题描述】:

这是一个内置于 Windows 中的 dll,odbc32.dll。该函数称为LoadTraceDll()

Visual Studio 2008 中的堆栈帧是:

odbc32.dll!LoadTraceDll() + 0x42f 字节

我使用了 PE 分析器,但在 odbc32.dll 的导出列表中没有看到它。

我的问题如下:

如何确定参数类型和返回类型(方法签名)? 我怎么称呼它?我可以避免调用它的相对地址吗?

完整的堆栈跟踪如下:

ODBCTracer.dll!TraceVersion()  Line 2259    C++
odbc32.dll!LoadTraceDll()  + 0x42f bytes    
odbc32.dll!FInitTrace()  + 0xf3 bytes   
odbc32.dll!DllMain()  + 0x14692 bytes   
odbc32.dll!_CRT_INIT()  - 0x3e3 bytes   
ntdll.dll!LdrpRunInitializeRoutines()  + 0x1e8 bytes    
ntdll.dll!LdrpLoadDll()  - 0x336 bytes  
ntdll.dll!LdrLoadDll()  + 0x9e bytes    
KernelBase.dll!LoadLibraryExW()  + 0x13f bytes  
odbccp32.dll!LoadDM()  + 0x2a bytes 
odbccp32.dll!TracingPageProc()  + 0xc46 bytes   
user32.dll!UserCallDlgProcCheckWow()  - 0x180d bytes    
user32.dll!DefDlgProcWorker()  + 0xba bytes 
user32.dll!DefDlgProcW()  + 0x36 bytes  
user32.dll!UserCallWinProcCheckWow()  + 0x11d bytes 
user32.dll!InternalCreateDialog()  - 0xc7 bytes 
user32.dll!CreateDialogIndirectParamAorW()  + 0x5b bytes    
user32.dll!CreateDialogIndirectParamW()  + 0x18 bytes   
comctl32.dll!_CreatePageDialog()  + 0xb1 bytes  
comctl32.dll!_CreatePage()  + 0x161 bytes   
comctl32.dll!PageChange()  + 0xca bytes 
comctl32.dll!PropSheetDlgProc()  + 0x36e bytes  
user32.dll!UserCallDlgProcCheckWow()  + 0x11b bytes 
user32.dll!DefDlgProcWorker()  + 0xba bytes 
user32.dll!DefDlgProcW()  + 0x36 bytes  
user32.dll!UserCallWinProcCheckWow()  + 0x11d bytes 
user32.dll!SendMessageWorker()  + 0x158 bytes   
user32.dll!SendMessageW()  + 0x5d bytes 
comctl32.dll!CCSendNotify()  + 0xfbd bytes  
comctl32.dll!SendNotifyEx()  + 0x80 bytes   
comctl32.dll!ChangeSel()  + 0x2dc bytes 
comctl32.dll!Tab_OnLButtonDown()  + 0xfc bytes  
comctl32.dll!Tab_WndProc()  + 0x56d bytes   
user32.dll!UserCallWinProcCheckWow()  + 0x11d bytes 
user32.dll!DispatchMessageWorker()  + 0x12a bytes   
user32.dll!IsDialogMessageW()  + 0x102 bytes    
comctl32.dll!Prop_IsDialogMessage()  + 0x1f0 bytes  
comctl32.dll!_RealPropertySheet()  + 0x31b bytes    
comctl32.dll!_PropertySheet()  + 0x55 bytes 
odbccp32.dll!MainSheet()  + 0x18c bytes 
odbccp32.dll!SQLManageDataSources()  + 0x4b bytes   
odbcad32.exe!WinMain()  + 0x25b bytes   
odbcad32.exe!ODBC___GetSetupProc()  + 0x4ae bytes   
kernel32.dll!BaseThreadInitThunk()  + 0xd bytes 
ntdll.dll!RtlUserThreadStart()  + 0x21 bytes    

【问题讨论】:

【参考方案1】:

如何确定参数类型和返回类型(方法签名)?

你不能。

(嗯,你可以,有一定的信心,但它需要强大的逆向工程技能。你必须反汇编库,找到函数的定义和调用方式,以及典型的操作序列和参数/变量大小,你可以推断出参数的类型和返回值可以是什么

我怎么称呼它?我可以避免调用它的相对地址吗?

您可以dlopen()...呃...LoadLibrary() DLL 然后使用GetProcAddres() 获取其地址,将其存储在函数指针中,然后调用它:

HMODULE hndl = LoadLibrary("My.DLL");
void (*func)() = GetProcAddress(hndl, "MyFunction");
func();

【讨论】:

这就是我所害怕的。 @JustinDearing 如果您想要方法签名,请切换到 Objective-C 并将类转储库进行逆向工程:P【参考方案2】:

如果您有图像的符号(PDB 文件),您可以检索未导出的符号及其签名,前提是这些符号是公开的(按照 PDB 公开与私有的说法)。使用DIA,您可以将符号与关联的图像文件匹配。有关 PDB 符号和图像之间的映射如何工作的示例,请参阅 here。

【讨论】:

看起来很有希望,让我们看看这个兔子洞有多深。

以上是关于如果我有符号,如何在 DLL 中找到参数签名并调用未导出的方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查检查PInvoke签名的调用约定和参数与非托管的目标签名是不是匹配?

如何创建 SharePoint 2010 wsp 并包含已构建为 DLL 和强签名的 Web 部件

如何查看 dll (c) exe 调用了哪个函数?

覆盖 DLL 的反参数

对用作 ActiveX 控件的 .NET DLL 进行签名

使用来自 C++ dll 的 __declspec(dllexport) 签名声明在 C# 中调用的问题