m0becのメモ帳

いろいろ書いてきます

SECCON2017 writeup

JPEG file

1bitだけ壊れたJPEGが渡される.JPEGのファイルフォーマットはこちらのサイトを参考にした.
FFで始まる箇所を重点的に調べていくとFF FC となっている箇所があった.FF FCJPEGの拡張のための予備となっているがFE FC に書き換えるとフラグの書いてある画像が出てくる.

Powerful Shell

文字コードをひたすら$ECCONに代入しているps1のソースコードが渡された.実行すると鍵盤が出てきてPlay the secret melodyと言われる.$ECCONに格納された文字列をファイル出力すると、なんとか読めるソースコードが手に入る.secret melodyは

$secret=@(440,440,493,440,440,493,440,493,523,493,440,493,440,349)

となっており、鍵盤に対応する数値は

ForEach($k in ('w','s','e','d','f','t','g','y','h','u','j','k')){
    $keytone+=@{$k=$keytone[$pk]*[math]::pow(2,1/12)};$pk=$k    
}

で決まっている.h,h,j,h,h,j,h,j,k,j,h,j,h,fで次のステージに進める.
次はパスワードを求められる. [System.Text.Encoding]::ASCII.GetString($plain)をファイル出力すると記号まみれのソースコードが手に入る.やり方は変えずに処理の中身をファイル出力していくとパスワードと入力を比べている箇所を見つけられる.

$ECCON=Read-Host -Prompt 'Enter the password'
If($ECCON -eq 'P0wEr$H311'){
    Write-Host 'Good Job!';
    Write-Host "SECCON{$ECCON}"
}

Run me!

以下のコードが渡される.

import sys
sys.setrecursionlimit(99999)
def f(n):
    return n if n < 2 else f(n-2) + f(n-1)
print "SECCON{" + str(f(11011))[:32] + "}"

実行してみても終わる気配がない.再帰が深すぎるのが原因.なので再帰しないプログラムにする.

s1 = 1
s2 = 2
numb = 3
ans = 0
while(1):
    if numb < 11011:
        ans = s1+s2
        s1 = s2
        s2 = ans
        numb += 1
    else:
        break
print s1
print s2
print numb
print str(ans)[:32]

SHA-1 is dead

SHA1衝突を利用する問題.73spica様のサイトを参考に解いてみた.とりあえずSHA-1が同じになるpdfをこちらのサイトで入手し、末尾に同じデータを追加して2017KiB以上になるようにしてから提出するとフラグがもらえた.

Simon and Speck Block Ciphers

Simon and Speck Block Ciphersを使って鍵を見つける問題.Simon and Speck Block CiphersはこちらのGithubのプログラムを利用した.鍵でわからない部分は4文字だけなので総当たりで調べるとcipherとplainが一致する鍵が手に入る.

from speck import SpeckCipher
from simon import SimonCipher

plain = 0x6d564d37426e6e71
cipher= 0xbb5d12ba422834b5

s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_"

for i1 in s:
    for i2 in s:
        for i3 in s:
            for i4 in s:
                key = "SECCON{" + i1+i2+i3+i4 + "}"
                tiny_cipher = SimonCipher(int(key.encode('hex'), 16), key_size=96, block_size=64)
                ans = tiny_cipher.encrypt(plain)
                if ans == cipher:
                    print key

Vigenere3d

ヴィジュネル暗号を二回行っている.鍵は14文字だが一回目と二回目のカギは文字列を反対にしただけであり、abcdefggfedcbaのような鍵で一回変換するのと同じである.また、平文の最初の7文字はわかっているので複合できる.

s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"

p = "SECCON{"
q = "POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9"
key = []

for i in range(len(p)):
    st = s.find(p[i]) - s.find(q[i])
    if st < 0:
        st = st+len(s)
    key.append(st)
for i in range(7):
    key.append(key[6-i])
    
ans = ""
key_num = 0
for i in q:
    n = s.find(i)+key[key_num]
    if n >= len(s):
        n -= len(s)
    ans += s[n]
    key_num = (key_num+1)%14
print ans

CODE BLUE CTF writeup

Common Modulus 1

Common Modulus AttackとはRSA暗号に対して同一の平文に対して同じnを使用し,なおかつ

gcd(e1,e2) = 1

の時に使用できる攻撃方法らしい.平文の生成はc1s1 + c2s2 = 1 を満たすs1,s2を用いると以下の式が成り立つ.

c1^s1*c2^s2 mod n = m mod n

