2017全国大学生信息安全竞赛 re450 Gadgetzan

这道题从我开始看到做出差不多花了8,9个小时,已经是我做过最复杂的逆向了(其中部分还在大佬的帮助下)。没有大佬的帮助,我肯定是做不出的,在此先感谢一下。

写这篇文章的主要目的是为了记录,算是我逆向路上的一个新的里程碑吧。

程序下载:Gadgetzan,patch时间的版本:Gadgetzan_patchtime

为了方便理解,我附上我的idb文件:Gadgetzan.idb


首先跟着字符串来到我们的主函数:

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
int __cdecl start_here(int a1)
{
int v1; // ecx@2
int result; // eax@3
char v3; // [sp-Eh] [bp-2Ch]@0
int input; // [sp+1h] [bp-1Dh]@1
int v5; // [sp+5h] [bp-19h]@1
int v6; // [sp+9h] [bp-15h]@1
int v7; // [sp+Dh] [bp-11h]@1
char v8; // [sp+11h] [bp-Dh]@1
int v9; // [sp+12h] [bp-Ch]@1
int *v10; // [sp+1Ah] [bp-4h]@1
v10 = &a1;
v9 = *MK_FP(__GS__, 20);
puts((int)"Welcome to Gadgetzan!~");
sub_8071770(1, (int)"Show me your key:", v3);
input = 0;
v5 = 0;
v6 = 0;
v7 = 0;
v8 = 0;
scanf("%16s", &input);
if ( strlen((int)&input) == 16 )
{
enc_func1((char *)&input); // chag_input
enc_func2((BYTE *)&input);
}
else
{
puts((int)"Key length error!");
}
result = 0;
if ( *MK_FP(__GS__, 20) != v9 )
canary(v1, *MK_FP(__GS__, 20) ^ v9);
return result;
}

得知input长度为16,且加密分在了两个函数内,就是这里的enc_func1enc_func2
func1先大致看了一眼,是将输入的字符串加密成等长(16bytes)的字符串,我们叫他chg_ipt


我们看func2,毕竟逆向是倒推的过程。

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
int __cdecl enc_func2(BYTE *chg_ipt)
{
BYTE _R; // bl@1
BYTE *ptr; // eax@1
_BYTE *ptr_2; // esi@1
signed int L; // eax@1
int k; // ecx@2
signed int v6; // eax@4
BYTE *ptr_3; // esi@7
_WORD *check_p; // ebp@7
int i; // edi@7
unsigned int val; // edx@7
int tmp_i; // ecx@8
int ck_WORD; // ebx@8
int ptr_v; // eax@10
__int16 check_v; // ax@13
BYTE R; // [sp+16h] [bp-36h]@2
__int16 Ra; // [sp+16h] [bp-36h]@7
signed int ipt_L; // [sp+18h] [bp-34h]@2
signed int ipt_R; // [sp+1Ch] [bp-30h]@2
int n; // [sp+20h] [bp-2Ch]@1
BYTE *tbl; // [sp+24h] [bp-28h]@1
BYTE *ptr_1; // [sp+2Ch] [bp-20h]@1
_R = 88;
ptr = (BYTE *)calloc(256, 1u);
ptr_1 = ptr;
tbl = (BYTE *)&bfr_tbl[8]; // 定值
ptr_2 = ptr;
L = 54;
n = 0;
while ( 1 ) // PART1
{
R = _R;
ipt_L = chg_ipt[n];
k = 0;
ipt_R = chg_ipt[-n + 15];
while ( 1 )
{
ptr_2[L] = (ipt_L >> k) & 1;
v6 = ipt_R >> k++;
ptr_2[R] = v6 & 1;
if ( k == 8 )
break;
L = (unsigned __int8)*(&bfr_tbl[8 * n] + k);
R = *(&tbl[k] + 120 - (_DWORD)bfr_tbl + (_DWORD)bfr_tbl);
}
if ( ++n == 16 ) // 最终出while的条件
break;
L = *tbl;
_R = tbl[128];
tbl += 8;
} // PART2
//
//
//
ptr_3 = ptr_1;
check_p = &check_start;
i = 0;
val = 0xFFFF8EBC;
for ( Ra = 0x86C1u; ; Ra = check_v )
{
tmp_i = 0;
ck_WORD = 0;
while ( 1 )
{
ptr_v = ptr_3[8 * tmp_i];
tmp_i += 2;
ck_WORD ^= ptr_v * val;
if ( tmp_i == 0x20 ) // 0x10次
break;
val = *(_WORD *)((char *)&check_end + 2 * i + tmp_i);
}
if ( (_WORD)ck_WORD != Ra )
break; // wrong
++ptr_3;
i += 16;
if ( check_p == &check_end )
{
puts((int)"Good job! The flag is your input...");
sub_804A470((int)ptr_1);
free((int)ptr_1);
return 0;
}
check_v = *check_p;
val = *(&check_end + i);
++check_p;
}
puts((int)"Wrong key!");
return 0;
}

func2分为PART1和PART2,PART1是将输入的字符串的每一bit按照某个box打乱,放在一个16*16的内存中,内存里看大概是这样的

由于从左到右和从右到左,每1bit被放了两遍,所以一共有8*16*2 = 16*16 = 256。

用于随机的box

伪算法:

1
2
3
4
5
6
7
for i in range(16*8):
L = box[i]
R = box[i+0x80]
bits_stream_L = fun(chg_ipt) #'12'->'0011000100110010'
bits_stream_R = fun(chg_ipt[::-1]) #'12'-> '21'->'0011001000110001'
bit_arr[L] = int(bits_stream_L[i])
bit_arr[R] = int(bits_stream_R[i])

