a good challenge in D-CTF 21-22. crypt 4 fun!

We try to search for relevant information about P2DPI , and find a paper in Github(The author is the author of this chal).

# Main Part:

n
''''''
class SR_Oracle():
	def __init__(self,g,h):
		self.g = g
		self.h = h
		self.k_sr = bytes_to_int(get_random_bytes(32))
	def compute_intermediate_rule(self,Ri):
		return Ri*self.k_sr
	def compute_obfuscated_tokens(self,ti_list):
		Ti_list=[]
		c = randint(0,2**32)
		for i in range(len(ti_list)):
			encrypted = int_to_bytes(self._encrypt(ti_list[i]).x)
			Ti_list.append(H2(c+i,encrypted))
		return (c,Ti_list)
	def _encrypt(self,msg):
		return (g*bytes_to_int(H1(msg))+h)*self.k_sr    
''''''
			if i == '1':
				n-=1
				if n < 1:
					exit()
				R = input().strip()
				Rinit = R.encode('utf-8') # 2lazy2compress
				R = R.split(' ')# 给 R 点
				R = ECC.EccPoint(int(R[0],16),int(R[1],16))
				sig = b64.b64decode(input().strip())# 对 Rinit 进行签名
				if R == g or R == h:
					print("Rule entropy too small.")
					exit()
				if not ver.verify(sig,Rinit):
					exit()
				s1 = SR.compute_intermediate_rule(R)
				print(hex(s1.x)[2:],hex(s1.y)[2:])
             elif i == '2':
				if n_traf:
					n_traf = False 
					c,Ti=SR.compute_obfuscated_tokens(tokenize(secure_message))
					print(str(c)+'|',end='')
					print(b64.b64encode(b''.join(Ti)).decode('utf-8'))

choice 1: to encrypt something by skRsk\cdot R , but RR can't be gg or hh . Also , you should sign the point.

choice 2: to encrypt secure message by compute_obfuscated_tokens

# Solution:

In this task,we act as a MB. And in this paper , we can see here( 3.3 Exhaustive message search vulnerability ).

image-20220213221849699

And find you can become an SR in a sense to encrypt msg without getting sk (k_SR) .

The implication is that you can do an MITM(man-in-the-middle) attack here.

That's the 1st step what you should do.

The next step is how to decrypt this token. We can find that if the secure message never changes , we just need to get a set of data.

''''''
IP = "35.246.134.224"
port = 32079
io = connect(IP, port)
io.recvuntil(b"Hello MiddleBox. Here is my g and h:\r\n")
data = io.recvline()
data = data.decode().strip().split()
g = (int(data[0], 16), int(data[1], 16))
data = io.recvline()
data = data.decode().split()
h = (int(data[0], 16), int(data[1], 16))
k0 = 233333
G = ECC.EccPoint(g[0], g[1])
H = ECC.EccPoint(h[0], h[1])
io.recvuntil(b"2. Get traffic\r\n")
P1 = k0 * G
io.sendline(b"1")
io.sendline((hex(P1.x)[2:] + " " + hex(P1.y)[2:]).encode())
sig = ver.sign((hex(P1.x)[2:] + " " + hex(P1.y)[2:]).encode())
io.sendline(b64.b64encode(sig))
data = io.recvline()
data = data.decode().split()
kG = ECC.EccPoint(int(data[0], 16), int(data[1], 16))
io.recvuntil(b"2. Get traffic\r\n")
P2 = k0 * H
io.sendline(b"1")
io.sendline((hex(P2.x)[2:] + " " + hex(P2.y)[2:]).encode())
sig = ver.sign((hex(P2.x)[2:] + " " + hex(P2.y)[2:]).encode())
io.sendline(b64.b64encode(sig))
data = io.recvline()
data = data.decode().split()
kH = ECC.EccPoint(int(data[0], 16), int(data[1], 16))
kG = pow(k0, n - 2, n) * kG
kH = pow(k0, n - 2, n) * kH
print("kG.x =", kG.x)
print("kG.y =", kG.y)
print("kH.x =", kH.x)
print("kH.y =", kH.y)
io.recvuntil(b"2. Get traffic\r\n")
io.sendline(b"2")
data = io.recvline()
data=data.decode().split('|')
c=int(data[0])
T=b64.b64decode(data[1].encode())
print(c)

Then, let's analyse the tokenize & compute_obfuscated_tokens .

We find that tokenize is so weak if you can know a block in it. and it's expressed in paper.

image-20220213223150492

The flag's format is CTF{sha256} . So we can get half a token block. But we don't know where the index of the flag is. It needs brute-force.( Only hexdigist(lower) * 4 * length(Ti) ).

image-20220213223103151

# Appendix:

This question is really interesting. Thanks to Ephvuln a lot !!!

I am honored to help him revise the blasting complexity of ASCII in the paper

请我喝[茶]~( ̄▽ ̄)~*

De3B4to 微信支付

微信支付

De3B4to 支付宝

支付宝