1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if
len
(flag) <
89
:
print
(
'no!'
)
return
n
=
0x4F62187B5F6590C6CFF0FBDBBEBDAF60AA861BD2F66F8F7FFD57A66AE50DB7D2FFFFFFFFFFFFFFFFFFFFF
p
=
193
q
=
n
/
/
p
assert
isPrime(q)
assert
n
=
=
p
*
q
base
=
0xB20446102D1C343D0575674CA28EBC0419BCFE4D75682C2AC81C9502454650BDDAEF6968AF269B54C182
_pow
=
int
(flag[:
85
],
16
)
powered
=
hex
(
pow
(base, _pow, n))[
2
: ]
if
len
(powered)
%
2
=
=
1
: powered
=
powered[:
-
1
]
encrypted
=
bytes.fromhex(powered)
那么作者在这里隐藏了离散对数问题吗?根据我们对n的另一个因子q的分析,q-1不为一个光滑数,所以没有办法在多项式时间求解该离散对数问题,也就是说我们知道了C无法求得flagpartone。
作者将获得的 C 进行flag的第二部分,flag的85-88字节,必须为ABAB,ABBA的形式的,连接C作为魔改AES的密钥。密文为一段硬编码的 C2 。该AES使用CBC模式,iv是b'ABCDEF0123456789'。
1
2
3
4
part2
=
flag[
85
:
89
]
codes
=
bytes.fromhex(vigenere(bytes.fromhex(
'064C1E530006484807565B1B4A5003064A455D040A40440758071C1C57005D1C195754094F4F0652071B4A02000C484B54510E411853515C404806595A4F44005106404A0259594B4A02570E4A1C54545D4D4F53530F41445754061B485553081B1E5154084B4E50560C481B07520C4D1E5D040D4F1F55035D1C4457565E4A1E50560D1C1C54035B1A1C5353084F1956595E1C1F57545D1D4E5C020E4E4E0600084A1E00575E4E4E5D500A1C1E54555D401E00560D1A4D0150094E490652591C4D5207064D4A0055594E4B54050D1E1855530A49195C580A4F4A51570B4E1C00540C4A185607084B1C50070C40485452074D1950040E4F1C05565A1B4C5300061E4E52580A4B4D5D525D1C1857595E411F5C5109191F5C510F4C4C5256091A4B56540B481B005808401B00530E191C00570C194C5C570B194A07590C4B4B5C54594B4D575907491952550B484807515C4A1853075A1945560259484F000406494F52515C1B4A070406401E00075D4E1B00585A414D555859194950575C1B4F55075A494454535B4B1851510E4C4951005C4D1802535C1C1F56045D484C0259081C4B02550A4B4B5607061A4F57570F194A52530F4D45025207401E0557084A4D5C535A4B1B50530C4E4F52510F1E4E55520C4A1C5C590E4F1F07580F1A4D0154064B4957520E4B49525307494E06535A1A1807515A404554025C411801520B1D4D50575C1E1850580F484D54520A1C1C54030B4A485253094F1E5C53074D1F5556084C1C53075D1B455C040C481E0607091B185456091E44540559411B53585B481E5D58594F1E53575D414C0052071C4C53070C48195204061C45550408191956530A4A4C54510B1C4F55020B4D1C02075D4F1C54070C4A1957570A404F5D500B4B4A07595A411F06500D1E4457540D4A4E050559194507500E414C00540A1E1F54545B1B4F06035B4F4C06035E4A4D06520F4C1F05595D194A55055E4C4450550C4B4A07030849495C025E4E4402055D1A4907565E4A4B51555B4D4C005559481F50510C4C4806525C411954505B1E1E0657074E4B06040E1B1F50005C1C4D025708191E5605074B4A0556081A4F56000C4A4857585B4D1B00520B1E4E02565B4F4457590B4F4E02590A1C4B5C535B4C1B54540A481E54530D411C5002091B1851595949485558061D4956525B1E4D0654091E4A5C505C48485D59061D4D05530F1D1E5C070A4A4850045B411F57510D40485705081E1E56055A4E4D5C52591B1850575E4E1F05590C4E4551555A4A1B5500071C4E0558064F4550575C4F1B52590B484A5102094B4B53040D1C4D5D030E484501030E1B4E5D515A4B1B0555084E4855555D4B4D02520C4F1C56020B1B4406555A1C4F5303591E4400505E1A1F5453071C4452030E1A1F06075B1D4C02505D1B4C5255061D4B54530B4C4B5659074F4D540309411F02520E4A195C515D4B1901570B491B07510F404C55550B414A5300074C1E53000C1B4555590A494E57560E4A4B52555D1A4E55535C414453025E494E57570A1A1906530D4E4C00035B4A4D570359414A07000D484500515D4B1952585E1B1F55515A1A4901510B1E4B01535C404F5C025A401B07040C1A1B0558594C1952580F484A5C520C49455D00064D1851035A1B4C56000A1E4C02000F4E1950560C401E5400084D4A05565D1A4F53515B491C07070D4E1E01035E4B44565706414F5C075C1A455000074A4954590F48480759061E185D03061A4F06030D4C1E01070F491E5C005E484C5C57064A4E01055B4E1F560406194D5D025E4F4C55055C404D05050B481C50575A4C4954565A481B56580E484B5751064A4C0659061D4A52040A414E05020B4A4F0503594F4554070A1C195D0309191B05500C1C4B55040A4A1F57540E1A4551580B4D18505206194F55000C4E4F5C510F1C4550555D4D4557035D1B4555050C4F4406020A1B495207591C4857040A401B5C54094F1C51530E4A4C53550E4948025409494F015408494E005609191B54500C4F4C00590F1D4A54555C41190650084E48550308401C57560F414B50555A4A4901075C1B4D53030B4B1B07530C1E4806550A1D450555064E185400071E4A53045D1C4952540D404957545A1A4E5100091B1C05035E1A4F5204071B1F57565A4E185350594C4907520F1D4F51520A4A4F0552094E1B5151094C4D5004094E49020207401E54045B1D1E00045B4B1B01500848445605064B4F5D05084B4905515A491B0704591B485705064C1E5D590E1C1952525C1C1B06500B1C440756061B1F05075B194B54500B1A1F5400071D490500064D1951035C4B4C54590B1E4A01005C414B055406411907055B4D480500081E4F565607404A0058074C4F53530B4F1F05565D414F5203074F48075307484B5100084C4955030C1E485D520E4A4F5253064E1E05005A4F4C53590E1A1851005A1C1F52050E484406505E1C1B07020E1A4507545E484551050E1B1B06025B4A445359061D4A05520A1A4E50580A4D4E515708194F005907494952070A1B195704594B1E5354094D4902545E4B4D05045E1D4B00570D4C4802575D4E4D005209194853040B194E50020C1B4A00025D494951560D404502070D1D1E02520B1B49055707414E5D515A404B07500E1B445258081D1F05055D1A1E07540B1D18565608194901050E411B56540B4B1F07555A4C4F55030D404C54510C1D4953000F1C4807520C491E53565E4A1851535E4A1F5C055C4D4552585B4C4C57000819495003591E4D5C050A1A1850000A494801530A1A4B06035E4A4D505906404D53030B1A4E00570C411F0754064A4A575207481853575A4E1F53050E191C570507494952500D41445C00594C4A54500D4C1802040F41495202081B4453070A4E4D06555E4A4E00570A4F4457005E1D1955580F4D4C55045A1A4806550E4B445D505C1B4802560F4A4850520B1A4B52570B4E4B51565A404455030D4A19575706491B515507481C0504074C4A02545B401E50530F1B4456520B411901070C1E1F5D50071D4B5259591B1802540C4F1C52585A19445151064A4E05535A481F06055C1A4C545807481B57055C411F06505B4D180253091E1C06560F1B1F5356591C4C05030F4D490205084B4A01500E194E5D54594F4507590A191C05030C404950550F4B4405590F1A4C5D000F1E4C00040C41485C075A484D0551091C4D06030C1E1F01045C1E4D53595D40185C040B4F1B54030F1E4850555D4F4C5656074F185D0407491957515A1D4806525E194505560F4F485C525E4A180750591D1905535C4B4E51025D1C4F5D07094A4B06580F481C0255064E1C00005B1C4956530F481B05540C40195D545940480703084E1F05540F481C00570C4E4F5400064D4454020F491E01550C4B4D0053094D4802075E1D4C5C02064B455C515C1E4C06570E4D1B53555A4F1857045E1D1E01550E40455C040B4D1851070F1C1C51555B1A1F5D000E1D4D01580E4D4D53050E1E485D050B1A1F54570F4B445D56591A1C5751064D495C570A4A4B54570F4C4C54530F491806550B4E1854030E4E1C5C020B4E4B5D000D4B1E54570D1B4452070B404806555C401E55055E1D4507530B1A1F0251084D4D5C585E4948005809494A54565E1A4E5D59074A195652594F4A07050E4D4B0552064B1E5356081B4C02555949195C57594B1807580D1C4A06025B1B4800530F4D445605074A4D5C07094F4856520B4B4F01565E414C51520A484D5C5108401C02585A4E1E0155591B1B55560B4019060206484950075D401C06040C1D4B0557591D1E00030A4B4557545B4E4956590A404850500E4A4C5D030C484507535C4E4451575E1E1F0500591D4E54505B4C4A0200064B4E0557074A195C550E1A1907505E1D1B52570E4C1856570A4F4E56520B4D4C54020C4B4805530A4C4B52025A1C4D5C545E411F53535A4D4A5D510B414C5756071C4501515E1A1C5D5306191F5755094F4A01025D4A1E57050A4E1F535609401B53030D1E1B51020B1C1851520D1E4F5358084F1957045B4E1E5C0208401C57565D4F485003594E1C515706191C0500084D4B0105081C195D035B1E4952035E1E1E00000B4B4456545A4F4A5104591E4801025C1A1E53070F404A0500091D4C01040A4F4E50535D494C53005C4E1B05525E481E02570E484D53575C1A485254081C485058061A1E0102074C1E025259484955040C1B4852550D404A01025D4B4E02500C1B1B54595E4F4854510D1C1E50030A4C48025206491F565008194F05055C4A4F06550A4D4A505506414C02035D414A00565A1E1C0607084C4C0505094F455003084C4457020C4E440200074D1C55040B4A4A5D535D4E4452540A4B1807070E491807500A481950510C404C50565C1B4901045C191852005C4B4A5105591A4E5C530C194F5D02094A4F565707484D075107191C53035B1C1C56565D1E4C52555E1C4B57525A1E4B55555C1B1B060008484A53535D4B4555055A411C5D59091A4E5559061D1957520B1B1E05560C4D1954550649455D520C4D485305081D4B53540E4F1850595E4B4900075E191B0707591C1852500B194B5C525C1D18010206401F5D540D4A1E5653094F1906055D4F4B00025A1A1E07045D4B4407035E4F445C570B1B4955040C491F5303591A4557055D4A1900040E4F1C5C595C1B180556591E195759074F4856045C4D4902510A4B4C54510F194E5D070E4A1C05585B4D1C50580E4D4C51550B1B1B5055594F4D06075E4B4E0752084F190507591D1F57555A411C05580E414C53520F4F4F07045A4E485C520F4F1E5C560F4F4B0607094E1854580C494401075C194F5D005B4C4E00595D4E4D07045A4C1C5C560A1B4D01580E491B5C580C494557035A1D440754594F4A5452084A440704071B4B5D03064A1950570F404556540A4F480158084C1F51525D4A4F5200'
),
"?x}da"
).decode())
encrypted
=
part2.encode()
+
encrypted
decrypted
=
aes_decrypt_cbc(codes, encrypted, b
'ABCDEF0123456789'
)
程序将解密后内容存入一个可读可写可执行的内存区域,最后使用ZwQueueApcThread创建一个
异步程序调用,这里把它当成call就行了。值得注意的是,解密后的内容在拷贝的过程会出现\0截断问题。
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/
/
AES
typedef struct {
unsigned char rk[
15
*
4
*
4
];
/
/
round
key
unsigned char iv[
16
];
} AES_CONTEXT;
const unsigned char Sbox[
256
]
=
{
/
/
0
1
2
3
4
5
6
7
8
9
a b c d e f
0x63
,
0x7c
,
0x77
,
0x7b
,
0xf2
,
0x6b
,
0x6f
,
0xc5
,
0x30
,
0x01
,
0x67
,
0x2b
,
0xfe
,
0xd7
,
0xab
,
0x76
,
/
/
0
0xca
,
0x82
,
0xc9
,
0x7d
,
0xfa
,
0x59
,
0x47
,
0xf0
,
0xad
,
0xd4
,
0xa2
,
0xaf
,
0x9c
,
0xa4
,
0x72
,
0xc0
,
/
/
1
0xb7
,
0xfd
,
0x93
,
0x26
,
0x36
,
0x3f
,
0xf7
,
0xcc
,
0x34
,
0xa5
,
0xe5
,
0xf1
,
0x71
,
0xd8
,
0x31
,
0x15
,
/
/
2
0x04
,
0xc7
,
0x23
,
0xc3
,
0x18
,
0x96
,
0x05
,
0x9a
,
0x07
,
0x12
,
0x80
,
0xe2
,
0xeb
,
0x27
,
0xb2
,
0x75
,
/
/
3
0x09
,
0x83
,
0x2c
,
0x1a
,
0x1b
,
0x6e
,
0x5a
,
0xa0
,
0x52
,
0x3b
,
0xd6
,
0xb3
,
0x29
,
0xe3
,
0x2f
,
0x84
,
/
/
4
0x53
,
0xd1
,
0x00
,
0xed
,
0x20
,
0xfc
,
0xb1
,
0x5b
,
0x6a
,
0xcb
,
0xbe
,
0x39
,
0x4a
,
0x4c
,
0x58
,
0xcf
,
/
/
5
0xd0
,
0xef
,
0xaa
,
0xfb
,
0x43
,
0x4d
,
0x33
,
0x85
,
0x45
,
0xf9
,
0x02
,
0x7f
,
0x50
,
0x3c
,
0x9f
,
0xa8
,
/
/
6
0x51
,
0xa3
,
0x40
,
0x8f
,
0x92
,
0x9d
,
0x38
,
0xf5
,
0xbc
,
0xb6
,
0xda
,
0x21
,
0x10
,
0xff
,
0xf3
,
0xd2
,
/
/
7
0xcd
,
0x0c
,
0x13
,
0xec
,
0x5f
,
0x97
,
0x44
,
0x17
,
0xc4
,
0xa7
,
0x7e
,
0x3d
,
0x64
,
0x5d
,
0x19
,
0x73
,
/
/
8
0x60
,
0x81
,
0x4f
,
0xdc
,
0x22
,
0x2a
,
0x90
,
0x88
,
0x46
,
0xee
,
0xb8
,
0x14
,
0xde
,
0x5e
,
0x0b
,
0xdb
,
/
/
9
0xe0
,
0x32
,
0x3a
,
0x0a
,
0x49
,
0x06
,
0x24
,
0x5c
,
0xc2
,
0xd3
,
0xac
,
0x62
,
0x91
,
0x95
,
0xe4
,
0x79
,
/
/
a
0xe7
,
0xc8
,
0x37
,
0x6d
,
0x8d
,
0xd5
,
0x4e
,
0xa9
,
0x6c
,
0x56
,
0xf4
,
0xea
,
0x65
,
0x7a
,
0xae
,
0x08
,
/
/
b
0xba
,
0x78
,
0x25
,
0x2e
,
0x1c
,
0xa6
,
0xb4
,
0xc6
,
0xe8
,
0xdd
,
0x74
,
0x1f
,
0x4b
,
0xbd
,
0x8b
,
0x8a
,
/
/
c
0x70
,
0x3e
,
0xb5
,
0x66
,
0x48
,
0x03
,
0xf6
,
0x0e
,
0x61
,
0x35
,
0x57
,
0xb9
,
0x86
,
0xc1
,
0x1d
,
0x9e
,
/
/
d
0xe1
,
0xf8
,
0x98
,
0x11
,
0x69
,
0xd9
,
0x8e
,
0x94
,
0x9b
,
0x1e
,
0x87
,
0xe9
,
0xce
,
0x55
,
0x28
,
0xdf
,
/
/
e
0x8c
,
0xa1
,
0x89
,
0x0d
,
0xbf
,
0xe6
,
0x42
,
0x68
,
0x41
,
0x99
,
0x2d
,
0x0f
,
0xb0
,
0x54
,
0xbb
,
0x16
/
/
f
};
const unsigned char InvSbox[
256
]
=
{
/
/
0
1
2
3
4
5
6
7
8
9
a b c d e f
0x52
,
0x09
,
0x6a
,
0xd5
,
0x30
,
0x36
,
0xa5
,
0x38
,
0xbf
,
0x40
,
0xa3
,
0x9e
,
0x81
,
0xf3
,
0xd7
,
0xfb
,
/
/
0
0x7c
,
0xe3
,
0x39
,
0x82
,
0x9b
,
0x2f
,
0xff
,
0x87
,
0x34
,
0x8e
,
0x43
,
0x44
,
0xc4
,
0xde
,
0xe9
,
0xcb
,
/
/
1
0x54
,
0x7b
,
0x94
,
0x32
,
0xa6
,
0xc2
,
0x23
,
0x3d
,
0xee
,
0x4c
,
0x95
,
0x0b
,
0x42
,
0xfa
,
0xc3
,
0x4e
,
/
/
2
0x08
,
0x2e
,
0xa1
,
0x66
,
0x28
,
0xd9
,
0x24
,
0xb2
,
0x76
,
0x5b
,
0xa2
,
0x49
,
0x6d
,
0x8b
,
0xd1
,
0x25
,
/
/
3
0x72
,
0xf8
,
0xf6
,
0x64
,
0x86
,
0x68
,
0x98
,
0x16
,
0xd4
,
0xa4
,
0x5c
,
0xcc
,
0x5d
,
0x65
,
0xb6
,
0x92
,
/
/
4
0x6c
,
0x70
,
0x48
,
0x50
,
0xfd
,
0xed
,
0xb9
,
0xda
,
0x5e
,
0x15
,
0x46
,
0x57
,
0xa7
,
0x8d
,
0x9d
,
0x84
,
/
/
5
0x90
,
0xd8
,
0xab
,
0x00
,
0x8c
,
0xbc
,
0xd3
,
0x0a
,
0xf7
,
0xe4
,
0x58
,
0x05
,
0xb8
,
0xb3
,
0x45
,
0x06
,
/
/
6
0xd0
,
0x2c
,
0x1e
,
0x8f
,
0xca
,
0x3f
,
0x0f
,
0x02
,
0xc1
,
0xaf
,
0xbd
,
0x03
,
0x01
,
0x13
,
0x8a
,
0x6b
,
/
/
7
0x3a
,
0x91
,
0x11
,
0x41
,
0x4f
,
0x67
,
0xdc
,
0xea
,
0x97
,
0xf2
,
0xcf
,
0xce
,
0xf0
,
0xb4
,
0xe6
,
0x73
,
/
/
8
0x96
,
0xac
,
0x74
,
0x22
,
0xe7
,
0xad
,
0x35
,
0x85
,
0xe2
,
0xf9
,
0x37
,
0xe8
,
0x1c
,
0x75
,
0xdf
,
0x6e
,
/
/
9
0x47
,
0xf1
,
0x1a
,
0x71
,
0x1d
,
0x29
,
0xc5
,
0x89
,
0x6f
,
0xb7
,
0x62
,
0x0e
,
0xaa
,
0x18
,
0xbe
,
0x1b
,
/
/
a
0xfc
,
0x56
,
0x3e
,
0x4b
,
0xc6
,
0xd2
,
0x79
,
0x20
,
0x9a
,
0xdb
,
0xc0
,
0xfe
,
0x78
,
0xcd
,
0x5a
,
0xf4
,
/
/
b
0x1f
,
0xdd
,
0xa8
,
0x33
,
0x88
,
0x07
,
0xc7
,
0x31
,
0xb1
,
0x12
,
0x10
,
0x59
,
0x27
,
0x80
,
0xec
,
0x5f
,
/
/
c
0x60
,
0x51
,
0x7f
,
0xa9
,
0x19
,
0xb5
,
0x4a
,
0x0d
,
0x2d
,
0xe5
,
0x7a
,
0x9f
,
0x93
,
0xc9
,
0x9c
,
0xef
,
/
/
d
0xa0
,
0xe0
,
0x3b
,
0x4d
,
0xae
,
0x2a
,
0xf5
,
0xb0
,
0xc8
,
0xeb
,
0xbb
,
0x3c
,
0x83
,
0x53
,
0x99
,
0x61
,
/
/
e
0x17
,
0x2b
,
0x04
,
0x7e
,
0xba
,
0x77
,
0xd6
,
0x26
,
0xe1
,
0x69
,
0x14
,
0x63
,
0x55
,
0x21
,
0x0c
,
0x7d
/
/
f
};
void KeyExpansion(AES_CONTEXT
*
ctx, const unsigned char
*
key) {
unsigned char t[
4
];
unsigned char tmp;
memcpy(ctx
-
>rk, key,
32
);
for
(
int
i
=
8
; i <
15
*
4
; i
+
+
) {
memcpy(t, ctx
-
>rk
+
4
*
(i
-
1
),
4
);
if
(i
%
8
) {
if
(i
%
8
=
=
4
) {
t[
0
]
=
Sbox[t[
0
]];
t[
1
]
=
Sbox[t[
1
]];
t[
2
]
=
Sbox[t[
2
]];
t[
3
]
=
Sbox[t[
3
]];
}
}
else
{
tmp
=
Sbox[t[
1
]];
t[
1
]
=
Sbox[t[
2
]];
t[
2
]
=
Sbox[t[
3
]];
t[
3
]
=
Sbox[t[
0
]];
unsigned char rc
=
1
;
for
(
int
j
=
0
; j < i
/
8
-
1
; j
+
+
)
rc
=
(
0x1B
*
(rc >>
7
)) ^ (
2
*
rc);
t[
0
]
=
rc ^ tmp;
}
ctx
-
>rk[i
*
4
]
=
ctx
-
>rk[i
*
4
-
32
] ^ t[
0
];
ctx
-
>rk[i
*
4
+
1
]
=
ctx
-
>rk[i
*
4
-
31
] ^ t[
1
];
ctx
-
>rk[i
*
4
+
2
]
=
ctx
-
>rk[i
*
4
-
30
] ^ t[
2
];
ctx
-
>rk[i
*
4
+
3
]
=
ctx
-
>rk[i
*
4
-
29
] ^ t[
3
];
}
}
unsigned char FFmul(unsigned char a, unsigned char b) {
unsigned char bw[
4
];
unsigned char res
=
0
;
int
i;
bw[
0
]
=
b;
for
(i
=
1
; i <
4
; i
+
+
) {
bw[i]
=
bw[i
-
1
] <<
1
;
if
(bw[i
-
1
] &
0x80
) {
bw[i] ^
=
0x1b
;
}
}
for
(i
=
0
; i <
4
; i
+
+
) {
if
((a >> i) &
0x01
) {
res ^
=
bw[i];
}
}
return
res;
}
void SubBytes(AES_CONTEXT
*
ctx, unsigned char
*
state) {
for
(
int
i
=
0
; i <
16
; i
+
+
)
state[i]
=
Sbox[state[i]];
}
void ShiftRows(AES_CONTEXT
*
ctx, unsigned char
*
state) {
unsigned char tmp[
4
];
*
(unsigned
int
*
) tmp
=
*
(unsigned
int
*
) (state
+
4
);
state[
7
]
=
tmp[
0
];
state[
4
]
=
tmp[
1
];
state[
5
]
=
tmp[
2
];
state[
6
]
=
tmp[
3
];
*
(unsigned
int
*
) tmp
=
*
(unsigned
int
*
) (state
+
8
);
state[
10
]
=
tmp[
0
];
state[
11
]
=
tmp[
1
];
state[
8
]
=
tmp[
2
];
state[
9
]
=
tmp[
3
];
*
(unsigned
int
*
) tmp
=
*
(unsigned
int
*
) (state
+
12
);
state[
13
]
=
tmp[
0
];
state[
14
]
=
tmp[
1
];
state[
15
]
=
tmp[
2
];
state[
12
]
=
tmp[
3
];
}
void MixColumns(AES_CONTEXT
*
ctx, unsigned char
*
state) {
unsigned char tmp[
16
];
memset(tmp,
0.
,
16
);
for
(
int
i
=
0
; i <
4
; i
+
+
) {
tmp[i]
=
FFmul(
2
, state[
0
+
i]) ^ FFmul(
3
, state[
4
+
i]) ^ FFmul(
1
, state[
8
+
i]) ^ FFmul(
1
, state[
12
+
i]);
tmp[i
+
4
]
=
FFmul(
1
, state[
0
+
i]) ^ FFmul(
2
, state[
4
+
i]) ^ FFmul(
3
, state[
8
+
i]) ^ FFmul(
1
, state[
12
+
i]);
tmp[i
+
8
]
=
FFmul(
1
, state[
0
+
i]) ^ FFmul(
1
, state[
4
+
i]) ^ FFmul(
2
, state[
8
+
i]) ^ FFmul(
3
, state[
12
+
i]);
tmp[i
+
12
]
=
FFmul(
3
, state[
0
+
i]) ^ FFmul(
1
, state[
4
+
i]) ^ FFmul(
1
, state[
8
+
i]) ^ FFmul(
2
, state[
12
+
i]);
}
memcpy(state, tmp,
16
);
}
void AddRoundKey(AES_CONTEXT
*
ctx, unsigned char
*
state, unsigned char
*
k) {
for
(
int
i
=
0
; i <
4
; i
+
+
) {
for
(
int
j
=
0
; j <
4
; j
+
+
) {
state[i
*
4
+
j] ^
=
k[j
*
4
+
i];
}
}
}
void InvSubBytes(AES_CONTEXT
*
ctx, unsigned char
*
state) {
for
(
int
i
=
0
; i <
16
; i
+
+
)
state[i]
=
InvSbox[state[i]];
}
void InvShiftRows(AES_CONTEXT
*
ctx, unsigned char
*
state) {
unsigned char tmp[
4
];
tmp[
0
]
=
state[
7
];
tmp[
1
]
=
state[
4
];
tmp[
2
]
=
state[
5
];
tmp[
3
]
=
state[
6
];
*
(unsigned
int
*
) (state
+
4
)
=
*
(unsigned
int
*
) tmp;
tmp[
0
]
=
state[
10
];
tmp[
1
]
=
state[
11
];
tmp[
2
]
=
state[
8
];
tmp[
3
]
=
state[
9
];
*
(unsigned
int
*
) (state
+
8
)
=
*
(unsigned
int
*
) tmp;
tmp[
0
]
=
state[
13
];
tmp[
1
]
=
state[
14
];
tmp[
2
]
=
state[
15
];
tmp[
3
]
=
state[
12
];
*
(unsigned
int
*
) (state
+
12
)
=
*
(unsigned
int
*
) tmp;
}
void InvMixColumns(AES_CONTEXT
*
ctx, unsigned char
*
state) {
unsigned char tmp[
16
];
memset(tmp,
0.
,
16
);
for
(
int
i
=
0
; i <
4
; i
+
+
) {
tmp[i]
=
FFmul(
0x0e
, state[
0
+
i]) ^ FFmul(
0x0b
, state[
4
+
i]) ^ FFmul(
0x0d
, state[
8
+
i]) ^ FFmul(
0x09
, state[
12
+
i]);
tmp[i
+
4
]
=
FFmul(
0x09
, state[
0
+
i]) ^ FFmul(
0x0e
, state[
4
+
i]) ^ FFmul(
0x0b
, state[
8
+
i]) ^ FFmul(
0x0d
, state[
12
+
i]);
tmp[i
+
8
]
=
FFmul(
0x0d
, state[
0
+
i]) ^ FFmul(
0x09
, state[
4
+
i]) ^ FFmul(
0x0e
, state[
8
+
i]) ^ FFmul(
0x0b
, state[
12
+
i]);
tmp[i
+
12
]
=
FFmul(
0x0b
, state[
0
+
i]) ^ FFmul(
0x0d
, state[
4
+
i]) ^ FFmul(
0x09
, state[
8
+
i]) ^ FFmul(
0x0e
, state[
12
+
i]);
}
memcpy(state, tmp,
16
);
}
void aes_init(AES_CONTEXT
*
ctx, const unsigned char
*
key, const void
*
iv) {
/
/
memcpy(ctx
-
>Sbox, sBox,
256
);
/
/
memcpy(ctx
-
>InvSbox, invsBox,
256
);
KeyExpansion(ctx, key);
if
(iv) memcpy(ctx
-
>iv, iv,
16
);
}
unsigned char
*
aes_decrypt_block(AES_CONTEXT
*
ctx, unsigned char
*
input
) {
unsigned char state[
16
];
int
i, r, c;
for
(
int
i
=
0
; i <
4
; i
+
+
) {
for
(
int
j
=
0
; j <
4
; j
+
+
) {
state[i
*
4
+
j]
=
input
[j
*
4
+
i];
}
}
AddRoundKey(ctx, state, ctx
-
>rk
+
14
*
16
);
for
(
int
i
=
13
; i >
0
; i
-
-
) {
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
AddRoundKey(ctx, state, ctx
-
>rk
+
16
*
i);
InvMixColumns(ctx, state);
}
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
AddRoundKey(ctx, state, ctx
-
>rk);
for
(
int
i
=
0
; i <
4
; i
+
+
) {
for
(
int
j
=
0
; j <
4
; j
+
+
) {
input
[i
*
4
+
j]
=
state[j
*
4
+
i];
}
}
return
input
;
}
void aes_decrypt_ecb(const void
*
key, void
*
data,
int
data_len) {
assert
(data_len
%
16
=
=
0
);
AES_CONTEXT ctx;
aes_init(&ctx, (const unsigned char
*
) key, NULL);
unsigned char
*
_data
=
(unsigned char
*
) data;
for
(
int
i
=
0
; i < data_len
/
16
; i
+
+
) {
aes_decrypt_block(&ctx, _data);
_data
+
=
16
;
}
}
void aes_decrypt_cbc(const void
*
key, const void
*
iv, void
*
data,
int
data_len) {
assert
(data_len
%
16
=
=
0
);
AES_CONTEXT ctx;
aes_init(&ctx, (const unsigned char
*
) key, iv);
unsigned char
*
_data
=
(unsigned char
*
) data;
unsigned char buf[
16
];
for
(
int
i
=
0
; i < data_len
/
16
; i
+
+
) {
memcpy(buf, _data,
16
);
aes_decrypt_block(&ctx, _data);
for
(
int
j
=
0
; j <
16
; j
+
+
) _data[j] ^
=
ctx.iv[j];
_data
+
=
16
;
memcpy(ctx.iv, buf,
16
);
}
}
int
main() {
unsigned char data[]
=
"\x94\xC7\xA9\x05\xC7\xDC\x74\xB9\x28\x9E\x58\x9C\x98\xDA\x3A\xBD"
"\xD3\x56\x72\xB3\x8C\x7F\xA3\x06\x00\x19\xE7\x0C\x85\xB8\xE7\x9D"
"\x09\x87\xF8\xF3\x7F\x61\x2A\x05\xB5\x27\x20\x99\x35\x9C\x51\x27"
"\xCC\x55\x73\x34\x73\x0F\xC3\x35\xC9\xE2\x7B\x1B\xBD\x93\x7A\x2C"
"\x47\x2D\xA0\xBD\xBA\x72\x77\xD2\x8A\xDB\x35\xBE\x38\xC1\x63\xBA"
"\x72\xCD\x6A\x63\x91\x5D\xC0\x4B\x8C\xD7\x2B\x0E\x16\x64\xB3\xFD"
;
unsigned char key[]
=
"\x44\x44\x45\x45\xaf\x20\x5d\xb8\xe5\x0e\xb8\x95\x2b\x78\x22\xcc\x7a\x3a\xeb\x55\x0c\x0a\xc9\xb7\xfc\xf1\x59\xc0\xe8\xc7\x29\xf4"
;
unsigned char iv[]
=
"ABCDEF0123456789"
;
unsigned char tmp[
16
*
BLOCK_SIZE];
for
(
int
i
=
0
; i <
100
; i
+
+
) {
memcpy(tmp, data,
16
*
BLOCK_SIZE);
key[
0
]
=
0x30
+
i
/
10
;
key[
1
]
=
0x30
+
i
/
10
;
key[
2
]
=
0x30
+
i
%
10
;
key[
3
]
=
0x30
+
i
%
10
;
aes_decrypt_cbc(key, iv, tmp,
16
*
BLOCK_SIZE);
if
(tmp[
0
]
=
=
0xC3
)
break
;
}
printf(
"%s\n"
, tmp[
0
]
=
=
0xc3
?
"Yes."
:
"No."
);
for
(
int
i
=
0
; i <
2
; i
+
+
) {
for
(
int
j
=
0
; j <
16
; j
+
+
) {
printf(
"%02x "
, key[i
*
16
+
j]);
}
putchar(
'\n'
);
}
putchar(
'\n'
);
for
(
int
i
=
0
; i < BLOCK_SIZE; i
+
+
) {
for
(
int
j
=
0
; j <
16
; j
+
+
) {
printf(
"%02x "
, tmp[i
*
16
+
j]);
}
putchar(
'\n'
);
}
return
0
;
}
仅仅魔改了密钥扩展,该AES为修改密钥扩展的14轮AES。与常见的AES-128不同,这个AES使用256bit(32字节)密钥,加密块却是128bit。在98k成员的有限的知识中应该不存在算法缺点。
如果我们假设这里能顺利运行,我们的问题就变成了需要猜测明文可执行指令,和密文,求出密钥。显然这个场景的是不可解问题。约等于AES的已知明文攻击。在没有实现缺陷的情况下,不可求出密钥。
所以,我们认为,以上两步中我们可以控制输入的flag的第一和第二部分控制AES解密结果,只要确保第一个字节为 0xc3 也就是 ret 指令就能让程序完美运行。平均256次穷举就能获得一个通过上述所有检查的输入。
经过分析,程序会根据输入的flag条件,在程序main函数中存在正确或者失败的字符串的内存中写入good或者bad。所以我们可以根据第三部分来控制main函数中的输出,我们想覆盖main函数中字符串的位置为220。根据分析我们需要控制 ‘kctf’ + 数据长度单字节 + 数据 为20字节。
1
2
3
4
5
6
7
8
9
10
11
12
13
flag:
a
-
z:
1
0
-
9
,A
-
Z:
0
other:
2
maybe,
3
debug: xx
type
[A[i]
*
10
+
B[i]] !
=
1
A[i
+
1
]
-
A[i]
=
=
1
|| A[i
+
1
]
-
A[i]
=
=
-
1
|| B[i
+
1
]
-
B[i]
=
=
1
|| B[i
+
1
]
-
B[i]
=
=
-
1
B[
14
]
=
=
0
|| B[
14
]
=
=
9
|| A[
14
]
=
=
0
|| A[
14
]
=
=
9
B[
14
] !
=
B[
0
] || A[
14
] !
=
A[
0
]
B[
0
]
=
=
0
type
[A[i]
*
10
+
B[i]
+
100
] !
=
1
B[
14
] <
=
9
1
2
3
[
'1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF'
+
'9911'
+
'0F'
+
f
'201{i}'
*
7
+
'01'
for
i
in
range
(
1
,
10
)]
1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F101110111011101110111011101101
1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F102110211021102110211021102102