rsa를 기반으로 한 significant 프로그램이다. server.py, diysig.py, chall.txt가 주어진다.

diysig.zip
0.00MB

    def verify(self):
        sock = self.request
        b2s = lambda ba: ''.join(list(map(chr, ba)))
        s2b = lambda st: b''.join(list(map(lambda c: bytes([ord(c)]), list(st))))

        sock.send(b"ENC : ")
        enc = self.recvline()
        sock.send(b"SIG : ")
        sig = self.recvline()
        if enc is None or sig is None:
            return

        try:
            if len(enc) % 2 == 1:
                enc = b'0' + enc
            c = int.from_bytes(bytes.fromhex(b2s(enc)), byteorder='big')
            h = int.from_bytes(bytes.fromhex(b2s(sig)), byteorder='big')
            s = DIYSig()
            H = s.getsig(c)
        except Exception as e:
            print("[verify] {}".format(e))
            return

        if h == H:
            sock.send(b"Signature OK!\n")
        else:
            sock.send(s2b("Invalid Signature: {:08x} != {:08x}\n".format(h, H)))

맨 밑줄에서 해시값이 틀리면 뭐랑 뭐가 틀렸는지 출력을 해줘서 해시값을 알 수가 있다.

    def _hash(self, m):
        """ DIY Hash Function """
        H = 0xcafebabe
        M = m
        # Stage 1
        while M > 0:
            H = (((H << 5) + H) + (M & 0xFFFFFFFF)) & 0xFFFFFFFF
            M >>= 32
        # Stage 2
        M = H
        while M > 0:
            H = ((M & 0xFF) + (H << 6) + (H << 16) - H) & 0xFFFFFFFF
            M >>= 8
        # Stage 3
        H = H | 1 if m & 1 else H & 0xfffffffe
        return H

Stage 3에 의해, m이 짝수면, 해시도 짝수, 홀수면 해시도 홀수이다. 흔한 LSB 문제이다.

 

Exploit Code

from pwn import *
from Crypto.Util.number import *

n = 0x6d70b5a586fcc4135f0c590e470c8d6758ce47ce88263ff4d4cf49163457c71e944e9da2b20c2ccb0936360f12c07df7e7e80cd1f38f2c449aad8adaa5c6e3d51f15878f456ceee4f61547302960d9d6a5bdfad136ed0eb7691358d36ae93aeb300c260e512faefe5cc0f41c546b959082b4714f05339621b225608da849c30f
e = 0x10001
c = 0x3cfa0e6ea76e899f86f9a8b50fd6e76731ca5528d59f074491ef7a6271513b2f202f4777f48a349944746e97b9e8a4521a52c86ef20e9ea354c0261ed7d73fc4ce5002c45e7b0481bb8cbe6ce1f9ef8228351dd7daa13ccc1e3febd11e8df1a99303fd2a2f789772f64cbdb847d6544393e53eee20f3076d6cdb484094ceb5c1

m = 0
cnt = 0
i = 0
while True:
    p=remote('18.179.178.246', 3001)
    p.sendlineafter('> ', '2')
    p.sendlineafter('ENC : ', str(hex(c))[2:])
    p.sendlineafter('SIG : ', '00000000')
    p.recvuntil('!= ')
    sig = int(p.recv(8), 16) - (m * pow(inverse(2, n), i, n)) % n
    if sig%2 == 0:
        #print('MSB is 0!')
        cnt += 1
    else:
        #print('MSB is 1!')
        m=pow(2, i)+m
        cnt = 0

    if cnt > 10:
        break
    p.close()
    c = c * pow(inverse(2, n), e, n) % n
    i += 1
    print long_to_bytes(m)

Capture the Flag

image


+ Recent posts