Hitcon2018中lost key的wp。

image1

完整的代码如下:    
lostKeyExp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env python
from Crypto.Util.number import *
from pwn import *
from fractions import Fraction

def long_to_hex(num):
	hexnum = hex(num)[2:]
	if len(hexnum)%2:
		hexnum = "0"+hexnum  
	return hexnum

# context(log_level='debug')
p = process("./encrypt.py")

cipherflag =  int(p.recvlines(2)[1],16)

# get n 
r = []  # remainder
for i in [2,3,4,5]:
	p.sendlineafter("cmd:", "A")
	p.sendlineafter("input:", str(i).zfill(2))
	r.append(p.recvline())
	p.sendlineafter("cmd:", "A")
	p.sendlineafter("input:", str(hex(i**2)[2:]).zfill(2))
	r.append(p.recvline())
kn = []
for i in range(len(r)/2):
	kn.append(int(r[2*i],16)**2-int(r[2*i+1],16))
# print kn
gcd = kn[0]
for i in range(len(kn)):
	gcd = GCD(kn[i],gcd)
n = gcd
# print n

# get cipher256 which is 256^e mod n
p.sendlineafter("cmd:", "A")
p.sendlineafter("input:", "0100")  
cipher256 = int(p.recvline(),16)

# get lastbyte--k map
mapTable = {}
for i in range(256):
	mapTable[-i*n%256] = i
	
p.sendlineafter("cmd:", "B")
p.sendlineafter("input:", long_to_hex(cipherflag))
lastbyte = int(p.recvline(),16)  # the last byte of flag

# get flag
L=0  # the initial range of flag/n is [0,1)
for i in range(128):
	cipherflag = cipherflag * cipher256 % n
	p.sendlineafter("cmd:", "B")
	p.sendlineafter("input:", long_to_hex(cipherflag))
	temp_lastbyte = int(p.recvline(),16)
	k = mapTable[temp_lastbyte]
	L = L + Fraction(k, 256**(i+1))

flag = int(L*n)-int(L*n)%256+lastbyte
print long_to_hex(flag).decode('hex')
    注意到在编写脚本时只需要计算flag的下限即可,因为最终完成128次循环后,flag下限值 L 与flag之差是小于
256的,那么通过 L 和已知的flag的最后一个字节即可算出准确的flag,对应代码中第60行。
    本地测试结果如下:

image2