[ 2025 COSS 아주대 CTF - 본선] - Write Up & 후기

2025. 7. 25. 23:48·CTF

2025. 07. 19 토요일 아주대학교에서 진행된 COSS CTF 본선에 참여하였다

동일하게 출전했고, 최종 결과 4위로 마무리 했다

솔직히 본선을 목표로 나간거였고, 수상은 생각도 못했는데, 수상하니깐 얼떨떨하고 너무 좋다

첫 본선에 첫 수상인 만큼 대회 하루의 일정을 정리해보려고 한다

08:10 - 기상

원래 8시에 일어나려다가 조금 늦었다

천둥 번개가 쳐서 늦게 잠들었더니, 알람을 못 들었다

그래도 늦지는 않았다

 

08:30 ~ 09:30 - 이동

대회장까지는 40분 정도 걸렸다

씻고 대충 빵 먹고 바로 출발해서 타이트하게 도착했다

401호였나? 거기서 인원 체크를 했는데, 아마 내가 가장 마지막으로 온 것 같았다

 

09:30 ~ 09:50 - 대회장 이동 및 준비

찐 대회장은 1층에 있었다

솔직히 비오고 그래서 그랬는지는 모르겠는데, 건물이 중후한 느낌이 있었다

근데 대회장은 엄청 깔끔하고 세련되어 있었다

그리고 인테리어가 이뻤다

맨 앞자리

가니깐 티셔츠도 나눠주셨다

또 다과도 있었는데, 간식들이 엄청 많았다

진짜 좋았다

대회 페이지 로그인 하고, 설명 간략하게 듣고, 와이파이 잡고, 딱 세팅해두니 시작할 시간이 되었다

 

10:00 ~ 15:30 - 본선 대회

시작하자마자 바로 misc로 달려갔다

mic check 같은거 있을 줄 알았는데 없었고, give me flag를 그리면 플래그를 주는 문제가 있었다

와우! 별거 아닌 문젠데 퍼블이다

꽤나 어려워서 자~알 그려야 한다

 

그리고 풀 문제를 보았다

팀원중 한 명이 크립토를 맡아서, 크립토 한 문제를 푸는동안에 나도 다른 크립토 문제를 보기 시작했다

Decrypt RSA 라는 문제로 누가 봐도 RSA 문제인걸 알 수 있다

Franklin-Reiter Related Message Attack 같이 생겨서 그냥 GPT한테 코드 던저주니깐 바로 알려줬다

from Crypto.Util.number import long_to_bytes
n  = 65756182677698595176310503281797205396723871448656240837096474734817334229057
c1 = 46677618784900339556238162525204951591280608902940779073106839725667571575750
c2 = 46210449457768784989069436594183693519377189857113615576663015891132602693402
k  = 1
f = [(-c1) % n, 0, 0, 1]
g = [((k**3 - c2) % n), (3*k**2) % n, (3*k) % n, 1]

def poly_trim(p):
    while p and p[-1] == 0:
        p.pop()
    return p

def poly_divmod(a, b):
    a = a.copy()
    poly_trim(a); poly_trim(b)
    deg_b = len(b) - 1
    inv_lc_b = pow(b[-1], -1, n)
    q = [0] * (len(a) - len(b) + 1) if len(a) >= len(b) else []
    while len(a) >= len(b) and a:
        d = len(a) - len(b)
        coeff = (a[-1] * inv_lc_b) % n
        q[d] = coeff
        for i, bi in enumerate(b):
            a[d + i] = (a[d + i] - coeff * bi) % n
        poly_trim(a)
    return poly_trim(q), poly_trim(a)

def poly_gcd(a, b):
    poly_trim(a); poly_trim(b)
    while b:
        _, r = poly_divmod(a, b)
        a, b = b, r
    # normalize leading coefficient to 1
    if not a:
        return a
    inv_lc = pow(a[-1], -1, n)
    return [(coeff * inv_lc) % n for coeff in a]

d = poly_gcd(f, g)
if len(d) != 2:
    raise ValueError(f"unexpected gcd degree: {len(d)-1}")
d0, d1 = d
m = (-d0 * pow(d1, -1, n)) % n

flag = long_to_bytes(m)
print(flag.decode())

# flag{fr4nkl1n-r3173r_4774ck}

이것도 퍼블이다

쉬운건 빨리 풀 수 있는데, 어려운 걸 못푼다 ㅜ

 

그 다음으로는 리버싱으로 갔다

1학년 리버싱 고트가 있어서, 쉬운 문제 하나 풀고 있는건 그 친구가 금방 풀 것 같았고, 나는 다른 문제를 보기 시작했다

딱 보니깐 풀만한게 Save the cat이라서 바로 시도해봤다

 

