0%

鲲鹏杯复现

前言:被鲲鹏杯搞晕了,赶紧复现,不然下次遇到了还是不会

初赛

Crypto

ez_fermat

题目如下:

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


p = getPrime(1024)
q = getPrime(813)
n = p * q
d = p
e = inverse(d, (p-1)*(q-1))
flag = b'NSSCTF{test_flag}'
m = bytes_to_long(flag)

print(n)
print()
print(e)
print()
print(pow(m, e, n))
'''
3904054379768621006670325403570678966655298185942026071119847032293541155818374237757771677885218395571231995625009566193044227004214661252741440763224075564545575267406326084344024197161667257443366163987563451174836819677982948383967049594961135059796888603091106117040559333549933923156522162926214187395074971581109581699786654634096916190024297067217856502521108656019066292650847674105723870976455422998577177791829507752873186832882421485628003948270492309102429874674621180956748281541598316433735992507502375267828628254040129556944239703219983

3346908455447174070992347616941127803725226412626643481301959623252314393488983877743239835001359838967907152394787518896740138558902876270534420306764838402995141451795721684856954259250045263865518237097216558225597879130005447703355004165638668981119439658709484546611239237700677748062521167324245405513546072909746940831890185954341722008854937777778339786187857409646068034455661780649005707291091511164030224458109751999287771088477121459794784223018351072171477613383398898036040202088356029117418211176259340287391200019380649219787316637601225

2297172673207318067644454311791059052521405524072070001463617943081937620680287073877519555417893924987805372814004437226029332185689205902364556330396100859963867726856821821201929153299863158902425114650689181400700850662495351899097507167512372167222348638943031627163322963150031484905075884684966357856735997039021272911282595603222713567742142545540368250995582560658624441813641267178033998653769097632742521154569310435572740012678651074392991522280691458449892215626597146075598152312643598829814235896873342805258450617148747956353285414172796'''

一眼顶针:RSA加密

题目给了n、e、c,要求m的话,得知道私钥d,要私钥d,得知道phi,那就得知道p和q的值了

在RSA加密算法中,我们知道e和p(d = p)是具有$e * p = 1 (mod phi)$关系的,根据模运算的性质可得:$e * p = 1 + k * phi$,根据欧拉定理,有$2 ^ {e*p}\equiv 2^{(1 + k * phi)}\equiv 2\ (mod\ n)$

解释一下为什么$2^{(1 + k * phi)}\equiv 2\ (mod\ n)$:通常$gcd(2,n) = 1$,又根据欧拉定理,$a^{phi}≡1(mod\ n)$,所以$2^{phi} \equiv 1 \ (mod\ n)$,两边同时乘以2就得到原式了

对于式子:$2 ^ {e*p}\equiv 2\ (mod\ n)$,两边同模p,就得到$2 ^ e \equiv 2\ (mod\ p)\$$(n\ mod\ p = 0)$,所以$2 ^ e -2\equiv k * p\ (mod\ n)\$,就可以推出:$p = gcd(2 ^ e - 2,\ n)$

Reverse

RE_signin

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
 0           0 RESUME                   0

1 2 LOAD_CONST 0 ('mrl64_l0v3Miku')
4 STORE_NAME 0 (key)

2 6 BUILD_LIST 0
8 LOAD_CONST 1 ((221, -25, 9072, 94, 163, -17, 10260, 0, 198, 16, 8547, 13, 158, -22, 9701, 29, 193, 41, 5096, 13, 219, 27, 6018, 125, 172, 15, 5243, 45, 182, -19, 5292, 84, 149, -41, 10476, 4, 174, 51, 4235, 12))
10 LIST_EXTEND 1
12 STORE_NAME 1 (cipher)

3 14 PUSH_NULL
16 LOAD_NAME 2 (input)
18 LOAD_CONST 2 ('Input your flag:>')
20 CALL 1
28 STORE_NAME 3 (flag)

4 30 BUILD_LIST 0
32 STORE_NAME 4 (temp)

6 34 PUSH_NULL
36 LOAD_NAME 5 (len)
38 LOAD_NAME 3 (flag)
40 CALL 1
48 LOAD_CONST 3 (40)
50 COMPARE_OP 55 (!=)
54 POP_JUMP_IF_FALSE 15 (to 86)

7 56 PUSH_NULL
58 LOAD_NAME 6 (print)
60 LOAD_CONST 4 ('Incorret!')
62 CALL 1
70 POP_TOP

8 72 PUSH_NULL
74 LOAD_NAME 7 (exit)
76 CALL 0
84 POP_TOP

10 >> 86 PUSH_NULL
88 LOAD_NAME 8 (range)
90 LOAD_CONST 5 (0)
92 PUSH_NULL
94 LOAD_NAME 5 (len)
96 LOAD_NAME 3 (flag)
98 CALL 1
106 CALL 2
114 GET_ITER
>> 116 FOR_ITER 189 (to 498)
120 STORE_NAME 9 (i)

11 122 LOAD_NAME 9 (i)
124 LOAD_CONST 6 (4)
126 BINARY_OP 6 (%)
130 STORE_NAME 10 (base)

