VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 42576|回复: 89

最简单的VB动态调用外部函数(附源代码)

[复制链接]
 楼主| 发表于 2008-5-7 22:52:21 | 显示全部楼层 |阅读模式
 此帖为
http://www.vbgood.com/viewthread.php?tid=69444&extra=page%3D1
的源代码


实现思路:
我是个懒人,我的目标就是干最少的活,完成最多的事情。
当我看到网上那么多帖子中讨论的方法都很麻烦时,我觉得应该有更简单的办法。
调用api其实就是call过去,我的第一反应是:
建一个空的function。
得到api的入口,然后复制代码,覆盖掉我的function。
执行我的function就等于执行了api。

但仔细一想不行,很多api会jmp +xxx,这样的话,我不能保证把jmp到的代码都复制下来
如果自己检测jmp,会变得很麻烦。

那么如果复制代码不行,那我不复制行不行?
接下来很容易就想到了,为什么不改写我的function,让他直接跳转到api呢?
好像可以耶~call不行,因为会有压栈动作,我这个汇编盲这点还是知道的。
那么就jmp吧……最近看api hook看得太多了,经典的5个字节。
jmp的好处多多,没有任何多余动作,参数完整保留到jmp目的地。

问题又来了,怎么才可以知道我的function在哪里呢?
容易,经常用到回调函数的朋友一定知道Addressof操作符吧,它的作用就是返回函数的入口。
但是vb里面是不能直接使用a=Addressof b的,必须在函数中调用。那么我们就走个弯路:
a=Clng("&H" & Hex(Addressof b))
把Addressof b当作参数传给Hex函数就可以了,得到16进制,然后再用Clng转换成10进制。
这样就得到了b函数的地址了。
那么接下来就容易了,只要在a地址处写入5个字节就行了,具体哪五个字节其实我也不知道,
我随便找了个程序,od载入一下,找了个jmp看一下16进制代码,明白了,原来是E9啊。
后面4个字节容易,算一下就行了。它=目标地址-E9的地址-5。

好了,问题基本解决。那么参数呢?走一步算一步吧,实验对象经典的MessageBoxA
4个参数。那么我就新建一个模块,输入2行代码:
Public Function myFunc(ByVal a As Long = 0, ByVal b As Long = 0, ByVal c As Long = 0, ByVal d As Long = 0) As Long
End Function
再来个主窗口:
text1=Clng("&H" & Hex(Addressof myFunc))
再来个按钮:
call myFunc(0,0,0,0)

编译,od载入,ctrl+g到text1里显示的地址,哈哈
xor eax,eax
ret
nop
还真简单,od里at MessageBoxA,然后记下MessageBoxA的地址,
返回myFunc地址,把原来的代码修改成jmp MessageBoxA-myFuc -5。
回到程序里点按钮,哈哈,msgbox出现了。

接下来就容易了,先测试下传参数怎么样。
call myFunc(me.hwnd, strptr("123"),strptr("456"),0)
因为myFunc的原型4个参数都是byval的long,而MessageBoxA的2、3个参数是字符串指针,
所以我就用strptr得到字符串的地址,然后传过去,就不会有问题了。
执行一下,果然没错。

再来看看多个参数怎么办。我想到了Optional,这样就可以不用管参数个数了。
因为如果有2个必选参数,4个Optional参数,那么你传2个参数进去,后面的4个参数因为不存在就不会压栈,
如果api有3、4、5、6个参数,我只要按参数个数传就可以了,少于myFunc的参数会自动省略掉。

试验一下吧:
改成
Public Function myFunc(Optional ByVal a As Long = 0, Optional ByVal b As Long = 0, Optional ByVal c As Long = 0, _
                       Optional ByVal d As Long = 0, Optional ByVal e As Long = 0, Optional ByVal f As Long = 0) As Long

End Function
其他不变。。。执行一下看看,omg,成功了,哈~
写上10个参数,应该可以应付任何api了吧?

哈哈,那么到这里原理大家都明白了吧?
至于如何写入那5个字节的jmp就随意了,CopyMemory和WriteProcessMemory都可以
我的程序用的是WriteProcessMemory,用起来顺手。
剩下的大家就看源代码吧~实现的核心代码其实就8行

最后弱弱的问一下。。。这帖子加精够不够格?

[ 本帖最后由 reker 于 2008-5-7 23:13 编辑 ]

vb动态api.rar

2.38 KB, 下载次数: 2351

点评

不如将Clng("&H" & Hex(Addressof b)) 改为Val(Addressof b)  发表于 2011-7-19 10:33

评分

