rsa를 기반으로 한 significant 프로그램이다. server.py, diysig.py, chall.txt가 주어진다.
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
'Writeup [crypto] > CTF 대회 기출' 카테고리의 다른 글
[zer0pts CTF 2020] dirty laundry (0) | 2020.03.17 |
---|---|
[zer0pts CTF 2020] nibelung (0) | 2020.03.14 |
[zer0pts CTF 2020] ROR (0) | 2020.03.10 |
[TUCTF 2018] XORientYourself (0) | 2020.03.08 |
[TokyoWesterns CTF 4th 2018] Revolutional Secure Angou (0) | 2020.03.08 |