Wp for SWPUTF2020's Crypto

很无语,T1刚开始数据给错,T2T3连不上,活活让人等到中午才更新

Happy

基础RSA,题目给出 $q+q\cdot p^3$ 和 $q\cdot p+q\cdot p^2$

我们简记为 $data_1$ 与 $data_2$ ,那么显然有 $data_1=q\cdot(p^3+1)$ 、 $data_2=q\cdot(p^2+p)$ 、 $data_1+3\cdot data_2=q\cdot(p^3+3p^2+3p+1)=q\cdot(p+1)^3$ 且 $gcd(data_1,data_2)=q\cdot(p+1)$ ,那么显然可得 $p=\sqrt{ \frac{data_1+3\cdot dota_2}{gcd(data_1,data_2)}}-1$ ,随后可得 $q=\frac{data_1}{p^3+1}$

然后RSA相关的数据都有了,直接解密即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from Crypto.Util.number import *
from gmpy2 import *

c = 0x7a7e031f14f6b6c3292d11a41161d2491ce8bcdc67ef1baa9e
e = 0x872a335
data1 = 1285367317452089980789441829580397855321901891350429414413655782431779727560841427444135440068248152908241981758331600586
data2 = 1109691832903289208389283296592510864729403914873734836011311325874120780079555500202475594

qp1 = gcd(data1,data2)
qwq = data1 + 3*data2

p12 = qwq // qp1
p = iroot(p12,2)[0] - 1
q = data1 // (p**3 + 1)

n = p * q
phi = (p-1) * (q-1)
d = inverse(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))

flag{happy_rsa_1}

Yusa的密码学课堂_CBC第一课

服务器提供了加密和解密,加密时会把iv给我们,并且要使得解密后的明文为yusayusayusayusaadmin

我们记第一块区域yusayusayusayusa记为pre块,第二块为name块,我们需要在保证pre块不变的情况下改变name块,由于是CBC模式,所以payload需要从后往前构造

首先使用11111进行注册,给pre块异或11111admin得到new_pre后即可达到将name变为admin的目的,但是这样会使得D(new_pre)块不可控,所以我们重新构造一个new_iv(比如1111111111111111),得到的结果即为D(new_pre)^new_iv,所以我们即可构造fianl_ivyusayusayusayusa异或D(new_pre),最终得到payload=final_iv+new_pre+name,将其打回服务器即可

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
from string import digits, ascii_letters
from pwn import *
from hashlib import sha256
from Crypto.Util.number import *
from Crypto.Cipher import AES

table = digits+ascii_letters
r = remote("das.wetolink.com", "42888")

r.recvuntil('3. exit')
r.sendline('1')
r.recvuntil("What's your name?")
r.sendline('11111')
r.recvuntil('Here is your token(in hex): ')
iv = long_to_bytes(int(r.recv(32).strip().decode(),16))
pre = long_to_bytes(int(r.recv(32).strip().decode(),16))
name = long_to_bytes(int(r.recv(32).strip().decode(),16))
string1 = b'admin '
string2 = b'11111 '

new_pre = ''
for i in range(16):
x = pre[i] ^ string1[i] ^ string2[i]
new_pre += chr(x)
new_pre = new_pre.encode('latin1')

new_iv = b'1'*16
payload = new_iv+new_pre+name
payload = hex(bytes_to_long(payload))[2:]
r.recvuntil('3. exit')
r.sendline('2')
r.recvuntil('Your token(in hex): ')
r.sendline(payload)
r.recv(32)
res = long_to_bytes(int(r.recv(32).strip().decode(),16))

qwq = b'yusa'*4
finalpayload = ''
for i in range(16):
x = qwq[i] ^ res[i] ^ new_iv[i]
finalpayload += chr(x)
finalpayload = finalpayload.encode('latin1')
finalpayload = finalpayload+new_pre+name
finalpayload = hex(bytes_to_long(finalpayload))[2:]
print(finalpayload)
r.recvuntil('3. exit')
r.sendline('2')
r.recvuntil('Your token(in hex): ')
r.sendline(finalpayload)

r.interactive()

Yusa的密码学课堂_ECB

Key固定,服务器提供输入一个字符串并将flag加在后面加密返回

我们先提交aaaaaa……通过观察返回加密结果的长度可以测得flag的长度(即构建padding

因为是ECB,没有iv混淆情况下,如果明文一致,密文一定是一致的,所以我们可以通过将flag一位一位推至下一个加密块,并且构建一个新块来进行爆破,找到一位即可加入已知flag来进行下一次爆破

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
from pwn import *
from hashlib import sha256
from Crypto.Util.number import *
from Crypto.Cipher import AES

BLOCKSIZE = 16
def pad(data):
pad_len = BLOCKSIZE - (len(data) % BLOCKSIZE) if len(data) % BLOCKSIZE != 0 else 0
return data + chr(pad_len) * pad_len

table = '1234567890qwertyuiopasdfghjklzxcvbnm{}'

r = remote("das.wetolink.com", "42887")
cnt = 0

def talk(x):
r.recvuntil('Amazing function: ')
r.sendline(x)
res = r.recvline(False)
return res.strip().decode()

def get(x):
x = hex(bytes_to_long(x.encode('latin1')))[2:]
return talk(x)

def put(x):
s = 'b' * x
return s

flaghash = talk('')
while(True):
cnt += 1
payload = '00'*cnt
tmp = talk(payload)
if(len(tmp) != len(flaghash)):
cnt -= 1
break
flaglen = len(flaghash) // 32 * 16 - cnt
need = 'a'*cnt

mine = ''
now = 1
for i in table:
tmp = pad(i + mine[:16])
if(len(tmp)!=16):
tmp += ' ' * (16 - len(tmp))
payload = tmp + need + put(now)
res = get(payload)
if(res[:32] == res[-32*(1+now//32):-32*(now//32)]):
mine = i + mine
print(mine)
now += 1
break

# r.interactive()

flag{7241502d1f614bf28bbaa4e898e9893e}

AK啦!溜~