apk 파일 하나가 주어졌고, 마침!! Hackquest에 안드로이드 리버싱 내용이 있어서 참고하면서 jadx로 디컴파일해서 소스코드 추출했다

이 파일 4개를 GPT한테 던져주고 "flag를 복구하는 python 코드 짜줘" 하니깐 코드 짜줬다

expected = [
    6, 102, 130, 179, 226, 146, 166, 20,
    116, 112, 98, 210, 244, 166, 54, 0,
    151, 66, 117, 7, 67, 36, 146, 51,
    230, 87, 135, 85, 39, 50, 85, 182
]

# 1. Invert column rotations
arr = expected.copy()
for i in range(4):
    for _ in range(i):
        temp = arr[i]
        arr[i] = arr[i + 12]
        arr[i + 12] = arr[i + 8]
        arr[i + 8] = arr[i + 4]
        arr[i + 4] = temp

# 2. Invert row rotations
for i in range(4):
    for _ in range(i):
        base = i * 4
        temp = arr[base]
        arr[base] = arr[base + 3]
        arr[base + 3] = arr[base + 2]
        arr[base + 2] = arr[base + 1]
        arr[base + 1] = temp

# 3. Invert XOR with "cat"
cat = [99, 97, 116]
for k in range(len(arr)):
    arr[k] ^= cat[k % 3]

# 4. Invert nibble mixing to recover the two 16‑char strings
N = 16
orig1 = []
orig2 = []
for i in range(N):
    lo1 = arr[i] >> 4
    hi2 = arr[i] & 0xF
    lo2 = arr[N + i] >> 4
    hi1 = arr[N + i] & 0xF
    orig1.append((hi1 << 4) | lo1)
    orig2.append((hi2 << 4) | lo2)

flag1 = ''.join(chr(c) for c in orig1)
flag2 = ''.join(chr(c) for c in orig2)

print("var1:", flag1)
print("var2:", flag2)

# var1: flag{y0u_f1nally
# var2: _sav3d_th3_c4ts}

딱 이거 풀고 나니깐 1시간이 지나있었다

이때까지는 좀 빨리 풀었나? 싶어서 나쁘지 않았던 것 같다

그 이후로는 막혔고, 뭘 풀어야할지 몰랐었다

web 중에서 Download이런걸 봤었는데, 어떤식으로 해야할지는 대충 느낌이 왔는데, 잘 안되서 팀원이 바로 풀어줬다

포너블 문제를 보니 죄다 힙에다가 하나는 QEMU였고, 내가 풀 자신이 없었다

 

그래서 그때 살짝 방황을 했다

문제 슥슥 보다가 12시가 되고 점심을 주셨다

+) 12:00 - 점심

점심이 ㄹㅇ GOAT였다

걍 한솥 도시락정도 줄 것 같았는데, 뭔 도시락에 새우 튀김과 스테이크와 전복이 한 마리 통으로 있었다

후식으로 컵 과일도 주셨다

캬

저거 먹으면서 아라마크 퀄리티 뺨치는 점심이라고 찬양했다

선배팀에서도 아라마크이야기가 나왔던 것 같다 ㄷㄷ

점심도 여유롭지 않고, 걍 노트북 위에서 10분 컷 하고 밥 먹었다

이때쯤되니깐 살짝 몽롱해지면서 정신이 나갔다

 

그리고 다시 대회를 뛰었다

이 이후로는 포너블 한 문제와 리버싱 한 문제를 풀기 시작했다

포너블은 힙이였고, "힙"하지 않은 나는 풀지 못하였다

리버싱 base 문제를 우리 팀이 못 풀었는데, 다른 팀에서는 왜 많이 푼지는 모르겠다

이 텍스트 파일 3개 주었고, 도저히 모르겠어서 걍 GPT나 엄청 돌렸다

import base64

encode_data = (
    "fniu3dQC3Wcimkeojn75nttmng3QQBxXMQ4cX9DkNMNbUCBhUY0e192zGHiFxwQYxVc7SPr0oPoW"
    "DjXVTukyKWtJfW3t3kxqmn4KjdgTjgp3nBDnQQNHMtBUXMiPNCQ9NYc4U9e81M7aGwt+GV3gxbxl"
    "SHRzojqFDunYDF67A+v="
)
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
cipher = base64.b64decode(encode_data)
cand = "".join(
    alphabet[(cipher[i] - i) & 0x3F]
    for i in range(len(cipher))
)
pad = "=" * ((4 - len(cand) % 4) % 4)
flag_raw = base64.b64decode(cand + pad)
print(flag_raw.decode())

아직도 도대체 왜 이렇게 푸는지는 모르겠는데 1시 40분쯤에 풀었다

 

