Void
YISF 2024 Finals 본문

후기
대회가 끝난지 3달만에 후기를 작성하네요. 600점 13등으로 대회를 마쳤습니다. 이번에서 본선처럼 퍼블을 따고 싶다는 목표가 있었고, 이 목표는 달성했지만 수상은 하지 못해 아쉬움이 남습니다. 포너블 1번문제가 제가 대회 시작 며칠 전에 공부한 Sig Return Rop 라는 공격기법 풀이었는데, 저는 해결하지 못했습니다. 만약 해결했다면 수상했을 가능성도 있었을 것 같아서 아쉽습니다. 예선에서는 3일동안 대회가 진행해서 높은 순위를 받을 수 있었지만, 본선은 어려웠던것 같습니다. 그래도 열심히 참여했고, 문제도 정말 재미있었습니다. 더 열심히 공부해 내년에는 수상하고싶습니다.
https://pdw0412.tistory.com/29
+ 당시 풀다가 포기했던 'Happy SIGnal' 업솔빙입니다. 이 문제 풀었으면 수상이었을 것 같은데 아쉽네요
Write Up
rev - Anyone can do it
rev - Anyone can do it
#Anyone.py
import random as SiYiYsFyIsFySiFYfSiYsFyIsFfYiS
SiYiYsFyIsFySiFYfSiYsFyIsFYiS = int("524899f", 18)
SiYiYsFyIsFySiFYfSiYsFyIsFfYiS.SiYiYsFyIsFySiFYfSiYsFyIsFYiS(SiYiYsFyIsFySiFYfSiYsFyIsFYiS)
SiYiYsFyIsFySiFYfSiYsFyIs = bytearray(open('flag.txt', 'rb').read())
YiYfSiYsFyIsFfYSyFyIsFyYsIsFy = 'a6f0bbebb1f3ba370fb15150e26c0e00066c46bd26b1f1f77237d0e45fddb7f7'
YiYSiYSfYfSiYsFsISiFyYs = [
b'YiYisFiFySiYsFsI',
b'IfYfSiYySi',
b'IyFsIyFySiF',
b'SiFyYsFfYs',
b'IfFyFsYiSfYs',
b'YiYisFiFySiYySfS',
b'IfYfSiYys',
b'FyFsIyIysI',
b'SfYsIfyFyIyS',
]
def IfYiSfSiFyYsFfSYiYfSiYsFyIsFfY(IiFyYsFfSYiYfSiYsFyIsFfY):
return bytearray([YiYFIfYiSfSiFyYsFfSYiYfSiYsFyIsFfY ^ 0xAA for YiYFIfYiSfSiFyYsFfSYiYfSiYsFyIsFfY in IiFyYsFfSYiYfSiYsFyIsFfY])
def IfYiSfSiFyYsFfSYiYfSiYsFyiSFFY(IfYisFsIFyYsFfSYiYfSiYsFyIsFfY):
return bytearray([YiYfSiYsFyIsFfYSyFyIsF ^ 0x55 for YiYfSiYsFyIsFfYSyFyIsF in IfYisFsIFyYsFfSYiYfSiYsFyIsFfY])
def YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS(hex):
for id in range(0, len(hex) - 2, 2):
hex[id], hex[id + 2] = hex[id + 2], hex[id]
for list in range(1, len(hex) - 2, 2):
hex[list], hex[list + 2] = hex[list + 2], hex[list]
return hex
YfSiYsFyIsFfYiSIf = [YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS, IfYiSfSiFyYsFfSYiYfSiYsFyIsFfY, IfYiSfSiFyYsFfSYiYfSiYsFyiSFFY]
YfSiYsFyIsFfYiSIf = [SiYiYsFyIsFySiFYfSiYsFyIsFfYiS.choice(YfSiYsFyIsFfYiSIf) for _ in range(256)]
def YiYfSiYsFfSiFySFySiYiFfYsFySiF(YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS, YsFySiYiIsFyFfSSiYiYsFyIsFySiF):
YsFySiYiIsFyFfSSiYiYsFyIsFySiF = [int(YsFySiYiIsFyFfSSiYiYsFyIsFySiF[i:i+2], 16) for i in range(0, len(YsFySiYiIsFyFfSSiYiYsFyIsFySiF), 2)]
for i in YsFySiYiIsFyFfSSiYiYsFyIsFySiF:
YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS = YfSiYsFyIsFfYiSIf[i % len(YfSiYsFyIsFfYiSIf)](YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS)
return YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS
def YiYsFyIsFySiFfYsF(YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS, YsFySiYiIsFyFfSSiYiYsFyIsFySiF):
YsFySiYiIsFyFfSSiYiYsFyIsFySiF = int(YsFySiYiIsFyFfSSiYiYsFyIsFySiF.hex(), 18)
for i in YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS:
num = int.from_bytes(i, byteorder='big')
YsFySiYiIsFyFfSSiYiYsFyIsFySiF += num
ar_hex = hex(YsFySiYiIsFyFfSSiYiYsFyIsFySiF)
return ar_hex
def YiYsFyIsFySiFfYsFs(YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS, YsFySiYiIsFyFfSSiYiYsFyIsFySiF):
result = bytearray()
for i, a in enumerate(YfSiYsFyIsFfYiSIfYiSfSiFyYsFfS):
if i % 2 == 0:
result.append(a | 0x57)
else:
result.append(a ^ 0x57)
return result
YiYsFySiFyIsSSiYsFyIsFyYiFfS = YiYfSiYsFfSiFySFySiYiFfYsFySiF(SiYiYsFyIsFySiFYfSiYsFyIs, YiYfSiYsFyIsFfYSyFyIsFyYsIsFy)
YiYsFySiFyIsSSiYsFyIsFyYiFfS = YiYsFyIsFySiFfYsF(YiYSiYSfYfSiYsFsISiFyYs, YiYsFySiFyIsSSiYsFyIsFyYiFfS)
print(YiYsFySiFyIsSSiYsFyIsFyYiFfS)
먼저 소스코드를 열어보면 소스코드가 난독화 되어 있다.
import random
key = int("524899f", 18)
random.seed(key)
# flag.txt 파일을 읽어와서 바이트 배열로 저장
flag_data = bytearray(open('flag.txt', 'rb').read())
# 고정된 해시 문자열
fixed_hash = 'a6f0bbebb1f3ba370fb15150e26c0e00066c46bd26b1f1f77237d0e45fddb7f7'
# 여러 개의 고정된 바이트 문자열 리스트
byte_list = [
b'YiYisFiFySiYsFsI',
b'IfYfSiYySi',
b'IyFsIyFySiF',
b'SiFyYsFfYs',
b'IfFyFsYiSfYs',
b'YiYisFiFySiYySfS',
b'IfYfSiYys',
b'FyFsIyIysI',
b'SfYsIfyFyIyS',
]
# XOR 연산을 통해 바이트 배열을 수정하는 함수
def xor_with_aa(byte_array):
return bytearray([byte ^ 0xAA for byte in byte_array])
# XOR 연산을 통해 다른 방식으로 바이트 배열을 수정하는 함수
def xor_with_55(byte_array):
return bytearray([byte ^ 0x55 for byte in byte_array])
# hex 값을 조작하는 함수
def manipulate_hex(hex_array):
for i in range(0, len(hex_array) - 2, 2):
hex_array[i], hex_array[i + 2] = hex_array[i + 2], hex_array[i]
for i in range(1, len(hex_array) - 2, 2):
hex_array[i], hex_array[i + 2] = hex_array[i + 2], hex_array[i]
return hex_array
# 함수 리스트를 랜덤하게 선택하여 256개 생성
function_list = [manipulate_hex, xor_with_aa, xor_with_55]
random_function_sequence = [random.choice(function_list) for _ in range(256)]
# 여러 변환을 적용하는 함수
def apply_transformations(data, hex_string):
hex_values = [int(hex_string[i:i+2], 16) for i in range(0, len(hex_string), 2)]
for value in hex_values:
data = random_function_sequence[value % len(random_function_sequence)](data)
return data
# 데이터를 조작하는 또 다른 함수
def manipulate_data(data, hex_value):
hex_int = int(hex_value.hex(), 18)
for item in data:
num = int.from_bytes(item, byteorder='big')
hex_int += num
return hex(hex_int)
# 조건에 따라 데이터를 변형하는 함수
def conditionally_transform_data(data, hex_value):
result = bytearray()
for i, byte in enumerate(data):
if i % 2 == 0:
result.append(byte | 0x57)
else:
result.append(byte ^ 0x57)
return result
# 최종 데이터 변환
transformed_data = apply_transformations(flag_data, fixed_hash)
final_data = manipulate_data(byte_list, transformed_data)
print(final_data)
gpt를 이용해서 다음과 같은 코드를 얻었다. 이제 변수들과 함수들을 분석해보자.
#output.txt
2b2dd9afa833f7a96dbfb8defdd2e25f86e3e6bcf45b5a3040855f30ff0faba63c982259cf5df440993043
transformed_data = apply_transformations(flag_data, fixed_hash)
final_data = manipulate_data(byte_list, transformed_data)
print(final_data)
프로그램의 마지막 코드 3줄로 final_data 가 output.txt 가 되어야 한다. 아래부터 분석해보자.
def manipulate_data(data, hex_value):
hex_int = int(hex_value.hex(), 18)
for item in data:
num = int.from_bytes(item, byteorder='big')
hex_int += num
return hex(hex_int)
mainpulate_data(data, hex_value) 함수는 transformed_data를 18진수로 바꾼 후, byte_list 의 원소를 가져와 바이트로 변환하고, 더해준 다음 리턴한다. 그렇다면 final_data(=output.txt) 를 알고 있으므로, transformed_data를 역산 할 수 있다. 그냥 final_data 에서 byte_list를 빼주면 된다. 여기서 주의해야할 점 이 있는데, 바로 맨 처음에 18진수로 변환 시켜주고, 또 리턴할 때는 16진수로 리턴한다. 그래서 final_data 에서 원소들을 모두 빼준 후, 원래의 transformed_data의 진법인 18진수로 바꾸고, 또 그 값을 16진수로 변환해야 한다.
n=6044385540073009298614759079622937375807664553353674797953897585463276501537019426147617268195629039875
def f(n) :
if(n==0) :
return
f(n//18)
print(end=str(hex(n%18))[2])
f(n)
ccf59dc299f5c89e9f9bc9f5cc9bd89f9df5dbdf999f9d9b9ac4d7e3f3ecf99dd199c299f5cec49af5 는 transformed_data의 hex값이다.
transformed_data = apply_transformations(flag_data, fixed_hash)
final_data = manipulate_data(byte_list, transformed_data)
print(final_data)
이제 apply_transformations() 만 역산하면 된다.
# 함수 리스트를 랜덤하게 선택하여 256개 생성
function_list = [rev_manipulate_hex, xor_with_aa, xor_with_55]
random_function_sequence = [random.choice(function_list) for _ in range(256)]
# 여러 변환을 적용하는 함수
def apply_transformations(data, hex_string):
hex_values = [int(hex_string[i:i+2], 16) for i in range(0, len(hex_string), 2)]
hex_values=list(reversed(hex_values))
for value in hex_values:
data = random_function_sequence[value % len(random_function_sequence)](data)
print(data)
return data
apply_transformations(data, hex_string)을 보자. 이 함수는 random_function_sequence 에서 함수를 가져온다. random_functino_sequence 는 random을 이용해서 function_list의 함수중에서 하나를 가져오지만, seed가 정해져 있으므로 우리는 random_function_sequence가 어떤 함수를 가져올지 알 수 있다. 그리고 fixed_hash, transformed_data 모두 알고 있고, manipulate_hex(), xor_with_aa(), xor_with_55() 모두 역산할 수 있는 함수들이므로, transformed_data 를 변경하는 작업을 거꾸로 해준다면 flag_data를 구할 수 있고, 이것이 flag다. 일단 apply_transformations(data, hex_string)을 역산하기 전에, transformed_data의 자료형을 bytearray로 바꿔줘야 한다. 그냥 hex값을 byte로 변환만 해주면 되며 다음과 같은 코드로 flag를 얻을 수 있다.
import random
key = int("524899f", 18)
random.seed(key)
fixed_hash = 'a6f0bbebb1f3ba370fb15150e26c0e00066c46bd26b1f1f77237d0e45fddb7f7'
byte_list = [
b'YiYisFiFySiYsFsI',
b'IfYfSiYySi',
b'IyFsIyFySiF',
b'SiFyYsFfYs',
b'IfFyFsYiSfYs',
b'YiYisFiFySiYySfS',
b'IfYfSiYys',
b'FyFsIyIysI',
b'SfYsIfyFyIyS',
]
def xor_with_aa(byte_array):
return bytearray([byte ^ 0xAA for byte in byte_array])
def xor_with_55(byte_array):
return bytearray([byte ^ 0x55 for byte in byte_array])
rev_set=[(0,2), (2,4), (4,6), (6,8), (8,10), (10,12), (12,14), (14,16), (16,18), (18,20), (20,22), (22,24), (24,26), (26,28), (28,30), (30,32), (32,34), (34,36), (36,38), (38,40), (1,3), (3,5), (5,7), (7,9), (9,11), (11,13), (13,15), (15,17), (17,19), (19,21), (21,23), (23,25), (25,27), (27,29), (29,31), (31,33), (33,35), (35,37), (37,39)]
def rev_manipulate_hex(hex_array):
for i in range(len(rev_set)-1, -1, -1) :
a, b=list(rev_set[i])[0], list(rev_set[i])[1]
hex_array[a], hex_array[b]=hex_array[b], hex_array[a]
return hex_array
function_list = [rev_manipulate_hex, xor_with_aa, xor_with_55]
random_function_sequence = [random.choice(function_list) for _ in range(256)]
def apply_transformations(data, hex_string):
hex_values = [int(hex_string[i:i+2], 16) for i in range(0, len(hex_string), 2)]
hex_values=list(reversed(hex_values))
for value in hex_values:
data = random_function_sequence[value % len(random_function_sequence)](data)
print(data)
return data
def manipulate_data(data, hex_value):
hex_int = int(hex_value.hex(), 18)
for item in data:
num = int.from_bytes(item, byteorder='big')
hex_int -= num
return hex(hex_int)
final_data=0x2b2dd9afa833f7a96dbfb8defdd2e25f86e3e6bcf45b5a3040855f30ff0faba63c982259cf5df440993043
for item in byte_list :
num=int.from_bytes(item, byteorder='big')
final_data-=num
print(final_data)
transformed_data=b'\xcc\xf5\x9d\xc2\x99\xf5\xc8\x9e\x9f\x9b\xc9\xf5\xcc\x9b\xd8\x9f\x9d\xf5\xdb\xdf\x99\x9f\x9d\x9b\x9a\xc4\xd7\xe3\xf3\xec\xf9\x9d\xd1\x99\xc2\x99\xf5\xce\xc4\x9a\xf5'
data=transformed_data
print('data', data)
for i in range(0, len(data) - 2, 2):
print(end='('+str(i)+','+str(i+2)+'), ')
for i in range(1, len(data) - 2, 2):
print(end='('+str(i)+','+str(i+2)+'), ')
data=apply_transformations(data, fixed_hash)
YISF{7h3_3nd_0f_7h3_b451c_f1r57_qu35710n}
'CTF' 카테고리의 다른 글
| UofTCTF 2025 - Pwn (4/6) (0) | 2025.01.15 |
|---|---|
| Layer7 CTF 2024 (0) | 2025.01.13 |
| 제 5회 JBU-CTF (1) | 2024.12.16 |
| LG U+ Security Hackathon : Growth Security 2024 Quals (0) | 2024.11.17 |
| YISF 2024 Quals (0) | 2024.08.23 |