Notice
Recent Posts
Recent Comments
Link
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Void

YISF 2024 Finals 본문

CTF

YISF 2024 Finals

pdw0412 2024. 11. 10. 10:25

 

 

후기

대회가 끝난지 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