首页
社区
课程
招聘
如果已知一个函数的地址,如何调用它?
发表于: 2011-10-27 15:51 7589

如果已知一个函数的地址,如何调用它?

2011-10-27 15:51
7589
我想实现一个这样的函数func1:传入任意的函数(pFunc)的地址和这个函数所需的参数(参数不知道具体类型),要怎么调用这个pFunc,并且返回pFunc返回值的地址?
函数原型我设计成这样:void* func1(void* pFunc, ...) 使用可变参数来传入pFunc所需的参数。要如何实现?
汇编和c都可以,谢谢啦!

要求:起码是带伪代码的才给分,如果是汇编的话最好做点注释,我是汇编盲。。。

多谢楼下的热心回复,现在我有点头绪了,但是我还有比较大的疑问:汇编调用函数之前要把所有的参数一个一个push到内存,然后调用call。。。那我可不可以把所有的参数按照函数约定的顺序包装到一块内存,然后整个push一次?这样的话还是用push么?

还有最后一个问题:如何获取可变参数(...)的结束地址?这个应该能获取吧,否则函数返回时如何清理堆栈呢?解决了这个问题就结贴哈。

现在只想到一个很搓的解决方案,在push参数之前先自己获取esp的值,然后fun1的参数里加入这个值作为参数的结束地址,over。

[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (16)
雪    币: 97
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
汇编的话,如果是用固定地址调用(即类似于 call 123456),(物理地址,虚拟地址,要分清点)
如果是C,直接转换成指针,调用。
2011-10-27 16:17
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好的,大哥,我是汇编菜鸟,求代码。。。
还有,在windows下面用call的话需要把虚拟地址转物理地址么?怎么转?
C下面不知道函数的类型,要怎么调用?
2011-10-27 16:23
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
同志们,这么好赚的分数不要让它白白溜掉啊
2011-10-27 16:35
0
雪    币: 343
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
C中不知道函数原型没办法调用的吧?就算是函数指针也是需要知道返回值和传入参数的。
汇编的话依次push后面的变参,然后call pFunc应该可以。但要注意调用约定。
2011-10-27 16:58
0
雪    币: 227
活跃值: (66)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
6
我现在没有编译环境,只能给你个伪代码。具体你还得自己解决
void* func1(void* pFunc, ...)
{
    取得所有变参; //参考http://hi.baidu.com/fffliuwenfei/blog/item/d903646d355fb4ff421694f2.html
int i = 变参总数;
while i > 0 {
__asm push 参数i;
i--;
}
__asm call pFunc
}

细节还得自己改(调用约定要注意)
2011-10-27 16:59
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
参数必须一个一个push么?可是va_arg(...)获取变参的时候要知道变量的类型大小?这个只有调用func1的人是知道的,但是func1本身是不知道的,咋办?
2011-10-27 17:20
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
还有我试了一下,貌似push的值都是int型的才行,如果我直接push一个bool或者short型的参数结果就出错,而且会堆栈溢出;这个push的时候能指定大小么?还是必须都转成int型之后才能push?
push的原理是什么?我可不可以把所有的参数按照函数约定的顺序包装到一块内存,然后整个push一次?这样的话还是用push么?
2011-10-27 17:52
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
fun(1,2,3);
=
push 1
push 2
push 3
call fun
-------------------假装就是这样吧
fun:
pop 3
pop 2
pop 1

push 就是入栈,等(call  地址 )的时候,是修改EIP寄存器,就是程序当前执行的语句地址。call到fun的时候,参数就在栈里,取出来接着用。
你也可以直接把参数定义成全局,那就不用入栈出栈了。
2011-10-27 19:07
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
10
函数调用,不一定要用push 指令,可以用sub 抬栈顶 ESP

mov [esp-4],var1
mov [esp-8],var2
mov [esp-0xb,var3
sub ESP,0B //相当于push 三次
call fooaddress

就可以了,不知道是不是你要的结果。
2011-10-28 02:52
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
[QUOTE=北极狐狸;1014086]函数调用,不一定要用push 指令,可以用sub 抬栈顶 ESP

mov [esp-4],var1
mov [esp-8],var2
mov [esp-0xb,var3
sub ESP,0B //相当于push 三次
call fooaddress

就可以了,不知道是不是...[/QUOTE]

不好意思,这几天在看另一个问题,没关注这帖子,这个方法挺好的,应该能行,但现在还有最后一个问题,如何知道可变参数的结束地址(va_start可以获取起始地址)?这样我就可以把可变参数mov进堆栈了,是吧?
2011-11-2 11:28
0
雪    币: 435
活跃值: (1207)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
12
没有函数原型 只有参数个数
那也得有调用约定啊
stdcall 还是cdecl还是fastcall或者thiscall usercall的就更麻烦了
不知道调用约定,只能逆那个函数看看了
总之不知道调用约定没法调,传参顺序是什么,栈谁来平衡,这都是问题
2011-11-2 12:19
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
调用方式先不管它吧,就当做是stdcall了
2011-11-2 12:32
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
坦白的说我考虑这样的函数是因为想用在多线程到单一线程的转换中。当一个函数被多个线程调用时,先判断是否为函数的工作线程,如果不是就把自己的函数地址和参数发给工作线程,让工作线程来执行它,所以这只是个内部的调用,更不用移植。所以不需要关心调用约定了,呵呵
2011-11-2 12:35
0
雪    币: 227
活跃值: (66)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
15
貌似没有push一块内存这一说
可变参数你百度一下可以找到很详细的解释
2011-11-2 12:48
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
我觉得11楼的解决方案可行,现在就是要找到可变参数的结束地址,然后从开始地址到结束地址整个拷贝到堆栈就可以了吧,百度上介绍可变参数是有的,但是还没找到有说明堆栈中参数下面的是指向哪里如何获取的
2011-11-2 13:59
0
雪    币: 153
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
搜了一下百度,貌似没戏

__cdecl:是C语言采用的默认调用方法,参数按从右到左的顺序压入栈,由调用者把参数弹出栈,它的优点是支持printf这样的可变参数调用。一般可变参数函数的调用都采用这种方式,比如int __cdecl scanf (const char *format,…)。对于"C",修饰名是在函数名前加下划线,如函数void test(void)的修饰名是__test。除非声明为 extern "C",否则 C++ 函数将使用不同的名称修饰方案。
thiscall: 函数体 this指针默认通过ECX传递,其它参数从右到左入栈。thiscall是唯一一个不能明确指明的函数修饰,因为thiscall不是关键字。它是C++类成员函数缺省的调用约定。由于成员函数调用还有一个this指针,因此必须特殊处理。3
thiscall意味着:参数从右向左入栈,如果参数个数确定,this指针通过ecx传递给被调用者;如果参数个数不确定,this指针在所有参数压栈后被压入堆栈。对参数个数不定的,调用者清理堆栈,否则函数自己清理堆栈。

看来C语言设计的时候也没办法知道可变参数的结束地址在哪里
2011-11-2 14:30
0
游客
登录 | 注册 方可回帖
返回
//