2024-强网拟态白盒资格赛-wp-Crypto

2024-强网拟态白盒资格赛-wp-crypto

今天是11月25日,周一。

三大项赛道第四,无人机赛道第七,不会挖洞ToT。

我对这件我做了一年的事情一直抱有十分复杂的情感,它是一个逃避的妙招,我可以以“我在努力”为由安慰自己,鼓励自己,欺骗自己,等等等等。

但是我还是做了,我确实做了,我用这个办法去逃避着我一直不想面对的很多东西,并且从中汲取可悲的幸福感。

信若心匪石席,何意卖弄所知?

漫道踌躇已久,已是旧时不识。

写写wp。

IMG_4042

broken_oracle

这一题其实第一想法是往一道日本的2016年的ctf题去想,一个中间位置的2字节选择密文攻击,但是一直没有思路。

其实这道日本的题也挺有意思的,也许可以讲一讲。

后来学长做出来了,在这里就把思路复现一下吧。

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
import socketserver
import signal
import os
import string
import random
from Crypto.PublicKey import RSA
from Crypto.Util.number import getPrime,getStrongPrime
from Crypto.Random import get_random_bytes


class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 4096
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()

def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass

def recv(self, prompt=b'> '):
self.send(prompt, newline=False)
return self._recvall()

