五、C语言函数的特殊调用方法

楔子:

”就像我们在大学课堂上学的,C语言可以调用,使用起来也很简单。“

//test.cpp
int Five(void){
	return 5;

}
typedef int number_function(void);
int Number;
number_function *Function;

extern "C" int mainCRTStartup(void){
	Function = Five;
	Number = Function();
	return 0;
}

可以看到,我利用typedef关键字获取了number_function的函数签名,这样就能利用别人的签名去调用Five()函数了。效果如下:
在这里插入图片描述
将int Five()函数反汇编后,形成的代码如下。我们知道,机器码是可以被CPU直接执行的,因此我们可以不要函数了,直接用机器码实现函数的功能。具体方法如下:
在这里插入图片描述
方法:
定义一个数组,存储这6个字节{B8 , 05 ,00 ,00 ,00 ,C3}机器码,用无符号数存。
利用typedef获取的函数指针,指向这个字符串,假装字符串是个函数,

结果,报错了,因为这个字符串默认存储在数据段,CPU是不能执行数据的,因此会有个access violation,即使我们告诉CPU这是可执行的。
当然,这也是地址空间布局随机化的缘故(ASLR),那么如何让操作系统把我们的这个字符串标示为可执行段呢?

windows系统提供一个接口,可以让你控制一段存储空间,并把机器代码放到CPU上运行;
接口是VirtualProtect();
VirtualAlloc();
在这里插入图片描述

VirtualProtect可以保存一个页的内存,但是不知道OS分配的页地址在哪里,于是用到了VirtualAlloc();它可让向OS申请一个页的内存,然后用Virtualprotect保证那个内存是安全可执行的。

/*int Five(void){
	return 5;

}
*/
typedef int number_function(void);
extern "C" void _delcspec(dllimport) *VirtualAlloc(
	void *lpAddress;
	unsigned __int64 dwSize;
	int unsigned flAllocationType;
	int unsigned flProtect;
);

int Number;
number_function *Function;

extern "C" int mainCRTStartup(void){
	char unsigned *CodeForFive=(char unsigned *)VirtualAlloc(0,4096,0x00001000,0x40);
	CodeForFive[0]=0xb8;
	CodeForFive[1]=0x05;
	CodeForFive[2]=0x00;
	CodeForFive[3]=0x00;
	CodeForFive[4]=0x00;
	CodeForFive[5]=0xc3;
	


	Function = (number_function *)(&CodeForFive[0]);
	Number = Function();
	return 0;
}

注意,在执行时必须在项目文件里面加上kernel32.dll。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值