Chinaunix
标题:
修改被调用函数的参数值
[打印本页]
作者:
hitty
时间:
2010-11-06 17:25
标题:
修改被调用函数的参数值
本帖最后由 hitty 于 2010-11-09 10:46 编辑
int main()
{
char str[] = "1234567";
*((int*)str-6)=str;
t("abc");
printf("\n%p\n",(int*)str-6);
return 0;
}
void t(char s[])
{
printf("%p,%s\n",&s,s);
}
复制代码
win32下调试了一下
*((int*)str-6) 的地址和 t函数中的的s地址一样
而在main中修改了这个地址的值,地址是完全对应,但printf结果还是abc
作者:
hitty
时间:
2010-11-08 09:07
作者:
hellioncu
时间:
2010-11-08 09:25
“abc”是个字符串常量,优化的缘故?
作者:
hitty
时间:
2010-11-08 11:56
如果是常量,那么应该是非法访问写入,但程序正常运行
希望更多牛人解答一下
作者:
还魂僵尸
时间:
2010-11-08 16:58
Linux(Ubuntu 10.10) i386环境
两个地址不一样~
作者:
jimmyixy
时间:
2010-11-08 17:27
vc 下不一样too
作者:
hitty
时间:
2010-11-09 10:46
冒死再顶一下,楼上两位在不同的环境下
*((int*)str- n 找准一下 可能是4或者3
作者:
hitty
时间:
2010-11-09 11:30
大家可能会觉得很奇怪,应该说还是一名C语言新手,为什么老是问这样的问题,
但是我觉得C语言的基本就是指针,地址的天下,搞清了它们,C语言就可以说找到门道了,
学习靠的是方法,写代码的同时还要知道为什么,
譬如这个问题就和它们息息相关,希望高人不惜赐教.
作者:
BJSH
时间:
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的原因, 你忽视了 先后。。
作者:
lenky0401
时间:
2010-11-10 08:54
多磨叽一点 地址也不是那么容易被猜到的 否则程序就太不安全了
可以google一下Address space layout randomization
作者:
hitty
时间:
2010-11-12 17:57
LZ的想法还是好的
确实C语言里, 一定要把指针的地址搞通,
同时程序运行空间结构, 以及汇编之类了解 ...
BJSH 发表于 2010-11-09 17:46
非常感谢
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2