高级话题:用ASM直接调用没有参数信息的dll库函数!

作者:不及格的程序员-八神

1. 背景资料

通常开发者获取到的通用dll函数库都会有说明文件,里面对dll库中公开的函数都会有api接口说明,比如函数的名称,返回值,参数类型以及参数的数量.

但是有时开发者也会找到一些dll库函数,这些库函数只能获取到函数名称,而没有关于函数的参数信息.

这种dll一般是来自第三方的,或是偷来的(我的项目中就是属于此类,我知道这个dll函数的功能很不错,我就是想将它嵌入到我的程序中.)).

对于前者,具有资料完备API编程信息,我们可以在c++,vb或.NET平台中轻松编写调用接口来执行dll中的函数,而后者由于没有参数信息,想调用就不那么简单了.

通常系统自带的dll函数库都会有api说明,或者也可以通过某些工具来获取dll库中的函数描述信息.

可是一些第三方的dll函数可能不会将函数信息写到dll中,这样我们就不能够获取参数信息了,也就无法调用了,真的没办法吗?

 

2. 解决办法

即然没有参数信息就没有办法声明函数的调用接口,不过没关系.

我想到一种简单的方式:用汇编语言来直接调用.

首先要有完整的第三方程序,先看看第三方程序在汇编语言层面上是如何调用函数的(通过反汇编).

通过调试软件(如:windbg,od,softace等)将第三方的程序运行起来,然后在我们需要的那个dll模块函数上加断点,分析它的汇编码.

其实很简单的,如果函数需要参数,那就看看它是通过栈的方式传的参数还是通过寄存器来传的参数.

一般汇编语言中参数都是传的参数地址,而不是值.另外传递参数的规则也要弄清.

如果传参方式是栈方式传参数,还要区分是调用者清除栈还是被调用者清除栈.

比如下面代码是调用md5加密,我就是用栈方式传递两个指针参数给函数.

    mov eax,dword ptr [cb] //传入待加密字符串地址

    push eax //参数2 入栈

    mov eax,dword ptr [result] //反回值字符串地址

    push eax //参数1 入栈

    call pFun //执行函数

结果result里就是我们加密后的结果了.

上面代码使用的是调用者清除栈方式,而清除栈方式是被调用者清除栈(通过反汇编可以发现指定函数里是使用哪种清栈方式.): 如果需要我们清除栈,那就在上面代码的最后写 add esp,8 代表释放两个指针参数的空间8个字节.

关于函数清栈方式参见我的另一篇随笔:函数的可变数目参数 与 栈

 

3. 如何加载dll与函数地址

 我使用win32 api 来加载dll库与函数地址,使用方式:

HINSTANCE dll = LoadLibrary(L"d:\\*******.dll");

FARPROC pFun = GetProcAddress(dll,"要调用的函数名称");

_asm

{

  mov eax,dword ptr [cb]

  push eax

  mov eax,dword ptr [result] 

  push eax

  call pFun

}

 

4. 注意事项

需要特别注意的是,对于(传入的/返回的)参数指针指向的数据区域大小需要多次试验,因为有时从汇编中很难发现局部变量的长度,所以尽量将我们声明的变量地址空间多一些.

还有就是dll函数的清栈方式,要仔细观察反汇编的结果,看看它用的是哪种调用方式,这样才能保障栈平横,不至于缓冲区溢出.

Advertisements
发表在 C++ | 留下评论

给javascript引擎添加sleep函数.

js有sleep函数吗?,有,我们自已加.

如何在js中让函数睡眠多少秒? 经常会有Javascript初学者提出这样的问题,自从js出现以来.

即然该功能如此需要,但为什么js中不提供这样的函数呢?

目前浏览器都是在UI线程解析js,以火狐浏览器为例,我重新编译了js引擎,并且在js引警中添加了sleep方法,该方法调用c语言的线程睡眠函数.  

将方法附加到Object上,方法签名为sleep();无参数.默认休眠1秒钟,如果你在js中调用该函数,浏览器UI界面将被阻碍。

另外如果你的js函数存在死循环,浏览器的js解析会检测到js执行超时会提醒你是否终止执行本页面的js.

最后提供新编译的js引擎,将它们替换firefox下的js引擎即可.

然后你可以写一段js玩一玩,比如"testSleep".sleep();因为我是在Object添加的,所以你可以在任何js对象上调用这个函数.

附件:js.rar

发表在 JavaScript | 留下评论

你妈逼,中国联通

今天联通客服打电话到我家,说我家2010-06月份固定电话费未缴费,操 前些天刚交的… 回执单我都看过了46元
媳妇儿到营业厅还查不到底账,操你妈的联通,收我两次话费…
发表在 生活 | 留下评论

