C/C++知识点之C语言花式玩法之把函数拷贝到数组执行 (需要mprotect)
小标 2018-09-19 来源 : 阅读 1460 评论 0

摘要:本文主要向大家介绍了C/C++知识点之C语言花式玩法之把函数拷贝到数组执行 (需要mprotect),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了C/C++知识点之C语言花式玩法之把函数拷贝到数组执行 (需要mprotect),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

在阅读内核代码的时候,明白了内核是通过页表项中的标志位_PAGE_READ,_PAGE_WRITE,_PAGE_EXECUTE来区分页的权限的。
进程在内核中的地址空间代码段,数据段,堆,栈之间最大的区别也是权限的区别,而系统调用mprotect恰好是用来改变内存页的权限的。
是否可以通过mprotect可以把栈上的数组修改成可执行权限,然后把函数内容拷贝到数组执行呢?值得尝试一下:

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 #include 
 6 #include 
 7 #include 
 8 
 9 int m_add(int i)
10 {
11         return i+10;
12 }
13 
14 int show_map()
15 {
16         char command[256];
17         sprintf(command, "cat /proc/%d/maps", getpid());
18         system(command);
19 }
20 
21 int main()
22 {
23         int (*func_p)(int);
24         int size;
25         int ret;
26         char m[1000];
27         size = (char *)show_map - (char *)m_add;
28         printf("size = %d\n",size);
29         func_p = m;
30 
31         ret = mprotect((void *)((long)func_p&(~0XFFFUL)), 4096, PROT_READ|PROT_WRITE|PROT_EXEC);
32         if(ret < 0){
33                 perror("mprotect: ");
34                 exit(ret);
35         }
36 
37         memcpy(func_p,m_add,size);
38 
39         printf("m_add(24) = %d\n",m_add(24));
40         printf("func_p(63) = %d\n",func_p(63));
41         printf("m_add = %p, func_p = %p\n", m_add, func_p);
42         show_map();
43         return 0;
44 }

执行结果:

size = 15
m_add(24) = 34
func_p(63) = 73
m_add = 0x561528db08c0, func_p = 0x7ffd4c19e300
561528db0000-561528db1000 r-xp 00000000 fe:01 477434                     /home/test/a.out
561528fb0000-561528fb1000 r--p 00000000 fe:01 477434                     /home/test/a.out
561528fb1000-561528fb2000 rw-p 00001000 fe:01 477434                     /home/test/a.out
5615298e7000-561529908000 rw-p 00000000 00:00 0                          [heap]
7fcc3280c000-7fcc329a1000 r-xp 00000000 fe:01 329984                     /lib/x86_64-linux-gnu/libc-2.24.so
7fcc329a1000-7fcc32ba1000 ---p 00195000 fe:01 329984                     /lib/x86_64-linux-gnu/libc-2.24.so
7fcc32ba1000-7fcc32ba5000 r--p 00195000 fe:01 329984                     /lib/x86_64-linux-gnu/libc-2.24.so
7fcc32ba5000-7fcc32ba7000 rw-p 00199000 fe:01 329984                     /lib/x86_64-linux-gnu/libc-2.24.so
7fcc32ba7000-7fcc32bab000 rw-p 00000000 00:00 0
7fcc32bab000-7fcc32bce000 r-xp 00000000 fe:01 329980                     /lib/x86_64-linux-gnu/ld-2.24.so
7fcc32dbc000-7fcc32dbe000 rw-p 00000000 00:00 0
7fcc32dcb000-7fcc32dce000 rw-p 00000000 00:00 0
7fcc32dce000-7fcc32dcf000 r--p 00023000 fe:01 329980                     /lib/x86_64-linux-gnu/ld-2.24.so
7fcc32dcf000-7fcc32dd0000 rw-p 00024000 fe:01 329980                     /lib/x86_64-linux-gnu/ld-2.24.so
7fcc32dd0000-7fcc32dd1000 rw-p 00000000 00:00 0
7ffd4c17e000-7ffd4c19e000 rw-p 00000000 00:00 0
7ffd4c19e000-7ffd4c19f000 rwxp 00000000 00:00 0                          [stack]
7ffd4c1e1000-7ffd4c1e3000 r--p 00000000 00:00 0                          [vvar]
7ffd4c1e3000-7ffd4c1e5000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

可以看到,函数指针func_p实际指向的是char数组m[1000]的地址,其值为0x7ffd4c19e300 确实位于栈7ffd4c19e000-7ffd4c19f000上面,而其成功的执行了+10的操作,返回了正确结果。
这个例子没有实际应用价值,一旦函数中存在库函数的调用,一般就会报错了。
不过它说明了从C语言往下看,栈,堆,数据段,代码段统统都是内存,只要配置相同,相互之间并无本质区别。
C语言是操作内存的语言,在经过操作系统的封装后,它所看到的是无差别的内存。所有的数据类型,你都可以把它们理解成语法糖。
那它和汇编有什么区别?汇编是操作CPU和寄存器的语言,可以访问CPU专有指令,可以访问特定的寄存器,而C语言的初衷,便是抹平体系结构之间的差异。

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程