この計算をしてあげれば平文が手に入る.

import gmpy

s1 = 14877
s2 = -14302
c1 = 767202255403494641285723819543278226263601155898823605265497361830705668240032418501494959141449028517100422081272691883369257107388411439611318808983979122090486252578041006071999581282663085495058515958745546211668701835250122032715473014598395050184702983368667972803718169481809394565706175141425650370279775233813674442957760484285820381853600163980060348710028919659329781877491724136976028815641232407109144869660767954119268355348405951052583739555066569345526640029961785158127382321111833599691079949415049786723663210542733655554868327542833053024595895523192888118675763242352407948643537985861448788568550308481655116845634952516676905251579084404308314639717162526798451410767058423619677212069270398132021729448047980766312818656065369023093123058422620085273728481545680423266197847937925342263870309939913221308330842487685037638837340238355192125668409039255551545407800543798158964963358868702135730305156935767426581823180696819366253148799571923731323928995477390559418822575259531941023518182807739949726026157027426545624061195471888653152768495272113769751755053321333829345939391638863918920798107792346015224509118930143010726156407828938941341788657835191853473698010478888928860138978235297618195944868175
c2 = 393205642868817442649216793359718556278406137459770244761832906195960432918468617731069456704644789806507809829093842629745066759599286729538728368882491382997337611417441529220397067642218119525968897551289230558627870154984979444195757677411673096443476021362319325097662392808170632471553717355895219405644518503783235536597143112954291157798713583737689125917709618182162360535659223966858707155741267214975141963463832314566520144602105237041672437684177707624423211972004800873375670613148140256099552724408192217550331987310558991433383571470532995856778764797540637679226825577553396934734325550293550389623919904744913990305949697308222046594160302362669510242921299755255790640101006152269619965560742243168099219363626217512940995615730916134775134764069912120583282148219405178065222313607957426887495658080497917440100549199528894874905968298614233827155712422019324710018755792249855902168601927285980197334672067920857960628679370550895555840658121626134216719240409691397735762685349162277111815727100169755960553688569326705249270662470879197234836585418835845237231721910938341557726245940031873345666571751867755961294973426045629909899256967038811807893676700888551318830676356324765330202998096318754445585853694
n = 791311309087374588934274354916349141233150778762086315374343850126808782284294921228110916322178898551691669133101997907127587121520288166574468605214516304122927763843434653215681360872523253290766297044510870617745122997739814947286892376888776319552516141136363673315815999597035068706744362048480852074989063152333880754375196551355543036200494314973628012006925154168913855587162465714207917714655810265293814697401062934881400969828166519415465439814160673468968009887672546243771190906300544375962002574334018175007498231632240021805593635057187842353840461973449205839419195826992169177108307004404365745462706797969436718212150888171299620800051183755681631250040936288149592343890616920153400691102933966724025765766418338452595218861582008026186067946508221264938736562082192890727980844444978081110599714993030990031363457184296168457089953510500474033234298252385232725393194957086065274263743550741242453140557383981358497807318476777558208795816650619401057283873302725816795298930817307745973266335447938091252055872816232968635169429875153933553733116356920185396530990560434510949092154539711124052490142742567527833751624924993906099869301505096094512729115132147653907827742334805918235749308541981388529841813147
e1 = 813647
e2 = 846359

s2 = -s2
c2 = gmpy.invert(c2,n)

v = pow(c1, s1, n)
w = pow(c2, s2, n)
m = str(hex((v * w) % n))
m = m.replace('0x','')
m = m.replace('L','')

print m.decode('hex')

Common Modulus 2

この問題ではgcd(e1,e2) = 3であり,Common Modulus 1 のプログラムを使用しても出力されるのは m3 mod n である.m3 < n だとすると出力の三乗根が平文となる.が,ぴったりな値を出す方法が分からなかったので平文に近い値で終了してあとは手動で求めた.

import gmpy

