热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

道简单的DLL题目,几乎难倒了所有C++高手!!!!!(加分版)

为感谢在上1版中做出辛勤回答者,将分数结算给“有容乃大,无欲则刚”和“每天学VC,补充你我的维C”。再做一版以给高手们加分。题目:我要取出DLL中的所有输出函数名的列表(包括地址,最好还有参数
为感谢在上1版中做出辛勤回答者,将分数结算给“有容乃大,无欲则刚”和“每天学VC,补充你我的维C”。
再做一版以给高手们加分。题目:
我要取出DLL中的所有输出函数名的列表(包括地址,最好还有参数类型列表)。
不谈COM类型的DLL,只是基本的动态库。
已经问了很多人,几乎一般的高手都被难倒了。
用ASM可能行不通了,因为只能查根据调用者的push次数来查。
但是我不能找到任意一个动态库的调用者。
但是PE(Portable Executable)好象没有记录“参数类型列表”
如有答对者给N00分,不惜!!!!

73 个解决方案

#1


好象VC在Debug版编译时记录了,“参数类型列表”,但是不知道记在哪里了。

#2


坐在炕头上,反复研究上一版中的答案。
发现property1(路标) 的答案最接近。
CALLBACK property1(路标) ( ) 回来加分。
其中GetExportDirectory和GetNtHeaders代码不全。
请重新“编译”一下。

#3


喝口小米粥,看看老毛子的程序,写得真精!!
(就是看不懂毛文)

#4


你的问题我早就注意到了,用DumpBin的缺陷就是无法得知参数,而就我看事实上你不可能得到dll输出函数的参数列表。

举例说明:我曾经参与过用驱动程序拦截上层API的项目,当时遇到的最大问题就是面对微软未公开的API,我们只能拦截到,却根本无法了解它们参数的含义,到后来也没办法解决。

当然,我算不上高手,对Dll很多地方并没有深入研究过,如果你真的找到了答案,希望能共享出来帮助大家,谢谢~

#5


#include 

#define MakePtr(base, offset) ((LPSTR)(base) + offset)

//@//////////////////////////////////////////////////////////////////////////
// §¤§Ý§à§Ò§Ñ§Ý§î§ß§í§Ö §á§Ö§â§Ö§Þ§Ö§ß§ß§í§Ö

static BOOL     g_bUnicodeOS = FALSE;
static HMODULE  g_hModuleUnicows = NULL;
static LPWORD   g_pdwOrd = NULL;
static LPDWORD  g_pdwAddrs = NULL;
static LPDWORD  g_pdwNames = NULL;
static DWORD    g_dwNames = 0;

//@//////////////////////////////////////////////////////////////////////////
// §£§ã§á§à§Þ§à§Ô§Ñ§ä§Ö§Ý§î§ß§Ñ§ñ §æ§å§ß§Ü§è§Ú§ñ, §Ó§à§Ù§Ó§â§Ñ§ë§Ñ§Ö§ä §Ñ§Õ§â§Ö§ã §æ§å§ß§Ü§è§Ú§Ú §Ú§Ù unicows.dll
// §ã §å§Ü§Ñ§Ù§Ñ§ß§ß§í§Þ §Ú§Þ§Ö§ß§Ö§Þ, §Ö§ã§Ý§Ú §ä§Ñ§Ü§Ñ§ñ §Ú§Þ§Ö§Ö§ä§ã§ñ

static LPDWORD GetFunctionAddress(LPCSTR azName)
{
DWORD dwName = 0; 
    while (dwName < g_dwNames)
    {
        if (0 == ::lstrcmpiA(MakePtr( g_hModuleUnicows, g_pdwNames[dwName]), azName))
            return (LPDWORD)MakePtr(g_hModuleUnicows, g_pdwAddrs[g_pdwOrd[dwName]]);
dwName ++;
    }

    return NULL;
}

BOOL _UnicowsInit(LPCSTR szLib)
{
/* int i = ::GetVersion();
    if (0 == (0x80000000 & ::GetVersion()))
    {
        // WinNT/2k/XP: §´§å§ä §ß§Ñ§Þ §Õ§Ö§Ý§Ñ§ä§î §ß§Ö§é§Ö§Ô§à
        g_bUnicodeOS = TRUE;
        return ::SetLastError(0), TRUE;
    }    */
    g_hModuleUnicows = ::LoadLibraryA(szLib);
    if (!g_hModuleUnicows)
        return FALSE; // §°§ê§Ú§Ò§Ü§Ñ §á§â§Ú §Ù§Ñ§Ô§â§å§Ù§Ü§Ö Unicows.dll

    // §¯§Ñ§ç§à§Õ§Ú§Þ §ä§Ñ§Ò§Ý§Ú§è§å §ï§Ü§ã§á§à§â§ä§Ñ
    PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(g_hModuleUnicows);

    if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER))
            || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
        return ::SetLastError(ERROR_INVALID_PARAMETER), FALSE;

    PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)
        MakePtr(g_hModuleUnicows, pDosHeader->e_lfanew);
    
    if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS))
            || IMAGE_NT_SIGNATURE != pNTHeaders->Signature)
        return ::SetLastError(ERROR_INVALID_PARAMETER), FALSE;

    IMAGE_DATA_DIRECTORY& expDir =
        pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    PIMAGE_EXPORT_DIRECTORY pExpDir = (PIMAGE_EXPORT_DIRECTORY )
        MakePtr(g_hModuleUnicows, expDir.VirtualAddress);

    // §©§Ñ§á§à§ß§Ú§Þ§Ñ§Ö§Þ §ä§Ñ§Ò§Ý§Ú§è§å §Ú§Þ§Ö§ß §Ú §Ñ§Õ§â§Ö§ã§à§Ó
    g_pdwOrd = (LPWORD)MakePtr(g_hModuleUnicows, pExpDir->AddressOfNameOrdinals);
    g_pdwNames = (LPDWORD)MakePtr(g_hModuleUnicows, pExpDir->AddressOfNames);
    g_pdwAddrs = (LPDWORD)MakePtr(g_hModuleUnicows, pExpDir->AddressOfFunctions);
    g_dwNames = pExpDir->NumberOfNames;

    return TRUE;
}

static LPCSTR GetNameFromOrdinal(HMODULE hModule,DWORD dwOrdinal)
{
    if (!hModule)
        return FALSE; // §¯§Ö§ä §ä§Ñ§Ü§à§Ô§à §Þ§à§Õ§å§Ý§ñ
    
    // §¯§Ñ§ç§à§Õ§Ú§Þ §ä§Ñ§Ò§Ý§Ú§è§å §ï§Ü§ã§á§à§â§ä§Ñ
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(hModule);


    if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER))
            || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
        return ::SetLastError(ERROR_INVALID_PARAMETER), FALSE;

    PIMAGE_NT_HEADERS pNTHeaders =(PIMAGE_NT_HEADERS)
        MakePtr( hModule, pDosHeader->e_lfanew);
   
    if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS))
            || IMAGE_NT_SIGNATURE != pNTHeaders->Signature)
        return ::SetLastError(ERROR_INVALID_PARAMETER), FALSE;
 
    IMAGE_DATA_DIRECTORY& expDir =
        pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    PIMAGE_EXPORT_DIRECTORY pExpDir = (PIMAGE_EXPORT_DIRECTORY)
        MakePtr( hModule, expDir.VirtualAddress);

    LPWORD pdwOrd = (LPWORD)MakePtr( hModule, pExpDir->AddressOfNameOrdinals);
    LPDWORD pdwNames = (LPDWORD)MakePtr(hModule, pExpDir->AddressOfNames);
    dwOrdinal -= pExpDir->Base;
g_dwNames = pExpDir->NumberOfNames;
    for (DWORD iName = 0; iName < pExpDir->NumberOfNames; iName++)
    {
        // §±§â§à§Ó§Ö§â§ñ§Ö§Þ §Ó§ã§Ö §ß§à§Þ§Ö§â§Ñ §á§à §á§à§â§ñ§Õ§Ü§å
        if (dwOrdinal == pdwOrd[iName])
            return MakePtr(hModule, pdwNames[iName]);
    }/**/
    return NULL;
}




int main(int,char**)
{
if(!_UnicowsInit("C:\\Test.dll"))
return -1;
LPCSTR szName = GetNameFromOrdinal(g_hModuleUnicows,1);
LPDWORD pTest = GetFunctionAddress(szName);

__asm
{
call pTest
}

szName = GetNameFromOrdinal(g_hModuleUnicows,2);
pTest = GetFunctionAddress(szName);
int nOffset= g_dwNames*sizeof(LONG);
__asm
{
push g_dwNames
push        szName
call        pTest
add         esp,nOffset
}
_UnicowsRebindImports(g_hModuleUnicows);
return 0;
}

#6


Text1.cpp刚起步,main是我写的。
其他抄老冒子的,乱码都是毛文。
我也看不懂。
http://www.rsdn.ru/archive/vc/issues/pvc071.htm

#7


我喝小米粥,啃咸菜,干了一晚上。
才眯一会,刚起炕。

