NUCTF-部分wp

本文最后更新于:2021年6月9日 下午

Reverse

encryption

程序有自加密代码,直接动态调试得到解密的代码。

根据特征发现是rc4加密,找到key和最终比较的结果,解密即可。

image-20210609134702424

image-20210609134710786

得到key:r3v3rs3_1s_s0_3z

image-20210609135158392

image-20210609135211161

最终比较的结果:91747F215A6CB4DB11A52D12D40F1970

进行解密:

image-20210609135239290

flag为:DACTF{7ce6798bc692ef04c6273a39d94dff9f}

vmm

给了opcode,所以去找opcode所对应的指令函数即可。

image-20210609135505266

image-20210609135752265

修改完函数名再回到第一张图里的函数,

image-20210609135905057

然后去分析这些函数。

这里要注意num_5这个函数:

image-20210609140032448

如果在调试,则会执行减1运算。

最后得出opcode指令:

1
2
3
4
5
6
7
6 input
7 下一个-1
2 交换
0 +2
3 位运算
1 ^0x66
5 无操作

得到最后比较的结果:

image-20210609140155634

image-20210609140202282

写python脚本进行还原:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
a = [0x00000066, 0x0000006B, 0x00000067, 0x00000063, 0x000000DE, 0x0000006F, 0x0000006F, 0x00000069, 0x000000F6, 0x00000026, 0x00000023, 0x00000079, 0x00000061, 0x000000F6, 0x000000AA, 0x00000039, 0x000000E2, 0x00000074, 0x00000003, 0x00000073, 0x00000072, 0x00000039, 0x00000031, 0x00000001, 0x00000067, 0x00000012, 0x000000FA, 0x00000000, 0x0000006E, 0x00000067, 0x0000007D, 0x00000040]
opcode = "720322033020331321721517131022"
for j in range(len(opcode)):
if opcode[j] == "0":
a[j+1] -= 2
elif opcode[j] == "1":
a[j+1] ^= 0x66
elif opcode[j] == "3":
for d in range(256):
v2 = 0
a1 = d
for i in range(8):
if (a1 & (1 << i)) > 0:
v2 |= (1 << (7 - i)) & 0xff
if v2 == a[j+1]:
a[j+1] = a1
break
elif opcode[j] == "5":
a[j+1] += 0
elif opcode[j] == "7":
a[j + 1] += 1
for j in range(len(opcode)-1, -1, -1):
if opcode[j] == "2":
s = a[j+1]
a[j+1] = a[j+2]
a[j+2] = s
result = ""
for i in range(len(a)):
result += chr(a[i])
print(result)

flag为:flag{goood!_yoU_Gett_r1ght_fl@g}

anbug

没有符号表,直接动态调试。

关键地方做了注释:

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
  sub_4A1640(&unk_4A88A0, "Welcome,Please Input\n");