s1 = -195322
s2 = 196221
e1 = 2623119
e2 = 2611101
n = 691611766208546073444876122261067788277978858453710639029761974358666489171591889808344592871468081368348731289584873825685836699513369087940744233044470468106283756269016888690397802087612562650740690626844050981638158798650899164329024889012339813251634342169796374490173324858177655412520581064091323105709703802894635752243504165527728325493775585018099572491218738859140069209745383085972126419677929983854492018948495162457428459536088314487922683148031388611849013227501962458386817851194913551405843074740308192841259015955432216658418219471365781271743026881045054161177699500233983945284463060091084401032681620162554495490307966608011765399197534175588394769839991952726269105973546086964385977836193216093842605576347580465390858378577913173391209728199847916944392685608959720919745441534152140791433228642857247821519585327091864890122871765266988285510728943279970135846908966516130597249552710186071954611133294079017500030355232895541367427153922527925908108643934213023557398363684188823565535815365161748782796247844503993809352854741573950620787090272760236473228652960605730173150252619759400890068298838592790770868307280012495168740250977525199965477849089021924445456338550258621310346872587368865023459114279
c1 = 632613645684838434911920364870092246688638723680203743297038042884981435531349983627632652213126007404455112992754038899192740232209237012089852184466576496173356903126767617531366105427616049893559911396536574555008451239827427140619373005107923039458285095437111146013805698400274937791209388463040761234346114146112603113513874269976957472698342250573902102976387047390228485927254752372525379266486917620487089416581168720140744193600912161065888758451629009978676721731074043142666019127528370181044741033938879227651226413524178992155234346229899043794846119210274959231350300191718278291314079326011260972911790929707654859407903619102516710246683375658271085356783673232677699444921875427077745087507202504075374873842972977165904031632108921391219453633100007509368853543202918527396858214941532156620908283394786740941868393377733920317480973184132461984594109692489226477402338664642727766514992506288377119275635222078018270479534265371971469799345627297451492177595572561618185463142728664331779856911512823762928116551034186671353283417747535010208121962539603383913657773795358612010178381857101029638404248669376029927680328805839410427459248430136708902815920536603541943356116875656311481908672896225539754812052984
c2 = 473583830101449207063655453483957320801977763405664178108962387145963115641321631378723122470718049239150183483107837540062110255460217493574236417576528210993551734521104360323008425196350719034294427914294044848231276934402896045785500160974092767601908407706594433190832523140982335688121038712802163776950422665847149664034820576774873956120202470663588902529914328392634164212558025176982387474287314624421143326789371057668708456922968762564019631616913937820209470604081356673188045257490667304640155390478645279862586730343779998826931285683980941686981775369499484033439920659579124275957233449431588512697916708510428626881790592757578867152025501459202793986322020476004209777449674143157280081483085868896558215825742742029607229809248023263081810931655981810534293127835168642962477010095223356972141559004635008185531900175232541978761179342338914489553003329293031284557554252476291770973145365678145226167965362251186233138510776436645583796590010200995100899736056399413460647507781994189935869541735701599175369334170081795310585938471394672279359692859881857399434361716843681313191143289947464231132723256066979526475873327590657111481299295002695482778491520250596998683754980263059514032256777144682239680031331

s1 = -s1
c1 = gmpy.invert(c1, n)

v = pow(c1, s1, n)
w = pow(c2, s2, n)
m3 = (v * w) % n

print(m3)
raw_input('')

dx_base = 10000
dx = dx_base
vec = 1
m = 219213882440882612559820558975569704125684550881
while(1):
    before = dx
    print('dx ',dx)
    print('m ',m)
    strage = m3 - m**3
    if dx_base < 2000:
        break
    elif strage < 0:
        if vec > 1:
            m -= dx
            dx *= 2
            vec += 1
        elif vec == -3:
            dx_base = dx_base/2
            m -= dx_base
        else:
            vec = 2
            dx = dx_base
    else:
        if vec < -1:
            m  += dx
            dx *= 2
            vec -= 1
        elif vec == 3:
            dx_base = dx_base/2
            m += dx_base
        else:
            vec = -2
            dx = dx_base


print('m ',m)
raw_input('')

while (1):
    if m3 - m**3 < 0:
        m -= dm
    elif m3-m**3 > 0:
        m += dm
    if dm < 5:
        break
    dm = dm / 2
print(m)

AlexCTFのWriteup

RE1:Gifted

giftedというELFファイルが渡される。とりあえずstringsコマンドを使ってみるとフラグが見える。 AlexCTF{Y0u_h4v3_45t0n15h1ng_futur3_1n_r3v3r5ing}

RE4:unVM me

unvm_me.pycが渡される。pycファイルを逆コンパイルするツール Easy Python Decompilerを使うと以下のコードになる。