PART2是用来验证的,根据PART1算出来的bits_arr和另一个16*16的box中的数做一定的运算得出16个数,若全部相等则success。

256的box。

check用的16个数:

伪算法:

1
2
3
4
5
6
7
8
9
10
for i in range(16):
tmp=0
check_word=0
for j in range(16):
check_word ^= (box[i*16+j] * bits_arr[j*16+i])&0xffff
if check_word != flag_word[i]:
wrong
exit
success

由于bits_arr[j*16+i]只存在0和1,所以check_word所异或的只能为box[i*16+j]或0,因此,我们可以爆破这16位0和1。

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#coding=utf8
import copy
check_sum = [0x86C1,0x39A3,0x0C239,0x0B7EF,0x0FEF,0x3FB4,0x2E25,0x2216,0x57D0,0x8065,0x699D,0x3B3,0x0CC0E,0x0D4A7,0x5260,0x0EA18]
val = [0x8EBC,0x475E,0x23AF,0x91D7,0x0C8EB,0x0E475,0x0F23A,0x791D,0x0BC8E,0x5E47,0x0AF23,0x0D791,0x0EBC8,0x75E4,0x3AF2,0x1D79,0x2F11,0x9788,0x4BC4,0x25E2,0x12F1,0x8978,0x44BC,0x225E,0x112F,0x8897,0x0C44B,0x0E225,0x0F112,0x7889,0x0BC44,0x5E22,0x0D000,0x6800,0x3400,0x1A00,0x0D00,0x680,0x340,0x1A0,0x0D0,0x68,0x34,0x1A,0x0D,0x8006,0x4003,0x0A001,0x0F0A2,0x7851,0x0BC28,0x5E14,0x2F0A,0x1785,0x8BC2,0x45E1,0x0A2F0,0x5178,0x28BC,0x145E,0x0A2F,0x8517,0x0C28B,0x0E145,0x5750,0x2BA8,0x15D4,0x0AEA,0x575,0x82BA,0x415D,0x0A0AE,0x5057,0x0A82B,0x0D415,0x0EA0A,0x7505,0x0BA82,0x5D41,0x0AEA0,0x69F8,0x34FC,0x1A7E,0x0D3F,0x869F,0x0C34F,0x0E1A7,0x0F0D3,0x0F869,0x0FC34,0x7E1A,0x3F0D,0x9F86,0x4FC3,0x0A7E1,0x0D3F0,0x0EB49,0x0F5A4,0x7AD2,0x3D69,0x9EB4,0x4F5A,0x27AD,0x93D6,0x49EB,0x0A4F5,0x0D27A,0x693D,0x0B49E,0x5A4F,0x0AD27,0x0D693,0x0C241,0x0E120,0x7090,0x3848,0x1C24,0x0E12,0x709,0x8384,0x41C2,0x20E1,0x9070,0x4838,0x241C,0x120E,0x907,0x8483,0x0F7A,0x7BD,0x83DE,0x41EF,0x0A0F7,0x0D07B,0x0E83D,0x0F41E,0x7A0F,0x0BD07,0x0DE83,0x0EF41,0x0F7A0,0x7BD0,0x3DE8,0x1EF4,0x21DC,0x10EE,0x877,0x843B,0x0C21D,0x0E10E,0x7087,0x0B843,0x0DC21,0x0EE10,0x7708,0x3B84,0x1DC2,0x0EE1,0x8770,0x43B8,0x0E43D,0x0F21E,0x790F,0x0BC87,0x0DE43,0x0EF21,0x0F790,0x7BC8,0x3DE4,0x1EF2,0x0F79,0x87BC,0x43DE,0x21EF,0x90F7,0x0C87B,0x8F1D,0x0C78E,0x63C7,0x0B1E3,0x0D8F1,0x0EC78,0x763C,0x3B1E,0x1D8F,0x8EC7,0x0C763,0x0E3B1,0x0F1D8,0x78EC,0x3C76,0x1E3B,0x57E8,0x2BF4,0x15FA,0x0AFD,0x857E,0x42BF,0x0A15F,0x0D0AF,0x0E857,0x0F42B,0x0FA15,0x0FD0A,0x7E85,0x0BF42,0x5FA1,0x0AFD0,0x2EEC,0x1776,0x0BBB,0x85DD,0x0C2EE,0x6177,0x0B0BB,0x0D85D,0x0EC2E,0x7617,0x0BB0B,0x0DD85,0x0EEC2,0x7761,0x0BBB0,0x5DD8,0x62CC,0x3166,0x18B3,0x8C59,0x0C62C,0x6316,0x318B,0x98C5,0x0CC62,0x6631,0x0B318,0x598C,0x2CC6,0x1663,0x8B31,0x0C598,0x53FE,0x29FF,0x94FF,0x0CA7F,0x0E53F,0x0F29F,0x0F94F,0x0FCA7,0x0FE53,0x0FF29,0x0FF94,0x7FCA,0x3FE5,0x9FF2,0x4FF9,0x0A7FC]
bit=[0]*16
out=[]
for k in range(len(check_sum)):
for i in range(0xffff):
check=0
for j in range(16):
bit[j] = (i&(1<<j))/(1<<j)#di -> gao
for j in range(16):
check ^=(bit[j]*val[k*16+j])
if (check&0xffff)==check_sum[k]:
#print bit
out.append(copy.deepcopy(bit))
break
for k in zip(*out):#矩阵转置
print k

得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0)
(1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1)
(1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0)
(1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0)
(0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1)
(1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0)
(0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0)
(0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0)
(1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1)
(1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1)
(1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1)
(1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1)
(1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0)
(1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0)
(0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0)
(1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1)

