Tokyo Westerns CTF 3rd 2017 Writeup

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

Welcome!! (Misc, Warmup)

問題で書かれているフラグを投入するだけ。

TWCTF{Welcome_To_TWCTF2017!!}

Palindromes Pairs - Coding Phase - (PPC, Warmup)

$ nc ppc1.chal.ctf.westerns.tokyo 8765
####################################
#        Palindromes Pairs         #
####################################

A word is called "palindrome" if it reads the same backward as forward.
For instance, "cba", "a", "caab" and "deaed" are palindromes.

Given the list of words s_1, s_2, s_3, ..., s_n, 
your task is the count pair (i, j) that the concatenation of s_i and s_j is palindrome.


Input Format:
The first line contains n.
The second line contains s_1, s_2, s_3, ..., s_n separated by space. 
n
s_1 s_2 s_3 ... s_n

Output Format:
Your program must output the number of pairs in one line.

Conditions:
 * n <= 50
 * |TestCase| = 50
 * Each word only contains lower alphabets.

Example Input 1:
3
a ba cab

Example Output 1:
3

Explanation of Example1:
'aa' (1,1), 'aba' (1,2), 'bacab' (2,3)

Example Input 2:
5
a aa aaa aaaa aaaaa

Example Output 2:
25


----- START -----
Input 1/50
50
xxx xxc x rx rcr sm c rs mm m s cr rmr xx cc mmx s m xx x m s c r sx cs r rrx r cs rx rx cs rrr xc sxr s s m cr sc scs r x x xmr rc rsm rmm xxm

与えられた文字から2つを組み合わせて回文がいくつできるかを答える。

import socket
import re
import itertools

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('ppc1.chal.ctf.westerns.tokyo', 8765))

data = s.recv(1024)
print data

for i in range(50):
    data = s.recv(1024)
    print data

    pattern = 'Input (.+)\n(.+)\n(.+)'
    m = re.search(pattern, data)
    chars = m.group(3).split(' ')

    count = 0
    for c in itertools.product(chars, repeat=2):
        text = ''.join(c)
        if text == text[::-1]:
            count += 1

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

data = s.recv(1024)
print data
TWCTF{find_favorite_smell}

BabyDLP (Crypto)

与えられたコードから暗号化は以下のようになっていることがわかる。

c = pow(g, m^s, p)
・c: 暗号
・g, pは固定値で値はわかっている。
・m: フラグを数値化したもの
・s: 指定可能

0を指定した時はm^sはフラグを数値化したものになる。下位ビットから1,2,4,8,16,…と順に1ビットずつ判定する。

・取得した暗号がフラグの暗号のg**(g**i)倍(mod p)であれば、フラグの該当ビットは立っていない。
・フラグの暗号が取得した暗号のg**(g**i)倍(mod p)であれば、フラグの該当ビットは立っている。
import socket
import re

p = 160634950613302858781995506902938412625377360249559915379491492274326359260806831823821711441204122060415286351711411013883400510041411782176467940678464161205204391247137689678794367049197824119717278923753940984084059450704378828123780678883777306239500480793044460796256306557893061457956479624163771194201
g = 2

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('ppc2.chal.ctf.westerns.tokyo', 28459))

print '0'
s.sendall('0\n')
base = s.recv(1024)
print base
base = int(base[2:], 16)

bin_flag = ''
flag = ''
i = 0
times = g**(g**i)
while True:
    bit_str = hex(g**i)[2:].replace('L', '')
    print bit_str
    s.sendall(bit_str + '\n')
    data = s.recv(1024)
    print data
    data = int(data[2:], 16)
    if i != 0:
        times = (times**2) % p
    if (base * times) % p == data:
        bin_flag = '0' + bin_flag
    elif (data * times) % p == base:
        bin_flag = '1' + bin_flag
    i += 1
    if i % 8 == 0:
        flag = chr(int(bin_flag, 2)) + flag
        bin_flag = ''
    if flag.startswith('TWCTF{'):
        break

print 'flag: ' + flag
TWCTF{0f97c1c3ac2aedbd7fb8cd39d50f2b561d31f770}