#8


问问题好好问,不要乱写标题

#9


同意!

#10


如果DLL导出来的C类型的函数,得到参数是不可能的,除非在主程序调用的时候挡截API,不过那也只能得到参数的个数,想到得到准确的参数类型还要进一步分析……

搞反向工程?做什么?

#11


你写的dll文件愿意让别人使用吗?

#12


到底有高手没??PE+ASM
用PE将DLL翻遍数据区,再用ASM把找不完的数据区翻一遍。
我就是气不过,找不到参数类型列表。

#13


impossible

#14


impossible???

请各位大虾,最后冲击一次。

除了参数个数,还能不能挖出来点什么??

#15


不感兴趣

#16


ms的自带工具dumpbin

#17


搞手都是自己反汇编,自己跟踪调试,自己分析,不可能有程序自动获取参数个数及参数含义的

#18


这个标题有些夸张

转帖:


使用Microsoft  Visual  Studio的工具DEPENDS.EXE可以查看动态库的接口函数,但如何能够看到这个动态库接口函数的参数呢?  
---------------------------------------------------------------  
 
可以通过反汇编来知道接口函数的参数,建议使用W32DSM来分析,也可以直接使用VC来分析,就是麻烦一点。  
现在使用W32DSM来具体说明:  
1。先打开需要分析的DLL,然后通过菜单功能-》出口来找到需要分析的函数,双击就可以了。  
它可以直接定位到该函数。  
2。看准该函数的入口,一般函数是以以下代码作为入口点的。  
push  ebp  
mov    ebp,  esp  
...  
3。然后往下找到该函数的出口,一般函数出口有以下语句。  
...  
ret    xxxx;//其中xxxx就是函数差数的所有的字节数,为4的倍数,xxxx除以4得到的结果  
就是参数的个数。  
其中参数存放的地方:  
ebp+08          //第一个参数  
ebp+0C          //第二个参数  
ebp+10          //第三个参数  
ebp+14          //第四个参数  
ebp+18          //第五个参数  
ebp+1C          //第六个参数  
。。。。  
-------------------------------------------  
还有一种经常看到的调用方式:  
sub  esp,xxxx          //开头部分  
//函数的内容  
。。。  
//函数的内容  
add  esp,xxxx  
ret                            //结尾部分  
其中xxxx/4的结果也是参数的个数。      
-------------------------------------------------  
还有一种调用方式:  
有于该函数比较简单,没有参数的压栈过程,  
里面的  
esp+04就是第一个参数  
esp+08就是第二个参数  
。。。  
esp+xx就是第xx/4个参数  
你说看到的xx的最大数除以4后的结果,就是该函数所传递的参数的个数。  
----------------------------------------------  
到现在位置,你应该能很清楚的看到了传递的参数的个数。至于传递的是些什么内容,还需要进一步的分析。  
最方便的办法就是先找到是什么软件在调用此函数,然后通过调试的技术,找到该函数被调用的地方。一般都是PUSH指令  
来实现参数的传递的。这时可以看一下具体是什么东西被压入堆栈了,一般来说,如果参数是整数,一看就可以知道了,  
如果是字符串的话也是比较简单的,只要到那个地址上面去看一下就可以了。  
如果传递的结构的话,没有很方便的办法解决,就是读懂该汇编就可以了。对于以上的分析,本人只其到了抛砖引玉,  
希望对大家有点用处。  
 

#19


楼上这个帖子早就看过了。按照它这种方法还是很难看到具体的参数类型。如果单纯就某个软件来言,我可以慢慢的根据汇编猜测出它的各个参数,如果想来个通用的方法,想必没有,不然软件也太好反汇编出源代码了,那我们还能够靠软件吃饭吗?
不过对于编译器厂商来说,应该留有一手未公开的东西,在DLL中放一些额外的数据,可以根据它们查看具体的参数类型。

#20


要想真正取得参数类型,并不容易,最多可以通过PUSH的次数,看出参数的个数。

#21


mark

#22


你是在分析别人的程序吧!这么难的事情,还想投机?

我以前分析过ms的打印驱动的两个dll,只要找到对应版本的调试符号文件(ms提供),可以用反汇编工具看到带有函数名的asm程序,但是要想得到参数类型,你只能得到有文档(源码也可)的输出接口函数的信息

其它的内部函数,你只能通过读asm程序,自己分析自己猜测了

老想天上掉陷饼是不可能的,你死了这条心吧!

#23


w32dasm一般般,ida更好用一点儿!

#24


我也想知道呀。
如果真的有这样的工具,微软也不用混了,呵呵