이게 내가 푼 마지막 문제였다

이때쯤 7위쯤으로 추락했고, 좀 문제를 직감했다

2시에 웹 팀원이 퍼블을 땄고, 2등으로 올라섰다

바로 추격당했고, 마지막으로 3시쯤 후배가 리버싱 문제를 풀며 4위로 대회를 마무리 했다

3시부터는 포너블을 시도해봤지만, 실패했다

많이 풀었는데 솔직히 쉬운 문제는 아닌 것 같다

이렇게 대회가 끝이 났다

ㄹㅈㄷ인건 2위 TheFatCat에서 끝나기 5분전 QEMU 정신나간 문제를 푸셔서 1등을 했다

TheKing이 실시간으로 상금 60만원이 증발해버린걸 보았다

ㄷㄷ

GOAT들의 경쟁은 무섭다

 

15:40 ~ 16:30 - ENKI 강연

10분정도 참가자들과 이야기 하고, 출제자 엔키에서 롸업을 알려줬다

웹 2개 포너블 2 문제 솔브 해주셨고, 아직 풀기까지는 연습이 더 필요한 것 같다

그리고 엔키 부사장님께서 강연을 해주셨다

이게 그냥 보안윤리 또 설명하면 좀 지루해질 수도 있었는데, 실제 공공기관이 어떤 원리로 공격을 당했는데 생각보다 세세하고, 자세하게 설명을 해주셨다

HackQuest처럼 사고의 흐름이 어떻게 흘러가야하는지를 잘 짚어주시면서 설명해주셔서 이해가 잘 되었다

그리고 "50%의 확률로 애니 프사는 과학이다" 를 주장하셨다

뭐 이렇게 강연 해주시고 시상식을 했다

 

16:30 ~ 16:50 - 시상식 및 사진 촬영

드디어 시상식을 했다

팀원 단체 사진도 있는데, 모자이크 하니깐 너무 범죄자 같아서 그냥 부계에 올렸다

첫 대회 본선인데, 10등만 피하자였는데, 수상을 해서 너무 좋았다

 

17:30 ~ 19:30 - 회식 in 아웃닭

디미고 3팀이서 치킨집을 갔다

10명이서 갔다

5마리 시켜서 이야기도 하고, 먹으면서 놀았다

인당 15000원에 치킨이라 정말 좋았다

또 아주대에서 기념 선풍기와 티셔츠도 주셨다

정말 감사하다

 

여하튼 이렇게 아주대학교 CTF를 마치게 되었다

처음 예선을 나갈때도, 본선만본선만!을 외치며 나간 대회였고, 내 생애 처음으로 본선을 나갔다

그 상황에서 첫 수상을 해서 너무 좋다

포너블을 더 공부해야겠다

정말 좋은 경험이였다!

'CTF' 카테고리의 다른 글

[ 제 31회 해킹 캠프 후기 ]  (7) 2025.09.01
[ 2025 제 1회 경기도 사이버 보안 캠프 후기 ]  (2) 2025.08.25
[2025 COSS 아주대 CTF - 예선 ] - Write Up & 후기  (0) 2025.06.23
[2025 Codegate 예선] - Write Up & 후기  (0) 2025.05.26
[2025 DIMI CTF Write Up] - Prob by pandas. with 후기  (3) 2025.03.25
'CTF' 카테고리의 다른 글
  • [ 제 31회 해킹 캠프 후기 ]
  • [ 2025 제 1회 경기도 사이버 보안 캠프 후기 ]
  • [2025 COSS 아주대 CTF - 예선 ] - Write Up & 후기
  • [2025 Codegate 예선] - Write Up & 후기
Hello🖐️I'm pandas from KDMHS
Hello🖐️I'm pandas from KDMHS
한국디지털미디어고등학교 23기 웹 프로그래밍과에서 해킹을 공부하고 있는 pandas입니다.
  • Hello🖐️I'm pandas from KDMHS
    웹 프로그래밍과에서 시스템 해킹 공부하기
    Hello🖐️I'm pandas from KDMHS
  • 공지사항

    • Hello I'm pandas 🖐️
    • 분류 전체보기 (26)
      • CTF (9)
      • 디미고 (8)
      • 백준 (1)
      • Dreamhack (5)
      • INFO (3)
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 인기 글

  • 태그

    해킹
    회고록
    웹프로그래밍과
    reversing
    ctf
    Python
    Baekjoon
    docker
    백준
    디미고
    DreamHack
    pwnable
    info
    팰린드롬
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Hello🖐️I'm pandas from KDMHS
[ 2025 COSS 아주대 CTF - 본선] - Write Up & 후기
상단으로

티스토리툴바