はまやんはまやんはまやん

hamayanhamayan's blog

Byte Bandits CTF 2023 (BBCTF 2023) Writeups

[Forensic] Imageception

stringsで見てみるとWindowsのメモリダンプっぽいので、Volatility 3でwindows.infoしてみる。

$ python3 ~/.opt/volatility3/vol.py -f imageception.raw windows.info
Kernel Base     0xf80778a18000
DTB     0x1aa000
Symbols file:///home/eric/.opt/volatility3/volatility3/symbols/windows/ntkrnlmp.pdb/68A17FAF3012B7846079AEECDBE0A583-1.json.xz
Is64Bit True
IsPAE   False
layer_name      0 WindowsIntel32e
memory_layer    1 FileLayer
KdVersionBlock  0xf80779627398
Major/Minor     15.19041
MachineType     34404
KeNumberProcessors      1
SystemTime      2022-12-16 08:28:29
NtSystemRoot    C:\Windows
NtProductType   NtProductWinNt
NtMajorVersion  10
NtMinorVersion  0
PE MajorOperatingSystemVersion  10
PE MinorOperatingSystemVersion  0
PE Machine      34404
PE TimeDateStamp        Wed Jun 28 04:14:26 1995

いい感じに解析できている。Windows 10のメモリダンプっぽい。 windows.pstreeで怪しいものがある。

548  472 winlogon.exe    0xa08f6cf1c080  6   -   1   False   2022-12-16 08:25:52.000000  N/A
* 884   548 dwm.exe 0xa08f6cd80080  17  -   1   False   2022-12-16 08:25:53.000000  N/A
* 3012  548 userinit.exe    0xa08f6e699300  0   -   1   False   2022-12-16 08:26:01.000000  2022-12-16 08:26:25.000000 
** 3044 3012    explorer.exe    0xa08f6e6d6300  86  -   1   False   2022-12-16 08:26:01.000000  N/A
*** 4880    3044    SecurityHealth  0xa08f6e5a22c0  6   -   1   False   2022-12-16 08:26:16.000000  N/A
*** 4448    3044    mspaint.exe 0xa08f6e45b080  8   -   1   False   2022-12-16 08:27:45.000000  N/A
*** 5012    3044    msedge.exe  0xa08f6ed07080  0   -   1   False   2022-12-16 08:26:17.000000  2022-12-16 08:27:40.000000 
**** 4328   5012    msedge.exe  0xa08f6f44f080  41  -   1   False   2022-12-16 08:27:39.000000  N/A
***** 4600  4328    msedge.exe  0xa08f6f3e0080  12  -   1   False   2022-12-16 08:27:39.000000  N/A
***** 5444  4328    msedge.exe  0xa08f6f1a4080  9   -   1   False   2022-12-16 08:27:39.000000  N/A
***** 5164  4328    msedge.exe  0xa08f6ef07080  7   -   1   False   2022-12-16 08:27:39.000000  N/A
***** 5708  4328    msedge.exe  0xa08f6f4da080  16  -   1   False   2022-12-16 08:27:39.000000  N/A
*** 5256    3044    DumpIt.exe  0xa08f6f404080  2   -   1   True    2022-12-16 08:28:27.000000  N/A
**** 4644   5256    conhost.exe 0xa08f6ebb1080  5   -   1   False   2022-12-16 08:28:27.000000  N/A

mspaint.exeが開かれている…
windows.cmdlineを実行してみると

4448 mspaint.exe "C:\Windows\system32\mspaint.exe" "C:\Users\bbctf\Desktop\imageception.png"

この画像を取得することはできないだろうか。
windows.filescanを見てみよう。

0xa08f6ca23200   \Users\bbctf\Desktop\imageception.png   216

ありますね…

python3 ~/.opt/volatility3/vol.py -f imageception.raw windows.dumpfiles --pid 4448 --virtaddr 0xa08f6ca23200 でファイルが落とせてくるので、適当にmv file.0xa08f6ca23200.0xa08f6c9d1350.DataSectionObject.imageception.png.dat imageception.pngとして開くとフラグが書いてある。

[Forensic] Random Requests

プロトコル階層統計を使って記録パケット種別を把握して色々眺めるとhttp && ip.src_host == 10.0.2.15で特徴的なリクエストが見られる。
GET /flag=の後に0か1か%20が記録されている。
時系列順に全部取ってきて、%20を空白ではなく改行にしてみると以下のような感じ。

01011010
01101101
01111000
01101000
01011010
00110011
01110100
...

バイト列を2進数表記したものに見える。
CyberChefのFrom Binaryで変換すると ZmxhZ3tuT1RfU29fcjRuZG9tX2g3N3BfcjNxdTM1dHN9 となる。
雑にCyberChefのMagicを使うとbase64とのことなので、From Base64も追加するとフラグが出てくる。

[Forensic] Vastness of Space

