또 뭐하지

[Dreamhack] X-Time Pad 본문

Write-up/Crypto

[Dreamhack] X-Time Pad

mameul 2024. 11. 18. 23:08
728x90

풀이

#!/usr/bin/env python3
import sys

#flag xor key
def flag_enc(): #flag_enc() 함수 정의
    with open('./flag', 'r') as f: #flag파일을 읽어옴
        flag = f.read()[3:-1] #아마 DH{}를 빼고 안의 내용만 읽어옴
        list = ['0b'] #'0b'로 초기화된 리스트
        for ch in flag: # flag 안의 한 글자씩 읽어옴
            list.append(format(ord(ch), 'b').zfill(8)) # flag의 글자들을 변환하여 list에 추가함 / format(number, 'b') : number를 이진수 문자열로 변환 / str_num.zfill(N) : N자리가 되도록 str 앞에 0을 붙임 
        binf = "".join(list) #list를 모두 붙여 하나의 문자열 binf로 바꿈
    with open('./key', 'r') as f: #key파일을 읽어옴
        key = f.read() # 읽어온 내용을 key에 저장함

    flag_enc = bin(int(binf, 2) ^ int(key, 2)) # binf와 key를 xor한 값을 문자열로 변환하여 flag_enc에 저장 / bin(number) : 전달받은 정수 값을 이진수 문자열로 변환 / int(str_num, base) : base진수의 str_num을 정수형(10진수)으로 변환
    print(f'flag_enc: {flag_enc}\n') # flag_enc를 출력함

    return key #key 반환함

def key_gen(key): # key_gen 함수
    # 기존의 키와 주어진 이진수와 xor하여 new_key를 획득함
    new_key = bin(int(key,2) ^ int('0b10010110101011100100111011100101101011110011001110000101111010111110010111100000111110000000010101101011001100010100010101111000111111100010001010110000010111110111110010001111110011110101001011111010100101010100001110010111111010001101111110011001010110011001010101010000001010100000101101001010010010100010100001011101011011010011010101111111010010100111011001100000101011100001010111111101000110011000110101111111010111001101111110011101101100011101001111111000010011010111100010111001100101011111101111111001',2))
    return new_key #new_key 반환


def input_enc(key): # input_enc 함수
    p = input("Plain text : ") # plain text를 입력 받아 p에 저장함
    if (len(p) > 64) : # 입력 받은 문자열의 길이가 64를 넘으면
        print('Max length: 64') # 최대길이가 64임을 알려줌
    else : # 입력받은 문자열의 길이가 64를 넘지 않으면
        plist = ['0b'] #plist를 '0b'값을 넣어 초기화
        for ch in p: # p의 한 글자씩 ch 읽어옴
            plist.append(format(ord(ch), 'b').zfill(8)) # p의 글자들을 변환하여 plist에 추가함
        binp = "".join(plist) # plist를 모두 붙여 하나의 문자열 binp로 바꿈
        key = key[0:len(binp)] # key를 plist의 길이에 맞게 자름

        input_enc = int(binp, 2) ^ int(key, 2) # binp와 key를 xor하여 input_enc에 저장
        print(f'input_enc: {input_enc}\n') # input_enc 값을 출력
        
        sys.exit() # 프로그램 종료
        
def main(): # main 함수
    o_key = flag_enc() # flag를 암호화 하고 key값을 받아 o_key에 저장
    n_key = key_gen(o_key) # key_gen으로 새 키 값을 받아 n_key에 저장 
    input_enc(n_key) # plain text를 받아 n_key로 암호화하고 프로그램 종료함


if __name__ == '__main__': # 스크립트를 직접 실행할 때
    main() #main 함수를 실행함

 

제공된 코드에서 암호화하는 과정을 요약해보면 아래와 같다.

flag_enc = flag ^ o_key

n_key = o_key ^ num

input_enc = plain_text ^ n_key

num은 코드에 주어져있고, flag_enc와 임의의 plain_text에 따른 input_enc는 서버에서 제공된다.

 

그러면 xor의 성질에 따른 복호화 과정은 아래와 같다.

o_key = n_key ^ num

n_key = input_enc ^ plain_text

=> o_key = input_enc ^ plain_text ^ num

=> flag = flag_enc ^ o_key

위 두 식을 코드로 구현했다.

from pwn import *

r = remote("host3.dreamhack.games", 20968)

r.recvuntil(b'flag_enc: ')
flag_enc = r.recvline()[:-1].decode()

r.sendlineafter(b'Plain text : ', b'0'*64)
r.recvuntil(b'input_enc: ')
input_enc = r.recvline()[:-1].decode()

r.close()

num = '0b10010110101011100100111011100101101011110011001110000101111010111110010111100000111110000000010101101011001100010100010101111000111111100010001010110000010111110111110010001111110011110101001011111010100101010100001110010111111010001101111110011001010110011001010101010000001010100000101101001010010010100010100001011101011011010011010101111111010010100111011001100000101011100001010111111101000110011000110101111111010111001101111110011101101100011101001111111000010011010111100010111001100101011111101111111001'
p = '0'*64

plist = ['0b'] 
for ch in p: 
    plist.append(format(ord(ch), 'b').zfill(8)) 
p_txt = "".join(plist)

o_key = int(input_enc)^int(p_txt,2)^int(num,2)
flag = bin(int(flag_enc,2)^o_key)

flag = ''.join(chr(int(flag[i:i+8], 2)) for i in range(0, len(flag), 8))


print(flag)

코드를 실행하면 아래와 같이 flag 값을 얻을 수 있다. 

'Write-up > Crypto' 카테고리의 다른 글

[Dreamhack] uncommon e  (0) 2024.11.15
[Dreamhack] 40 Birthdays  (0) 2024.11.08
[Dreamhack] No sub please!  (1) 2024.11.08
[Dreamhack] Insecure Seed  (0) 2024.10.31
[Dreamhack] Easy Linguistics  (0) 2024.10.24