# Embedded file name: unvm_me.py
import md5
md5s = [174282896860968005525213562254350376167L,
 137092044126081477479435678296496849608L,
 126300127609096051658061491018211963916L,
 314989972419727999226545215739316729360L,
 256525866025901597224592941642385934114L,
 115141138810151571209618282728408211053L,
 8705973470942652577929336993839061582L,
 256697681645515528548061291580728800189L,
 39818552652170274340851144295913091599L,
 65313561977812018046200997898904313350L,
 230909080238053318105407334248228870753L,
 196125799557195268866757688147870815374L,
 74874145132345503095307276614727915885L]
print 'Can you turn me back to python ? ...'
flag = raw_input('well as you wish.. what is the flag: ')
if len(flag) > 69:
    print 'nice try'
    exit()
if len(flag) % 5 != 0:
    print 'nice try'
    exit()
for i in range(0, len(flag), 5):
    s = flag[i:i + 5]
    if int('0x' + md5.new(s).hexdigest(), 16) != md5s[i / 5]:
        print 'nice try'
        exit()

print 'Congratz now you have the flag'

これは入力した文字を5文字ずつ読み込みmd5変換した数値とmd5sの数値を比較するプログラムである。 要するにmd5sの数値を16進数にしてから逆変換してつなげればflagになるので、md5を逆変換してくれるサイトにぶん投げれば終了!
md5s[6]の8705…は16進数にすると31桁になるがこれは先頭の0がいなくなっただけなので、逆変換するときに0をつければいい。 ALEXCTF{dv5d4s2vj8nk43s8d8l6m1n5l67ds9v41n52nv37j481h3d28n4b6v3k}

CR1:Ultracoded

ZEROとONEが大量に書かれたファイルが渡されるZEROとONEを0,1に変換した後、8bitずつ16進数にしてAsciiコードに変換すると次の文字列になる。 Li0gLi0uLiAuIC0uLi0gLS4tLiAtIC4uLS4gLSAuLi4uIC4tLS0tIC4uLi4uIC0tLSAuLS0tLSAuLi4gLS0tIC4uLi4uIC4uLSAuLS0uIC4uLi0tIC4tLiAtLS0gLi4uLi4gLiAtLi0uIC4tLiAuLi4tLSAtIC0tLSAtIC0uLi0gLQ== Base64変換されている感じがするので、Base64でデコードする。
.- .-.. . -..- -.-. - ..-. - .... .---- ..... --- .---- ... --- ..... ..- .--. ...-- .-. --- ..... . -.-. .-. ...-- - --- - -..- -
点と棒だけである。モールス信号っぽい?ってことでモールス信号をデコードしてくださるサイトに投げる。
ALEXCTFTH15O1SO5UP3RO5ECR3TOTXT
flagゲット!!となるが難しいのはここからである…
適当に{}で囲ってもはじかれてしまう。思いつく限りのパターンをたたきこんでると点数が入った。
ALEXCTF{th15_1S_5up3r_5ecr3t_txt} (たぶんこれかな)(自信ない)  

CR2:Many time secrets

16進数が書いてあるファイルが渡される。catで見ると次のようになる。

0529242a631234122d2b36697f13272c207f2021283a6b0c7908
2f28202a302029142c653f3c7f2a2636273e3f2d653e25217908
322921780c3a235b3c2c3f207f372e21733a3a2b37263b313012
2f6c363b2b312b1e64651b6537222e37377f2020242b6b2c2d5d
283f652c2b31661426292b653a292c372a2f20212a316b283c09
29232178373c270f682c216532263b2d3632353c2c3c2a293504
613c37373531285b3c2a72273a67212a277f373a243c20203d5d
243a202a633d205b3c2d3765342236653a2c7423202f3f652a18
2239373d6f740a1e3c651f207f2c212a247f3d2e65262430791c
263e203d63232f0f20653f207f332065262c3168313722367918
2f2f372133202f142665212637222220733e383f2426386b