老年生活

今天上班的路上看到一位老人在路边 画画,当时我就一种美好的回忆,小时候的美好时光…
发表在 生活 | 留下评论

过生日罗

星期三
 
今天是阴历5月12日,我过生日,明天的阳历是6月24日也是我过生日,好多年才会碰到两个生日在一起的,这样也挺有意思的。
发表在 生活 | 留下评论

怀旧2 -电脑时代

作者:不及格的程序员-八神


在前一篇怀旧中(见怀旧 你是否还记得蜜桃精-纯真的80年代的),介绍了许多值得回忆的东西,这篇继续追忆过去的美好时光.

电脑是20世纪最最伟大的发明之一

实际上,在我中学快毕业时,就听到有人说要报考到职业高中里学习微机(微型计算机,不如个人电脑好听),当时还不知道它是什么东西,认为它就是一个比计算器大些的计算器.

直到1996,才在电脑游戏厅看到它真正的样子,孩子们用它在玩红色警界.

我太落后了,POWER键是开关都不知道.与此同时学校里开了微机课,操作系统是dos6,286cpu…

 

应该说个人电脑起源于施乐公司

下图为Xerox Alto,制造于1973.但它未产品化,直到1984年苹果公司仿造它制造出了更好的MAC电脑.

 

在没有个人电脑之前,人们都在是大型机/小型机上才能获得编程的乐趣.有一个天才小子斯蒂夫沃兹,由于它在父亲(在洛克马丁西德公司工作)的良好教育下,小时候就是一个发明家,以至于长大,很容易就能设计并造出个人电脑.

下图苹果II型电脑以及内部构造,它没有显示器,需要接到电视或投影仪上.

苹果电脑使用MOS科技公司(创始人来自于摩托罗拉)的微处理器6502,见下图

 

另一条主线,微软的产生.

Altair 8800(牛朗星)1974年面世,比尔盖茨与保罗艾伦因主动为它编写BASIC程序而出名.

这种机器也没有显示器,而且没有键盘,只有开关与指示灯,输出结果只有看哪些灯亮了

 

最后奉上一些珍贵老照片:

摩托罗拉公司的移动电话早期产品,大家应该在电影中已看到过多次了,比如二战,越战.

Intel 4004微处理器

苹果早期的智能手机
牛顿.

另外乔布斯很注重面子与名利.

乔布斯与比尔,后者是很历害的软件开发工程师,它开发了mac电脑上的图形编辑软件MacPaint,PhotoShop中常见的马蚁线效果就是它的发明.

MacPaint 软件的工具栏,微软的画图工具,Photoshop都是仿制品.

….

 


发表在 计算机与 Internet | 一条评论

怀旧

作者:不及格的程序员-八神

我是一个怀旧的人,喜欢回忆过去,记忆中的过去总是美好的

那时的天空总是很蓝.

小时候兜里根本没钱,有一毛两毛的就不错了,最便宜的小食品是汽水糖,一分钱一个.

还有一个叫蜜桃精的袋装糖品,现在已找不到它的样子.但是袋子里还有各式各样的小勺还是能找到的.

能吃上这种两色两味的小人雪糕,更是有钱人家的孩子能做的.

在小的时候一般都照过这样的"艺术照"

上学之后,小学课本,这一课大家都不会忘吧

在同学间流行的东西彩笔(我没有过,买不起),日记(女生写的比较多).

 

作为一个程序员,我要回忆的过去还包括:

格蕾丝·赫柏,它发现了第一只bug.

斯蒂夫·盖瑞·沃兹尼亚克,是它制造了苹果I,II型个人电脑,并且为它写了BASIC解释器.甚至蓝盒子与电视干扰器,它是个软硬全才.而乔布斯只能说是个滑头儿而已.(看来有点技术崇拜)

微软,先后与apple,ibm合作,树立了商业地位.bill gates 最聪明的小屁孩儿.

ABOBE公司,来自施乐的两个老头约翰与杰西卡.(施乐非常神奇,里面有许多高人,查尔斯-西蒙尼,恩格尔巴特,而且这里才是图形化电脑的发源地,乔布斯"偷"了它.)

公司创立时,乔布斯来参观,并谈谈合作的事情

 

还有IBM公司(通过收够成为真正的计算机公司),Intel公司(开始是卖内存条的),摩托罗拉(开始是做收音机的),仙童(里面的高人更多),康柏(依靠Intel386处理器的兼容机一路走红)…

发表在 生活 | 留下评论