#25


yun,
这个题目一点都不简单啊

#26


都厉害 ,我看不懂

#27


是啊,高手就是高手,他们讨论什么我都~~~

#28


我要取出DLL中的所有输出函数名的列表(包括地址,最好还有参数类型列表)。

WIN32DASM
IDA PRO
有功能可以查看 DLL导出的函数

#29


如果是普通的dll,标准的dll,那是不可能得出函数的参数类型表的,
参数的个数倒还是可以得到,类型?基本就是得不到的,除非你写出一个非常智能的代码来根据,push进来那个DWORD来分析出他的数据类型?实在太难了,普通的int数据和一个char *都是32位的DWORD,我是实在想不出,如何判断出是字符串还是int.

从另一个角度想想,如果dll里的函数名以及参数表都可以通过它自身得到,那,dll还有什么秘密可言,几乎可以认为是公开源代码了。如果dll里的函数名以及参数表都可以通过它自身得到,那编译器何必还要.lib .h 文件来辅助?

#30


不可能得到参数列表,如果能得到还要头文件作甚!
比如有个参数是引用,是结构,或者是class的对象作为参数,或者是interface,情况太多太复杂,楼主不需要在这个不可能的事上多浪费精力了!

#31


哎,怪只怪微软操作系统和编译器当初也没详细的设计好!
兄弟我近期在研究可不可以把Windows上的EXE和DLL,经过PE改写它的文件头之后可以在Linux上运行。
省得用VI太麻烦了,有没有高手给我一段Linux上的PE结构??

不升感谢!!

#32


对于参数的解析很多人已经问过了,手工分析可行,不过效率却不敢恭唯
这个问题的一部分本是可以机器分析的,只不过由于编译器之间的差异使这个问题更加困难,通过某些开源的反汇编工具可以分析出参数的基本类型,即长度和基本类型,不过对于向指针类型这样的复杂类型,由于传递的参数值对不同结构的指针的传值方式都是相同的,因此具体结构的解析则要深入对该指针类型的偏移量的访问,由于在这一点上并没有明确的标准,这也是无法完全自动实现的根本原因

#33


因此,我将这个问题归结于非标准化带来的差异
如果要实现自动反编译之类的功能,恐怕也是一个值得深究的研究型题目了,需要从很广的面上来抽象出各种应用的特征和语义表述,这在当前是没有可能的

#34


PE格式没有定义任何所谓的参数类型表,只定义了一个重分配表和一个入口依移使得加载器能够计算出绝对地址,从而能够将调用转换为一个 call 或 jmp 调用,这也是导出表的唯一作用

#35


richmain (吕起民) 
-----------------------------------------
此人是不是“软媒”的那个SB ,有点面熟。耶

#36


楼上的,不管是不是,只要现在遵守CSDN版规就可以了,以前的事情可以不再追究

#37


mark

#38


导出函数可以看到,VC不是有个自带的工具吗?
参数列表不可能得到,除非dll这种模型有budge,


#39


我觉得楼主是SB,我也可以这样说
:一个简单的问题,谁能在VC里给我凋 
int 10h (bios中断10 )
我给1000分,
看谁他ma会
100分算个b啊。
不要想空手套白狼啦。
这种问题没有解的

#40


没有一劳永逸的方法吧,不过如果是具体的程序,似乎也没有哪个不能被破解。

#41


歇会吧.此乃最优做法。

#42


直接在cmd下面dumpbin不就行了。

#43


回复人: yafizyh(亚斐) ( ) 信誉:99  2005-7-10 19:10:19  得分: 0  
 
 
   
richmain (吕起民) 
-----------------------------------------
此人是不是“软媒”的那个SB ,有点面熟。耶

  
 


这两天我在网上看到软媒的招聘,说是1W至1.5W,我现在才9K,是不真的啊?是真的我来啊。

#44


反正我们公司由3个是1.5瓦的[算我一个吧],0.9瓦的有很多。。

#45


还有个老头念心是1千瓦的,干3年了。。

#46


0.9瓦都是04毕业的,只有1个是03毕业的。
0.9瓦需求量最大。

#47


It's actually possible, if you have the debug symbol files (PDB files). Microsoft actually makes debug symbols files available online for developer. 

Anyone has used them?

With debug symbol files, your program can have the same information a debugger has.

Check source code here:

http://www.debuginfo.com/examples/src/LocalsByAddr.cpp

Read Matt Pietrek's article:

http://msdn.microsoft.com/msdnmag/issues/02/03/hood/default.aspx

#48


..

#49