再对PART1求逆,就是根据box把相应的bit放回原来的位置

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
out = [0]*256
tbl=[0x36,0x4F,0x62,0x0D8,0x0B5,0x84,0x0CD,0x0F6,0x0DC,0x2A,0x0E6,0x0ED,0x0AB,0x52,0x1,0x0AF,0x0D0,0x0A,0x68,0x14,0x27,0x0A1,0x0DB,0x87,0x9C,0x0E7,0x29,0x66,0x35,0x0E9,0x0B4,0x91,0x8B,0x0CE,0x0F3,0x34,0x56,0x5E,0x23,0x61,0x70,0x0C3,0x0A7,0x32,0x2D,0x80,0x0C,0x0C4,0x0F5,0x2C,0x72,0x0A4,0x0C9,0x6,0x0B9,0x6E,0x19,0x12,0x7,0x22,0x0D6,0x0D3,0x0,0x71,0x98,0x0E,0x6B,0x0CA,0x64,0x3D,0x0BA,0x0FE,0x88,0x2,0x0E3,0x46,0x0EF,0x1F,0x2F,0x8F,0x2E,0x3A,0x31,0x9B,0x0F0,0x0E2,0x7B,0x99,0x0BB,0x0A8,0x48,0x63,0x0D4,0x8D,0x0F4,0x69,0x0BF,0x0E8,0x4B,0x0DE,0x0DA,0x76,0x0B0,0x10,0x0B8,0x97,0x0C6,0x9F,0x16,0x0F7,0x0AC,0x0DD,0x45,0x0BC,0x0C5,0x0E1,0x0AD,0x7C,0x5B,0x0FC,0x0CC,0x0AE,0x59,0x9A,0x6F,0x0E5,0x67,0x0A3,0x58,0x0C7,0x8C,0x65,0x81,0x49,0x53,0x83,0x40,0x39,0x5D,0x37,0x0B1,0x74,0x8E,0x4D,0x0CF,0x33,0x0F8,0x0A2,0x75,0x73,0x0FA,0x0D7,0x4A,0x0CB,0x82,0x78,0x17,0x0E0,0x95,0x7D,0x8,0x0F1,0x0BD,0x41,0x0B7,0x4,0x0F,0x8A,0x0D1,0x51,0x3E,0x38,0x93,0x0C2,0x89,0x0D2,0x96,0x94,0x1A,0x0FB,0x5F,0x7E,0x60,0x24,0x54,0x0EA,0x7F,0x0B,0x1B,0x43,0x26,0x2B,0x1C,0x0B3,0x4E,0x85,0x3F,0x5A,0x0C0,0x1E,0x50,0x77,0x0FF,0x9,0x0E4,0x9E,0x25,0x9D,0x5,0x13,0x0EE,0x0D5,0x30,0x0AA,0x28,0x79,0x86,0x4C,0x0F9,0x57,0x6D,0x0EB,0x47,0x0B2,0x0D9,0x18,0x0B6,0x0BE,0x7A,0x0C1,0x0A0,0x0D,0x5C,0x0C8,0x0A5,0x44,0x6A,0x3C,0x20,0x0A6,0x3,0x11,0x3B,0x15,0x90,0x0FD,0x92,0x0EC,0x0A9,0x21,0x55,0x1D,0x0DF,0x6C,0x42,0x0F2]
enc=[
1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0,
1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0,
1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0,
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0,
0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0,
0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0,
1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1,
1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1,
1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0,
1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0,
1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1
]
for i in range(0x80):
L = tbl[i]
R = tbl[i+0x80]
out[i] = enc[L]
out[i+0x80] = enc[R]
out2=[]
for i in range(32):
ch=0
for j in range(8):
ch +=out[j+8*i]*(2**j)
out2.append(ch)
out3=''
for i in out2:
out3+=hex(i)[2:]
print out3[:32]

得到chg_ipt:cad3e543f23c3fec33a93f95dd8c4c2a