12 132 LOAD_NAME 10 (base)
134 LOAD_CONST 5 (0)
136 COMPARE_OP 40 (==)
140 POP_JUMP_IF_FALSE 42 (to 226)

13 142 LOAD_NAME 4 (temp)
144 LOAD_ATTR 23 (NULL|self + append)
164 PUSH_NULL
166 LOAD_NAME 12 (ord)
168 LOAD_NAME 3 (flag)
170 LOAD_NAME 9 (i)
172 BINARY_SUBSCR
176 CALL 1
184 PUSH_NULL
186 LOAD_NAME 12 (ord)
188 LOAD_NAME 0 (key)
190 LOAD_NAME 9 (i)
192 LOAD_CONST 7 (14)
194 BINARY_OP 6 (%)
198 BINARY_SUBSCR
202 CALL 1
210 BINARY_OP 0 (+)
214 CALL 1
222 POP_TOP
224 JUMP_BACKWARD 55 (to 116)

14 >> 226 LOAD_NAME 10 (base)
228 LOAD_CONST 8 (1)
230 COMPARE_OP 40 (==)
234 POP_JUMP_IF_FALSE 42 (to 320)

15 236 LOAD_NAME 4 (temp)
238 LOAD_ATTR 23 (NULL|self + append)
258 PUSH_NULL
260 LOAD_NAME 12 (ord)
262 LOAD_NAME 3 (flag)
264 LOAD_NAME 9 (i)
266 BINARY_SUBSCR
270 CALL 1
278 PUSH_NULL
280 LOAD_NAME 12 (ord)
282 LOAD_NAME 0 (key)
284 LOAD_NAME 9 (i)
286 LOAD_CONST 7 (14)
288 BINARY_OP 6 (%)
292 BINARY_SUBSCR
296 CALL 1
304 BINARY_OP 10 (-)
308 CALL 1
316 POP_TOP
318 JUMP_BACKWARD 102 (to 116)

16 >> 320 LOAD_NAME 10 (base)
322 LOAD_CONST 9 (2)
324 COMPARE_OP 40 (==)
328 POP_JUMP_IF_FALSE 42 (to 414)

17 330 LOAD_NAME 4 (temp)
332 LOAD_ATTR 23 (NULL|self + append)
352 PUSH_NULL
354 LOAD_NAME 12 (ord)
356 LOAD_NAME 3 (flag)
358 LOAD_NAME 9 (i)
360 BINARY_SUBSCR
364 CALL 1
372 PUSH_NULL
374 LOAD_NAME 12 (ord)
376 LOAD_NAME 0 (key)
378 LOAD_NAME 9 (i)
380 LOAD_CONST 7 (14)
382 BINARY_OP 6 (%)
386 BINARY_SUBSCR
390 CALL 1
398 BINARY_OP 5 (*)
402 CALL 1
410 POP_TOP
412 JUMP_BACKWARD 149 (to 116)

19 >> 414 LOAD_NAME 4 (temp)
416 LOAD_ATTR 23 (NULL|self + append)
436 PUSH_NULL
438 LOAD_NAME 12 (ord)
440 LOAD_NAME 3 (flag)
442 LOAD_NAME 9 (i)
444 BINARY_SUBSCR
448 CALL 1
456 PUSH_NULL
458 LOAD_NAME 12 (ord)
460 LOAD_NAME 0 (key)
462 LOAD_NAME 9 (i)
464 LOAD_CONST 7 (14)
466 BINARY_OP 6 (%)
470 BINARY_SUBSCR
474 CALL 1
482 BINARY_OP 12 (^)
486 CALL 1
494 POP_TOP
496 JUMP_BACKWARD 191 (to 116)

10 >> 498 END_FOR

21 500 LOAD_NAME 4 (temp)
502 LOAD_NAME 1 (cipher)
504 COMPARE_OP 55 (!=)
508 POP_JUMP_IF_FALSE 15 (to 540)

22 510 PUSH_NULL
512 LOAD_NAME 6 (print)
514 LOAD_CONST 4 ('Incorret!')
516 CALL 1
524 POP_TOP

23 526 PUSH_NULL
528 LOAD_NAME 7 (exit)
530 CALL 0
538 POP_TOP

25 >> 540 PUSH_NULL
542 LOAD_NAME 6 (print)
544 LOAD_CONST 10 ('Corret!!!')
546 CALL 1
554 POP_TOP
556 RETURN_CONST 11 (None)

搜一下就知道这个是python的opcode,可以用AI来帮你还原成python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
key = 'mrl64_l0v3Miku'
cipher = [221, -25, 9072, 94, 163, -17, 10260, 0, 198, 16, 8547, 13, 158, -22,
9701, 29, 193, 41, 5096, 13, 219, 27, 6018, 125, 172, 15, 5243, 45, 182, -19,
5292, 84, 149, -41, 10476, 4, 174, 51, 4235, 12]
flag = input('Input your flag:>')
temp = []
if len(flag) != 40:
print('Incorrect!')
exit()
for i in range(len(flag)):
base = i % 4
if base == 0:
temp.append(ord(flag[i]) + ord(key[i % 14]))
elif base == 1:
temp.append(ord(flag[i]) - ord(key[i % 14]))
elif base == 2:
temp.append(ord(flag[i]) * ord(key[i % 14]))
else:
temp.append(ord(flag[i]) ^ ord(key[i % 14]))
if temp != cipher:
print('Incorrect!')
exit()
else:
print('Correct!!!')

大概就是根据flag中每个元素的下表分成0、1、2、3四组,每组转为ASCII值,跟key中对应的转为ASCII的元素进行四种运算,最终组合成cipher。

分析完就可以写逆向的代码了:将cipher中的每个元素根据下表分为4组,和key对应的元素的ASCII进行相反的四种运算,再转为字符串就可以了。

这是手搓的exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cipher = [221, -25, 9072, 94, 163, -17, 10260, 0, 198, 16, 8547, 13, 158, -22, 9701, 29, 193, 41, 5096, 13, 219, 27, 6018, 125, 172, 15, 5243, 45, 182, -19, 5292, 84, 149, -41, 10476, 4, 174, 51, 4235, 12]
key = 'mrl64_l0v3Miku'
flag = []
for i in range(len(cipher)):
base = i % 4

if base == 0:
flag.append(chr((cipher[i] - ord(key[i%14]))))

elif base == 1:
flag.append(chr((cipher[i] + ord(key[i%14]))))

elif base == 2:
flag.append(chr((cipher[i] // ord(key[i%14]))))

elif base == 3:
flag.append(chr((cipher[i] ^ ord(key[i%14]))))

print(''.join(flag))

这是官方的exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
#include<string>
#include<vector>
using namespace std;

int main(){
vector<int> cipher = {221, -25, 9072, 94, 163, -17, 10260, 0, 198, 16, 8547,
13, 158, -22, 9701, 29, 193, 41, 5096, 13, 219, 27, 6018, 125, 172, 15, 5243,
45, 182, -19, 5292, 84, 149, -41, 10476, 4, 174, 51, 4235, 12};
string key = "mrl64_l0v3Miku";
string flag;
for(int i = 0; i < cipher.size(); i++){
switch(i % 4){
case 0: flag.push_back(cipher[i] - key[i%14]); break;
case 1: flag.push_back(cipher[i] + key[i%14]); break;
case 2: flag.push_back(cipher[i] / key[i%14]); break;
case 3: flag.push_back(cipher[i] ^ key[i%14]); break;
}
}
cout << flag;
return 0;
}

PS:写代码的能力是要有的,不是所有的exp都能通过AI给你写出来。所以,从简单的练起

🎲

决赛

RE

REsignin_revenge

给了一串以太坊字节码(看不出来就问问AI)

1
0x600601d9050611ce3016022016020901b6309a90782600202017fffffffffffffffffffffffffffffffffffffffffffffffffffffa7a7b3cfa9cc191865666666abcdef653a1e2d49f19665123456789abc654d494b55585918180600

我们不妨先来了解一下什么是以太坊

  • 以太坊是一条区块链,其中嵌入了计算机。它是以去中心化、无需许可、抗审查的方式构建应用程序和组织的基础。
  • 在以太坊宇宙中,有一台规范化计算机(被称为以太坊虚拟机,即EVM),其状态的得到以太坊网络中所有人的一致同意。每个参与以太坊网络的人(每个以太坊节点)都会保存一份该计算机的状态。
  • **以太币(ETH)**是以太坊上的原生加密货币。目的是允许计算市场化
  • 智能合约就相当于一种自动售货机:通过特认定参数调用脚本后,如果满足某些特定条件,就会执行一些操作

用这个Bytecode to Opcode Disassembler | Etherscan就可以反编译出opcode

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
[1] PUSH1 0x06
[2] ADD
[3] 'd9'(Unknown Opcode)
[4] SDIV
[5] MOD
[6] GT
[7] 'ce'(Unknown Opcode)
[8] ADDRESS
[9] AND
[10] MUL
[11] SHA3
[12] AND
[13] MUL
[14] MULMOD
[15] ADD
[16] 'b6'(Unknown Opcode)
[17] ADDRESS
[18] SWAP11
[19] SWAP1
[45] PUSH25 0x2600202017ffffffffffffffffffffffffffffffffffffffff
[46] SELFDESTRUCT
[47] SELFDESTRUCT
[48] SELFDESTRUCT
[49] SELFDESTRUCT
[50] SELFDESTRUCT
[51] SELFDESTRUCT
[52] STATICCALL
[80] PUSH27 0x7b3cfa9cc191865666666abcdef653a1e2d49f19665123456789ab
[81] 'c6'(Unknown Opcode)
[82] SLOAD
[83] 'd4'(Unknown Opcode)
[84] SWAP5
[85] 'b5'(Unknown Opcode)
[86] SSTORE
[87] DUP6
[88] SWAP2
[89] DUP2
[90] DUP1
[92] PUSH1 0x0

对照https://ethereum.org/zh/developers/docs/evm/opcodes/一步一步手撕就能做出来了

ezam_plus