ez_driver & kernel

两个驱动逆向,先放一个链接

Windows 驱动开发 新手入门(一)_windows驱动开发-CSDN博客

理论知识

部分代码

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
NTSTATUS DriverAddDevice(PDRIVER_OBJECT pDriverObj, PDEVICE_OBJECT pPhysicalDeviceObject)
{
DbgPrint("AddDevice\n");

NTSTATUS status = STATUS_SUCCESS;

UNICODE_STRING deviceName;
UNICODE_STRING linkName;
PDEVICE_OBJECT pDeviceObj = NULL; //创建设备对象
PDEVICE_EXTENSION pDeviceExt = NULL; //设备扩展对象
RtlInitUnicodeString(&deviceName, DEVICE_NAME); //初始化Unicode字符串 设备名称
RtlInitUnicodeString(&linkName, LINK_NAME);//初始化Unicode字符串 符号链接名称

//创建设备
status = IoCreateDevice(pDriverObj, sizeof(PDEVICE_EXTENSION), &deviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObj);
if (!NT_SUCCESS(status))
{
return status;
}
//让扩展对象指向刚刚创建的设备的扩展
pDeviceExt = (PDEVICE_EXTENSION)(pDeviceObj->DeviceExtension);
pDeviceExt->PDeviceObject = pDeviceObj;
pDeviceExt->DeviceName = deviceName;
pDeviceExt->SymLinkName = linkName;

// 将设备对象挂接在设备堆栈上
pDeviceExt->PNextStackDevice = IoAttachDeviceToDeviceStack(pDeviceObj, pPhysicalDeviceObject);

//创建符号链接
status = IoCreateSymbolicLink(&linkName, &deviceName);
if (!NT_SUCCESS(status))
{
IoDeleteSymbolicLink(&pDeviceExt->SymLinkName);
status = IoCreateSymbolicLink(&linkName, &deviceName);
if (!NT_SUCCESS(status))
{
return status;
}
}

pDeviceObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
pDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING;

DbgPrint("Leave AddDevice\n");

return status;
}

驱动入口

在之前写程序时,程序入口函数为main,参数有argcargv代表着命令行的参数个数及对应的字符串指针,驱动也有入口函数为DriverEntry,其返回类型为NTSTATUS

函数的第一个参数pDriverObj是刚被初始化的驱动对象指针,函数的第二个参数pRegistryString是驱动在注册表中的键值。

DriverUnload是驱动卸载的回调,如果我们不设置DriverUnload,那么此时我们将无法正常的卸载驱动,系统这么做的原因是为了保证系统的稳定性。
比如我们在DriverEntry中添加了某些系统回调,此时我们没有DriverUnload,因此系统不知道什么时候该移除这些回调,如果暴力移除驱动,此时系统回调会出问题,系统回调表中存在了一个被移除掉的驱动的回调,当调用时系统蓝屏 。

派遣函数MajorFunction

我们在驱动入口函数中看到了 pDriverObj->MajorFunction 数组,其作用是针对每一个的事件都有与之对应的回调函数。

因为WDM驱动不在DriverEntry入口中去创建设备和对应的符号链接,而是移到了DriverAddDevice函数中,所以pDriverObj->MajorFunction中我们并没有单独指定pDriverObj->MajorFunction[IRP_MJ_CREATE]pDriverObj->MajorFunction[IRP_MJ_CLOSE],而是将所有的派遣函数指向一个通用的回调函数DispatchRoutine

其中设备名称在代码中被我们宏定义为L"\\Device\\MyWdmDevice",符号链接被我们定义为L"\\??\\MyWdmLink"

Device是用来和应用层通信的,应用层程序可以通过SymbolicLink找到对应的设备。

IoCreateDevice就是创建设备的函数

第一个参数为驱动对象指针
第二个参数为设备扩展结构(DeviceExtension)的大小
第三个参数为设备名称,具体可以查看微软文档。

IoCreateSymbolicLink就是创建符号链接的函数

第一个参数为符号链接名称,第二个参数为设备名称

DeviceExtension

设备扩展结构,你可以将某些信息保存在扩展结构中,这样可以避免使用全局变量,应用层通信时,可以读取或写入的信息的结构,之后NT式驱动的例子中会用到。

IRP

在通用的派遣函数DispatchRoutine中,我们看到了一个参数pIrp,IRP的含义是 I/O Request Packet缩写,是在驱动中IO请求的结构体,其具体作用,我决定放在NT式驱动中细说。

ez_driver

image-20240525155814130

我们可以在驱动入口处看到,先调用了 DriverUnloadDriverUnload是驱动卸载的回调,如果我们不设置DriverUnload,那么此时我们将无法正常的卸载驱动,系统这么做的原因是为了保证系统的稳定性。

然后是注册,其中设备名称在代码中被宏定义为L"\\Device\\MYDEVICE",符号链接被我们定义为L"\\??\\DeviceNONO"

之后调用了 IoCreateDevice 函数进行设备创建

再通过IoCreateSymbolicLink创建符号链接的,第一个参数为符号链接名称,第二个参数为设备名称

if 里面我们可以看到 MajorFunction ,那么后面跟的应该就是对应的回调函数,在执行之前又获取了 DriverStartDreiverSize,然后进入了 sub_140001990 函数,

image-20240525160555030

这个函数对DriverStart 开始的一段数据进行比对,比对的内容是三条汇编语句

其opcode为,0xC1, 0xE9, 0x05, 0x33, 0xC1, 0x03

image-20240525160655705

看来是对这三条语句进行搜索,只要匹配成功,就调用 sub_1400018F0 函数把常数 6 覆写到 (_BYTE*)(a1+i+2) 上,其实就是 opcode 中的 0x05改成了 0x06

我们写个idapython跑一下

1
2
3
4
5
6
7
8
9
10
11
12
import idaapi
import idc

start_addr = 140001000
end_addr = 140006000
pattern = "C1 E9 05 33 C1 03"
cur_addr = start_addr
while cur_addr < end_addr:
cur_addr = idc.find_binary(cur_addr, SEARCH_DOWN, pattern)
print(hex(cur_addr))
if cur_addr == idc.BADADDR:
break

结果是0x140001d58

image-20240525162048520

然后我们进入加密函数

image-20240525161100242

是一个tea加密,由于之前的分析,加密函数被修改了,>>5 被改成了 >>6

然后是一个自写加密,加解密是对称的,抄过来就行

image-20240525162135083

解密即可

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
#include <iostream>
#include <Windows.h>
BYTE byte_140004000[] =
{
0x72, 0x62, 0xAE, 0x34, 0x52, 0x9A, 0x06, 0xAF,
0x72, 0xFB, 0x40, 0xC0, 0x10, 0x35, 0xBD, 0xD4,
0x22, 0xA5, 0x93, 0x07, 0xB4, 0xFB, 0xB5, 0xCA,
0xE8, 0x01, 0xF5, 0xAE, 0xED, 0x7B, 0xB8, 0x6A
};
__int64 __fastcall sub_140001A70(unsigned int *input, int a2)
{
int j; // [rsp+4h] [rbp-44h]
int i; // [rsp+8h] [rbp-40h]
unsigned int input_xor; // [rsp+Ch] [rbp-3Ch] BYREF
unsigned char *p_input_xor; // [rsp+10h] [rbp-38h]
unsigned int v6; // [rsp+18h] [rbp-30h]
char v7[16]; // [rsp+20h] [rbp-28h]

v7[1] = a2 ^ 0x25;
v7[0] = a2 ^ 0x7A;
v7[8] = a2 ^ 0x1A;
v7[2] = a2 ^ 0x35;
v7[9] = a2 ^ 0x6D;
v7[3] = a2 ^ 0x23;
v7[11] = a2 ^ 0x94;
v7[4] = a2 ^ 0xC5;
v7[5] = a2 ^ 0x4B;
v7[6] = a2 ^ 0x21;
v7[7] = a2 ^ 0x35;
v7[10] = a2 ^ 0x91;
v7[12] = a2 ^ 0x2C;
v7[13] = a2 ^ 0xC1;
v7[14] = a2 ^ 0x92;
v7[15] = a2 ^ 0x51;
for ( i = 0; i < 4; ++i )
{
p_input_xor = (unsigned char*)&input_xor;
input_xor = *input ^ a2;
for ( j = 0; j < 4; ++j )
*p_input_xor++ ^= v7[15 - (((unsigned __int8)i + (unsigned __int8)j) & 0xF)] | ((unsigned __int8)j << j) | j | 4;
v6 = ~a2 ^ input_xor;
*input++ = v6;
}
}
int main()
{
int v8 = 0;
BYTE* v17 = byte_140004000;
do
{
sub_140001A70((unsigned int *)v17, v8++);
v17 += 16;
} while (v8 < 2);
for (unsigned char c : byte_140004000)
printf("%d,", c);
printf("\n");
}
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
#include<bits/stdc++.h>
using namespace std;
void decrypt(uint32_t *v, uint32_t *key)
{
uint32_t l = v[0], r = v[1], sum = 0x9E3779B9 * 33;
for (int i = 0; i < 33; ++i)
{
r -= (key[(sum >> 11) & 3] + sum) ^ (l + ((l >> 5) ^ (16 * l)));
sum += 0x61C88647;
l -= (key[sum & 3] + sum) ^ (r + ((r >> 6) ^ (16 * r)));

}
v[0] = l, v[1] = r;
}
int main(){
uint32_t key[4];
// uint8_t enc[] = {0x72, 0x62, 0xAE, 0x34, 0x52, 0x9A, 0x06, 0xAF,
// 0x72, 0xFB, 0x40, 0xC0, 0x10, 0x35, 0xBD, 0xD4,
// 0x22, 0xA5, 0x93, 0x07, 0xB4, 0xFB, 0xB5, 0xCA,
// 0xE8, 0x01, 0xF5, 0xAE, 0xED, 0x7B, 0xB8, 0x6A};
uint8_t enc[] = {216,10,158,244,59,162,215,207,72,43,33,160,195,93,221,84,137,205,162,199,220,195,101,170,211,209,149,206,63,19,217,234};
key[0] = 0x1A2B;
key[1] = 0x3A4D;
key[2] = 0x5E6F;
key[3] = 0xAA33;
for (int i=0;i<32;i+=8){
uint32_t *p = (uint32_t *)&enc[i];
p[0] = __builtin_bswap32(p[0]);
p[1] = __builtin_bswap32(p[1]);
decrypt((uint32_t*)p,key);
p[0] = __builtin_bswap32(p[0]);
p[1] = __builtin_bswap32(p[1]);
}
for (int i=0;i<32;i++){
printf("%c",enc[i]);
}
return 0;
}

可以用Unicorn脚本进行动态调试

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
from unicorn import *
from unicorn.x86_const import *
import struct
from capstone import *
REAL_BASE_OFFSET = 0x400
md = Cs(CS_ARCH_X86, CS_MODE_64)
def read(name):
with open(name,'rb') as f:
return f.read()
def hookDbgPrint(mu,address,size,user_data):
code = mu.mem_read(address, size)
# for instruction in md.disasm(code, address):
# print("0x%x: %s %s" % (instruction.address, instruction.mnemonic, instruction.op_str))
DbgList = [0x1400015C9]
if (address in DbgList):
mu.reg_write(UC_X86_REG_RIP, address+5)
print(f"hook: {address}")
if (address == 0x140001940):
TEAoutput = mu.mem_read(mu.reg_read(UC_X86_REG_RAX), 32)
if (address == 0x1400017DB):
# mu.mem_write(mu.reg_read(UC_X86_REG_RSP) + 40, b'12345678')
TEAinput = mu.mem_read(mu.reg_read(UC_X86_REG_RSP) + 40, 8)
print("tea in: ",bytes(TEAinput))
if (address == 0x14000166D):
mu.mem_write(mu.reg_read(UC_X86_REG_RSP) + 144, b'12345678')
if (address == 0x14000182D):
TEAoutput = mu.mem_read(mu.reg_read(UC_X86_REG_RSP) + 40, 8)
print("tea out: ",end='')
for i in TEAoutput:
print(i,end=',')
print()
if (address == 0x14000197A):
ENCoutput = mu.mem_read(mu.reg_read(UC_X86_REG_RSP) + 40, 8)
print("enc out:",end='')
for i in ENCoutput:
print(i,end=',')
print()
def hookEND(mu : Uc,address,size,user_data):
if (address == 0x14000197A):
print("end")
# exit(0)
mu.emu_stop()
mu = Uc (UC_ARCH_X86, UC_MODE_64)
BASE = 0x140001000
STACK_ADDR = 0x1000
STACK_SIZE = 1024*1024
mu.mem_map(BASE, 1024*1024)
mu.mem_map(STACK_ADDR, STACK_SIZE)
mu.mem_write(BASE, read("./ez_driver.sys"))
mu.reg_write(UC_X86_REG_RBP, STACK_ADDR + STACK_SIZE // 2)
mu.reg_write(UC_X86_REG_RSP, STACK_ADDR + STACK_SIZE // 3)
mu.hook_add(UC_HOOK_CODE,hookDbgPrint)
mu.hook_add(UC_HOOK_CODE,hookEND)
mu.emu_start(0x14000161D, 0x140004000)

crazyaes

先用 010editor 跟出题人对脑电波,把EE改成PE,再恢复UPX的标识,用4.00版本以上upx脱壳。

一共修改了 4 处

  1. 反调试以后修改了 key,藏在回调函数里

image-20240526000356533

  1. 轮密钥加以后异或

    image-20240526000608921

  2. sub_bytes异或 0xA1

    image-20240526000635514

  3. mix_column 异或 0x54

    image-20240526000730436

然后写脚本解密即可

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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
typedef enum {
AES_CYPHER_128,
AES_CYPHER_192,
AES_CYPHER_256,
} AES_CYPHER_T;
/*
* Encryption Rounds
*/
int g_aes_key_bits[] = {
/* AES_CYPHER_128 */
128,
/* AES_CYPHER_192 */
192,
/* AES_CYPHER_256 */
256,
};
int g_aes_rounds[] = {
/* AES_CYPHER_128 */
10,
/* AES_CYPHER_192 */
12,
/* AES_CYPHER_256 */
14,
};
int g_aes_nk[] = {
/* AES_CYPHER_128 */
4,
/* AES_CYPHER_192 */
6,
/* AES_CYPHER_256 */
8,
};
int g_aes_nb[] = {
/* AES_CYPHER_128 */
4,
/* AES_CYPHER_192 */
4,
/* AES_CYPHER_256 */
4,
};

static const uint32_t g_aes_rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
0x40000000, 0x80000000,
0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0xed000000,
0x9a000000
};

static const uint8_t g_aes_sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
static const uint8_t g_inv_sbox[256] = {

0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
uint8_t aes_sub_sbox(uint8_t val)
{
return g_aes_sbox[val];
}
uint32_t aes_sub_dword(uint32_t val)
{
uint32_t tmp = 0;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 0) & 0xFF))) << 0;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 8) & 0xFF))) << 8;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 16) & 0xFF))) << 16;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 24) & 0xFF))) << 24;
return tmp;
}
uint32_t aes_rot_dword(uint32_t val)
{
uint32_t tmp = val;
return (val >> 8) | ((tmp & 0xFF) << 24);
}
uint32_t aes_swap_dword(uint32_t val)
{
return (((val & 0x000000FF) << 24) |
((val & 0x0000FF00) << 8) |
((val & 0x00FF0000) >> 8) |
((val & 0xFF000000) >> 24));
}

void aes_key_expansion(AES_CYPHER_T mode, uint8_t *key, uint8_t *round)
{
uint32_t *w = (uint32_t *)round;
uint32_t t;
int i = 0;
do
{
w[i] = *((uint32_t *)&key[i * 4 + 0]);
}
while (++i < g_aes_nk[mode]);
do
{
if ((i % g_aes_nk[mode]) == 0)
{
t = aes_rot_dword(w[i - 1]);
t = aes_sub_dword(t);
t = t ^ aes_swap_dword(g_aes_rcon[i / g_aes_nk[mode] - 1]);
} else if (g_aes_nk[mode] > 6 && (i % g_aes_nk[mode]) == 4)
{
t = aes_sub_dword(w[i - 1]);
} else
{
t = w[i - 1];
}
w[i] = w[i - g_aes_nk[mode]] ^ t;
}
while (++i < g_aes_nb[mode] * (g_aes_rounds[mode] + 1));
}

void aes_add_round_key(AES_CYPHER_T mode, uint8_t *state,uint8_t *round, int nr)
{
uint32_t *w = (uint32_t *)round;
uint32_t *s = (uint32_t *)state;
int i;
for (i = 0; i < g_aes_nb[mode]; i++)
{
s[i] ^= w[nr * g_aes_nb[mode] + i];
}
}

void aes_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;
for (i = 0; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < 4; j++)
{
state[i * 4 + j] = aes_sub_sbox(state[i * 4 + j]);
state[i * 4 + j] ^= 0xA1;

}
}
}

void aes_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;
for (i = 1; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < i; j++)
{
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++)
{
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}

uint8_t aes_xtime(uint8_t x)
{
return ((x << 1) ^ (((x >> 7) & 1) * 0x1b));
}

uint8_t aes_xtimes(uint8_t x, int ts)
{
while (ts-- > 0)
{
x = aes_xtime(x);
}
return x;
}

uint8_t aes_mul(uint8_t x, uint8_t y)
{

return ((((y >> 0) & 1) * aes_xtimes(x, 0)) ^
(((y >> 1) & 1) * aes_xtimes(x, 1)) ^
(((y >> 2) & 1) * aes_xtimes(x, 2)) ^
(((y >> 3) & 1) * aes_xtimes(x, 3)) ^
(((y >> 4) & 1) * aes_xtimes(x, 4)) ^
(((y >> 5) & 1) * aes_xtimes(x, 5)) ^
(((y >> 6) & 1) * aes_xtimes(x, 6)) ^
(((y >> 7) & 1) * aes_xtimes(x, 7)));
}

void aes_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2 };
uint8_t s[4];
int i, j, r;
for (i = 0; i < g_aes_nb[mode]; i++)
{
for (r = 0; r < 4; r++)
{
s[r] = 0;
for (j = 0; j < 4; j++)
{
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++)
{
state[i * 4 + r] = s[r];
state[i * 4 + r] ^= 0x54;
}
}
}

int aes_encrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = { 0 };
/* round key */
uint8_t s[4 * 4] = { 0 };

unsigned char xor_key[] =
{
0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x03, 0x02, 0x02, 0x03,
0x00, 0x01, 0x03, 0x02, 0x01, 0x00
};

/* state */
int nr, i, j;
/* key expansion */
aes_key_expansion(mode, key, w);
/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode])
{
/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];
printf("round %d\n", i);
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++)
{
if (nr > 0)
{
/* do SubBytes */
aes_sub_bytes(mode, s);
printf("after aes_sub_bytes\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
/* do ShiftRows */
aes_shift_rows(mode, s);
printf("after aes_shift_rows\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
if (nr < g_aes_rounds[mode])
{
/* do MixColumns */
aes_mix_columns(mode, s);
printf("after aes_mix_columns\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
}
}
/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
printf("after aes_add_round_key\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");

for(int j = 0; j < 16; j++)s[j] ^= xor_key[j];
printf("after xor\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
}
/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = s[j];
}
return 0;
}

int aes_encrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
return aes_encrypt(mode, data, len, key);
}

int aes_encrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv)
{
uint8_t w[4 * 4 * 15] = { 0 };
/* round key */
uint8_t s[4 * 4] = { 0 };
/* state */
uint8_t v[4 * 4] = { 0 };
/* iv */
int nr, i, j;
/* key expansion */
aes_key_expansion(mode, key, w);
memcpy(v, iv, sizeof(v));
/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode])
{
/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j] ^ v[j];
/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++)
{
if (nr > 0)
{
/* do SubBytes */
aes_sub_bytes(mode, s);
/* do ShiftRows */
aes_shift_rows(mode, s);
if (nr < g_aes_rounds[mode])
{
/* do MixColumns */
aes_mix_columns(mode, s);
}
}
/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
}
/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = v[j] = s[j];
}
return 0;
}

void inv_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;
for (i = 1; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < g_aes_nb[mode] - i; j++)
{
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++)
{
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}

uint8_t inv_sub_sbox(uint8_t val)
{
return g_inv_sbox[val];
}

void inv_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;
for (i = 0; i < g_aes_nb[mode]; i++)
{
for (j = 0; j < 4; j++)
{
state[i * 4 + j] = inv_sub_sbox(state[i * 4 + j] ^ 0xA1);
}
}
}

void inv_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 0x0e, 0x0b, 0x0d, 0x09, 0x09, 0x0e, 0x0b, 0x0d,
0x0d, 0x09, 0x0e, 0x0b, 0x0b, 0x0d, 0x09, 0x0e };
uint8_t s[4];
int i, j, r;

for (i = 0; i < g_aes_nb[mode]; i++)
{
for (r = 0; r < 4; r++)
{
s[r] = 0;
for (j = 0; j < 4; j++)
{
s[r] = s[r] ^ aes_mul(state[i * 4 + j] ^ 0x54, y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++)
{
state[i * 4 + r] = s[r];

}
}
}

int aes_decrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = {0};
/* round key */
uint8_t s[4 * 4] = { 0 };
unsigned char xor_key[] =
{
0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x03, 0x02, 0x02, 0x03,
0x00, 0x01, 0x03, 0x02, 0x01, 0x00
};
/* state */
int nr, i, j;
/* key expansion */
aes_key_expansion(mode, key, w);

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode])
{
/* init state from user buffer (cyphertext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];
printf("after key_exp\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
/* start AES cypher loop over all AES rounds */
for (nr = g_aes_rounds[mode]; nr >= 0; nr--)
{
for(int j = 0; j < 16; j++) s[j] ^= xor_key[j];
printf("after xor\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
printf("after aes_add_round_key\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
if (nr > 0)
{
if (nr < g_aes_rounds[mode])
{
/* do MixColumns */
inv_mix_columns(mode, s);
printf("after inv_mix_columns\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
}
/* do ShiftRows */
inv_shift_rows(mode, s);
printf("after inv_shift_rows\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
/* do SubBytes */
inv_sub_bytes(mode, s);
printf("after inv_sub_bytes\n");
for(int j = 0; j < 16; j++)printf("0x%2x, ", s[j]);
printf("\n");
}
}
/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = s[j];
}
return 0;
}

int main()
{
unsigned char buf[] =
{
0xB4, 0x38, 0x36, 0x30, 0x1E, 0x68, 0x48, 0x57, 0x51, 0x01,
0xB7, 0x03, 0x9B, 0x98, 0xE3, 0x7E,
};

uint8_t key[] = {0x67, 0x61, 0X68, 0x34, 0x33, 0x6A, 0x4A, 0x4B, 0x67, 0x66,
0x6A, 0x47, 0x4D, 0x65, 0x41, 0x52};

aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key);

for (int i = 0; i < sizeof(buf); i++)
{
printf("%c", (buf[i] & 0xFF));
}

return 0;
}