色々試すとexiftoolで情報が出てくる。

$ exiftool Empty_Space.jpg
...
XP Comment                      : The password is "BBCTF"
...

steghideを使うとCSVファイルが得られる。

$ steghide extract -sf Empty_Space.jpg -p BBCTF -xf out.bin
wrote extracted data to "out.bin".

$ file out.bin
out.bin: CSV text

xy座標っぽいのでそれをドットに変換して画像にしてみる。

from PIL import Image

picture = Image.new("RGB", (300, 300), "white")
pixels = picture.load()

with open('out.bin') as fp:
    for line in fp.readlines():
        x = int(line.split(',')[0])
        y = int(line.split(',')[1])
        #print(f'{x},{y}')
        pixels[x,y] = (0, 0, 0, 0)

picture.save("flag.png", "PNG")

するとQRコードが出てくるので復号するとフラグが出てくる。

[misc] Meaning of Life

数字を入れるとシークされたいつもの動画へのURLのbase64エンコード物がもらえる。
何も怪しいところがないので数字を全探索してみる。

import requests
import re
import time

for idx in range(1, 100):
    time.sleep(3)
    r = requests.post('http://misc.bbctf.fluxus.co.in:2002/', data={'key_num': idx}).text
    m = re.findall(r'<p><b>Hash Value : </b> ([^<]*) </p>', r)
    print(f'{idx} -> {m[0]}')

これを動かすと42で雰囲気が変わる。

42 -> aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1GSVViUkprS2psRQ==

実際動画も変わっていて、ピーという音が鳴る動画になる。
雰囲気はモールス信号…

頑張って復号するとCIC4D4FLI35となり、これをflag{}でくるむと正答。

[misc] Peer Pressure

クリックするといつもの動画に飛ばされる。
Burpの履歴を見るとGET /aGVhZA==?が呼ばれている。
aGVhZA==はbase64デコードするとHEADになるので、HEADで呼べばいいのか?
HEAD /aGVhZA==?とすると、レスポンスヘッダーのpngとしてbase64エンコードされた何かが送られてきた。
デコードしてみると普通のpngファイル。

適当にもってきて、試しにexiftoolをしてみるとフラグがあった。
exiftool a.png | grep flag

[misc] Virus Attack

netcatでつないでみるとpythonインタプリターっぽいものが出てくる。

>>> id
<built-in function id>

となるのでpythonインタプリターなのだろう。

>>> system
Sorry You cant write system

怒られた。色々打ってみるとブラックリストがあるみたい。
以下見た禁止文字。多分他にもいろいろある。

system
read
os
import
S

適当にガチャガチャやっているとLFIできることが分かった。
ファイル名をエスパーするとフラグが得られる。
set(open('flag.txt'))

[web] Hi-Score

1秒間に100回クリックできればいいらしい。
クリックしてみると特にリクエストは飛んでいない。
/static/TheScript.jsで色々処理がなされているみたい。

クリックしたときのコードは以下のような感じ。

function Clicks() {
    var _0x287a2f = _0x1a8b;
    if (klicks == 0x0) end = new Date()[_0x287a2f(0x1f5)]();
    (end1 = new Date()[_0x287a2f(0x1f5)]() - end),
        (klicks += 0x1),
        (score = (klicks / end1) * 0x3e8);
    if (score == Infinity) score = 0x0;
    (score = score[_0x287a2f(0x204)](0x3)),
        (document[_0x287a2f(0x1f4)](_0x287a2f(0x1fd))["innerHTML"] =
            _0x287a2f(0x207) + score + _0x287a2f(0x1fc));
    if (score >= 0x64) _0x125e1a();
    else document["getElementById"](_0x287a2f(0x1f8))[_0x287a2f(0x200)] = "";
    function _0x125e1a() {
        var _0x162e81 = _0x287a2f;
        document["getElementById"](_0x162e81(0x1f8))[_0x162e81(0x200)] =
            _0x162e81(0x1fe);
    }
}

特に注目したいのがif (score >= 0x64) _0x125e1a();の部分。
得点が一定以上なら0x125e1aが呼ばれる。
ここで使われている
0x162e81は0x287a2fであり、冒頭を見ると0x1a8bなので、
実行されるのは以下のコードとなる。

document["getElementById"](_0x1a8b(0x1f8))[_0x1a8b(0x200)] = _0x1a8b(0x1fe);

これをChrome Developer ToolsのConsoleで直接動かしてやればフラグへのリンクが出てくる。

[web] Improper Error Handling

適当に入れてみるとError: Length too shortと言われる。
ちょっと伸ばしてみよう。

GET /api/error?length=111111111111111111111111111111111111111111111111 とするとINDhKQiOO28IpK0vqn9xOjc1QOWjL2pXN31IsOTeCOoFT4qE
なんだこれは

適当に長さを調整するとフラグが出てくる
GET /api/error?length=11111111111111111111111111111111