問題文ではone time pad の意味を理解していない、みたいなことが書いてあった。同じ鍵でxorし続けたんだなぁ、と予想をたてALEXCTF{でxorをすると文章が出てくる。文章の続きを予測しながらxorしていくと鍵(flag)がわかる。
ALEXCTF{HERE_GOES_THE_KEY}

CR4:Poor RSA

RSAの公開鍵とRSAエンコードしてからBase64でさらにエンコードしたflagが渡される。RSAの数式はよくわからないので
http://kira000.hatenadiary.jp/entry/2016/02/07/191924 からコードをもってきて使うとflagが出る。 ALEXCTF{SMALL_PRIMES_ARE_BAD}

Fore1:Hit the core

渡されたファイルをstringsで眺めると怪しい文字列が出てくる。

cvqAeqacLtqazEigwiXobxrCrtuiTzahfFreqc{bnjrKwgk83kgd43j85ePgb_e_rwqr7fvbmHjklo3tews_hmkogooyf0vbnk0ii87Drfgh_n kiwutfb0ghk9ro987k5tfb_hjiouo087ptfcv}

Aから5文字おきに読んでいくとflagになった。 ALEXCTF{K33P_7H3_g00D_w0rk_up}

SC1:Math bot

ncでつなぐと計算問題が表示されて答えを入力する。計算問題は500問あり、すべてに正解するとflagが表示される。てけいさん for ビギナーズだ!。以下のプログラムでflagを入手した。
どこかと通信して処理を行うプログラムは初めてなので変なところがあったら教えてくださると助かります。

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


#nc 195.154.53.62 1337
def connect(ip, port):
    return remote(ip, port)

conn = connect('195.154.53.62', 1337)

while 1:
    try:
        st1 = conn.recvuntil(':', drop=True)
    except:
        print conn.recv(1024)
        break
    print st1
    st2 = conn.recvline()
    print st2
    stri = conn.recvline()
    print stri
    str_lis = stri.split(" ")
    ans = 0
    if str_lis[1] == "+":
        ans = int(str_lis[0]) + int(str_lis[2])
    elif str_lis[1] == "-":
        ans = int(str_lis[0]) - int(str_lis[2])
    elif str_lis[1] == "*":
        ans = int(str_lis[0]) * int(str_lis[2])
    elif str_lis[1] == "/":
        #ans = input()
        ans = int(str_lis[0]) // int(str_lis[2])
    elif str_lis[1] == "%":
        ans = int(str_lis[0]) % int(str_lis[2])
    ans_str = str(ans)
    ans_str += "\n"
    conn.send(ans_str)

flagはメモし忘れました。

SECCON 2016 Writeup

Vigenere

k: ????????????
p: SECCON{???????????????????????????????????}
c: LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ

k=key, p=plain, c=cipher, md5(p)=f528a6ab914c1ecf856a1d93103948fe

 

タイトルからヴィジュネル暗号を解くものだと思っていたが、問題文に

md5(p)=f528a6ab914c1ecf856a1d93103948fe

とある。これをmd5をデコードしてくれるサイトに貼り付ければpが求まり、flagが入手できた。

 

VoIP

 pcapファイルが渡されたのでWiresharkで開くとRTPで埋め尽くされている。Wikipediaによると音声や動画を送るのに使われてるっぽい。Wiresharkには音声パケットを再生する機能があり、 電話>VoIP通話 でリストが作られ、それを選択して再生を押すと音声を再生できる…できるんだが、音声が編集されていて相当聞きにくい。さらにListening能力の低さも相まってかなり苦しんだ。Listening大事。

 

Anti-Debugging

 ファイルが渡されるのでfileコマンドで調べるとexeファイルだとわかるのでとりあえず実行するとパスワードを聞かれる。IDA Demoで解析してみるとタイトルの通りアンチデバッギングと思われるものが大量に存在していることがわかる。とりあえず分岐のある所にブレークポイントを設置し、分岐のたびにフラグがてに入りそうな場所に移動させていく。IDA Demoで分岐の方向を変更する方法は行きたい分岐先で 右クリック>Set IP を押せばよい。これを繰り返せばフラグが手に入る。

CTF for ビギナーズ in 東京 のwrite up

 Misc(200) CountUp Game

 先手PC後手自分で連続した数字を三つまで進めることができ、21を含むと負け…というゲームで10回連続でかつとflagがもらえるというもの。例として

PC:1
[1]
My[1~3]:3
[2, 3, 4]
PC:2
[5, 6]

こんな感じでゲームが進んでいく。
 このゲームには必勝法が存在していて後手であるプレイヤーは自分の番を4の倍数で終わらせることができ、相手が1なら自分は3、相手が2なら自分は2、とやっていけば毎回自分は20で終わらせていけばflagゲット!!。

 Web(200) Can you login as admin?

 よく覚えていないが、タイトルからしてたぶんusernameにadminを入力してパスワードに講義でやったSQLインジェクションでログインできたハズ。

 Forensics(100) Find Key

 pcapファイルが渡されたのでとりあえず

$ strings for1.pcap | grep '{'

とするとフラグがでてきた。

 Binary(100) Plain

 bin100というELFファイルをもらえるのでとりあえずstringsコマンド

$ strings bin100 | grep '{'

とするとこれもフラグが出てくる。