def handle(self):
p=getStrongPrime(512)
q=getStrongPrime(512)
e=65537
n=p*q
phi=(p-1)*(q-1)
d=pow(e,-1,phi)
token=os.urandom(1000//8)
c=pow(bytes_to_long(token),e,n)
self.send(b"n=")
self.send(hex(n).encode())

self.send(b"your token is")
self.send(hex(c).encode())

signal.alarm(60)
for i in range(100):
self.send(b"give me your message to decrypt")
c=self.recv()
try:
c=int(c,16)
except:
self.send(b"wrong!")
self.request.close()


m=pow(c,d,n)
brokenm=m&((2**(40)-1)*(2**492))
self.send(hex(brokenm).encode())
self.send(b"give me your token")
t1=self.recv()
if bytes.fromhex(t1.decode())==token:
f=open("./flag","rb")
flag=f.read()
f.close()
self.send(flag)
else:
self.send(b"wrong! try again!")
self.request.close()


class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass


class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass


if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 9999
print("HOST:POST " + HOST+":" + str(PORT))
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()

其实思路也很简单,我们每次可以知道中间的40位,那么我们逐步乘2**12 得到$m_0+kn$,这个k不会很大,如果爆破出来的k能接近原来的中间四十位(类似),则说明这个k爆破成功。

然后我们对于每一次的比特泄露都缩小范围,近似确定即可。

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# from Crypto.Util.number import *
from gmpy2 import *
import hashlib
from string import ascii_letters, digits
from pwn import *
from itertools import product
import re
from fractions import Fraction
from Crypto.Util.number import *


def forty_bit_extractor(x):
a, b, length = 492, 531, 1000
x = bin(x)[2:].zfill(length)[::-1]
assert len(x[a:b + 1][::-1]) == 40
return x[a:b + 1][::-1]


table = ascii_letters + digits
context.log_level = 'debug'

class Solve():
def __init__(self):
self.sh = remote('172.25.19.4', 9999)
# self.sh = remote('127.0.0.1', 9999)

def proof_of_work(self):
sample1 = 'sha256(XXXX+EiHCHlPjoO2PnV2Z) == c4f17d1f76f7f11f75349dcd84f51b6e615aa756271841558ec8dda57e274959'
sample2 = 'Give me XXXX:'
proof = self.sh.recvuntil(sample2.encode()).decode()
t = re.findall(r'.*\+(\w+)\s==\s(.*)', proof)
tail = t[0][0]
_hash = t[0][1]
for i in product(table, repeat=4):
head = ''.join(i)
t = hashlib.sha256((head + tail).encode()).hexdigest()
if t == _hash:
self.sh.sendline(head.encode())
break

def inter(self, c, apx):
self.sh.recvuntil(b'give me your message to decrypt\n> ')
payload = hex(c * apx)[2:]
self.sh.sendline(payload.encode())
brokenm = self.sh.recvline().decode()[2:]
brokenm = int(brokenm, 16)
return brokenm

def solve(self):
e = 0x10001
self.sh.recvuntil(b"n=\n")
n = self.sh.recvline().decode()[2:]
n = int(n, 16)
self.sh.recvuntil(b"your token is\n")
c = self.sh.recvline().decode()[2:]
c = int(c, 16)

gift11 = []
gift11.append(self.inter(c, 1))
tmp = forty_bit_extractor(gift11[0])

hello = 0
for i in range(1, 42):
m0 = self.inter(c, pow(2, (12 * i) * e, n))
gift11.append(m0)
for k0 in range(2 ** 12):
x = (hello + k0) * n + m0
x = forty_bit_extractor(x)[:28]
for delta in [0, 1, -1]:
if x == bin(int(tmp[-28:], 2) + delta)[2:].zfill(28):
tmp = tmp[:-28] + forty_bit_extractor((hello + k0) * n + m0)
hello = (hello + k0) << 12
break
tmp = bin(int(tmp, 2) + 1)[2:].zfill(532) # but why?

hello = 0
mo = 2**12
L = Fraction(0, 1)
R = Fraction(1, 1)
cipher_power_mod_n = pow(mo, e, n)
tmp1 = forty_bit_extractor(gift11[0])
print(f"{len(gift11)=}")
for i in range(1, 42):
c = c * cipher_power_mod_n % n
for k0 in range(2 ** 12):
m0 = (hello + k0) * n + gift11[i]
x = forty_bit_extractor(m0)[:28]
for delta in [0, 1, 2]:
if x == bin(int(tmp1[-28:], 2) + delta)[2:].zfill(28):
L, R = L + Fraction(k0, mo ** (i + 42 + 1)), L + Fraction(k0 + 1, mo ** (i + 42 + 1))
tmp1 = tmp1[:-28] + forty_bit_extractor((hello + k0) * n + gift11[i])
hello = (hello + k0) << 12
break
for i in range(58):
self.inter(c, 1)
tmp1 = bin(int(tmp, 2))[2:].zfill(532)# but why?
print(bin(int(L*n)))
token = bin(int(L*n))[2:][:468] + tmp
print(token)
self.sh.recvuntil(b"give me your token\n")
self.sh.sendline(long_to_bytes(int(token, 2)).hex())
self.sh.interactive()


if __name__ == '__main__':
solution = Solve()
solution.solve()

notiv

1
2
3
4
from Crypto.Random import get_random_bytes

pad_x923=lambda x,block_size=16:x+get_random_bytes((block_size-(len(x)%block_size)-1))+bytes([(block_size-len(x)%block_size)])
unpad_x923=lambda x,block_size=16:x[:-((x[-1]-1)%block_size)-1]
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# !/usr/bin/env python
from hashlib import sha256
import socketserver
import os
import sys
import random
import signal
import string
from hashlib import sha256
from mypad import *

from Crypto.Cipher import AES
from random import *
from Crypto.Util.number import *


class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()

def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass

def recv(self, prompt=b'> '):
self.send(prompt, newline=False)
return self._recvall()

def close(self):
self.request.close()

def proof_of_work(self):
seed(os.urandom(8))
proof = ''.join(
[choice(string.ascii_letters+string.digits) for _ in range(20)])
_hexdigest = sha256(proof.encode()).hexdigest()
self.send(f"[+] sha256(XXXX+{proof[4:]}) == {_hexdigest}".encode())
x = self.recv(prompt=b'[+] Plz tell me XXXX: ')
if len(x) != 4 or sha256(x+proof[4:].encode()).hexdigest() != _hexdigest:
return False
return True

def handle(self):
try:
if not self.proof_of_work():
self.send(b"try again!")
self.close()
exit()

#signal.alarm(120)
count = 0
for _ in range(50):
seed(os.urandom(8))
key = pad_x923(b"")
chal = hex(getrandbits(64*3))[2:].zfill(16*3)

for i in range(200):
iv = long_to_bytes(getrandbits(128)).rjust(16, b"\00")
cipher = AES.new(key, AES.MODE_CBC, iv)
test = self.recv(b":> ").decode()
tb = bytes.fromhex(test)
ret = cipher.encrypt(pad_x923(tb))
if len(ret) > 16:
self.send(b"forbid")
continue
self.send((iv+ret).hex().encode())

s = self.recv(b">> ").decode()
iv = bytes.fromhex(s[:32])
ans = bytes.fromhex(s[32:])
cipher = AES.new(key, AES.MODE_CBC, iv)
att = cipher.decrypt(ans)
att = unpad_x923(att)
if att == chal.encode():
count += 1
self.send(b"you got %d score" % count)
if count >= 20:
f=open("./flag","rb")
FLAG=f.read()
f.close()
self.send(b"cong!your flag is "+FLAG)
else:
self.send(b"sorry,plz try again")
except:
self.send(b"something wrong! plz try again!")
self.close()


class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass


class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass


if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 12345
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()

这一题的思路其实在现场太紧张了,当时根本打不开,没有往字节反转的方向想。

解释一下,大概就是给了两百次给iv,同个key的加密机会,但是只能加密最多15字节,并且会有最后一个字节的扰动,但是这个最后一个字节固定是\x15。

我们的目标是我们加密一个48字节(因为padding实际上是64字节)的字符串然后给出iv解密并成功。

这个成功视作一个实验的话,五十次实验至少要成功二十次。

两百次iv实在是太多了,所以显然要先做梅森旋转爆随机数出来。

但是这里就花掉了156次,还剩44次。

也就是说,我们还知道44个可能的iv,能给我们加密。

我们需要回顾cbc的原理。

image-20240924201801788

第一层思路:我可以把这个四个分组的加密分别拆成四次,控制明文分组为我需要的明文分组和上一个密文分组的异或,从而顺利加密。
$$
myplain_i = plain_i \oplus cip_{i-1}
$$
这确实是最基本的思路,但是我们会发现明文的填充无法控制,这个时候就需要iv的帮助。

第二层思路:我可以遍历寻找44个iv,使得某个明文加密时,填充对其没有影响。
$$
((myplain_i\oplus iv_i)||0x15)\oplus iv_i = myplain_i
$$
等价于
$$
myplain_i[15] \oplus iv_i[15] = 0x15
$$
这也是第一时间能反应到的思路,但是我们会发现,$myplain_i$的最后一个字节有256种,然而我们能选择的$iv_i$只有44种,这意味着在256种$iv_i$中,我们需要恰好的4种,但是我们只能选44种,用超几何分布算一下这个概率大概只有0.07%。

我们再次审题计算50次实验成功20次的概率,几乎为0.

第三层思路:

4fdba66ae9e321614e09129a0027b9e7

如图所示,初始iv是我们给定的,因此第一步完全不用担心,我们需要的是知道一对由key加密的(cipher,plain),然而我们前156次加密恰好做了这样的事情。

我们假设需要解密出来的目标明文分别是$chal_1,chal_2,chal_3,chal_4$.

给定的解密密文分别是$c_1,c_2,c_3,c_4$.

我们有:

$$c_1= ENC(iv_{x}\oplus (plain_{x}|0x0f))$$

$$iv_1 = iv_{x}\oplus (plain_{x}|0x0f) \oplus chal_1$$

因此第一个成功的概率为1。$c_1$有156种可能。

但是后面就回到了我们的第二层思路,结合第三层思路,我们有第四层思路。

第四层思路:我们接下来要得到$c_2$,分析$c_2$的得到过程。

存在可能的$iv_i$和$c_1$:
$$
c_2 = ENC(chal_2 \oplus c_1) = ENC(((iv_i\oplus chal_2 \oplus c_1)||0x0f)\oplus iv_i)
$$
我们要在156*44种可能的$iv_i$和$c_1$对中寻找满足上式的$(iv_i,c_1)$.

其实也就是$(iv_i\oplus chal_2 \oplus c_1)[15]=0x0f$

经过查找,还是挺多的。大概在20-30个上下。

第二步解决。

第三步同理,我们要在$iv_i$之后的$iv_j$以及可能的$c_2$寻找:
$$
c_3 = ENC(chal_3 \oplus c_2) = ENC(((iv_j\oplus chal_3 \oplus c_2)||0x0f)\oplus iv_j)
$$
其实也就是$(iv_j\oplus chal_3 \oplus c_2)[15]=0x0f$

经过查找,大概是在2-4对左右。

第三步解决。

第四步其实已经很不容易了,在接下来的2-4对以及所剩无几的$iv_k$里还要找一对来满足上面的式子,显然是不足的(其实可能可以,多试几次,概率也不算太小)

但是我还是要说说我的一遍过思路qwq。

第五层思路:unpad存在问题。

其实这个是最先想到的,我觉得没有人会忍得住把它给出的pad和官方实现比较一下。

一比较就会发现,这个pad和unpad多了个余数。

这意味着,如果一个64字节的字符串去unpad,最后一个字节只要是16的倍数,最后都能unpad到相同的字节。

我们的第四步只需要让$c_4$的最后一个字节是16的倍数即可。

$(iv_k\oplus chal_4 \oplus c_3)[15]=0x10x$

所以在第四步中剩余的1-4对和剩下的iv中寻找16/256的可能,是大概足够的。

上述算法大概能在五十次内成功35次。

其实我觉得这题只能从贪心角度做可能会大大降低成功率,实际上也不会?

贴出wp

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
from exploit.mt19937.recoverMT19937 import *
from Crypto.Random import get_random_bytes
from hashlib import sha256
from pwn import *
from hashlib import sha256
from tqdm import trange
from Crypto.Cipher import AES
from Crypto.Util.number import *
from random import Random

context.log_level = "debug"
xor_bytes = lambda b1, b2: bytes(a ^ b for a, b in zip(b1, b2))
pad_x923=lambda x,block_size=16:x+get_random_bytes((block_size-(len(x)%block_size)-1))+bytes([(block_size-len(x)%block_size)])
unpad_x923=lambda x,block_size=16:x[:-((x[-1]-1)%block_size)-1]
from itertools import product
from string import ascii_letters, digits
table = ascii_letters + digits
def proof_of_work():
sample1 = '[+] sha256(XXXX+IhJ7E8Ybs24CFirU) == 6a7993845557327af63c683c46449a39a06f3306136fe0a44833b09ba1558ecd'
sample2 = '[+] Plz tell me XXXX: '

proof = sh.recvuntil(sample2.encode()).decode()
t = re.findall(r'.*\(XXXX\+(\w+)\)\s==\s(.*)\n.*', proof)
tail = t[0][0]
_hash = t[0][1]
for i in product(table, repeat=4):
head = ''.join(i)
t = hashlib.sha256((head + tail).encode()).hexdigest()
if t == _hash:
sh.sendline(head.encode())
break

#预测部分
def recover_chal(_key):
keys = []
for _ in _key:
i_key = bin(_)[2:].zfill(128)
for j in range(len(i_key) // 32 - 1, -1, -1):
keys.append(int(i_key[j * 32: (j + 1) * 32], 2))

parts = recover_state(keys[:624])
state = backtrace([0] * 4 + parts)[:624]
prng = Random()
prng.setstate((3, tuple(state + [0]), None))
k1, k2, k3, k4 = prng.getrandbits(32), prng.getrandbits(32), prng.getrandbits(32), prng.getrandbits(32)
chal = bin(k4)[2:].zfill(32) + bin(k3)[2:].zfill(32) + bin(k2)[2:].zfill(32) + bin(k1)[2:].zfill(32)
keys = [k4, k3, k2, k1] + keys
parts = recover_state(keys[:624])
state = backtrace([0] * 4 + parts)[:624]
prng = Random()
prng.setstate((3, tuple(state + [0]), None))
k1, k2, k3, k4 = prng.getrandbits(32), prng.getrandbits(32), prng.getrandbits(32), prng.getrandbits(32)
chal += bin(k4)[2:].zfill(32) + bin(k3)[2:].zfill(32)
return chal
def recover_iv(_key):
keys = []
for _ in _key:
i_key = bin(_)[2:].zfill(128)
for j in range(len(i_key) // 32 - 1, -1, -1):
keys.append(int(i_key[j * 32: (j + 1) * 32], 2))

parts = recover_state(keys[:624])
state = backtrace([0] * 4 + parts)[:624]
prng = Random()
prng.setstate((3, tuple(state + [0]), None))
# skip chal
for i in range(4):
prng.getrandbits(32)

iv = []
for i in range(200):
k1 = bin(prng.getrandbits(32))[2:].zfill(32)
k2 = bin(prng.getrandbits(32))[2:].zfill(32)
k3 = bin(prng.getrandbits(32))[2:].zfill(32)
k4 = bin(prng.getrandbits(32))[2:].zfill(32)
iv.append(k4 + k3 + k2 + k1)
return iv

def iv2random( iv):
return bytes_to_long(iv)

sh = remote("172.25.19.6",12345)
proof_of_work()
for xxx in range(50):
pairs = []
r = []
ivlist = []
plainlist = []
c1list = []
plaintext = b'30'*15
for i in range(156):
tb = os.urandom(15)
sh.sendlineafter(b':> ', tb.hex())
plainlist.append(tb)
iv_ret = bytes.fromhex(sh.recvline()[:-1].decode())
iv = iv_ret[:16]
ci = iv_ret[16:]
pairs.append([iv, ci])
c1list.append(ci)
r.append(iv2random(iv))
chal = recover_chal(r)
xx = recover_iv(r)
chal = hex(int(chal, 2))[2:].zfill(16 * 3)
chal1, chal2, chal3 = chal.encode()[:16], chal.encode()[16:32], chal.encode()[32:48]
ivlis = [long_to_bytes(int(i,2)) for i in xx]
ivlist = ivlis[:156]
ivlist2 = ivlis[-44:]
###

chal4list = [b'\x00' * 15 + bytes([i]) for i in range(0x10, 0x100, 0x10)]

tanxinlist = [[0,0,0] for _ in range(44)]
#如果ivi^chal2^c1的最后一位是\x01 则填充对其无影响
#我们寻找这个[ivi,c1]
succlistchal1 = []
succlistchal2 = []
succlistchal3 = []
x = 0

for i in ivlist2:
for j in c1list:
if xor_bytes(xor_bytes(i,j),chal2)[-1] == 1:
succlistchal1.append([i,j,x]) #j是c1
tanxinlist[x][0]+=1
x+=1

c2list = []
c3list = []
c4list = []
count = 0
for i in range(44):
if tanxinlist[i][2]!=0:
position = [index for index, sublist in enumerate(succlistchal3) if sublist[2] == i]
ivnew = succlistchal3[position[0]]
tb = xor_bytes(xor_bytes(ivnew[0],ivnew[1]),ivnew[3])[:15]
sh.sendlineafter(b':> ', tb.hex())
iv_ret = bytes.fromhex(sh.recvline()[:-1].decode())
x = iv_ret[16:]
c4list.append([x,ivnew[1],ivnew[4],ivnew[5]]) #4321
elif tanxinlist[i][1]!=0:
position = [index for index, sublist in enumerate(succlistchal2) if sublist[2] == i]
ivnew = succlistchal2[position[0]]
tb = xor_bytes(xor_bytes(ivnew[0],ivnew[1]),chal3)[:15]
sh.sendlineafter(b':> ', tb.hex())
iv_ret = bytes.fromhex(sh.recvline()[:-1].decode())
x = iv_ret[16:]
c3list.append([x,ivnew[2],ivnew[1],ivnew[3]]) #1是c2 3是c1
for c3l in c3list:
x = c3l[1]
for ivi in ivlist2[c3l[1]+1:]:
x+=1
for chal4 in chal4list:

# print(c2l[0],ivi,chal3)
# print(xor_bytes(xor_bytes(c2l[0],ivi),chal3))
if xor_bytes(xor_bytes(c3l[0],ivi),chal4)[-1] == 1 and tanxinlist[ivlist2.index(ivi)][2]==0:
succlistchal3.append([ivi,c3l[0],x,chal4,c3l[2],c3l[3]]) #c3l0是c3 c3l1-c2 c3l3-c1
tanxinlist[ivlist2.index(ivi)][2]+=1
print(tanxinlist)

if(succlistchal3):
count+=1
elif tanxinlist[i][0]!=0: #i是位置
position = [index for index, sublist in enumerate(succlistchal1) if sublist[2] == i]
ivnew = succlistchal1[position[0]]
tb = xor_bytes(xor_bytes(ivnew[0],ivnew[1]),chal2)[:15]
sh.sendlineafter(b':> ', tb.hex())
iv_ret = bytes.fromhex(sh.recvline()[:-1].decode())
x = iv_ret[16:]
c2list.append([x,ivnew[2],ivnew[1]])
# print(ivlist2)
for c2l in c2list:
x = c2l[1]
for ivi in ivlist2[c2l[1]+1:]:
x+=1
# print(c2l[0],ivi,chal3)
# print(xor_bytes(xor_bytes(c2l[0],ivi),chal3))
if (xor_bytes(xor_bytes(c2l[0],ivi),chal3)[-1] == 1) and tanxinlist[ivlist2.index(ivi)][1]==0:
succlistchal2.append([ivi,c2l[0],x,c2l[2]]) # c2l[0]是c2 2是c1
tanxinlist[ivlist2.index(ivi)][1]+=1
# print(tanxinlist)
print(len(succlistchal2))

# print(succlistchal2)
else:
tb = os.urandom(15)
sh.sendlineafter(b':> ', tb.hex())
iv_ret = bytes.fromhex(sh.recvline()[:-1].decode())

if(c4list):
where = c1list.index(c4list[0][3])
ivfirst = xor_bytes(xor_bytes(pad_x923(plainlist[where]),ivlist[where]),chal1)
print("@@@",chal.encode())
print(c4list[0])
end = c4list[0][3]+c4list[0][2]+c4list[0][1]+c4list[0][0]
print(ivfirst.hex())
print(end.hex())
fate = ivfirst.hex()+end.hex()
sh.sendlineafter(b'>> ', fate)
else:
fate = os.urandom(16+64).hex()
sh.sendlineafter(b'>> ', fate)
sh.recvline()
sh.recvline()
sh.recvline()

令人感叹,做出了大家做不出来的题,那天晚上5点在酒店鏖战,即使加起来只有1500分,但是难得的很有成就感。

但是跟nebula,cnss相比还是很有差距啊。

继续努力吧。


2024-强网拟态白盒资格赛-wp-Crypto
https://py-thok.github.io/2024/11/25/2024-强网拟态白盒资格赛-wp-Crypto/
作者
PYthok-Ptk
发布于
2024年11月25日
许可协议