再来看func1。

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
int __cdecl enc_func1(char *input)
{
char *ipt_1; // eax@1
int v2; // eax@1
int key; // esi@1
int v4; // edx@1
bool v5; // zf@1
int v6; // ecx@1
char *input_1; // [sp+18h] [bp-50h]@1
int v9; // [sp+1Ch] [bp-4Ch]@1
int v10; // [sp+20h] [bp-48h]@1
int v11; // [sp+24h] [bp-44h]@1
int chg_input; // [sp+28h] [bp-40h]@1
int v13; // [sp+2Ch] [bp-3Ch]@1
int v14; // [sp+30h] [bp-38h]@1
int v15; // [sp+34h] [bp-34h]@1
unsigned __int8 v16; // [sp+38h] [bp-30h]@1
unsigned __int8 v17; // [sp+39h] [bp-2Fh]@1
unsigned __int8 v18; // [sp+3Ah] [bp-2Eh]@1
unsigned __int8 v19; // [sp+3Bh] [bp-2Dh]@1
unsigned __int8 v20; // [sp+3Ch] [bp-2Ch]@1
unsigned __int8 v21; // [sp+3Dh] [bp-2Bh]@1
unsigned __int8 v22; // [sp+3Eh] [bp-2Ah]@1
unsigned __int8 v23; // [sp+3Fh] [bp-29h]@1
unsigned __int8 v24; // [sp+40h] [bp-28h]@1
unsigned __int8 v25; // [sp+41h] [bp-27h]@1
unsigned __int8 v26; // [sp+42h] [bp-26h]@1
unsigned __int8 v27; // [sp+43h] [bp-25h]@1
unsigned __int8 v28; // [sp+44h] [bp-24h]@1
unsigned __int8 v29; // [sp+45h] [bp-23h]@1
unsigned __int8 v30; // [sp+46h] [bp-22h]@1
unsigned __int8 v31; // [sp+47h] [bp-21h]@1
unsigned __int8 v32; // [sp+48h] [bp-20h]@1
unsigned __int8 v33; // [sp+49h] [bp-1Fh]@1
unsigned __int8 v34; // [sp+4Ah] [bp-1Eh]@1
unsigned __int8 v35; // [sp+4Bh] [bp-1Dh]@1
unsigned __int8 v36; // [sp+4Ch] [bp-1Ch]@1
unsigned __int8 v37; // [sp+4Dh] [bp-1Bh]@1
unsigned __int8 v38; // [sp+4Eh] [bp-1Ah]@1
unsigned __int8 v39; // [sp+4Fh] [bp-19h]@1
unsigned __int8 v40; // [sp+50h] [bp-18h]@1
unsigned __int8 v41; // [sp+51h] [bp-17h]@1
unsigned __int8 v42; // [sp+52h] [bp-16h]@1
unsigned __int8 v43; // [sp+53h] [bp-15h]@1
unsigned __int8 v44; // [sp+54h] [bp-14h]@1
unsigned __int8 v45; // [sp+55h] [bp-13h]@1
unsigned __int8 v46; // [sp+56h] [bp-12h]@1
char v47; // [sp+57h] [bp-11h]@1
int v48; // [sp+58h] [bp-10h]@1
v16 = 0xE6u;
v48 = *MK_FP(__GS__, 20);
v17 = 0xB8u;
v18 = 0xA1u;
v19 = 0xE3u;
v20 = 0x80u;
v21 = 0x82u;
v22 = 0xE6u;
v23 = 0xB8u;
v24 = 0xA1u;
v25 = 0xE3u;
v26 = 0x80u;
v27 = 0x82u;
v28 = 0xE6u;
v29 = 0xB8u;
v30 = 0xA1u;
v31 = 0xE3u;
v32 = 0x80u;
v33 = 0x82u;
v34 = 0xE6u;
v35 = 0xB8u;
v36 = 0xA1u;
v37 = 0xE3u;
v38 = 0x80u;
v39 = 0x82u;
v40 = 0xE6u;
v41 = 0xB8u;
v42 = 0xA1u;
v43 = 0xE3u;
ipt_1 = *(char **)input;
v44 = 0x80u;
v45 = 0x82u;
v46 = 0xE6u;
input_1 = ipt_1;
v2 = *((_DWORD *)input + 1);
v47 = -72;
8 = 8;
keyround = 14;
v9 = v2;
v10 = *((_DWORD *)input + 2);
v11 = *((_DWORD *)input + 3);
key = malloc(60 * size_int);
init_key((int)&v16, key);
AES_LIKE((int)&input_1, (int)&chg_input, key);
*(_DWORD *)input = chg_input;
*((_DWORD *)input + 1) = v13;
*((_DWORD *)input + 2) = v14;
v6 = *MK_FP(__GS__, 20) ^ v48;
v5 = *MK_FP(__GS__, 20) == v48;
*((_DWORD *)input + 3) = v15; // chag input here
if ( !v5 )
canary(v6, v4);
return 0;
}

前面一长段的v16不用管他,因为只是用来生成key的,key可以动态dump。之后就是把key,input传入一个向AES一样的函数,代码如下。


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
int __cdecl AES_LIKE(int input, int output, int key)
{
int v3; // edi@1
int v4; // esi@1
void *v5; // esp@1
int *in; // ebx@1
int j; // eax@3
int k; // edx@3
int v9; // edi@7
signed int i; // esi@7
int v11; // edx@8
int v12; // esi@9
int v13; // ecx@9
int v14; // edx@9
int v15; // edi@9
int v16; // eax@11
int result; // eax@14
int v18; // [sp+0h] [bp-48h]@1
int v19; // [sp+Ch] [bp-3Ch]@1
int _key; // [sp+10h] [bp-38h]@1
int _input; // [sp+14h] [bp-34h]@1
int *v22; // [sp+18h] [bp-30h]@3
int *v23; // [sp+1Ch] [bp-2Ch]@1
int v24; // [sp+2Ch] [bp-1Ch]@1
v3 = 0;
v4 = 0;
_input = input;
v19 = output;
_key = key;
v24 = *MK_FP(__GS__, 20);
v23 = (int *)size_int;
v5 = alloca(4 * size_int);
in = &v18;
do
{
if ( (signed int)v23 > 0 )
{
j = 0;
k = 0;
v22 = in;
do
{
++k;
*((_BYTE *)v22 + j + v3) = *(_BYTE *)(_input + 4 * j + v4);// 4*4转置
j = (unsigned __int8)k;
}
while ( (signed int)v23 > (unsigned __int8)k );
in = v22;
}
++v4;
v3 += (int)v23;
}
while ( v4 != 4 );
v9 = 1;
i = 1;
AddRoundKey((int)in, _key, 0);
if ( keyround > 1 )
{
do
{
++i;
SubBytes((int)in);
ShiftRow((int)in);
MixColumn(v11, (int)in);
AddRoundKey((int)in, _key, v9);
vm_func(in);
v9 = (unsigned __int8)i;
}
while ( (unsigned __int8)i < keyround );
}
v12 = 0;
SubBytes((int)in);
ShiftRow((int)in);
AddRoundKey((int)in, _key, (unsigned __int8)keyround);
v14 = size_int;
v15 = v19;
v23 = in;
do
{
if ( v14 > 0 )
{
v16 = 0;
v13 = 0;
do
{
++v13;
*(_BYTE *)(v15 + 4 * v16 + v12) = *((_BYTE *)v23 + v16 + v12 * v14);// 4*4转置
v14 = size_int;
v16 = (unsigned __int8)v13;
}
while ( (unsigned __int8)v13 < size_int );
}
++v12;
}
while ( v12 != 4 );
result = *MK_FP(__GS__, 20) ^ v24;
if ( *MK_FP(__GS__, 20) != v24 )
canary(v13, v14);
return result;
}

