[CTF] TokyoWesternsCTF2020

Easy_hash(crypto)

レ(゚∀゚;)ヘ=З=З=З 2023. 12. 21. 10:25
728x90

주어진 코드

import struct
import os   
MSG = b'twctf: please give me the flag of 2020'
assert os.environ['FLAG']
def easy_hash(x):
    m = 0
    for i in range(len(x) - 3):
        m += struct.unpack('<I', x[i:i + 4])[0]
        m = m & 0xffffffff
    return m
def index(request):
    message = request.get_data()
    if message[0:7] != b'twctf: ' or message[-4:] != b'2020':
        return b'invalid message format: ' + message
    if message == MSG:
        return b'dont cheet'
    msg_hash = easy_hash(message)
    expected_hash = easy_hash(MSG)
    if msg_hash == expected_hash:
        return 'Congrats! The flag is ' + os.environ['FLAG']
    return 'Failed: easy_hash({}) is {}. but expected value is {}.'.format(message, msg_hash, expected_hash)

 

easy_hash(x)함수를 먼저 해석해 보았다. struct.unpack(‘는 struck.unpack(format, buffer)의 형태로 쓰여지고 format은 포맷 문자열이며 format에 따라 buffer에서 언패킹이 된다.

포맷 문자열은 데이터의 패킹 및 언패킹 시 기대되는 배치를 지정하는데 사용되는 메커니즘이다. 문자열의 첫 번째 문자를 사용하여 패킹 된 바이트 순서, 크기, 정렬 표시가 가능하다. 

포맷 문자열에서 사용된 것은 문자인 ‘<’가 있는데, 이것은 리틀 엔디안이다. 엔디안은 1차원에서 연속된 대상을 배열하는 방법이며 바이트 순서라고도 하고 이 중 리틀 엔디안은 작은 단위가 앞에 오는 배열 방법이다.  두 번째로 사용된 것은 포맷문자 ‘I’이다. ‘I’는 int, 정수형이고 표준크기가 4이다.

12번째 줄에서 사용된 0xffffffff는 unsigned int로 변환시켜주는 역할을 한다.

즉, easy_hash(x)함수에서는 4만큼의 크기를 가지고 리틀 엔디안을 따르며 값을 언패킹하며 m에 그 값들을 더한다.. 그리고 m값은 다시 unsigned int로 변환시켜주어 최종적으로m을 return하는 것이다.

 

해결과정

easy_hash(x) 함수에서 unpack했을 때 ‘0’의 값을 갖는 문자를 추가한다. 

따라서 MSG(b’twctf: please give me the flag of 2020’)에 \x00값이 추가하게 되면 p’twctf: please give me the flag if \x002020이 된다. 이렇게 되면 해시는 유지되면서 메시지는 다르게 되어 Flag값을 얻을 수 있게 된다. Flag을 얻기 위해 변경한 MSG값을 requests.post하여 print하면 성공한다.

1) cmd창에서 python에 접속하였다.

2)

requests를 쓰기 위하여 import requests 하였다.

3)

Flag을 받아올 변수를 M으로 지졍하여 requests.post에 MSG를 전달해 Flag를 받아왔다.

4)

받아온 M값을 M.text로 출력하였다.

5)

Flag인 TWCTF{colorfully_decorated_dream}을 얻었다.

 

 

 

 

'[CTF] TokyoWesternsCTF2020' 카테고리의 다른 글

urlcheck v1(webhacking)  (0) 2023.12.21
Mask(misc)  (0) 2023.12.21