-
用户需要输入一段数据,数据保存在 user_input 数组中,程序会使用 printf 函数打印数据内容,并且该程序以 root 权限运行。更加可喜的是,这个程序存在一个格式化漏洞。让我们来看看利用这些漏洞可以搞些什么破坏。
-
程序说明:
程序内存中存在两个秘密值,我们想要知道这两个值,但发现无法通过读二进制代码的方式来获取它们(实验中为了简单起见,硬编码这些秘密值为 0x44 和 0x55)。尽管我们不知道它们的值,但要得到它们的内存地址倒不是特别困难,因为对大多数系统而言,每次运行程序,这些内存地址基本上是不变的。实验假设我们已经知道了这些内存地址,为了达到这个目的,程序特意为我们打出了这些地址。
有了这些前提以后我们需要达到以下目标: -
找出 secret[1] 的值
-
修改 secret[1] 的值
-
修改 secret[1] 为期望值
注意:因为实验环境是 64 位系统,所以需要使用 %016llx 才能读取整个字。但为了简便起见,对程序进行了修改了,使用 %08x 也能完成实验。
1- 3的十六进制数为0x 000d。十六进制数0xda7017 对应的十进制数是 14315540
wget http://labfile.oss.aliyuncs.com/courses/228/vul_prog.c
编译时可以添加以下参数关掉栈保护。
$ gcc -z execstack -fno-stack-protector -o vul_prog vul_prog.c
$ sudo chmod u+s vul_prog
- 1.运行 vul_prog 程序去定位 int_input 的位置,这样就确认了 %s 在格式字符串中的位置。
12 和后面的 %016llX 都是自己随意输入的, %016llX 的个数最好在10个以上。
12 的十六进制码就是 0x000C ,可以看到输出中 12 的十六进制在第 8 个位置上,这样我们就能确定格式化字符串的位置了。
-
2.输入 secret[1] 的地址,记得做进制转换,同时在格式字符串中加入 %s .
- -
在 %.897u 前有 6 个 64 位地址,每个地址对应 16 个字符,加上逗号一共就是 6*(16+1)=102 ,在 %.897u 后面的地址上还有一个 , 占一个字符。所以一共是 102+1=103 个字符,要改成 1000 的话,我们就还差 1000-103=897 个字符。
把第一个 scanf 语句去掉,并去掉与 int_input 变量相关的所有语句,修改后的 vul_prog.c 程序如下:
/* vul_prog.c */
#include <stdlib.h>
#include <stdio.h>
#define SECRET1 0x44