这个函数总体上没和传统的aes改变多少,主要改了两处:


一是MixColumn函数中的a。

正常的a是这样的。

而这里是0xD,0xE,0xF,0xD。

对这个a求逆我们用matlab。

所以inv_a = [7,1,5,2](此处感谢大佬的帮助)


二是自己加了一个vm函数

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
int (__cdecl *__cdecl vm_func(_DWORD *a1))(_DWORD, _DWORD)
{
_DWORD *in; // ebx@1
_DWORD *v2; // ebp@1
_DWORD *v3; // edi@1
struc_1 *s; // eax@1
int v5; // edx@1
struc_1 *v6; // ST1C_4@1
int v7; // edx@1
in = (_DWORD *)calloc(64, 1u);
v2 = (_DWORD *)calloc(64, 1u);
v3 = (_DWORD *)calloc(32, 1u);
s = (struc_1 *)malloc(16);
v5 = *a1;
s->reg = (reg *)v3;
s->out = (int)in;
s->pc = (int)&code;
v6 = s;
in[4] = 'uhci'; // input + ichunqiuichunqiu
*in = v5;
v7 = a1[1];
in[5] = 'uiqn';
in[6] = 'uhci';
in[7] = 'uiqn';
in[1] = v7;
in[2] = a1[2];
in[3] = a1[3];
s->tmp_val = (int)(v2 + 32);
interpreter(s);
*a1 = *in;
a1[1] = in[1];
a1[2] = in[2];
a1[3] = in[3];
free((int)in);
free((int)v2);
free((int)v3);
return free((int)v6);
}

