格式化字符串实例

实验环境

Ubuntu 16.04 32bits

实验

实验一

vul_formatstr2.c代码:
在这里插入图片描述

编译vul_formatstr2.c:
在这里插入图片描述

用gdb跟踪程序的执行 :
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

栈顶为0xbfffec40,user_input的首地址为0xbfffeb5c,位于栈顶开始的第7个(4字节)单元。

user_input的首地址与栈顶的距离为7个(4字节)单元。

在这里插入图片描述
第七个“%08x”表示第七个格式,代表字符串“ABCD”;
第八个“%08x”表示第八个格式,代表字符串“%08x”。

其中的第7个格式化输出0x44434241就是字符串"ABCD"的十六进制代码。
将"ABCD"替换成要改写的内存地址,并且第7个格式化参数为%n,正确设置第6个格式化参数,就可以改写内存的值。
通常,scanf()会将键盘输入的字符转换成ASCII码再存入,比如输入字符5会存为0x35。若直接通过键盘输入,则需要将地址根据ASCII码反转换成键盘可输入的字符,比如0x31323231的键盘输入是1221。然而问题是ASCII码表中只有128个字符,且0x80之后没有对应的字符,因此无法从键盘输入任意4字节的内存地址。

解决办法是将要输入的数据写入到文件,然后利用命令行的重定向功能,将该文件作为程序的输入。这样一来程序从文件中而不是从键盘中获得输入数据,就避开了任意数字的输入问题。
这里要注意的是scanf把一些特殊数字作为分隔符,如果在scanf里仅有一个“%s”的话,分隔符之后的数据将不会被读取。这些数字为0x0A(新行),0x0C(换页),0x0D(返回),0x20(空格)。在输入文件中要避免使用这些特殊数字。

程序read2file.c从键盘输入4字节和格式化串,并将其存入文件
mystring中。

read2file.c代码:
在这里插入图片描述

……
scanf("%u",&u_addr);	//输入需要改写内容的地址
……
scanf("%s",buf+4);	//输入格式字符串
……

由于地址随机化机制使得vul_formatstr2.c中的变量地址动态变化,为了使实验成功需要关闭地址随机化机制:

sudo sysctl -w kernel.randomize_va_space=0

在这里插入图片描述

假定要修改变量B的内容,设B的地址=0xbfffeca4=3221220516
在这里插入图片描述

因 此 read2file 从 键 盘 输 入 整 数 3221220516 和 格 式 串%08x.%08x.%08x.%08x.%08x.%08x.%08x.

编译read2file.c:
在这里插入图片描述
运行:

在这里插入图片描述
结果,修改成功:
在这里插入图片描述

实验二

改写的值>0xffff时,上述方法不可用。
如果变量的值太大,需要分两次写内存才能避免可能的段错误。

变量B的值改成0xfedcba98:
修改read2file.c为read2file2.c,将输入的“地址”及“地址+2”输入到格式串的前3个(4字节)单元中。

read2file2.c代码:
在这里插入图片描述
编译:
在这里插入图片描述
运行:

在这里插入图片描述
修改成功。

实验三

修改将变量B的值改成0xba98fedc

修改read2file2.c代码:
在这里插入图片描述
编译:
在这里插入图片描述
运行:
在这里插入图片描述
修改成功。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值