如何用汇编实现C语言函数调用

请教一个模拟C语言函数调用的过程:
现在我们知道C函数的入口地址,知道函数参数的起始地址和长度,但不知道这个
参数列表本身,我们要调用这个C函数,并把返回值放在指定的返回值起始地址中
,已知这个返回值的长度,但并不知道返回类型

体系是Intel 64位机,编译器是gcc。

多谢各位大侠了!

#include <stdio.h>

struct args {
int a;
float b;
};

int func(int a, float b) {

printf("a = %d, b = %f\n", a, b);

return a;
}

int main() {

// Now we know a function pointer 'func' but we don't know the argument
list
// And we have a pointer of struct args but we don't know it's member
either
// Q: How can we call 'func' ?

struct args arg_list;
arg_list.a = 5;
arg_list.b = 6.5;
void *arg_list_p = &arg_list;
size_t arg_list_len = sizeof(struct args);

int ret;
size_t ret_sz = sizeof(int);
void *ret_p = &ret;

// You have: the function pointer "func", the start address of arguments
"arg_list_p",
// the size of the arguments "arg_list_len", the return address of
"ret_p"
// the size of the return value "ret_sz"

// Add your code here
}
感谢 下一个往站ex 网友的回答。但我没有描述清楚我的问题。 我的目的是,用汇编实现调用,而不是func本身。

我实现了一段 AT&T 格式的汇编码,但是一直有segment fault:

__asm__ __volatile__(
"push %%rbp;"
"mov %%rsp, %%rbp;"
"push %%rsi;"
"push %%rdi;"
"sub %3, %%rsp;"
"mov %%rsp, %%rdi;"
"mov %4, %%rsi;"
"mov %3, %%rcx;"
"rep movsb;"
"call *%2;"
"mov %%rax, %1;"
"add %3, %%rsp;"
"pop %%rdi;"
"pop %%rsi;"
"mov %%rbp, %%rsp;"
"pop %%rbp;"
: "=r"(ret)
: "r"(ret), "r"(func_ptr), "r"(arg_list_len), "r"(arg_list_p)
: "memory"
);

出错原因可能是SP赋值不正确

1。对于“汇编调用”:
我知道你要调用func,而不是它本身,但如果这个函数比较复杂时是必须用逆向先分析func这个函数,然后再确定参数列表和返回值的……

2。对于你的内联汇编的代码:
这里到底要不要用add %3, %%rsp;还是一个问题,因为要看函数使用的是什么调用标准,有标准C的,VB的,Pascal的,包括fastcall,stdcall,cdecl等……

3。对于“知道函数参数的起始地址和长度”:
这个的话,除了参数中有字符数组和直接结构体什么的,所有的基本变量基本都是每8字节(64位)一个,并且Intel一般都用bigendian的,也就是说,在内存中 01 02 03 04 05 06 07 08 读入寄存器后会变为: 0x0807060504030201
所以说对于简单的函数,用8字节一个参数来做就好了……
而对于有字符数组什么的就必须用逆向分析了……

这个……只能进行逆向分析了……
反正你知道了函数的地址和长度……
就是你把编译为机器码的程序用反编译工具翻译成汇编,然后分析一下就好了,C语言的汇编还是比较简单……
比如这个函数:
int func(int a, int* b) {
// float要用到CPU的FPU,指令记不得,要查下
// 为了简单就改为int*
printf("a = %d, b = %d\n", a, *b);
return a;
}
编译成机器码后,反编译,如果不加优化,一般都会这样:
(假设函数入口地址为0400000h)
sub_0400000:
push rbp
mov rbp,rsp ; C函数参数度取使用堆栈式

; 参数在内存中这样: |...| a | b | ... |
; 由于是64位,故8字节对齐
mov rax,[rbp+8] ; rax = *(rbp+8) // 这里就是 rax = a
push rsi
mov rsi,[rbp+16] ; rsi = *(rbp+16) // rsi = b

; 调用C函数都是这样堆栈式,最后一个参数最先入栈
push [rsi]
push rax
push "a = %d, b = %d\n" ; 这里是便于理解,实际上是push这个字符串常量的指针
call printf ; printf("a = %d, b = %d\n",rax,*rsi)
add rsp,24 ; 平衡堆栈,用了3个参数,要还原3*8=24字节,但根据函数类型的不同去平衡,像调用VB的函数就不需要平衡堆栈……

; 还原数据
mov rsp,rbp
pop rsi
pop rbp

; 一般返回数据都用rax装载
mov rax,[rbp+8] ;rax=a
ret ; return rax