只能说导出函数名可以,知道参数就不可能了。除非你去破解。。。。

#50


要是能做到你说的那样
那我们全用破解版了

推荐阅读
  • 在第七天的深度学习课程中,我们将重点探讨DGL框架的高级应用,特别是在官方文档指导下进行数据集的下载与预处理。通过详细的步骤说明和实用技巧,帮助读者高效地构建和优化图神经网络的数据管道。此外,我们还将介绍如何利用DGL提供的模块化工具,实现数据的快速加载和预处理,以提升模型训练的效率和准确性。 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • C#编程指南:实现列表与WPF数据网格的高效绑定方法 ... [详细]
  • ESP32 IRAM 内存优化策略与实践总结
    本文总结了针对ESP32 IRAM内存溢出问题的优化策略与实践经验。通过详细分析ESP32的内存结构和IRAM分配机制,提出了一系列有效的解决方案,包括代码优化、内存管理技巧和编译器配置调整,旨在帮助开发者有效解决`.espressif/tools/xtensa-esp32-elf/esp-2`等类似错误,提升系统性能和稳定性。 ... [详细]
  • 利用Swiss数据集进行多元线性回归分析,首先通过散点图矩阵(pairs plot)初步探索各变量之间的关系。接着,绘制残差图以评估模型的拟合效果和假设条件的合理性,进一步诊断和验证模型的有效性。通过这些图形工具,可以更深入地理解模型的性能和潜在问题。 ... [详细]
  • JVM参数设置与命令行工具详解
    JVM参数配置与命令行工具的深入解析旨在优化系统性能,通过合理设置JVM参数,确保在高吞吐量的前提下,有效减少垃圾回收(GC)的频率,进而降低系统停顿时间,提升服务的稳定性和响应速度。此外,本文还将详细介绍常用的JVM命令行工具,帮助开发者更好地监控和调优JVM运行状态。 ... [详细]
  • 技术日志:深入探讨Spark Streaming与Spark SQL的融合应用
    技术日志:深入探讨Spark Streaming与Spark SQL的融合应用 ... [详细]
  • Java 8 引入了 Stream API,这一新特性极大地增强了集合数据的处理能力。通过 Stream API,开发者可以更加高效、简洁地进行集合数据的遍历、过滤和转换操作。本文将详细解析 Stream API 的核心概念和常见用法,帮助读者更好地理解和应用这一强大的工具。 ... [详细]
  • voc生成xml 代码
    目录 lxmlwindows安装 读取示例 可视化 生成示例 上面是代码,下面有调用示例 api调用代码,其实只有几行:这个生成代码也很简 ... [详细]
  • 第五章详细探讨了 Red Hat Enterprise Linux 6 中的 Ext3 文件系统。5.1 节介绍了如何创建 Ext3 文件系统,包括必要的命令和步骤,以及在实际操作中可能遇到的问题和解决方案。此外,还涵盖了 Ext3 文件系统的性能优化和维护技巧,为用户提供全面的操作指南。 ... [详细]
  • 表面缺陷检测数据集综述及GitHub开源项目推荐
    本文综述了表面缺陷检测领域的数据集,并推荐了多个GitHub上的开源项目。通过对现有文献和数据集的系统整理,为研究人员提供了全面的资源参考,有助于推动该领域的发展和技术进步。 ... [详细]
  • 本文探讨了将PEBuilder转换为DIBooter.sh的方法,重点介绍了如何将DI工具集成到启动层,实现离线镜像引导安装。通过使用DD命令替代传统的grub-install工具,实现了GRUB的离线安装。此外,还详细解析了bootice工具的工作原理及其在该过程中的应用,确保系统在无网络环境下也能顺利引导和安装。 ... [详细]
  • 在Adobe After Effects中,通过高效添加地图指北针,可以显著提升地理信息的准确性和视觉效果。本文介绍了一种方法,利用代码函数 `public static void ExportMapEx(string filepath, int resolution, AxMapControl curMapControl)`,实现地图导出时自动添加指北针,确保地理数据的精确性和一致性。此外,还详细探讨了如何优化指北针的位置和样式,以增强地图的可读性和专业性。 ... [详细]
  • 精通jQuery:深入解析事件处理机制与应用技巧
    本文详细探讨了jQuery的事件处理机制及其应用技巧,通过具体的代码示例,逐一解析了每个jQuery代码片段与其对应的HTML结构。文章以标记为基准,CSS作为通用样式,确保每段代码都能独立运行。HTML和CSS代码统一放置在文章末尾,方便读者参考和实践。 ... [详细]
author-avatar
潇潇沐林风_921
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有