字节码解释器代码:(此处再次感谢大佬的帮助233)

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
unsigned int __cdecl interpreter(struc_1 *vm_ds)
{
char *byte_code_buffer; // edx@1
unsigned int byte_code; // eax@1
__int8 *tmp_pc; // eax@3
int v4; // eax@5
byte_code_buffer = (char *)vm_ds->pc;
byte_code = *(_BYTE *)vm_ds->pc - 12;
while ( 1 )
{
switch ( byte_code )
{
case 0x98u:
tmp_pc = byte_code_buffer + 2;
if ( vm_ds->reg->flag != 1 )
goto LABEL_4;
break;
case 0xA0u:
goto LABEL_4;
default:
goto LABEL_6;
case 0x9Du:
or_set((int)vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0x94u:
dec_set(vm_ds, byte_code_buffer[1]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0x8Du:
set_output((int)vm_ds, byte_code_buffer[1], *(_DWORD *)(byte_code_buffer + 2), 4);
goto LABEL_10;
case 0x7Eu:
get_output_to_reg((int)vm_ds, byte_code_buffer[1], *(_DWORD *)(byte_code_buffer + 2), 1);
goto LABEL_12;
case 0x7Au:
set_next_code_from_reg(&vm_ds->pc, byte_code_buffer[1], 1);
goto LABEL_14;
case 0x79u:
subb_reg((int)vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0x77u:
set_output((int)vm_ds, byte_code_buffer[1], *(_DWORD *)(byte_code_buffer + 2), 1);
goto LABEL_10;
case 0x67u:
tmp_pc = byte_code_buffer + 2;
if ( vm_ds->reg->flag )
goto LABEL_4;
break;
case 0x65u:
set_next_code_from_reg(&vm_ds->pc, byte_code_buffer[1], 4);
goto LABEL_14;
case 0x64u:
xor(vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0x5Bu:
set_tmp_v((int)vm_ds, byte_code_buffer[1]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0x2Au:
tmp_pc = byte_code_buffer + 2;
if ( vm_ds->reg->flag == 2 )
goto LABEL_4;
break;
case 0x25u:
and_reg(vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0x21u:
mov(vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0x1Eu:
tmp_pc = byte_code_buffer + 2;
if ( vm_ds->reg->flag <= 1u )
goto LABEL_4;
break;
case 9u:
mul(vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 8u:
tmp_pc = byte_code_buffer + 2;
if ( vm_ds->reg->flag == 1 )
goto LABEL_4;
break;
case 0u:
inc(vm_ds, byte_code_buffer[1]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0xF3u:
return byte_code;
case 0xF2u:
get_output_to_reg((int)vm_ds, byte_code_buffer[1], *(_DWORD *)(byte_code_buffer + 2), 4);
goto LABEL_12;
case 0xEFu:
tmp_pc = byte_code_buffer + 2;
if ( !vm_ds->reg->flag )
LABEL_4:
tmp_pc = &byte_code_buffer[*(_DWORD *)(byte_code_buffer + 1) - 3];
break;
case 0xEDu:
set_next_code_from_reg(&vm_ds->pc, byte_code_buffer[1], 2);
LABEL_14:
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0xE6u:
get_output_to_reg((int)vm_ds, byte_code_buffer[1], *(_DWORD *)(byte_code_buffer + 2), 2);
LABEL_12:
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0xDDu:
set_output((int)vm_ds, byte_code_buffer[1], *(_DWORD *)(byte_code_buffer + 2), 2);
LABEL_10:
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0xD9u:
tmp_pc = byte_code_buffer + 2;
vm_ds->tmp_val = *(_DWORD *)(byte_code_buffer + 1);
break;
case 0xBFu:
set_reg_add_16(vm_ds, byte_code_buffer[1]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0xB7u:
cmp(vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0xB5u:
add_reg(vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
case 0xABu:
div_reg((int)vm_ds, byte_code_buffer[1], byte_code_buffer[2]);
tmp_pc = (__int8 *)vm_ds->pc;
break;
}
while ( 1 )
{
byte_code_buffer = tmp_pc + 3;
v4 = (unsigned __int8)tmp_pc[3];
vm_ds->pc = (int)byte_code_buffer;
byte_code = v4 - 12;
if ( byte_code <= 0xF3 )
break;
LABEL_6:
tmp_pc = byte_code_buffer - 2;
}
}
}

由此还原字节码:

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
from pwn import *
def c2n(char):
return str(ord(char))
def disasm(code):
pc = 0
while(1):
c = ord(code[pc])-12
print hex(pc),':',
if c == 0x98:
print 'jnz ' + hex(u32(code[pc+1:pc+5]))
pc+=(2+3)
elif c == 0xa0:
print 'jmp ' + hex(u32(code[pc+1:pc+5]))
pc+=3
elif c == 0x9d:
print 'or $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0x94:
print 'dec $' + c2n(code[pc+1])
pc+=2
elif c == 0x8d:
print 'out $' + c2n(code[pc+1]) + ', !' + hex(u32(code[pc+2:pc+6]))
pc+=6
elif c == 0x7e:
print 'in $' + c2n(code[pc+1]) + ', !' + hex(u32(code[pc+2:pc+6]))
pc+=6
elif c == 0x7a:
print 'set_next_code_byte $' + c2n(code[pc+1])
pc+=2
elif c == 0x79:
print 'sub $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0x77:
print 'outb $' + c2n(code[pc+1]) + ', !' + hex(u32(code[pc+2:pc+6]))
pc+=6
elif c == 0x67:
print 'jge ' + hex(u32(code[pc+1:pc+5]))
pc += 5
elif c == 0x65:
print 'set_next_code $' + c2n(code[pc+1])
pc+=2
elif c == 0x64:
print 'xor $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0x5b:
print 'settmp $'+ c2n(code[pc+1])
pc+=2
elif c == 0x2a:
print 'jg $' + hex(u32(code[pc+1:pc+5]))
pc += 5
elif c == 0x25:
print 'and $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0x21:
print 'mov $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0x1e:
print 'jbe $' + hex(u32(code[pc+1:pc+5]))
pc += 5
elif c == 0x9:
print 'mul $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0x8:
print 'jz $' + hex(u32(code[pc+1:pc+5]))
pc+=5
elif c == 0:
print 'inc $' +c2n(code[pc+1])
pc+=2
elif c == 0xf3:
print 'ret'
pc+=3
elif c == 0xef:
print 'j0 $' + hex(u32(code[pc+1:pc+5]))
pc+=5
elif c == 0xed:
print 'set_next_code_word $' + c2n(code[pc+1])
pc+=2
elif c == 0xe6:
print 'in_word $' + c2n(code[pc+1]) + ', !' + hex(u32(code[pc+2:pc+6]))
pc+6
elif c == 0xdd:
print 'out_word $' + c2n(code[pc+1]) + ', !' + hex(u32(code[pc+2:pc+6]))
pc += 6
elif c == 0xd9:
print 'set_tmp #' + hex(u32(code[pc+1:pc+5]))
pc+=5
elif c == 0xbf:
print 'get_tmp $' + c2n(code[pc+1])
pc+=2
elif c == 0xb7:
print 'cmp $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0xb5:
print 'add $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
elif c == 0xab:
print 'div $' + c2n(code[pc+1]) + ', $' + c2n(code[pc+2])
pc+=3
else:
print c2n(code[pc+1])
pc+=1
code = '700000E510000000CB01E50F000000CB02C30002735800000071008A030000000071018A04000000007003047100830300000000E50F000000CB03E50E000000CB0485030085040071038A030000000071048A050000000070050371048305000000000C000C01ACAAFFFFFFFF'.decode('hex')
disasm(code)
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
0x0 : xor $0, $0
0x3 : set_tmp #0x10
0x8 : get_tmp $1
0xa : set_tmp #0xf
0xf : get_tmp $2
0x11 : cmp $0, $2
0x14 : jge 0x58
0x19 : set_next_code $0
0x1b : in $3, !0x0
0x21 : set_next_code $1
0x23 : in $4, !0x0
0x29 : xor $3, $4
0x2c : set_next_code $0
0x2e : outb $3, !0x0
0x34 : set_tmp #0xf
0x39 : get_tmp $3
0x3b : set_tmp #0xe
0x40 : get_tmp $4
0x42 : sub $3, $0
0x45 : sub $4, $0
0x48 : set_next_code $3
0x4a : in $3, !0x0
0x50 : set_next_code $4
0x52 : in $5, !0x0
0x58 : xor $5, $3
0x5b : set_next_code $4
0x5d : outb $5, !0x0
0x63 : inc $0
0x65 : inc $1
0x67 : jmp 0xffffffaa
0x6a : ret

通过整理逻辑,写出加密函数和解密函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
def unknow(plain):
data = list(plain.decode('hex')+'ichunqiu'*2)
for i in range(15):
data[i] = chr(ord(data[i])^ord(data[i+16]))
data[14-i] = chr(ord(data[15-i])^ord(data[14-i]))
print ''.join(data).encode('hex')[:32]
def inv_unknow(plain):
data = list(plain.decode('hex')+'ichunqiu'*2)
for i in reversed(range(15)):
data[14-i] = chr(ord(data[15-i])^ord(data[14-i]))
data[i] = chr(ord(data[i])^ord(data[i+16]))
print ''.join(data).encode('hex')[:32]

结合前面变形的AES,写出完整的func1逆代码。

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
head = 'e6b8a1e38082e6b8a1e38082e6b8a1e38082e6b8a1e38082e6b8a1e38082e6b86b18f5bbeb9a13034a799381acc13262133194f3b2d21471546ab592d4e8532a3583528bde1941889460d20938a1e06b0ac04d6cb812591dec78ec8f3890bfa5fea8569220b1171ab4d1c5138c702578bb8513a003974abdefefa632d77f1997554f81eb75fe96f1c12f53e24d5f769aa4ec4822a77b029f4894a4ad9febbd3a010c869674f21067b5dd4385f882351f0d604eb3aa1b4c2ce28fe8817d6455bbfbee8d738f1c9d143ac1de91c243eb8e43aa0a3de9b146110b3eae90765afb2bf3f3bf287cef223c462efcad846d1723'.decode('hex')
box=[0x36,0x4F,0x62,0x0D8,0x0B5,0x84,0x0CD,0x0F6,0x0DC,0x2A,0x0E6,0x0ED,0x0AB,0x52,0x1,0x0AF,0x0D0,0x0A,0x68,0x14,0x27,0x0A1,0x0DB,0x87,0x9C,0x0E7,0x29,0x66,0x35,0x0E9,0x0B4,0x91,0x8B,0x0CE,0x0F3,0x34,0x56,0x5E,0x23,0x61,0x70,0x0C3,0x0A7,0x32,0x2D,0x80,0x0C,0x0C4,0x0F5,0x2C,0x72,0x0A4,0x0C9,0x6,0x0B9,0x6E,0x19,0x12,0x7,0x22,0x0D6,0x0D3,0x0,0x71,0x98,0x0E,0x6B,0x0CA,0x64,0x3D,0x0BA,0x0FE,0x88,0x2,0x0E3,0x46,0x0EF,0x1F,0x2F,0x8F,0x2E,0x3A,0x31,0x9B,0x0F0,0x0E2,0x7B,0x99,0x0BB,0x0A8,0x48,0x63,0x0D4,0x8D,0x0F4,0x69,0x0BF,0x0E8,0x4B,0x0DE,0x0DA,0x76,0x0B0,0x10,0x0B8,0x97,0x0C6,0x9F,0x16,0x0F7,0x0AC,0x0DD,0x45,0x0BC,0x0C5,0x0E1,0x0AD,0x7C,0x5B,0x0FC,0x0CC,0x0AE,0x59,0x9A,0x6F,0x0E5,0x67,0x0A3,0x58,0x0C7,0x8C,0x65,0x81,0x49,0x53,0x83,0x40,0x39,0x5D,0x37,0x0B1,0x74,0x8E,0x4D,0x0CF,0x33,0x0F8,0x0A2,0x75,0x73,0x0FA,0x0D7,0x4A,0x0CB,0x82,0x78,0x17,0x0E0,0x95,0x7D,0x8,0x0F1,0x0BD,0x41,0x0B7,0x4,0x0F,0x8A,0x0D1,0x51,0x3E,0x38,0x93,0x0C2,0x89,0x0D2,0x96,0x94,0x1A,0x0FB,0x5F,0x7E,0x60,0x24,0x54,0x0EA,0x7F,0x0B,0x1B,0x43,0x26,0x2B,0x1C,0x0B3,0x4E,0x85,0x3F,0x5A,0x0C0,0x1E,0x50,0x77,0x0FF,0x9,0x0E4,0x9E,0x25,0x9D,0x5,0x13,0x0EE,0x0D5,0x30,0x0AA,0x28,0x79,0x86,0x4C,0x0F9,0x57,0x6D,0x0EB,0x47,0x0B2,0x0D9,0x18,0x0B6,0x0BE,0x7A,0x0C1,0x0A0,0x0D,0x5C,0x0C8,0x0A5,0x44,0x6A,0x3C,0x20,0x0A6,0x3,0x11,0x3B,0x15,0x90,0x0FD,0x92,0x0EC,0x0A9,0x21,0x55,0x1D,0x0DF,0x6C,0x42,0x0F2]
inv_box = [0]*256
inv_a = [7,1,5,2]
a = [0xe,0xd,0xd,0xf]
int_1 = 14
def AddRoundKey(tmp,head,k):
for j in range(4):
tmp[j] ^= ord(head[16*k+4*j])
tmp[j+4] ^= ord(head[16*k+4*j+1])
tmp[j+8] ^= ord(head[16*k+4*j+2])
tmp[j+12] ^= ord(head[16*k+4*j+3])
return tmp
def inv_ShiftRows(tmp):
for i in range(1,4):
for j in range(i):
v3 = tmp[4*i+3]
for k in range(3,0,-1):
tmp[4*i+k] = tmp[4*i+k-1]
tmp[4*i] = v3
return tmp
def ShiftRows(tmp):
for i in range(1,4):
for j in range(i):
v3 = tmp[4*i]
for k in range(0,3):
tmp[4*i+k] = tmp[4*i+k+1]
tmp[4*i+3] = v3
return tmp
def SubBytes(tmp):
for i in range(4):
for j in range(4):
tmp[4*i+j] = box[16 * (tmp[4*i+j] & 0xF) + (( tmp[4*i+j] & 0xF0) >> 4)]
return tmp
def inv_SubBytes(tmp):
for i in range(256):
inv_box[box[i]] = i
for i in range(4):
for j in range(4):
tmp[4*i+j] = inv_box[tmp[4*i+j]]
tmp[4*i+j] = 16 * (tmp[4*i+j] & 0xF) + (( tmp[4*i+j] & 0xF0) >> 4)
return tmp
def mix_single_column(v6):
d = [0]*4
d[0] = gmult(a[0],v6[0])^gmult(a[3],v6[1])^gmult(a[2],v6[2])^gmult(a[1],v6[3]);
d[1] = gmult(a[1],v6[0])^gmult(a[0],v6[1])^gmult(a[3],v6[2])^gmult(a[2],v6[3]);
d[2] = gmult(a[2],v6[0])^gmult(a[1],v6[1])^gmult(a[0],v6[2])^gmult(a[3],v6[3]);
d[3] = gmult(a[3],v6[0])^gmult(a[2],v6[1])^gmult(a[1],v6[2])^gmult(a[0],v6[3]);
return d
def gmult(aa,bb):
p=0
hbs=0
for i in range(8):
if (bb&1):
p ^= aa
hbs=aa&0x80
aa<<=1
aa = aa&0xff
if hbs:
aa ^= 0x1b
bb>>=1
return p
def mix_columns(tmp):
v6 = [0]*4
for i in range(4):
for j in range(4):
v6[j] = tmp[4*j+i]
v6 = mix_single_column(v6)
for j in range(4):
tmp[4*j+i] = v6[j]
return tmp
def inv_mix_columns(tmp):
v6 = [0]*4
for i in range(4):
for j in range(4):
v6[j] = tmp[4*j+i]
v6 = inv_mix_single_column(v6)
for j in range(4):
tmp[4*j+i] = v6[j]
return tmp
def inv_mix_single_column(v6):
d = [0]*4
d[0] = gmult(inv_a[0],v6[0])^gmult(inv_a[3],v6[1])^gmult(inv_a[2],v6[2])^gmult(inv_a[1],v6[3]);
d[1] = gmult(inv_a[1],v6[0])^gmult(inv_a[0],v6[1])^gmult(inv_a[3],v6[2])^gmult(inv_a[2],v6[3]);
d[2] = gmult(inv_a[2],v6[0])^gmult(inv_a[1],v6[1])^gmult(inv_a[0],v6[2])^gmult(inv_a[3],v6[3]);
d[3] = gmult(inv_a[3],v6[0])^gmult(inv_a[2],v6[1])^gmult(inv_a[1],v6[2])^gmult(inv_a[0],v6[3]);
return d
def print_iv(iv):
out=''
for i in range(len(iv)):
out += chr(iv[i])
print out.encode('hex')
def inv_unknow(plain):
text=''
for i in range(16):
text+=chr(plain[i])
data = list(text+'ichunqiu'*2)
for i in reversed(range(15)):
data[14-i] = chr(ord(data[15-i])^ord(data[14-i]))
data[i] = chr(ord(data[i])^ord(data[i+16]))
out_data=[]
for i in range(16):
out_data.append(ord(data[i]))
return out_data
def unknow(plain):
text=''
for i in range(16):
text+=chr(plain[i])
data = list(text+'ichunqiu'*2)
for i in range(15):
data[i] = chr(ord(data[i])^ord(data[i+16]))
data[14-i] = chr(ord(data[15-i])^ord(data[14-i]))
out_data=[]
for i in range(16):
out_data.append(ord(data[i]))
return out_data
def enc(iv1):
print iv1
iv1 = list(iv1.decode('hex'))
for i in range(len(iv1)):
iv1[i] = ord(iv1[i])
tmp=[0]*16
iv2=[0]*16
for i in range(4):
for j in range(4):
tmp[4*i+j] = iv1[4*j+i]
tmp = AddRoundKey(tmp,head,0)
for k in range(1,int_1):
tmp = SubBytes(tmp)
tmp = ShiftRows(tmp)
tmp = mix_columns(tmp)
tmp = AddRoundKey(tmp,head,k)
tmp = unknow(tmp)
tmp = SubBytes(tmp)
tmp = ShiftRows(tmp)
tmp = AddRoundKey(tmp,head,14)
for i in range(4):
for j in range(4):
iv2[4*j+i] = tmp[4*i+j]
for i in range(len(iv2)):
iv2[i] = chr(iv2[i])
iv2 = ''.join(iv2)
iv2 = iv2.encode('hex')
return iv2
def dec(iv1):
print iv1
iv1 = list(iv1.decode('hex'))
for i in range(len(iv1)):
iv1[i] = ord(iv1[i])
tmp=[0]*16
iv2=[0]*16
for i in range(4):
for j in range(4):
tmp[4*i+j] = iv1[4*j+i]
tmp = AddRoundKey(tmp,head,int_1)
tmp = inv_ShiftRows(tmp)
tmp = inv_SubBytes(tmp)
for k in range(int_1-1,0,-1):
tmp = inv_unknow(tmp)
tmp = AddRoundKey(tmp,head,k)
tmp = inv_mix_columns(tmp)
tmp = inv_ShiftRows(tmp)
tmp = inv_SubBytes(tmp)
tmp = AddRoundKey(tmp,head,0)
for i in range(4):
for j in range(4):
iv2[4*j+i] = tmp[4*i+j]
for i in range(len(iv2)):
iv2[i] = chr(iv2[i])
iv2 = ''.join(iv2)
iv2 = iv2.encode('hex')
return iv2
iv1 = 'cad3e543f23c3fec33a93f95dd8c4c2a'
print dec(iv1).decode('hex')

得到我们的输入为:mo4a3Ov2r5qIYgF8


正确后,程序会打印tickets:

可以看出,这是一个二维码。

简单处理并扫描,提示我们flag为输入加上“D4wn”

终于得到了我们的flag:mo4a3Ov2r5qIYgF8D4wn

ye~~~~