Wp for C1CTF2020's Crypto

先放一句话role=Tsunate;

题目倒是蛮好玩的

Base的千层套路

拿到的是一个base编码后的结果,写个脚本一直解码,最后得到flag

c1ctf{Ba5e_3nc0ding_i5_e4sy}

PigIsSoCute

题目给了一个piggggggg.txt,打开是base64编码的一个图片,在线转换一下得到一个图片

25.png

猪圈密码解一下得到一个字符串,根据题目描述尝试栅栏后得到一个有意义的字符串

c1ctf{pigissocutebutporkissoexp}

ezrsa

刚开始看到 $e=3$ ,而且三个密文都一样,并且比 $n$ 小得多,尝试直接开三次方后无果,其实是出题人自己把数据给错了,给的c根本就不是立方,直接就是flag。

后来更新了附件, $c$ 和 $n$ 大小差不多,但是给了三次加密,拓展欧几里得合并一下就有了

MITM

刚开始出题人把题目名称写错了哈哈哈哈哈

既然是中间人攻击,那么我们就应该在与A交互时伪装成B,在与B交互时伪装成A

过了pow之后给了 $g$ 和 $p$ ,这里一定要把和谁交互分清楚,因为出题人名字起的太像了,所以刚开始把自己给绕进去了,我们把与Hiro交互的数据统一加上Hiro前缀,把与Zero交互的数据统一加上Zero前缀,根据题目在[2,p-1)随便选个数计算 $Hiro_A =g^{Hiro_a}\ mod\ q$ ,并且得到 $Zero_A$ ,然后再与Hiro进行一次秘钥交换,得到 $Hiro_B$ 和 $ZeroB$ ,这样我们就可以得到与两个人分别的Key,因为 $Hiro_{Key}= {Hiro_B}^{Hiro_a} = {Hiro_A}^{Hiro_b}$ ,所以再两人交换 $m$ 时就可以进行自如的加密解密,最后得到的两个 $m$ 拼起来就是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
56
57
58
59
60
61
62
63
from string import digits, ascii_letters
from pwn import *
from hashlib import sha256
from Crypto.Util.number import *

table = digits+ascii_letters
r = remote("8.136.142.239", "30400")

def passpow():
rev = r.recvuntil("sha256(XXXX+")
suffix = r.recv(16).decode()
r.recvuntil(" == ")
res = r.recv(64).decode()
def f(x):
hashresult = hashlib.sha256((x+suffix).encode()).hexdigest()
if hashresult == res:
return 1
else:
return 0
prefix = util.iters.mbruteforce(f,table,4,'upto')
r.recvuntil("Give me XXXX:")
r.sendline(str(prefix))

passpow()
print('Successfully pass the pow!')

r.recvuntil("[Hiro]: g = ")
g = int(r.recvline(False).strip().decode())
r.recvuntil("[Hiro]: p = ")
p = int(r.recvline(False).strip().decode())

Hiro_a = 3
Hiro_A = pow(g,Hiro_a,p)
r.recvuntil("[Aside]: You intercepted Zero's message, which is `A = ")
Zero_A = int(r.recvuntil("`")[:-1].strip().decode())
r.recvuntil("> ")
r.sendline(str(Hiro_A))

Zero_b = 3
Zero_B = pow(g,Zero_b,p)
r.recvuntil("[Aside]: You intercepted Hiro's message, which is `B = ")
Hiro_B = int(r.recvuntil("`")[:-1].strip().decode())
r.recvuntil("> ")
r.sendline(str(Zero_B))

Hiro_Key = pow(Hiro_B,Hiro_a,p)
Zero_Key = pow(Zero_A,Zero_b,p)

r.recvuntil("[Aside]: You intercepted Hiro's message, which is `C_b = ")
Hiro_got = int(r.recvuntil("`")[:-1].strip().decode())
r.recvuntil("> ")
m = (Hiro_got * inverse(Hiro_Key,p)) % p
print(long_to_bytes(m))
Zero_give = (m * Zero_Key) % p
r.sendline(str(Zero_give))

r.recvuntil("[Aside]: You intercepted Zero's message, which is `C_a = ")
Zero_got = int(r.recvuntil("`")[:-1].strip().decode())
r.recvuntil("> ")
m = (Zero_got * inverse(Zero_Key,p)) % p
print(long_to_bytes(m))
Hiro_give = (m * Hiro_Key) % p
r.sendline(str(Hiro_give))