参与人数 28威望 +135 金钱 +38 人气 +12 收起 理由
ghostelove + 1 赞一个!
刘国华 + 1 赞一个!
ls645618331 + 5 + 1 精品文章。
19900603 + 10 + 3 经典有型,不顶不行
dahual + 5 分加迟了。。。
yrsaini + 1 ok
h907308901 + 1 + 1 好帖必须加分
xingjing + 5 + 1 虽然以前看过 现在想用 才知道那是多少的重
新林 + 4 + 1 学习了~~~
chunyangsuhao + 1 -1 广告/SPAM
happynight + 1 + 1 我很赞同
vbdeBug + 1 精品文章
yesong + 5 精品文章
hehao_00 + 8 yeah
FlamesHsu + 5 + 1 我很赞同
枫叶永恒 + 5 精品文章
八戒2 + 10
随风逐流 + 5 不需要理由吗?
Jerry74 + 5 + 1 需要理由吗
bhmeimei + 2 + 1 下载了就该评
VBProFan + 22 + 38 原创内容 + 精品文章
qaz003 + 2 谢谢分享,一定要加分~~
youhm + 10 我很赞同
suanzi + 5 精品文章
startbin321 + 5 我很赞同
icesboy + 5 您必须输入理由才能进行操作
dolphins + 2 发布源码
我不是西门 + 5 精品文章

查看全部评分

发表于 2008-5-7 22:56:18 | 显示全部楼层
sf?
看之前来顶顶
仔细看完还回来顶的
回复 支持 反对

使用道具 举报

发表于 2008-5-7 23:05:04 | 显示全部楼层
真的厉害,确实称的上最简单的动态调用了。加分加分!!!
不过我今天的用完了,只能加5了,呵呵。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-7 23:10:21 | 显示全部楼层
原帖由 我不是西门 于 2008-5-7 23:05 发表
真的厉害,确实称的上最简单的动态调用了。加分加分!!!
不过我今天的用完了,只能加5了,呵呵。

明天再加,我不介意的,呵呵。
回复 支持 反对

使用道具 举报

发表于 2008-5-8 08:23:29 | 显示全部楼层
晕,你不是号称一点汇编都不用的么?
与其这样还不如 CallWindowProc 了,参数可以任意多。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-8 09:55:34 | 显示全部楼层
原帖由 FlowerCode 于 2008-5-8 08:23 发表
晕,你不是号称一点汇编都不用的么?
与其这样还不如 CallWindowProc 了,参数可以任意多。

同志,虽然你是高手,本人也很佩服你,
但是,请看完帖子再做评论,谢谢。
同样两个人,个人就比较欣赏icesboy同志。

我的这个方法参数可以达到n个,而不会有任何效率问题产生,速度和你用vb调用自己的函数是一样的
参数压栈是由vb自己完成的。我就改了5个字节的jmp而已。

由vb:
push xxxxx
call myFunc
xor eax,eax
ret

变为vb:
push xxxxx
call myFunc
jmp api

api:
xxxxxxx
ret

评分

参与人数 1威望 +2 收起 理由
qaz003 + 2 呵呵,这个好~~

查看全部评分

回复 支持 反对

使用道具 举报

发表于 2008-5-8 10:39:31 | 显示全部楼层
晕,那么多Optional看了就头疼,你咋不用ParamArray呢,这样可对付N多个参数
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-5-8 10:48:58 | 显示全部楼层
原帖由 dolphins 于 2008-5-8 10:39 发表
晕,那么多Optional看了就头疼,你咋不用ParamArray呢,这样可对付N多个参数

ParamArray?我以前都不知道有这个东西,后来昨天在论坛里看到过一次..然后试了一下,貌似不行....
那么多Optional反正就是复制粘贴.....,而且那个模块就这2行代码,一个Private xxx,一个end function
写完了就不用管了。。。。。扔到角落里面去就好了
回复 支持 反对

使用道具 举报

发表于 2008-5-8 13:19:42 | 显示全部楼层
但是vb里面是不能直接使用a=Addressof b的,必须在函数中调用。那么我们就走个弯路:
a=Clng("&H" & Hex(Addressof b))


这个弯路太弯了。。。可以定义 f(x)=x 来解决。。

至于如何写入那5个字节的jmp就随意了,CopyMemory和WriteProcessMemory都可以


CopyMemory 不可以。貌似执行区域默认不可写。

真的厉害,确实称的上最简单的动态调用了。加分加分!!!


同意。。

晕,你不是号称一点汇编都不用的么?
与其这样还不如 CallWindowProc 了,参数可以任意多。


在某种程度上同意。。不过这样又慢了。。

直接改内存的问题则是 IDE 兼容性。

后面的发言不做评论。。。
回复 支持 反对

使用道具 举报

发表于 2008-5-8 13:48:06 | 显示全部楼层
至于如何写入那5个字节的jmp就随意了,CopyMemory和WriteProcessMemory都可以
CopyMemory 不可以。貌似执行区域默认不可写。


刚看到 VirtualProtect 这个函数。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2022-7-4 23:03

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表