Hacking/DreamHack

textbook-des__crypto

SurTesterS 2024. 5. 7. 23:35

1. 코드 분석

class TDES:
    def __init__(self, key1, key2):
        assert len(key1) == 8
        assert len(key2) == 8
        self.keys = [key1, key2, key1]
        self.cipher = [DES.new(key, DES.MODE_ECB) for key in self.keys]
        self._block_size = 16

    def encrypt(self, plaintext, mode):
        assert len(mode) == 3
        for m in mode:
            assert m in 'ED'
        assert len(plaintext) % self._block_size == 0

        for cipher, m in zip(self.cipher, mode):
            if m == 'E':
                plaintext = cipher.encrypt(plaintext)
            else:
                plaintext = cipher.decrypt(plaintext)
        return plaintext
#zip 함수는 self.cipher[::-1]과 mode[::-1]의 요소들을 짝지어줍니다.

    def decrypt(self, plaintext, mode):
        assert len(mode) == 3
        for m in mode:
            assert m in 'ED'
        assert len(plaintext) % self._block_size == 0

        for cipher, m in zip(self.cipher[::-1], mode[::-1]):
            if m == 'D':
                plaintext = cipher.encrypt(plaintext)
            else:
                plaintext = cipher.decrypt(plaintext)
        return plaintext

 

코드를 보면 TDES 는 key1, key2 에 따라 DES 모드로 encrypt, decrypt 를 세번 수행하며, 모드는 'E', 'D' 로 설정이 된다. 

결국, EDE로 암호화 된 flag 를 DED 모드로 복호화 할 수 없기 때문에, 모드의 조합으로 decrypt 된 flag 를 구할 수 있다.

 

Fenc = (E1 ○ D2 ○ E1) P(평문) 

위에서  E1을 삭제 하기 위해  DDD 암호화 사용

Fenc1=(D1 ○ D2 ○ D1 ○   E1 ○ D2 ○ E1) P(평문) => (D1 ○ D2 ○ D2 ○ E1) P(평문)

E1 삭제를 위해 EED 암호화 사용

Fenc2 = (D1 ○  E2 ○  E1 ○  D1 ○ D2 ○ D2 ○  E1) P(평문) => (D1 ○ D2  ○  E1) P(평문)

EED 암호화 사용

Fenc2 = ( D1 ○  E2 ○ E1 ○ D1 ○ D2 ○ E1) P(평문) =>  P(평문)

 

2. solve.py

from pwn import *


def menu_enc(msg, mode):
    p.sendlineafter('> ', '1')
    p.sendlineafter('> ', msg)
    p.sendlineafter('> ', mode)
    p.recvuntil('> ')
    msg_enc = p.recvline()[:-1].decode()
    return msg_enc


# p = process(["python3", "./prob.py"])
p = remote('host3.dreamhack.games',0000)

p.sendlineafter('> ', '2')
p.recvuntil('> ')
flag_enc = p.recvline()[:-1].decode()

plain1 = menu_enc(flag_enc, 'DDD')
plain2 = menu_enc(plain1, 'EED')
flag = menu1(plain2, 'EED')
flag_byte = bytes.fromhex(flag)

print(flag)
print(flag_byte)

#p.interactive()

 

3. 결과 값