이번에 아주대학교 CTF 본선을 치뤘다.

문제는 총 7문제 풀었고, 최종 점수 1879점으로 대회를 6등으로 마무리 하였다.(5등이랑 점수가 같은..)

팀원이 한 문제만이라도 풀어줬다면 하는 마음이 한 켠에 있긴 하지만, 그냥 나의 실력을 탓하기로 했다.

문제는 리버싱이 너무 쉬웠어서 확실히 LLM 때문에 리버싱 난이도 조절이 힘들구나 하고 생각했다.

문제 유형 자체는 신박하고 재밌는 것들이 많았다.

misc - lets draw

그냥 주어진 웹사이트에 give me flag를 적으면 플래그가 나온다.

rev - circuit

입력값 n1~n16이 주어지고 그의 답인 Y1~Y16을 제출하면 되는 간단한 문제이다.

이런 간단한 문제는 속도가 생명인 CTF에선 GPT한테 넘기는게 이롭다.

solve code by GPT

from pwn import *

def nand(a, b): return 1 - (a & b)
def nor(a, b): return 1 - (a | b)
def xnor(a, b): return 1 - (a ^ b)

def solve(vals):
    n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16 = vals
    y1 = nand(n1, n2)
    y2 = n3 ^ n4
    y3 = 1 - (n5 & n6)
    y4 = y1 & n7
    y5 = y2 | y3
    y6 = nor(n8, n9)
    y7 = xnor(y5, n10)
    y8 = nand(y6, y4)
    y9 = n11
    y10 = y7 & (1 - y9)
    y11 = xnor(n13, n14)
    y12 = nand(y10, y11)
    y13 = y12 ^ n15
    y14 = nor(y8, y13)
    y15 = nor(n16, nand(n1, n16))
    y16 = 1 - (y14 & y15)
    return [y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15,y16]

p = remote('43.202.158.172', 12345)

nums = []
for i in range(16):
    line = p.recvline(timeout=5).decode().strip()
    if not line:
        exit()
    if line.startswith('Result'):
        break
    nums.append(int(line.split(':')[1].strip()))
print(nums)
res = solve(nums)
p.sendline(' '.join(map(str, res)))
p.interactive()

rev - base

난 아직 이해를 하지 못하였지만 GPT한테 data와 encode_data를 주고 이 관계에 따라서 encode_flag를 복호화 해달라고 했더니 답을 찾아주었다.

import base64, itertools

hint = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
cipher1 = "fniu3dQC3Wcimkeojn75nttmng3QQBxXMQ4cX9DkNMNbUCBhUY0e192zGHiFxwQYxVc7SPr0oPoWDjXVTukyKWtJfW3t3kxqmn4KjdgTjgp3nBDnQQNHMtBUXMiPNCQ9NYc4U9e81M7aGwt+GV3gxbxlSHRzojqFDunYDF67A+v="
cipher2 = "N90cNVeJXHDBDP3/N9BsNt2WXMi8NHW="

std = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
ref = base64.b64encode(hint.encode()).decode().rstrip("=")

mapping = {}
for c, r in zip(cipher1.rstrip("="), ref):
    mapping[c] = std.index(r)

for perm in itertools.permutations([i for i in range(64) if i not in mapping.values()], 2):
    test = mapping.copy(); test['s'], test['/'] = perm
    bits = "".join(f"{test[ch]:06b}" for ch in cipher2.rstrip("="))
    bits = bits[:-cipher2.count("=")*2]
    data = bytes(int(bits[i:i+8],2) for i in range(0,len(bits)//8*8,8))
    try:
        txt = data.decode()
        if txt.startswith("flag{"):
            print(txt)
    except UnicodeDecodeError:
        pass

기억은 안나지만, 아마 flag{Base64_find_table}이 플래그 아닐까 싶다.

rev - mad sphinx

이번 대회의 제일 어려운 리버싱 문제이다.

사실 이것도 별로 어렵지 않다.

예선 때의 문제인 angry sphinx 문제의 후속작이다.