格式化字符串漏洞实验

格式化字符串攻击原理是利用格式化函数(如printf())的沿着堆栈指针向下打印的特性,通过只提供格式化字符串但不提供对应的变量,读取栈内空间的内容。

更进一步,通过将某个要攻击的目标地址放入栈中,就可以利用格式化字符串读写里面的值。

因此,它的攻击分为两步:

(1)第一步,将目标地址放入栈中;

(2)第二步,设计格式化字符串,读写目标地址里的值。

格式化字符串漏洞是由像 printf(user_input) 这样的代码引起的,其中 user_input 是用户输入的数据,具有 Set-UID root 权限的这类程序在运行的时候,printf 语句将会变得非常危险。

  • 实验一:

找出 secret[1]的值

输入命令:

ls
vi miao.c
gcc -z execstack -fno-stack-protector -o miao miao.c

其中miao.c的代码为

#include <stdlib.h>
#include <stdio.h> #define SECRET1 0x44
#define SECRET2 0x55 int main(int argc, char *argv[])
{
char user_input[100];
int *secret;
long int_input;
int a, b, c, d; /* other variables, not used here.*/ /* The secret value is stored on the heap */
secret = (int *) malloc(2*sizeof(int)); /* getting the secret */
secret[0] = SECRET1; secret[1] = SECRET2; printf("The variable secret's address is 0x%8x (on stack)\n", &secret);
printf("The variable secret's value is 0x%8x (on heap)\n", secret);
printf("secret[0]'s address is 0x%8x (on heap)\n", &secret[0]);
printf("secret[1]'s address is 0x%8x (on heap)\n", &secret[1]); printf("Please enter a decimal integer\n");
scanf("%d", &int_input); /* getting an input from user */
printf("Please enter a string\n");
scanf("%s", user_input); /* getting a string from user */ /* Vulnerable place */
printf(user_input);
printf("\n"); /* Verify whether your attack is successful */
printf("The original secrets: 0x%x -- 0x%x\n", SECRET1, SECRET2);
printf("The new secrets: 0x%x -- 0x%x\n", secret[0], secret[1]);
return 0;
}

编译后进行执行

并定位 int_input 的位置,这样就确认了%s 在格式字符串中的位置

找到输出中和输入相同的数字,这就是int_input在栈中存储的位置。

下面把secret[1]的地址填进去,并打印相应地址中的内容。(记得做进制转换)同时在格式字符串中加入%s,

结果如图

得到输出结果为U,这正是ASCII码中0x55的对应字母

从打印信息中可以发现secret[0]和secret[1]位于堆,即实际地址在堆中。第

一个secret(即变量secret的值)的地址可以在栈中找到,因为变量secret位于栈中。换句话说,如果想重写secret[0],它的地址已经在栈中,格式化字符串可以利用这一信息。然而,

尽管secret[0]就在secret[1]后面, 但在栈中它的地址无效。

修改 secret[1]的值

修改secret[1]的方法非常简单,仅需把前面的%s替换为%n即可,它的功能是将%n之前printf已经打印的字符个数赋值给传入的指针。通过%n我们就可以修改内存中的值了。和%sleak内存一样,只要栈中有我们需要修改的内存的地址就可以使用格式化字符串的漏洞修改它。

修改的结果是,secret[1]综合那个存储前面输出的字符数。

修改 secret[1]为期望值

为了修改secret[1]为期望值,我们只需要控制前面输出的字符数量。对于每个%x,我们可以修改为%0?x来填充前置0,或使用%.?d来控制小数点后的位数,使其总长度达到特定位数。

实验二

现在让我们把第一个 scanf 语句去掉,并去掉与 int_input 变量相关的所有语句,同时设置关闭地址随机化选项。操作如下:



程序将一个格式化字符串写入了一个叫 mystring 的文件,前 4 个字节由任意你想放 入格式化字符串的数字构成,接下来的字节由键盘输入。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
char buf[1000];
int fp, size;
unsigned int *address;
/* Putting any number you like at the beginning of the format string */
address = (unsigned int *) buf;
*address = 0x113222580;
/* Getting the rest of the format string */
scanf("%s", buf+4);
size = strlen(buf+4) + 4;
printf("The string length is %d\n", size);
/* Writing buf to "mystring" */
fp = open("mystring", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fp != -1) {
write(fp, buf, size);
close(fp);
} else {
printf("Open failed!\n");
}
}

修改 secret[0]的值

修改 test.c 后编译 test.c 与 write_string.c 然后通过 write_string 程序将内容输入进 mystring 文件中,文件内容包括代码中加入的头四个字节和你之后输入的内容。实验过程如下:



0x31=49=5*8+5个逗号+开头4个字节。

20169219《Linux内核原理及分析》第十二周作业的更多相关文章

  1. 2018-2019-1 20189221 《Linux内核原理与分析》第八周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第八周作业 实验七 编译链接过程 gcc –e –o hello.cpp hello.c / gcc -x cpp-o ...

  2. 2018-2019-1 20189221 《Linux内核原理与分析》第七周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第七周作业 实验六 分析Linux内核创建一个新进程的过程 代码分析 task_struct: struct task ...

  3. 2018-2019-1 20189221 《Linux内核原理与分析》第六周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第六周作业 实验五 实验过程 将Fork函数移植到Linux的MenuOS fork()函数通过系统调用创建一个与原来 ...

  4. 2018-2019-1 20189221《Linux内核原理与分析》第五周作业

    2018-2019-1 20189221<Linux内核原理与分析>第五周作业 实验四 实验过程 当用户态进程调用一个系统调用时,cpu切换到内核态并开始执行一个内核函数. 在Linux中 ...

  5. 2018-2019-1 20189221《Linux内核原理与分析》第三周作业

    2018-2019-1 20189221<Linux内核原理与分析>第三周作业 实验二 完成一个简单的时间片轮转多道程序内核代码 实验过程 在实验楼中编译内核 编写mymain.c函数和m ...

  6. 2019-2020-1 20199329《Linux内核原理与分析》第十三周作业

    <Linux内核原理与分析>第十三周作业 一.本周内容概述 通过重现缓冲区溢出攻击来理解漏洞 二.本周学习内容 1.实验简介 注意:实验中命令在 xfce 终端中输入,前面有 $ 的内容为 ...

  7. 2019-2020-1 20199329《Linux内核原理与分析》第十一周作业

    <Linux内核原理与分析>第十一周作业 一.本周内容概述: 学习linux安全防护方面的知识 完成实验楼上的<ShellShock 攻击实验> 二.本周学习内容: 1.学习& ...

  8. 2019-2020-1 20199329《Linux内核原理与分析》第八周作业

    <Linux内核原理与分析>第八周作业 一.本周内容概述: 理解编译链接的过程和ELF可执行文件格式 编程练习动态链接库的两种使用方式 使用gdb跟踪分析一个execve系统调用内核处理函 ...

  9. 2019-2020-1 20199329《Linux内核原理与分析》第七周作业

    <Linux内核原理与分析>第七周作业 一.本周内容概述: 对Linux系统如何创建一个新进程进行追踪 分析Linux内核创建一个新进程的过程 二.本周学习内容: 1.学习进程的描述 操作 ...

  10. 2019-2020-1 20199329《Linux内核原理与分析》第六周作业

    <Linux内核原理与分析>第六周作业 一.本周内容概述: 学习系统调用的相关理论知识,并使用库函数API和C代码中嵌入汇编代码两种方式使用getpid()系统调用 学习系统调用syste ...

随机推荐

  1. scrapy入门实践1

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 这就是整个Scrapy的架构图了: 各部件职能: Scrapy ...

  2. Makefile生成

    安装:sudo yum install automake使用: 1 运行autoscan生成两个文件:autoscan.log和configure.scan.将configure.scan重命名为co ...

  3. GXT4.0 BorderLayoutContainer布局

    T字型布局. @Override public void onModuleLoad() { BorderLayoutContainer con = new BorderLayoutContainer( ...

  4. FMDB是iOS平台的SQLite数据库框架

    1.FMDB简介 什么是FMDBFMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 为什么使用FMDB使用起来更加面向对象,省去了很多麻烦.冗余的C语言 ...

  5. 用IntelliJ IDEA建maven项目,如何解决main下无法创建java源文件

    一.缺少java源文件 如下图: 现在想要在main下面增加java源文件,效果图如下所示: 首先,在main目录下新建java文件夹,就是源文件目录, 然后,右键,选择Mark Directory ...

  6. vue日常练习一

    <html lang="en"> <head> <meta charset="UTF-8"> <title>Ti ...

  7. Android Binder 系统学习笔记(一)Binder系统的基本使用方法

    1.什么是RPC(远程过程调用) Binder系统的目的是实现远程过程调用(RPC),即进程A去调用进程B的某个函数,它是在进程间通信(IPC)的基础上实现的.RPC的一个应用场景如下: A进程想去打 ...

  8. xcode中用pods管理第三方库<转>

    安装pods :http://www.cnblogs.com/wangluochong/p/5567082.html 史上最详细的CocoaPods安装教程 --------------------- ...

  9. Anaconda 安装教程(Win10环境) Tensorflow安装

    序 Python易用,但用好却不易,其中比较头疼的就是包管理和Python不同版本的问题,特别是当你使用Windows的时候.为了解决这些问题,有不少发行版的Python,比如WinPython.An ...

  10. 【WebRTC】术语

    WebRTC,名称源自网页实时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API.它于2011年6月1日开源并在Goog ...