c1ctf{Dif7ie_he1lman_is_n0t_p3rfect}

aesstudy1

写题解之前说点有的没的,因为出题人太爱讲故事,所以…

26.png

题目就是套娃AES,给一步做一步就好了,

step1

给了key,给了msg,要我们返回加密后的结果

step2

看来半天不知道要我干啥,也不知道要我返回啥,自己一个人傻看了一个小时才去问了出题人

我怎么知道要把Tsunate换成Kakashi啊

因为AES是16个字节一块块加密的,而且是ECB模式,因为出题人的精心构造,正好4块并且结构很整齐,如下:

1
2
3
4
Tsunate can see 
AAA Message and
Kakashi can see
BBB Message.....

所以,只需要把第三块的密文覆盖到第一块再打回去就行了

另外,我怎么知道要把前面那句话一起打回去啊

step2过了之后就能拿到第一个flag了

setp3

要登录,并且一共有两块,第一块会作为iv和解密后的第二块异或,而题目告诉了我们明文第二块是MN;role=Konoha;,给第一块异或\x00\x00\x00\x00\x00\x00\x00\x00Kakashi;\x00\x00\x00\x00\x00\x00\x00\x00Tsunate;就可以使得明文变成role=Tsunate;

我怎么知道要换成Tsunate啊,不是Konoka的登录系统吗

step4

服务器提供一次AES的解密,让我们猜iv,我们给服务器发送32位\x00,得到两块结果,根据AES.CBC的解密,可以知道第一块是D(input1)^iv,第二块是D(input2)^input1,因为我们构造的input1input2都是16位\x00,所以这两块异或所得就是iv,再发回服务器就行了

step4过掉,第二个flag就拿到了

finalexp.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
62
63
64
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("8.136.131.7", "30339")

r.recvuntil("The key in hex is ")
key1 = long_to_bytes(int(r.recvuntil(',')[:-1].strip().decode(),16))
r.recvuntil("the msg in hex is ")
msg1 = long_to_bytes(int(r.recvuntil(',')[:-1].strip().decode(),16))
r.recvuntil("the AES-ECB-128 encryption:")

aes1 = AES.new(key1,AES.MODE_ECB)
cipher1 = aes1.encrypt(msg1)
cipher1 = hex(bytes_to_long(cipher1))[2:]
r.sendline(cipher1)

r.recvuntil(".....|")
cipher2 = r.recvline(False)
cipherlist = []
for i in range(4):
cipherlist.append(cipher2[i*32:(i+1)*32])
payload2 = b'Kakashi can see AAA Message and Kakashi can see BBB Message.....|'+cipherlist[2]+cipherlist[1]+cipherlist[2]+cipherlist[3]
r.recvuntil("Input the message after you modified:")
r.sendline(payload2)

r.recvuntil("And you interrupt the ciphertext ")
# m = b'SSID=AVsasbSJtpTMN;role=Konoha;'
iv = long_to_bytes(int(r.recv(32).strip().decode(),16))
cipher3 = r.recv(32)
r.recvline()
aaa = b' Kakashi;'
bbb = b' Tsunate;'
payload3 = ''
for i in range(len(aaa)):
tmp = aaa[i] ^ bbb[i] ^ iv[i]
payload3 += chr(tmp)
payload3 = payload3.encode('latin1')
payload3 = hex(bytes_to_long(payload3))[2:]
payload3 = payload3+str(cipher3)[2:-1]
r.sendline(payload3)

r.recvuntil('Input something:')
r.sendline('\x00'*32)
r.recvuntil('your input (in hex): ')
iiv = r.recvline(False)
print(iiv)
iiv1 = long_to_bytes(int(iiv[0:32].strip().decode(),16))
iiv2 = long_to_bytes(int(iiv[32:64].strip().decode(),16))
print(iiv1)
print(iiv2)
payload4 = ''
for i in range(len(iiv1)):
tmp = iiv1[i] ^ iiv2[i]
payload4 += chr(tmp)
payload4 = payload4.encode('latin1')
payload4 = hex(bytes_to_long(payload4))[2:]
r.recvuntil('Tell me the iv in hex:')
r.sendline(payload4)

r.interactive()

BuyAndSell 2

PaddingOracleAttack确实很简单,但这压轴web我是一点办法都没有(

我是废物!

假装自己AK了,爬了爬了