School CTF 2017 Writeup

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

StRiNgMuTaToR 1.0 (ppc 100)

オペコードに従い、反転やシフトを行う。

import socket
import re

def recvuntil(s, tails):
    data = ""
    while True:
        for tail in tails:
            if tail in data:
                return data
        data += s.recv(1)

def reverse(s):
    return s[::-1]

def swap(s):
    l = len(s) / 2
    s1 = s[l:]
    s2 = s[:l]
    return s1 + s2

def reverse_halves(s, code):
    l = len(s) / 2
    s1 = s[:l]
    s2 = s[l:]
    if code == 2:
        s1 = s1[::-1]
    elif code == 3:
        s2 = s2[::-1]
    return s1 + s2

def reverse_quoters(s, code):
    l = len(s) / 4
    s1 = s[:l]
    s2 = s[l:l*2]
    s3 = s[l*2:l*3]
    s4 = s[l*3:]
    if code == 4:
        s1 = s1[::-1]
    elif code == 5:
        s2 = s2[::-1]
    elif code == 6:
        s3 = s3[::-1]
    elif code == 7:
        s4 = s4[::-1]
    return s1 + s2 + s3 + s4

def cycle_left_quoters(s, code):
    l = len(s) / 4
    s1 = s[:l]
    s2 = s[l:l*2]
    s3 = s[l*2:l*3]
    s4 = s[l*3:]
    if code == 8:
        s1 = s1[1:l] + s1[0]
    elif code == 9:
        s2 = s2[1:l] + s2[0]
    elif code == 10:
        s3 = s3[1:l] + s3[0]
    elif code == 11:
        s4 = s4[1:l] + s4[0]
    return s1 + s2 + s3 + s4

def cycle_right_quoters(s, code):
    l = len(s) / 4
    s1 = s[:l]
    s2 = s[l:l*2]
    s3 = s[l*2:l*3]
    s4 = s[l*3:]
    if code == 12:
        s1 = s1[l-1] + s1[:l-1]
    elif code == 13:
        s2 = s2[l-1] + s2[:l-1]
    elif code == 14:
        s3 = s3[l-1] + s3[:l-1]
    elif code == 15:
        s4 = s4[l-1] + s4[:l-1]
    return s1 + s2 + s3 + s4

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('nc.task.school-ctf.org', 41447))

pattern = 'program \'(.+)\' to the sequence \'(.+)\''

data = recvuntil(s, '\n')
data += recvuntil(s, '\n')
data += recvuntil(s, ' ')
print data + 'start'
s.sendall('start\n')

for i in range(100):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n')
    m = re.search(pattern, data)
    opcodes = m.group(1)
    seq = m.group(2)
    data += recvuntil(s, ' ')

    for opcode in opcodes:
        code = int(opcode, 16)
        if code == 0:
            seq = reverse(seq)
        elif code == 1:
            seq = swap(seq)
        elif code >= 2 and code <= 3:
            seq = reverse_halves(seq, code)
        elif code >= 4 and code <= 7:
            seq = reverse_quoters(seq, code)
        elif code >= 8 and code <= 11:
            seq = cycle_left_quoters(seq, code)
        else:
            seq = cycle_right_quoters(seq, code)

    print data + seq
    s.sendall(seq + '\n')
    data = recvuntil(s, '\n')
    print data

data = recvuntil(s, '\n')
print data
SchoolCTF{U/c@n-n3v3r_0wN_M3}