Gen's blog

CTFとか、競プロとか、その他諸々

DoubleS1405 CTF Writeup

Harekazeで参加。チームで 881ptを獲得し、順位は 9 位 (得点 130 チーム中)、私はそのうち250pt(+200pt)をとった。

[Rev 100] Exec

PowerPCのバイナリが渡される。powerpc-linux-gnu-objdump で.rodata領域を見ると、flagis_MY_TRAP_CARDという文字列と?\\x148\x05\x16k?7:0\x0d1?(p3"'というバイト列が見つかる。バイナリの中身を読む前にXORを試したらフラグが出てきた。

Flag: Y0u_le4rned_pow3rpc

[Crypto 150] RSA

最初、渡されるスクリプト(の一部)が以下のようになっていたが、明らかに間違っている(recv==encという比較であれば、送られてきたencをそのまま渡せばよい)ので、enc_dataもしくはSECRET_LOGIC()を行う前のデータとの比較であると想定した。

これは後ほど修正があった様子。

if True:
    enc_data = SECRET_LOGIC()
    enc = powmod(enc_data, e, n)
    conn.send("enc : %d\ne : %d\np : %d\nq : %d\n" % (enc, e, p, q))

    recv = conn.recv(1024)

    if end - start > 1:
        conn.send("time out")
        conn.close()

    if recv == enc:
        conn.send(FLAG)
        conn.close()

    conn.send("wrong")
    conn.close()

else:
    conn.close()
    print "error"

enc, e, p, qが送られてくるので、復号することは容易だが毎回送られてくるデータは異なる。そのうちの1つに着目すると、

復号結果: 8755777115341080594761456402455437710685895952551191971666112763595998769587018749591234410595235907226473499074309848886437298673992843291278177512204044380308909676435457547909426657896511491773395035272677030211195668187992227281682442084623728957

これを16進数に変換後、hexstringとみなしてデコードした結果: NDU0NDM4NTQ2OTA1MzQxNjQ5NTY4MDE1MzY4Njk5MDAyNzY5MTgxODYyNTYyNjEwNDI0OTI4MzAxNzMwNjA3MzczMTI3ODM4OTEwNjA=

さらにこれをbase64とみなしてデコードした結果: 45443854690534164956801536869900276918186256261042492830173060737312783891060

これを16進数に変換後、hexstringとみなしてデコードした結果: dxOmJnmqANLoRFzfGpfs1AW74l4VFlzt

というようになっていた。上でいうdxOmJnmqANLoRFzfGpfs1AW74l4VFlztを送り返すとFlagが貰える。

一応、以下のようなスクリプトを書いた。

from pwn import *
from base64 import b64decode
import Crypto.PublicKey.RSA

r = remote('203.251.182.94', 4000)

r.recvuntil('enc : ')
enc = int(r.recvuntil('\n')[:-1])
r.recvuntil('e : ')
e = int(r.recvuntil('\n')[:-1])
r.recvuntil('p : ')
p = int(r.recvuntil('\n')[:-1])
r.recvuntil('q : ')
q = int(r.recvuntil('\n')[:-1])

log.info(enc)
log.info(e)
log.info(p)
log.info(q)

def gcd(a, b):
    while b:
        a, b = b, a%b
    return a

def lcm(a, b):
    return a * b / gcd(a,b)

def gcd2(a, b):
    if b == 0:
        u = 1
        v = 0
    else:
        q = a / b
        r = a % b
        (u0, v0) = gcd2(b, r)
        u = v0
        v = u0 - q * v0
    return (u, v)

d = gcd2(e,lcm((p-1),(q-1)))[0]
rsa = Crypto.PublicKey.RSA.construct((p*q, long(e), d, p, q))

flag = hex(int(b64decode(hex(rsa.decrypt(enc))[2:].decode('hex'))))[2:].decode('hex')
log.info(flag)
r.send(flag)
log.info(r.recv())

Flag: Y34hh_RSA_1S_S0_E4sy

([For 200] AI Mouse)

リンちゃん(@jtwp470)がUSBのパケットを解析->マウスの軌跡を画像化までやってくれていて、ほとんどFlagはとれていた。しかし、字が汚すぎて判別がつかないという問題があり、Flagの読み取りだけお手伝いさせてもらった。(ほとんど漁夫の利みたいな感じになってしまったので、申し訳ない気持ち)

f:id:Gen_IUS:20170330222424j:plain

Flag: c4tch_th3_m0us3!

なんだけど、どう見ても最初のcは大文字だし、最後のが!ってのは無理があると思う…