v0 = (void *)sub_4A40C0(32i64);
sub_491C10(v0);
Block = v0;
sub_4A2810((const char *const)&off_4A8540, v0);// scanf
v1 = (void *)sub_4A40C0(24i64);
sub_48EA20(v1);
v44 = v1;
for ( i = 0; ; ++i )
{
v2 = i;
if ( v2 >= sub_42AF30((__int64)Block) )
break;
v29 = *(char *)sub_490290(Block, i);
sub_48E8E0(v44, &v29);
}
v3 = Block;
if ( Block )
{
sub_491F50(Block);
j_free(v3);
}
if ( (unsigned __int64)sub_429600(v44) <= 0x23 )// 长度大于35
{
v4 = (__int64 *)sub_4A4200(8i64);
v5 = sub_4A40C0(16i64);
sub_46CA50(v5, "Invalid Length!");
*v4 = v5;
sub_4A49E0(v4, &`typeinfo for'std::logic_error *, 0i64);
}
v6 = (void *)sub_4A40C0(24i64);
sub_48EA20(v6);
inp = v6;
for ( j = 0; j <= 3; ++j )
{
v28 = 0i64;
for ( k = 0; k <= 8; ++k ) // 分成4组,每组9个,可以得出长度是36,每组判断是否大于128,然后进行 << 7 然后相加。
{
if ( *(_QWORD *)sub_48E840((__int64)v44, 9 * j + k) > 0x80ui64 )
{
v7 = *(_QWORD *)sub_48E840((__int64)v44, 9 * j + k);
*(_QWORD *)sub_48EA90(v44, 9 * j + k) = v7 & 0x7F;
}
v8 = v28 << 7;
v28 = v8 + *(_QWORD *)sub_48E840((__int64)v44, 9 * j + k);
}
sub_48E910(inp, &v28);
}
v9 = v44;
if ( v44 )
{
sub_48EA40(v44);
j_free(v9);
}
v10 = (void *)sub_4A40C0(16i64);
sub_41F380(v10);
v42 = v10;
v32[0] = 0xDEADBEEFDEADBEEFui64;
v32[1] = 0x2331145141919810i64;
v32[2] = 0x1926081719260817i64;
v32[3] = 0x2020010720200107i64;
v30 = v32;
v31 = 4i64;
sub_460040(&v33);
v11 = (void *)sub_4A40C0(24i64);
v26 = v30;
v27 = v31;
sub_48E990(v11, &v26, &v33);
v41 = v11;
sub_4600B0(&v33);
v12 = (void *)sub_4A40C0(24i64);
sub_48EA20(v12);
v40 = v12;
for ( l = 0; l <= 3; ++l )
{
v13 = sub_48E840((__int64)v41, l); // 上方的数组
sub_41F220(v42, v13); // 上方数组+1
v14 = *(_QWORD *)sub_48E840((__int64)v41, l);
v34 = v14 + *(_QWORD *)sub_48E840((__int64)inp, l);// 输入与数组进行相加然后,这里的输入是经过变换后的,不是最开始的输入。
sub_48E8E0(v40, &v34);
}
v15 = v41;
if ( v41 )
{
sub_48EA40(v41);
j_free(v15);
}
v16 = v42;
if ( v42 )
{
sub_41F3E0(v42);
j_free(v16);
}
v17 = inp;
if ( inp )
{
sub_48EA40(inp);
j_free(v17);
}
v37[0] = 0x23310D0D278CA5E5i64;
v37[1] = 0x979467986E3ECA70ui64;
v37[2] = 0x5B03D9A511B2F98Di64;
v37[3] = 0x58DEC6AB7C5CFE05i64;
v35 = v37;
v36 = 4i64;
sub_460040(&v38);
v18 = (void *)sub_4A40C0(24i64);
v26 = v35;
v27 = v36;
sub_48E990(v18, &v26, &v38);
v39 = v18;
sub_4600B0(&v38);
for ( m = 0; m <= 3; ++m )
{
v19 = *(_QWORD *)sub_48E840((__int64)v39, m);// 最终比较
if ( v19 != *(_QWORD *)sub_48E840((__int64)v40, m) )
{
v20 = (__int64 *)sub_4A4200(8i64);
v21 = sub_4A40C0(16i64);
sub_46CA50(v21, "Invalid Input"); // output
*v20 = v21;
sub_4A49E0(v20, &`typeinfo for'std::logic_error *, 0i64);
}
}
v22 = v40;
if ( v40 )
{
sub_48EA40(v40);
j_free(v22);
}
v23 = v39;
if ( v39 )
{
sub_48EA40(v39);
j_free(v23);
}
v24 = (__int64 *)sub_4A4200(8i64);
v25 = sub_4A40C0(16i64);
sub_47F170(v25, "Success!How do you done this?");
*v24 = v25;
sub_4A49E0(v24, &`typeinfo for'std::runtime_error *, 0i64);
}

python脚本解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
v1 = [0xDEADBEEFDEADBEEF, 0x2331145141919810, 0x1926081719260817,0x2020010720200107]
v2 = [0x23310D0D278CA5E5, 0x979467986E3ECA70, 0x5B03D9A511B2F98D, 0x58DEC6AB7C5CFE05]
r1 = []
for i in range(4):
if v2[i] > v1[i]:
r1.append(v2[i]-1-v1[i])
else:
r1.append(v2[i]+(1 << 64)-1-v1[i])
print(r1)
# ['0x44834e1d48dee6f5', '0x746353472cad325f', '0x41ddd18df88cf175', '0x38bec5a45c3cfcfd']
r2 = ""
for i in range(4):
for j in range(9, 0, -1):
r2 += chr((r1[i] >> 7 * (j-1)) & 0x7f)
print(r2)

flag为:DASCTF{Mut1Thre4d_Ant1_D3bu8_14Easy}

MISC

艾斯的信仰

压缩包 明文攻击。

跑出密钥进行解密:

image-20210609163935168

打开flag.txt 发现当铺密码,解密即可。

yusa的音乐

010打开,将00替换为0x30,将0xff替换为0x31,然后粘贴二进制文本,得到rar文件。

得到一个hint和一个png图片。

image-20210609170932814

hint是零宽字符隐写。

进行解密:https://stylesuxx.github.io/steganography/

flag_is:91ec477ed0cccb2f5d6393cc2880f273

funnygame