之前已经知道了函数这个玩意在计算机中的本质,本身在栈中存放其实就是一个指针的方式,而指针指向的内容就是在内存中存放的机器码。
解释到这里就已经很明显了,函数其实并不是一定要在编译期载入内存后静态,也就是固定的方式运行的。
我们可以手动开辟内存,输入机器码,然后让指针指向这块内存。从而实现在运行时动态生成函数。
哦呼~想想就有点激动,这个逻辑其实就有点像动态语言,例如PHP,JAVA,Python的解释器的工作方式。
而且这个方式可以不用在语言中编写汇编,可以绕过某些平台无法在C中编写汇编的限制。
首先我们得获取机器码,我这里直接通过反汇编直接获取。
1//0x00005555555547a7 <+0>: 55 push rbp
2//0x00005555555547a8 <+1>: 48 89 e5 mov rbp,rsp
3//0x00005555555547ab <+4>: b8 01 00 00 00 mov eax,0x1
4//0x00005555555547b0 <+9>: 5d pop rbp
5//0x00005555555547b1 <+10>: c3 ret
6int ret() {
7 return 1;
8}
然后把这些机器码写进内存, 之后进行类型强转之后,就可以直接运行。
1char ret_code[] = {
2 0x55,
3 0x48, 0x89, 0xe5,
4 0xb8, 0x10, 0x00, 0x00, 0x00,
5 0x5d,
6 0xc3
7 };
8
9 void *tmp = mmap(
10 NULL,
11 getpagesize(),
12 PROT_READ | PROT_WRITE | PROT_EXEC,
13 MAP_ANONYMOUS | MAP_PRIVATE,
14 -1,
15 0
16 );
17
18 memscp3(tmp, ret_code, sizeof(ret_code));
19
20 ret_p p = tmp;
21
22 int bbb = p();
23
24 printf("%d\n", bbb);