不知道诸位看官是否有过这样的经历:在不经意之间发现一个DLL文件,它里边有不少有趣的导出函数——但是由于你不知道如何调用这些函数,所以只能大发感慨而又无能为力焉。固然有些知名的DLL可以直接通过搜索引擎来找到它的使用方式(比如本文中的例子ipsearcher.dll),不过我们诚然不能希望自己总能交到这样的好运。所以在本文中,作者希望通过自己文理不甚通达的讲解能够给大家以授人以渔的效果。
先决条件
阅读本文,你需要具备以下先决条件:
- 初步了解汇编语言,虽然你并不一定需要去读懂DLL中导出函数的汇编代码,但是你至少应该了解诸如push、mov这些常用的汇编指令。
- 一个能够查看DLL中导出函数的工具,Visual Studio中自带的Dependency Walker就足够胜任了,当然你也可以选择eXeScope。
- 一个调试器。理论上讲VC也可以完成调试的工作,但它毕竟是更加针对于源代码一级调试的工具,所以你最好选择一个专用的汇编调试器。在本文中我用的是OllyDbg——我不会介绍有关这个调试工具的任何东西,而只是简要介绍我的调试过程。
准备好了吗?那么我们做一个热身运动吧先。
热身——函数调用约定
这里要详细介绍的是有关函数调用约定的内容,如果你已经了解了这方面的内容,可以跳过本节。
你可能在学习Windows程序设计的时候早已接触过“函数调用约定”这个词汇了,那个时候你所了解的内容可能是一个笼统的概念,内容大抵是说函数调用约定就是指的函数参数进栈顺序以及堆栈修正方式。譬如cdecl调用约定是函数参数自右而左进栈,由调用者修复堆栈;stdcall调用约定亦是函数参数自右而左进栈,但是由被调用者修复堆栈……噢不,这太晦涩了——在源代码上我们是无法看到这些东西的!
那么我们别无选择,只有深入到汇编一层了。考虑以下C++代码: