Wargame/Crypto

[Dreamhack] ROT128

월루이 2023. 7. 4.

1. 문제

주어진 encfile을 복호화하여 flag 파일 내용을 알아낸 뒤, flag.png에서 플래그를 획득하는 문제

 

 

소스코드

#!/usr/bin/env python3

hex_list = [(hex(i)[2:].zfill(2).upper()) for i in range(256)]

with open('flag.png', 'rb') as f:
    plain_s = f.read()

plain_list = [hex(i)[2:].zfill(2).upper() for i in plain_s]

enc_list = list(range(len(plain_list)))

for i in range(len(plain_list)):
    hex_b = plain_list[i]
    index = hex_list.index(hex_b)
    enc_list[i] = hex_list[(index + 128) % len(hex_list)]

enc_list = ''.join(enc_list)

with open('encfile', 'w', encoding='utf-8') as f:
    f.write(enc_list)

 

 

 

 

2. 풀이

더보기
hex_list = [(hex(i)[2:].zfill(2).upper()) for i in range(256)]

with open('flag.png', 'rb') as f:
    plain_s = f.read()

plain_list = [hex(i)[2:].zfill(2).upper() for i in plain_s]

간단하게 문법 설명을 하자면,

 

[2:]는 앞에 2글자를 자른다는 얘기고, zfill(2)는 무조건 두자리수로 만들어 주기 위해 한자리면 0을 채워준다는 얘기다.

 

그러므로

hex_list = ['00', '01', ... 'FF']

plain_s = "\x89\x50..."

plain_list = ['89', '50', ...]

로 구성된다.

 

 

 

 

for i in range(len(plain_list)):
    hex_b = plain_list[i]
    index = hex_list.index(hex_b)
    enc_list[i] = hex_list[(index + 128) % len(hex_list)]

enc_list = ''.join(enc_list)

with open('encfile', 'w', encoding='utf-8') as f:
    f.write(enc_list)

 

plain_list[i]에 해당하는 인덱스를 구한 후, 대충 어떠한 과정을 거쳐 enc_list[i]를 생성하고

''.join을 이용해서 리스트 형식인 것을 문자열로 만들어준 후 출력한 것이 enc_list가 된다.

 

 

 

 

 

 

즉, flag.png를 구하기 위해서는 encfile을 읽고 방금 이해한 과정을 거꾸로 하면 된다.

encfile은 긴 문자열로 되어있으므로 이것을 두개씩 잘라 리스트형식으로 만들어준다.

 

for문을 거꾸로 실행해준 후, 16진수 문자열로 구성되어 있으므로 바이트 데이터로 변환해준다.

그리고 그 값을 저장해주면, png파일이 생성된다.

 

완성된 코드는 아래와 같다.

hex_list = [(hex(i)[2:].zfill(2).upper()) for i in range(256)]

with open('encfile', 'r') as f:
    enc_s = f.read()
enc_list = [enc_s[i:i+2] for i in range(0, len(enc_s), 2)]

plain_list = list(range(len(enc_list)))

for i in range(len(enc_list)):
    hex_b=enc_list[i]
    index = hex_list.index(hex_b)
    plain_list[i] = hex_list[(index - 128) % len(hex_list)]

plain_list=''.join(plain_list)
byte_data = bytes.fromhex(plain_list)

with open('flag.png', 'wb') as f:
    f.write(byte_data)

 

댓글