首页
社区
课程
招聘
[原创]kctf2022 秋季赛 第十题 两袖清风 wp
2022-12-10 19:44 14598

[原创]kctf2022 秋季赛 第十题 两袖清风 wp

2022-12-10 19:44
14598

先看一看ida的f5

看见了1300行的f5,忍不住想关掉ida。

 

但是面对困难不要怕,经过一小会分析,我们恢复了一点细节。

 



作者在程序中插入了很多的 antidebug 技巧。同时字符串一般都用维吉尼亚进行了加密。

 


 

完成程序初始化之后,我们可以看到程序开始了校验逻辑。

 


 

将第一步份校验逻辑用python写下,可以发现那个模数n可以在factordb上查询到一个小因子p。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# flag = input('Please enter your key:')
# print('Start cheking your key ...')
 
if len(flag) < 89:
    print('no!')
    return
 
n = 0x4F62187B5F6590C6CFF0FBDBBEBDAF60AA861BD2F66F8F7FFD57A66AE50DB7D2FFFFFFFFFFFFFFFFFFFFF
# factored from factordb
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)

乍一看像是 RSA ,实际上是一个离散对数问题,flag的第一部分是长度为85的十六进制数据。

 

$ base^{flagpartone} \mod n = C $

 

那么作者在这里隐藏了离散对数问题吗?根据我们对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 # vigenere(encrypted, "Y?j0?")
decrypted = aes_decrypt_cbc(codes, encrypted, b'ABCDEF0123456789')

之后解密的内容我们记为 Code1 。也就是“decrypted”。

 


 

程序将解密后内容存入一个可读可写可执行的内存区域,最后使用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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
// 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";
 
    #define BLOCK_SIZE 4
    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次穷举就能获得一个通过上述所有检查的输入。

 

该步骤最多可产生 16 ^ 85 / 256 种解。

 


 

然后程序使用UUID的方式编码shellcode。

 


 

经过分析,程序会根据输入的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

A数组代表输入hex中的的高位组成的数组,B数组代表输入hex中的的低位组成的数组。

 

这里宽松的约束条件也能产生很多组解。

 

笔者这里给出九组解。

1
2
3
['1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF' + '9911' + '0F' + f'201{i}' * 7 + '01' for i in range(1, 10)]
1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F101110111011101110111011101101
1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F102110211021102110211021102102



[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2022-12-11 10:40 被全盲法师编辑 ,原因: 修改错别字
收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回