免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5017 | 回复: 10
打印 上一主题 下一主题

修改被调用函数的参数值 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-06 17:25 |只看该作者 |倒序浏览
本帖最后由 hitty 于 2010-11-09 10:46 编辑

  1. int main()
  2. {
  3.     char str[] = "1234567";
  4.     *((int*)str-6)=str;
  5.     t("abc");
  6.     printf("\n%p\n",(int*)str-6);
  7.     return 0;
  8. }


  9. void t(char s[])
  10. {
  11.     printf("%p,%s\n",&s,s);
  12. }
复制代码
win32下调试了一下

*((int*)str-6) 的地址和 t函数中的的s地址一样
而在main中修改了这个地址的值,地址是完全对应,但printf结果还是abc

论坛徽章:
0
2 [报告]
发表于 2010-11-08 09:07 |只看该作者

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
3 [报告]
发表于 2010-11-08 09:25 |只看该作者
“abc”是个字符串常量,优化的缘故?

论坛徽章:
0
4 [报告]
发表于 2010-11-08 11:56 |只看该作者
如果是常量,那么应该是非法访问写入,但程序正常运行

希望更多牛人解答一下

论坛徽章:
0
5 [报告]
发表于 2010-11-08 16:58 |只看该作者
Linux(Ubuntu 10.10) i386环境

两个地址不一样~

论坛徽章:
0
6 [报告]
发表于 2010-11-08 17:27 |只看该作者
vc 下不一样too

论坛徽章:
0
7 [报告]
发表于 2010-11-09 10:46 |只看该作者
冒死再顶一下,楼上两位在不同的环境下
*((int*)str- n 找准一下 可能是4或者3

论坛徽章:
0
8 [报告]
发表于 2010-11-09 11:30 |只看该作者
大家可能会觉得很奇怪,应该说还是一名C语言新手,为什么老是问这样的问题,
但是我觉得C语言的基本就是指针,地址的天下,搞清了它们,C语言就可以说找到门道了,
学习靠的是方法,写代码的同时还要知道为什么,
譬如这个问题就和它们息息相关,希望高人不惜赐教.

论坛徽章:
0
9 [报告]
发表于 2010-11-09 17:46 |只看该作者
LZ的想法还是好的
确实C语言里, 一定要把指针的地址搞通,
同时程序运行空间结构, 以及汇编之类了解后, 你会有更深刻的认识。

至于*((int*)str-6) 这个位置, 不同的系统包括总线位数不同, 不同的编译器, 甚至是同一编译器的
不同版本, 都有可能是不同的。

gcc -S 后看一下函数t:

.globl t
        .type   t, @function
t:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        movl    8(%ebp), %eax
        movl    %eax, 8(%esp)
        leal    8(%ebp), %eax
        movl    %eax, 4(%esp)
        movl    $.LC3, (%esp)
        call    printf
        leave
        ret

简单的看一下t这个函数, 你本意想要改的无非是t函数中, 调用printf 之前的8(%esp) 的位置

即使你的偏移计算正确, 在调用t之前修改了这个位置, 实际上调用t的过程是:

把参数放在了 call t 时的 (%esp) 处
进入t函数后,
movl    8(%ebp), %eax
movl    %eax, 8(%esp)

s在t中的堆栈位置, 会被重写。


so 。。 即使你之前的 偏移 计算正确, 编译器也会在调用函数时给你重写掉

这是为啥还是输出abc的原因, 你忽视了 先后。。

论坛徽章:
0
10 [报告]
发表于 2010-11-10 08:54 |只看该作者
多磨叽一点 地址也不是那么容易被猜到的 否则程序就太不安全了
可以google一下Address space layout randomization
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP