[CryptoHack] Collider

모든 문서가 해시에 의해 참조되는 자신의 입자 물리학 문서를 확인하라고 한다. 문제 파일을 보자.

import hashlib
from utils import listener


FLAG = "crypto{???????????????????????????????????}"


class Challenge():
    def __init__(self):
        self.before_input = "Give me a document to storen"
        self.documents = {
            "508dcc4dbe9113b15a1f971639b335bd": b"Particle physics (also known as high energy physics) is a branch of physics that studies the nature of the particles that constitute matter and radiation. Although the word particle can refer to various types of very small objects (e.g. protons, gas particles, or even household dust), particle physics usually investigates the irreducibly smallest detectable particles and the fundamental interactions necessary to explain their behaviour.",
            "cb07ff7a5f043361b698c31046b8b0ab": b"The Large Hadron Collider (LHC) is the world's largest and highest-energy particle collider and the largest machine in the world. It was built by the European Organization for Nuclear Research (CERN) between 1998 and 2008 in collaboration with over 10,000 scientists and hundreds of universities and laboratories, as well as more than 100 countries.",
        }

    def challenge(self, msg):
        if "document" not in msg:
            self.exit = True
            return {"error": "You must send a document"}

        document = bytes.fromhex(msg["document"])
        document_hash = hashlib.md5(document).hexdigest()

        if document_hash in self.documents.keys():
            self.exit = True
            if self.documents[document_hash] == document:
                return {"error": "Document already exists in system"}
            else:
                return {"error": f"Document system crash, leaking flag: {FLAG}"}

        self.documents[document_hash] = document

        if len(self.documents) > 5:
            self.exit = True
            return {"error": "Too many documents in the system"}

        return {"success": f"Document {document_hash} added to system"}


"""
When you connect, the 'challenge' function will be called on your JSON
input.
"""
listener.start_server(port=13389)

 

documents에 두 개의 해시값이 저장되어 있다.

challenge 함수에서는 내가 전송한 문자열의 md5 해시값을 계산하고, 이것이 documents에 저장된 해시값과 동일하지만 기존의 평문은 이와 동일하지 않다면 flag를 출력해준다.

따라서 second pre-image를 구하는 문제가 된다.

그런데 아무리 생각해도 second pre-image를 구하는 방법이 떠오르지 않았고, 브루트 포싱으로도 불가능하다는 것을 깨달았다.

 

그래서 코드를 다시 보니, document에 없는 해시값이면 새롭게 추가하는 부분을 발견했다.

이 말은 즉슨, 굳이 기존 documnet에 포함된 값이 아니더라도, 내가 추가한 값과 같은 해시값을 가지면서 평문은 다른, 즉 collision 쌍을 알 수 있다면 해결 가능하다고 생각했다!

 

md5 충돌쌍을 얻기 위해서는 seed lab의 md5collgen 함수를 이용할 수 있지만,, 이미 다 지워버려가지고 다시 깔기 귀찮아서 그냥 인터넷어 떠도는 충돌쌍을 하나 얻어냈다.

 

이 두 평문이 같은 해쉬값을 가진다고 한다.

import hashlib

a="d131dd02c5e6eec4693d9a0698aff95c2fcab58712467eab4004583eb8fb7f8955ad340609f4b30283e488832571415a085125e8f7cdc99fd91dbdf280373c5bd8823e3156348f5bae6dacd436c919c6dd53e2b487da03fd02396306d248cda0e99f33420f577ee8ce54b67080a80d1ec69821bcb6a8839396f9652b6ff72a70"
b="d131dd02c5e6eec4693d9a0698aff95c2fcab50712467eab4004583eb8fb7f8955ad340609f4b30283e4888325f1415a085125e8f7cdc99fd91dbd7280373c5bd8823e3156348f5bae6dacd436c919c6dd53e23487da03fd02396306d248cda0e99f33420f577ee8ce54b67080280d1ec69821bcb6a8839396f965ab6ff72a70"

a1=bytes.fromhex(a)
a_hash=hashlib.md5(a1).hexdigest()

b1=bytes.fromhex(b)
b_hash=hashlib.md5(b1).hexdigest()

print(a_hash)
print(b_hash)

 

실제로 코드로 확인해봤더니 같은 해쉬값을 가지고 있었다.

이제 이 충돌쌍을 가지고 payload를 작성해주었다.

from pwn import *
import json

context.log_level='debug'

p = remote('socket.cryptohack.org', 13389)

p.recvline()

a="d131dd02c5e6eec4693d9a0698aff95c2fcab58712467eab4004583eb8fb7f8955ad340609f4b30283e488832571415a085125e8f7cdc99fd91dbdf280373c5bd8823e3156348f5bae6dacd436c919c6dd53e2b487da03fd02396306d248cda0e99f33420f577ee8ce54b67080a80d1ec69821bcb6a8839396f9652b6ff72a70"
b="d131dd02c5e6eec4693d9a0698aff95c2fcab50712467eab4004583eb8fb7f8955ad340609f4b30283e4888325f1415a085125e8f7cdc99fd91dbd7280373c5bd8823e3156348f5bae6dacd436c919c6dd53e23487da03fd02396306d248cda0e99f33420f577ee8ce54b67080280d1ec69821bcb6a8839396f965ab6ff72a70"

# JSON 데이터 생성
data = {
    "document": a
}

# JSON 데이터를 서버로 전송
p.sendline(json.dumps(data))

# 서버로부터 응답 받기
response = p.recvline()

data = {
    "document": b
}

# JSON 데이터를 서버로 전송
p.sendline(json.dumps(data))

# 서버로부터 응답 받기
response = p.recvline()

p.interactive()

 

먼저 a를 보내서 새로운 해시값을 document에 추가한다. 그리고 b를 보내면 이는 평문은 다르지만 해시값이 같은 충돌쌍이기에 flag를 출력하게 된다.

실행결과는 위와 같다.

flag를 얻어낼 수 있었다!

🚩 crypto{m0re_th4n_ju5t_p1g30nh0le_pr1nc1ple}

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