[DreamHack] [Crypto] 이상한 랜섬웨어 - Revenge

image.png

image.png

역시 새벽 시간이라서 운 좋게 퍼블에 성공했다.

난이도는 어렵지 않다.

같은 출제자님의 기존 이상한 랜섬웨어의 Revenge 버전이라, 업그레이드 됐을 것이라고 생각한다.

정확하게는 기존 문제를 풀어보질 않아서 잘 모르겠다…

분석 시작하겠다.

import hashlib
import random
import os

k = b"DH{??????????????????????????????????????????????????????????????}"

def a(data, uk):
    seed = int.from_bytes(hashlib.md5(uk).digest(), 'big')
    random.seed(seed)
    indices = list(range(len(data)))
    random.shuffle(indices)
    return bytes([data[i] for i in indices])

def ra(data, uk):
    seed = int.from_bytes(hashlib.md5(uk).digest(), 'big')
    random.seed(seed)
    indices = list(range(len(data)))
    random.shuffle(indices)
    result = [0] * len(data)
    for orig, shuf in enumerate(indices):
        result[shuf] = data[orig]
    return bytes(result)

def b(data, k):
    k_stream = hashlib.sha256(k).digest()
    return bytes([b ^ k_stream[i % len(k_stream)] for i, b in enumerate(data)])

def c(data, k):
    uk = b"cry_me_a_river"
    pw = str(0x????).encode() # 0x000 ~ 0xffff
    salt = b"ransomrevenge"
    
    dk = hashlib.pbkdf2_hmac('sha256', pw, salt, 1000, dklen=32)
    s1 = int.from_bytes(hashlib.md5(pw).digest()[:4], 'big')
    s2 = int.from_bytes(hashlib.md5(dk).digest()[:4], 'big')
    
    ad = a(data, uk)
    
    random.seed(s1)
    indices = list(range(len(ad)))
    random.shuffle(indices)
    shuffled1 = bytes([ad[i] for i in indices])
    
    xored = b(shuffled1, dk)
    
    random.seed(s2)
    indices = list(range(len(xored)))
    random.shuffle(indices)
    final = bytes([xored[i] for i in indices])
    
    return final

if not os.path.exists('flag.txt'):
    with open('flagg.txt', 'rb') as f:
        plain = f.read().strip()
    lol = c(plain, k)
    with open('flag.txt', 'wb') as f:
        f.write(lol)

flagg.txt 파일이 존재하면 open을 사용하지만, 해당 파일은 첨부파일에 존재하지 않는다.

flag.txt 파일을 확인해보면, 암호화된 형식의 내용이 보인다.

아마도 바이너리 형태인 것 같다. open() 명령어로 ‘rb’로 읽는 이유가 이 파일이 바이너리 형식이라 그런 것 같다.

조금 헤맸던 이유는 문제의 힌트 때문이였다.

발표 자료의 첫 글자가 W로 시작한다고 적혀 있는데, 그걸 flag의 첫 글자라고 생각했다..

DH{W..} 형태의 flag값이라고 생각해서 그것만 검색하다가 값을 제대로 못찾았다.

문제 힌트에서 주어진 첫 글자 W 는 모든 평문의 첫 글자였다.

어쩐지 flag.txt 파일의 길이가 길더라..