이번에 아주대학교 CTF 본선을 치뤘다.
문제는 총 7문제 풀었고, 최종 점수 1879점으로 대회를 6등으로 마무리 하였다.(5등이랑 점수가 같은..)
팀원이 한 문제만이라도 풀어줬다면 하는 마음이 한 켠에 있긴 하지만, 그냥 나의 실력을 탓하기로 했다.
문제는 리버싱이 너무 쉬웠어서 확실히 LLM 때문에 리버싱 난이도 조절이 힘들구나 하고 생각했다.
문제 유형 자체는 신박하고 재밌는 것들이 많았다.
그냥 주어진 웹사이트에 give me flag를 적으면 플래그가 나온다.
입력값 n1~n16이 주어지고 그의 답인 Y1~Y16을 제출하면 되는 간단한 문제이다.
이런 간단한 문제는 속도가 생명인 CTF에선 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()
난 아직 이해를 하지 못하였지만 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}이 플래그 아닐까 싶다.
이번 대회의 제일 어려운 리버싱 문제이다.
사실 이것도 별로 어렵지 않다.
예선 때의 문제인 angry sphinx 문제의 후속작이다.