想调用未知参数列表的函数就是把以上过程倒过来,看着汇编把C的代码写出来……
破解注册码什么也是这样玩的……
实际上你可以直接用反编译的软件,比如IDA,直接自动分析,它反编译的虽然是汇编,但参数列表还是大部分都显示的……
但是,当编译器加优化大部分情况就必须自己分析了,因为:
int func(int a, int* b) {
printf("a = %d, b = %d\n", a, *b);
return a;
}
在优化情况下可能为(直接用寄存器传递数据):
sub_040000:
push rdx
mov rdx,rax
push rax
push rbx
push "a = %d, b = %d\n"
call printf
mov rax,rdx
pop rdx
ret

其实像www.pediy.com看雪学院有不少这方面的教程……
温馨提示:内容为网友见解,仅供参考
第1个回答  2010-08-17
逆向分析吧。百度大婶很多类似教材 。自己调试

汇编语言是怎么调用c语言的程序的?
1、 C程序调用汇编程序 汇编程序的设计要遵守ATPCS(ARM—Thumb Procedure Call Standard),保证程序调用时参数的正确传递。在汇编程序中使用EXPORT 伪操作声明本程序,使得本程序可以被别的程序调用。在C程序使用extern声明该汇编程序。下面是一个C程序调用汇编程序的例子。其中汇编程序strcopy实现字符串复制功能...

如何用汇编实现C语言函数调用
我知道你要调用func,而不是它本身,但如果这个函数比较复杂时是必须用逆向先分析func这个函数,然后再确定参数列表和返回值的……2。对于你的内联汇编的代码:这里到底要不要用add %3, %%rsp;还是一个问题,因为要看函数使用的是什么调用标准,有标准C的,VB的,Pascal的,包括fastcall,stdcall,cdecl...

c语言调用其他文件的函数怎么编译
调用函数库的话用#include <XXX.h>或者#include"XXX.h"区别是你库文件放在同一个文件夹还是在IDE的安装目录下面,如果你库文件在你工程文件夹里面用#include<XXX.h>,否则用#include "XXX.h"如果你说自己写库的话是需要两个宏命令,#ifndef _XXX_H #define _XXX_H,然后你函数名用extern表示 ...

汇编怎样调用C
1、需要说明和建立调用者与被调用者间的关系被调用的过程或函数应预先说明为外部类型,如汇编子程序,应用PUBLIC说明其可被外部模块引用;调用程序则应预先说明要引用的外部模块名。2、参数传递问题在汇编子程序之间通常采用寄存器作为参数传递的工具,汇编语言与高级语言程序间的参数传递,一般采用堆栈来传递,即...

单片机汇编语言中怎么实现函数的调用啊?
1要知道程序的入口地址,比如是A,把20h里的值给A,这个不多说:mov a,20h 2 lcall SQT 3 知道程序的出口,比如出口是a,b ,于是,mov 20h,a mov 21h,b ok!

c语言中如何调用汇编程序
1、如果汇编程序是可执行文件,比如exe文件,则可以使用system函数直接调用。比如下面的代码,用system()打开windows上的记事本程序。include include int main(){ system("notepad.exe");return 0;}2、在C语言源码中,可以通过内联汇编来直接编写汇编程序代码。不同的编译器使用内联汇编的方法不同,vc\/...

怎么在汇编中引用c语言的全局变量
最简单的诶办法就是 引用伪变量。比如:unsigned int uni;∶_AX=uni;然后在汇编中直接 取 AX 的值就是了。

C语言和汇编怎样引用对方定义的变量?
C中要使用汇编里面函数的话 需要在汇编里面使用export xxx 导出函数标号 C中加extern xxx汇编要使用C里面的函数的话 需要在汇编里使用import xxx 导入外部标号

c语言里如何调用汇编里的变量
比如说C语言写成dll形式,另的语言调用dll来完成代码共用。要在c语言里调用汇编里的变量,首先要理解汇编里的变量是如何存放的,因为C语言的实现又跟操作系统有关,所以又必须理解C语言在这个系统里是如何实现的。用汇编语言写个call,c语言里按照这个call约定调用这个call,就可以调用call里面的变量了。

汇编与C语言--浅谈汇编如何实现C语言的特性
汇编语言与C语言的互动,通过特定指令和属性进行指导。例如,`#pragma pack(n)`用于指定结构和联合成员的紧凑对齐。若删除`#pragma pack(1)`,则结果是按照最大元素宽度进行对齐,给version分配了两个字节的空间。`__attribute__`用于调整指令对齐方式,例如,改变`align`参数以适应不同需求。这些指令和...

相似回答