该程序没有 main 函数,在 sub_402D4C 里首先通过 PEB 找到 kernel32 模块,拿到两个关键函数 GetProcAddress 和 LoadLibraryA。借助它们找到本函数内所需的所有导入函数,并将一众函数指针保存到自定义结构体中:
1
2
3
4
5
6
7
8
9
struct custom
{
int
kernel32_hModule;
HMODULE (__stdcall
*
LoadLibraryA)(LPCSTR lpLibFileName);
FARPROC (__stdcall
*
GetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
/
/
LocalAlloc
/
/
ExitProcess
/
/
...
};
其中 GetModuleHandleW 的后四个参数实为 DialogBoxParamA 的参数,因为汇编里它们四个在调用 GetModuleHandleW 前就入栈了,IDA 没能分辨出来。
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
else
if
( v22
=
=
273
&& a3
=
=
1002
)
{
v40
=
custom;
v21
=
(
*
(custom
+
92
))(a1,
1001
);
/
/
GetDlgItem
if
( v21 )
{
for
( i
=
0
; i <
0x100
;
+
+
i )
input
[i]
=
0
;
input_len
=
(
*
(v40
+
96
))(v21);
/
/
GetWindowTextLengthA
if
( input_len <
=
210
&& input_len >
=
1
)
{
(
*
(v40
+
100
))(v21,
input
,
255
);
/
/
GetWindowTextA
input_len
=
(
*
(v40
+
24
))(
input
);
/
/
lstrlenA
if
( input_len >
=
1
&& input_len <
=
128
)
{
for
( j
=
input_len; j <
128
;
+
+
j )
{
if
( j
%
2
)
input
[j]
=
32
;
else
input
[j]
=
127
;
}
v39
=
1
;
}
else
{
v39
=
0
;
}
}
else
{
v39
=
0
;
}
}
else
{
v39
=
0
;
}
if
( v39 )
{
v48
=
custom;
if
( (
*
(custom
+
56
))(
0
, crackme_exe_path,
255
) )
/
/
GetModuleFileNameW
{
v27
=
104
;
v28
=
0
;
v29
=
-
72
;
v30
=
0
;
v31
=
-
1
;
v32
=
-
48
;
v19
=
0
;
v36
=
0
;
v8[
17
]
=
-
1
;
for
( k
=
0
; k <
0x44
;
+
+
k )
*
(v8
+
k)
=
0
;
v8[
0
]
=
68
;
for
( m
=
0
; m <
0x10
;
+
+
m )
*
(&v42
+
m)
=
0
;
if
( (
*
(v48
+
28
))(crackme_exe_path,
0
,
0
,
0
,
0
, CREATE_SUSPENDED,
0
,
0
, v8, &v42) )
/
/
CreateProcessW
{
v6[
0
]
=
65543
;
if
( !(
*
(v48
+
32
))(v43, v6) )
/
/
GetThreadContext
goto LABEL_69;
v19
=
v6[
44
];
v36
=
(
*
(v48
+
44
))(v42,
0
,
128
,
4096
,
4
);
/
/
VirtualAllocEx
if
( !v36 )
goto LABEL_69;
for
( n
=
0
; n <
0x80
; n
+
=
v17 )
{
v17
=
0
;
if
( !(
*
(v48
+
48
))(v42, n
+
v36, &
input
[n],
128
-
n, &v17) )
/
/
WriteProcessMemory
{
v16
=
0
;
goto LABEL_45;
}
}
v16
=
1
;
if
( !v16 )
goto LABEL_69;
LABEL_45:
v20
=
(
*
(v48
+
20
))(
0
);
/
/
GetModuleHandleW
v10
=
*
(v20
+
60
)
+
v20;
v9
=
v19
-
*
(v10
+
40
);
v11
=
sub_B31000
-
v20;
v28
=
v36;
v30
=
sub_B31000
+
v9
-
v20;
for
( ii
=
0
; ii <
0xC
; ii
+
=
v15 )
{
v15
=
0
;
if
( !(
*
(v48
+
48
))(v42, ii
+
v19, &v27
+
ii,
12
-
ii, &v15) )
/
/
WriteProcessMemory
{
v14
=
0
;
goto LABEL_52;
}
}
v14
=
1
;
LABEL_52:
if
( v14 )
{
(
*
(v48
+
36
))(v43);
/
/
ResumeThread
v35
=
2
;
if
( (
*
(v48
+
60
))(v42,
30000
) )
/
/
WaitForSingleObject
{
(
*
(v48
+
64
))(v42,
2
);
/
/
TerminateProcess
}
else
{
v18
=
0
;
if
( (
*
(v48
+
52
))(v42, &v18) && v18 !
=
2
)
/
/
GetExitCodeProcess
v35
=
v18;
}
if
( v35
=
=
2
)
{
strcpy(v25,
"Unknown Error"
);
(
*
(v48
+
88
))(
0
, v25, v25,
0
);
/
/
MessageBoxA
(
*
(v48
+
16
))(
0
);
/
/
ExitProcess
v13
=
0
;
}
else
{
if
( v43 )
{
(
*
(v48
+
64
))(v42,
2
);
/
/
TerminateProcess
(
*
(v48
+
40
))(v43);
/
/
CloseHandle
}
if
( v42 )
(
*
(v48
+
40
))(v42);
/
/
CloseHandle
if
( v35 !
=
1
)
(
*
(v48
+
16
))(
0
);
/
/
ExitProcess
v13
=
v35;
}
v33
=
v13;
}
else
{
LABEL_69:
v34
=
2
;
strcpy(v24,
"Unknown Error"
);
(
*
(v48
+
88
))(
0
, v24, v24,
0
);
/
/
MessageBoxA
(
*
(v48
+
16
))(
0
);
/
/
ExitProcess
v12
=
0
;
v33
=
0
;
}
}
else
{
v33
=
-
1
;
}
}
else
{
v33
=
-
1
;
}
if
( v33 )
{
strcpy(v23,
"SUCCESS!"
);
strcpy(v26,
"INFO"
);
(
*
(custom
+
88
))(
0
, v23, v26,
0
);
/
/
MessageBoxA
}
}
(
*
(custom
+
16
))(
0
);
/
/
ExitProcess
}
一开始我用 x32dbg 启动父进程,用 IDA 附加子进程。在跟进第一个加密函数后,天真的我按下了 F5,当听到电脑的风扇声时,我意识到问题没有那么简单。同时,我发现对同一组输入,输出的加密结果竟然每次都不一样,那八成是存在调试器检测了。
在汇编层面进行一些分析后,我发现本题的每个加密函数中都存在非常多的无用代码,应该是用来做代码膨胀的,这直接导致 IDA 需要分析大量无用逻辑来生成伪代码。虽然一直等下去有可能能跑出来,但是我怕还没看到伪代码就该下一题了,于是就采用选择明文攻击及对输入下硬件访问断点(简称连蒙带猜)来找到和还原加密逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def
enc1(plain: bytes)
-
> bytes:
tbl
=
bytes.fromhex(
"b466efcad9ebb6423614b123b5abd400b0bb96e430a87e5e872daa0147a03dd2dae185f5ff0cfdad07aff2c8739446fce77f1570baf3085f0aa38d1fe6056dc44d31881799c6b26b831c80db6927fac22eec4b2f62a4d339bc6a4a8633bf929144b9cdacf6976ce9906554747609e249f0f9a2139a1632f4823f6f290b5a22b39c4e68d0c1e041ae6428d5048f9f78cc1d180d675be5487b19edd7dd55590e258e2c4012601e10bdc571f851c721c01b45e83ba1f76e2b8cb7d60fde35892a1a7d95d1723ca53411b8525c75ee9bf1fba96179c9203ec337817ccb5798dcbe243a586302d8ea4f43849d064c9efee3a7a68a0356938b7ace385326cfdf775d50"
)
pp
=
b
"0123456789ABCDEF"
*
8
ee
=
bytes.fromhex(
"3031157034f3365f3839418843994546307f32703435365f38394142439945b23031323334f3363738a34188434445b23031323334f336373839418543994546303132703435365f38a34142434445b2303132703435363738a3414243444546307f323334f3365f3839418843994546307f32333435363738394142434445b2"
)
idxs
=
[]
for
i
in
range
(
len
(ee)):
if
ee[i] !
=
pp[i]:
idxs.append(i)
cc
=
list
(pp)
cipher
=
list
(plain)
for
idx
in
idxs:
cc[idx]
=
tbl[pp[idx]]
cipher[idx]
=
tbl[plain[idx]]
rr
=
bytes.fromhex(
"0b3a177e1fc61b4a70304b8958ad0560115632373b7020731c1a5b55059e658c232e150c31cf3507288173885e5c76ba2200731d2ab0130124117b8501a47d0f3c250b7470021c4617a5434146434ebf2122256d2b101f1c17967a7f00030c096326535653985b2e47bac803d60ed8e597d281868bf4f3f0ebe6a2a7aaabb449"
)
for
i
in
range
(
len
(cc)):
cipher[i] ^
=
cc[i] ^ rr[i]
return
bytes(cipher)
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
def
enc2(plain: bytes)
-
> bytes:
tbl
=
bytes.fromhex(
"38393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637716e66655e61696b5d64676f5c606a7063685b6d5f626c8788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff72737475767778797a7b7c7d7e7f80818283848586"
)
pp
=
bytes.fromhex(
"5a69aef84e591d6a7a3a3ef22d6b781f40e463b16a23265316102e227058189d727d445b60503301225206f32b2f0bab7353224a7b2f15072e1b0efe746200706d765af221511a661d763636333033ae707174eb7a43191a1d450f08757071763294020102075d0e4db0bd78a3c8a59ac660d0d1daa7f5f6e1ecd7d0dfd8c958"
)
cc
=
list
(pp)
cipher
=
list
(plain)
for
i
in
range
(
len
(plain)):
cc[i]
=
tbl[pp[i]]
cipher[i]
=
tbl[plain[i]]
for
i
in
range
(
0x40
):
cc[i], cc[
0x80
-
i
-
1
]
=
cc[
0x80
-
i
-
1
], cc[i]
cipher[i], cipher[
0x80
-
i
-
1
]
=
cipher[
0x80
-
i
-
1
], cipher[i]
for
i
in
range
(
0x20
):
cc[i], cc[
0x40
+
i]
=
cc[
0x40
+
i], cc[i]
cipher[i], cipher[
0x40
+
i]
=
cipher[
0x40
+
i], cipher[i]
rr
=
bytes.fromhex(
"680567cabc021234390d1ed230593e9cc250360d412f2e553e2e386c711999bb8f646b9c500264121a186ac43ec4222d93415f434746dd02370b7402256ad50455bf8f97818915916565a6f4fad443f8868aefa6a5fcf10159470c16141db429977f1142703e7e7940727203b2288f6a2ff41971056669f0183c5c4013ae0458"
)
for
i
in
range
(
len
(cc)):
cipher[i] ^
=
cc[i] ^ rr[i]
cc
=
list
(rr)
for
i
in
range
(
0x20
):
cc[
0x20
+
i], cc[
0x60
+
i]
=
cc[
0x60
+
i], cc[
0x20
+
i]
cipher[
0x20
+
i], cipher[
0x60
+
i]
=
cipher[
0x60
+
i], cipher[
0x20
+
i]
rr
=
bytes.fromhex(
"f6b0c1702bb6869da6bcba77bde9b92f51db99a5efa3a6d4b8b2bcc0c781342b14dd80ccd0a3e8c0e7c0f79a198205f8b46e99fe90e4ca51afb5e498ca74df8488615077606bf6758083411c1369ac087036514d500731f9b5a9b3efeee95eda7ddf9a71a7c3a6d1deddac03f60de8e65f8c918c97970fd1e3dea2d5db962af9"
)
for
i
in
range
(
len
(cc)):
cipher[i] ^
=
cc[i] ^ rr[i]
return
bytes(cipher)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def
enc3(plain: bytes)
-
> bytes:
tbl
=
bytes.fromhex(
"c4189868c047179a23f21a2f75ffd837eb1c7d1861cdf1b74914c18590e1616d7bd4f82307d23443325c3c1aeddff337e4ae04e36d2506bd4ea1f351bd3f8ca1974465b774ac094bdb56552fe61bfc579daa9b47710921084a979b12601de096438c39b57b9bfe9e0e196ceb9a9632a14c5c7e3291bd9017d0db023a8f002eb2"
)
tbl
=
list
(tbl)
cipher
=
list
(plain)
for
i
in
range
(
0
,
len
(cipher),
2
):
cipher[i], cipher[i
+
1
]
=
cipher[i
+
1
], cipher[i]
for
i
in
range
(
len
(tbl)):
tbl[i] ^
=
cipher[(
0x75
+
i)
%
128
]
for
i
in
range
(
0x40
):
tbl[i], tbl[
0x80
-
i
-
1
]
=
tbl[
0x80
-
i
-
1
], tbl[i]
for
i
in
range
(
len
(tbl)):
tbl[i]
=
(tbl[i]
+
0x80
) &
0xFF
return
bytes(tbl)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def
enc4(plain: bytes)
-
> bytes:
cipher
=
list
(plain)
pp1
=
bytes.fromhex(
"a53f0c50366abda69abc3ecf6f580d6be2286767b4b24360f7cdf44e9c88f5931131d090a4b71fd9e1e0957144ed5f7dbc2ceceece0a5291bf6db45b822f9587c5954189bf76d9d7bf713f0aa36ceeb414f393794788f7754208923f11de80144e78c441def8bb74decb3a47247b014001990f031fb08b788c3512a3361749d3"
)
cc1
=
bytes.fromhex(
"a642115b4c77f1b5fdba36cb428a409f17f2309fdea03474e6d0f7519f8bf8961434d393a7ba22dce4e3987447f05876b525e5e7c7034b8ab866ad547b289082c0903c84ba71d4d2ba6c3a059e67f5bb1bfa9a804e8ffe7c490f994618e587144e78c441def8bb74decb3a472483094809a1170b27b89380943d1aab3e0c3ec8"
)
dis
=
[]
for
i
in
range
(
len
(pp1)):
dis.append((cc1[i]
-
pp1[i]) &
0xFF
)
for
i
in
range
(
len
(cipher)):
cipher[i]
+
=
dis[i]
cipher[i] &
=
0xFF
return
bytes(cipher)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def
enc5(plain: bytes)
-
> bytes:
cipher
=
[]
for
i
in
range
(
0x30
,
-
1
,
-
0x10
):
for
j
in
range
(
0xF
,
-
1
,
-
1
):
cipher.append(plain[i
+
j])
cipher
+
=
list
(plain[
0x40
:])
tbl
=
bytes.fromhex(
"d5a04a5de8a503a8dd2d980a4d8f901234023d5545b73f2cbabc07c70186df532961253e09217b85b60895300bb09e6bdbf9af51844950d210ebac2b48c56a74cdfd1d314bd6f3b381367e9c582f4c6c0513635a419b387c6519d047c4927a6fefb15783271a71d8fa2ae142a28ceaff166400561e374328ab06c9c3d3a614aeb5e6969a9d5f2615f223a7a34e8772ec208059a440f70ce7bb33ede2ee0f8eb20e3c916824754660a17932b8738b76d11fda8d22f00dc011c2e0665ed79ffe88dc7d8aca4404d417c61b94f654694f6de5be3b6ecbf18278f4def5bd2ece67c835ad7752c17fb99339f8e418bfd9cfb489cc5c1cfcaa3a7062fb5be3a99997e9"
)
for
i
in
range
(
0x80
):
cipher[i]
=
tbl[cipher[i]]
pp
=
bytes.fromhex(
"9620b6c3418b71c2a79c5d17937f210d436589b31ebb52c12e256660a46e84450c62a3b21370e5b91e840e67b2db5c2cb2cda71df65066990dcc285847021d46dc20489d6664cb3b66a2aca58ed8aa5ec75bedb54cec97d3361233f3ba7f15454cab44fd67625e1e67f6acb3099a2d812d3c2c0a85c2a4b540c507b86a4d6ac6"
)
cc
=
bytes.fromhex(
"1e76d27f22bf0ba060c447584fa9b895954c4a32bdc046d036cd250181466efc2f002f48486ec74947015bcc5249878f274d2cfb1ab6a9b9a362ca9cff8f586ac125846ea7c2acf7c225d7662ca5b39e5387ca66b8687d953a4d09b09436291f92e9a38ace7ce6cdd1ba7464e488dc9118143ec808ec822e4438538100d068b3"
)
for
i
in
range
(
len
(cipher)):
cipher[i] ^
=
pp[i] ^ cc[i]
return
bytes(cipher)
1
2
3
4
5
6
def
enc6(plain: bytes)
-
> bytes:
p
=
bytes.fromhex(
"cf00fa1ac6497c69840b0c74e6d8c2ad50e23957b7b581e678aac75be30e61d895f5d38858be754f4dcf567f9f1cf0cc89fed6aee83cf43e20c8c8fadbc6f2cbd16eca9559b795199d171848be19fa92a30f49b7dc3ec2f54599d28e29a38546bc459e3b969792d0fb06532ac838a4c8fd72055c12d398bbd1f5ad497a5a831b"
)
c
=
bytes.fromhex(
"5a125abad541706a858bf87f4354c5ab409259b7e73511f6589a87ab23de41f885c5d2855fbf7a4d44df76ef7fec30fc005fe6ee885cb41e60e8880a1b16d2ebe11efa65eabc97298c061940be6770a8132f0907acaedbc505dbf2e563b7ad50eec6ee66e6f7b240eb0603bad868f498ed52956c62f3a8cbe1863b497658ae6b"
)
tbl
=
[p[i] ^ c[i]
for
i
in
range
(
len
(p))]
return
bytes([tbl[i] ^ plain[i]
for
i
in
range
(
len
(plain))])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def
enc7(plain: bytes)
-
> bytes:
tbl1
=
bytes.fromhex(
"588d51e8d4d9a5c53094c6bab325c238a4c8aaf74e2e603b3ab2a975a12316fb64e42478322631434bbcb8ac639b7e871b42b59e612a866e4cd2355ad6e9b91db77fa8537bd7de799a745f0bf001ade24a3d98651e6cd8dbabe5442221cb507615565c2972896d418c8e19e1919df2063f1a7d978a8392dc77f936cf48a0c78214e3963984b188284611afa352fe10f457f1e0ca547ca27049a72db6d090da7a67c3bd1cf6f52b9308691359624feaced3eceb5ed10e04204d0f8bbbc9bf03059ccc40dfef853e3cf3ffd50a272fee8f6a1ffd955d817355dde75b6f18c4ae450d689fc012edcd0c33f8fc2c003747bee634a666b0b49971806b07fac1170209"
)
tbl2
=
bytes.fromhex(
"35b3a22a08d483add97fb6c277933814aa1341488d79eca0f6529df8a64d30fa6124b557658ef9f0d1c3c41acd252f676aa44c17686682c7cc6343e987dd8cb2ea3f7cfc6d115db8b1bd562cc186b044056236a8399427ae7b80df73e5e233e3d3cba7859b9991d0006921e66e9806372b8bf42e95a3cf0c7119530410c96b3aee1b88e12397d6f2d54fe4be4270ffe8de5c7db9f126a9843bced2bcc6d83d501c81db2d6045493e587692c512fb9c54ba070290ef477e75af18bb51f5209a9631349f599e46bfa1ca89014a5a1f1e5bf78fb7d7fe5ee01528e7dcda725f55030d64744b29c04e78ab40226f1d09f3a516c8fd6cac8a0fed0a3c327a0b0eebb4"
)
tbl3
=
bytes.fromhex(
"7f9458886cfd2dafe88538c7287bebeeb925894fd2053a0cde8ffccb65ad45c959e12b2f4372c381db8eab010677075e74bc03628c543d3718e279840a307e2e83f95746d15b1a1f116820a76495710b5627a350bbc102e035b582d333ca4a0eef26f413b786acc83ed8759d233b934ca15ab6a0048b8a551922be61e69690c099c69ed7603241f087e9aa175f7c4b1b0d40ffb34269e410faa9d62cf5edbad9480f4ef378d014f7a66eaea870669a52801d34366b5da4ecdf0891ce9c4992a221cc2a6df8bd514d6ae55ce767b0f2f12412989b29b4b197fbc453cdda44e3dd1e6f31dc3cc576ead5f673c28d3f1ccf477aa50039fe7db215d4b863bf9f1609"
)
tbl4
=
bytes.fromhex(
"4f8a646ddee94796105c220be55999d3319533ff1821ab3d2d78291e7758844db99ff851357d2b666ec2b15e2cdc5fd742ae98371fe2439cd94bcadfec9761398334676345366270243f877e467ca203d47394a41da6bb1add8cebd6d8be93feb419a832002a0a11c94ced28f3fc8ea0a1f675c0ce0754fbb512ea914e9dc7746014ac8f385ac152501c539bf1c4e36a4a41b2e8e19071b3cc0c57f9d2ada523bd7615effdbcf5af85dae068f4c8fa69d5256b273b891655db9ee448b69aee80f7170406b0921bcfbf6f86727bf05db713ba050f01e6aa2fc35b7a026ccda32ea9c53c568882e78d3e8120cb0d79f244653a260830a7b84940d07fc6d18b0e09"
)
tbl5
=
b
'\x1d\xbcs,\xdb\x81\xe3\x04\x06U\x8dF\xfcQ\x83\x00G\x14v-C\xf8\xc6\x10l\x11\x1c\xc0\x96V\x99\xbd\xd7\xeb\xa8\t\xc4=\x0ci\xea\xfd.j\xbf\x947!\x0fo(\x1f\xa7\x1bg6\x13\xd9\xff\xe8d0?\xf4q+\x8c\\p\'[email protected]\xa0z#\xcct\x871\xc1DN\x80&c\x07\x12W\x91<`h|w\xb7\x84\xae\x9c\xc9\xc2\xd0\xc3\x97\xf1B%y$\xc8\x02\xca/\xe4\xf0Or\x92\x0b\xfb\xa3n\xe7\x1eT\xc7\xa4J\xe0\xd5\x86\xb1\xf7\x8bY\xd2\x89\xf5\x08E\n:\x93\xd4\xd6}\xf9{\x85\x9d\xfe\xd3"L;~\xbe\xab\xb0\xb9\xa9\x88\xa6\xda\xbb\xf6\x1a\x05\xde\x18>\x8e\xb4\xfa\xba\xb3\xb8\xb6k\x0eK5\xcb\xec\xdc\x17\x8f \xf2*eb\x82\xf3\xa2\xcf^\xb5\xe6\xce\x9ff\xe9PR\xef[\x9e\xdd\x8a\xe2Iau\xed8\xd8\xd1\xe1)\x15\x98ZS\x01\xa5M\xcd\xc5\x90]\r9\x7f4\xdf_\x16\x03\xee\xa1\xad\x9b\xaf\xb23X\xe5\x19HA\xaa\x95\xac\x9ax'
tbl6
=
b
'V\xd6x\xdc\x8fs\xcf\x8e\x0b\x14\xaa\xfa?=\xc0\xf1)\xde\x8b:t\xb1n\x8cH\xc5\xc4R\xdd.\xd76yD\x7f\xe1\xc1\x99\xd4\x9a\xd8h\xa52WC\x17\xa2\xdf\x87\x82\xf8\xe6\xe7\xb5\x004\xb2\xc9\rX\xaeK\xad\xc3\xc7\x88\x91\n\x051dz>Mb\x06m\xa4\xc6\xe3Bji\xa3\xcc\xb0\x92a\xbf\x8a!Q\x07\xa7-&A\x10\x08\x19\xe2\x1ckr\xca\xb4\x18\x94U\xdaJ\xf3Y^"\x0cE\xbe\[email protected]}\xd0]*\xf2\x0eO/\xcd\x90\x03\x97\xff<\x968\x15\x80\xec\x0f\xc2\x1b\xb3\xeb\x9b~I\xaf{g\x9d$\x86\tf\xf7\\;\xd3\xfd\x04o\x1f\xd9\xb8\xa8ev\x8d\x95\xbb\xb9l\xb7\xee\x01\xf4 `\x1au\xf65\x89%\xbd\x11\x83,\xbcF\xd5\xcb\xab(w\'\xd2\xc8\xe0\xb6N\xd1\x98\xe9\xcep\xe4P+\xe8\xa1#\xa6\xfe\xedS\x9c\xa9\x127Z[\x81\xbaLT\xf9\x9e\xdb3\xea\x939\x1d\x02qc\x16\x85\x1e\x9f|\xac\xf0\xf5\x84\xef\xa00\xe5\x13_\xfc'
tbl7
=
b
' ;\xec\xbe\xb6\x87\x85\x9fS\xefW\xe0\xc3\x01\xf8:\xe7AKr)\x0bl\x04y\xfc\x18\xb4g\xce\xf0\x0eZ4\x9e\xf6\x94\xacXo\xf3\xc42\x8aU\x9c\x07\xb0e\xe3\x9bRQ\xc7\xddc\xa9\x12\x0f\x95\x80Y\x1a\xcf{0\xa8\xab1/a\x16\x1cMi"p\xcbu<\xd3t\x91\xf1O\xa5\xe2\xfd\xbd\x11m6+\xaa\xd5\x90\xe4\x8d\xda\xb8\xa2\xaf\x1d\x98\x1f\x88*I\x82x\x99\xebGf\xca?\xa6J&\xdfD\x7f\x13\xa4\xb1\x02z\xc9\x9d\x00\xd6^\xbaC\xc2\x03\xff(5\xbcdq\xdc\xa3[\xd4\xee\x83\xf7F-k}\xaeb\xd9\xa7,\xc8\r\xa1\x8ej\xe8`n\[email protected]%h\xf4\xb7\xb3w\xc18\xc0\xd8\xd1\xfe\xb9\'\xbfE]=\x19\xf5\xcc9\xde\x81\x9a3\xc5s\x15\\P\x89N\xa0!$\xdb\xbbV\x17_\xad\xf2\x8c\x8f\x96\x97\xe5T\x86\t\x1bB\x10H\xb5\xf9~|\x05\xd7>\x067\xe6\x93\xfa\xe9v\n\x1e\xed\x0c.\xcd\xfb\x08\xea\x84\x92\xd0\xc6L\xe1#\xd2\x14\x8b'
cipher
=
list
(plain)
tbls
=
[tbl1, tbl2, tbl3, tbl4, tbl5, tbl6, tbl7]
for
tbl
in
tbls:
for
i
in
range
(
len
(cipher)):
cipher[i]
=
tbl[cipher[i]]
return
bytes(cipher)
target
=
bytes([
121
,
23
,
66
,
107
,
59
,
80
,
122
,
227
,
70
,
208
,
222
,
78
,
36
,
167
,
138
,
106
,
105
,
208
,
2
,
6
,
240
,
39
,
36
,
189
,
192
,
187
,
227
,
30
,
9
,
163
,
151
,
48
,
60
,
182
,
235
,
104
,
144
,
9
,
208
,
234
,
17
,
242
,
196
,
96
,
165
,
203
,
195
,
252
,
69
,
251
,
92
,
83
,
192
,
128
,
58
,
153
,
89
,
111
,
47
,
84
,
74
,
217
,
14
,
106
,
52
,
222
,
210
,
236
,
175
,
74
,
11
,
164
,
138
,
182
,
250
,
147
,
31
,
4
,
16
,
68
,
238
,
228
,
214
,
158
,
244
,
69
,
18
,
77
,
55
,
60
,
240
,
17
,
248
,
200
,
68
,
118
,
99
,
16
,
115
,
45
,
104
,
215
,
157
,
47
,
195
,
132
,
42
,
182
,
204
,
181
,
55
,
97
,
79
,
15
,
22
,
188
,
187
,
140
,
83
,
39
,
238
,
119
,
170
,
31
,
156
,
194
,
24
,
222
])
assert
enc7(enc6(enc5(enc4(enc3(enc2(enc1(user_input)))))))
=
=
target
第七个函数比较小,当时一不小心反编译出来,就花了点时间写去混淆的 IDAPython 脚本。原理是基于模式匹配,识别出其中的 13 种无用代码的模式(对应附件 patterns.txt),再将它们 nop 掉。脚本在该函数上效果很好,运行后只因本只剩下核心逻辑,代码如下(运行前要先创建加密函数,拿到函数的起始、结束地址):
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
import
re
def
nop(ea:
int
, size:
int
):
for
i
in
range
(size):
patch_byte(ea
+
i,
0x90
)
def
printable(hex_str:
str
):
return
32
<
=
int
(hex_str,
16
) <
127
def
deobfus(start:
int
, end:
int
):
cur
=
start
while
cur < end:
asm1
=
generate_disasm_line(cur,
0
)
asm2
=
generate_disasm_line(cur
+
get_item_size(cur),
0
)
m1
=
re.match(r
"mov +\[ebp\+var_(.+)\], *1000h"
, asm1)
m2
=
re.match(r
"lea +eax, *\[ebp\+var_(.+)\]"
, asm2)
if
m1
and
m2
and
m1.group(
1
)
=
=
m2.group(
1
):
print
(f
"found pattern-1 at: {hex(cur)}"
)
asm3
=
generate_disasm_line(cur
+
0xd4
-
6
,
0
)
if
re.match(r
"mov +\[ebp\+var_(.+)\], *eax"
, asm3):
nop(cur,
0xd4
)
cur
+
=
0xd4
continue
m1
=
re.match(r
"mov +\[ebp\+var_(.+)\], *(.{2})h"
, asm1)
m2
=
re.match(r
"mov +\[ebp\+var_(.+)\], *(.{2})h"
, asm2)
if
m1
and
m2
and
int
(m1.group(
1
),
16
)
-
int
(m2.group(
1
),
16
)
=
=
1
and
printable(m1.group(
2
))
and
printable(m2.group(
2
)):
if
get_bytes(cur
+
0x1d7
-
2
,
2
)
=
=
b
'\xeb\xc7'
:
print
(f
"found pattern-2 at: {hex(cur)}"
)
nop(cur,
0x1d7
)
cur
+
=
0x1d7
continue
elif
get_bytes(cur
+
0x1bb
-
2
,
2
)
=
=
b
'\xeb\xc7'
:
print
(f
"found pattern-2 at: {hex(cur)}"
)
nop(cur,
0x1bb
)
cur
+
=
0x1bb
continue
elif
get_bytes(cur
+
0x12d
-
5
,
5
)
=
=
b
'\xE9\x5A\xFF\xFF\xFF'
:
print
(f
"found pattern-11 at: {hex(cur)}"
)
nop(cur,
0x12d
)
cur
+
=
0x12d
continue
m1
=
re.match(r
"and +\[ebp\+var_(.+)\], *0"
, asm1)
m2
=
re.match(r
"lea +eax, *\[ebp\+var_(.+)\]"
, asm2)
if
m1
and
m2
and
m1.group(
1
)
=
=
m2.group(
1
):
asm3
=
generate_disasm_line(cur
+
0xb5
-
7
,
0
)
if
re.match(r
"or +\[ebp\+var_(.+)\], *0FFFFFFFFh"
, asm3):
print
(f
"found pattern-3 at: {hex(cur)}"
)
nop(cur,
0xb5
)
cur
+
=
0xb5
continue
m1
=
re.match(r
"and +\[ebp\+var_.+\], *0"
, asm1)
m2
=
re.match(r
"and +\[ebp\+var_.+\], *0"
, asm2)
asm3
=
generate_disasm_line(cur
+
0x73
,
0
)
m3
=
re.match(r
"cmp +\[ebp\+var_.+\], *0Ah"
, asm3)
if
m1
and
m2
and
m3:
if
get_bytes(cur
+
0x15c
-
5
,
5
)
=
=
b
"\xE9\x0A\xFF\xFF\xFF"
:
print
(f
"found pattern-4 at: {hex(cur)}"
)
nop(cur,
0x15c
)
cur
+
=
0x15c
continue
m1
=
re.match(r
"and +\[ebp\+var_.+\], *0"
, asm1)
m2
=
re.match(r
"mov +\[ebp\+var_.+\], *1"
, asm2)
asm3
=
generate_disasm_line(cur
+
0x90
,
0
)
m3
=
re.match(r
"cmp +\[ebp\+var_.+\], *5"
, asm3)
if
m1
and
m2
and
m3:
if
get_bytes(cur
+
0x192
-
5
,
5
)
=
=
b
"\xE9\xF1\xFE\xFF\xFF"
:
print
(f
"found pattern-5 at: {hex(cur)}"
)
nop(cur,
0x192
)
cur
+
=
0x192
continue
if
m1
and
m2
and
get_bytes(cur
+
0x98
,
2
)
=
=
b
"\x72\xC1"
:
asm3
=
generate_disasm_line(cur
+
0xb5
-
0xa
,
0
)
if
re.match(r
"mov +\[ebp\+var_.+\], *1"
, asm3):
print
(f
"found pattern-12 at: {hex(cur)}"
)
nop(cur,
0xb5
)
cur
+
=
0xb5
continue
m1
=
re.match(r
"mov +\[ebp\+var_.+\], *0Ah"
, asm1)
m2
=
re.match(r
"mov +\[ebp\+var_.+\], *2"
, asm2)
asm3
=
generate_disasm_line(cur
+
0x7a
,
0
)
m3
=
re.match(r
"cmp +\[ebp\+var_.+\], *9"
, asm3)
if
m1
and
m2
and
m3:
if
get_bytes(cur
+
0x109
-
5
,
5
)
=
=
b
"\xE9\x64\xFF\xFF\xFF"
:
print
(f
"found pattern-6 at: {hex(cur)}"
)
nop(cur,
0x109
)
cur
+
=
0x109
continue
m1
=
re.match(r
"mov +\[ebp\+var_.+\], *1"
, asm1)
m2
=
re.match(r
"mov +\[ebp\+var_.+\], *3"
, asm2)
asm3
=
generate_disasm_line(cur
+
0x92
,
0
)
if
m1
and
m2
and
"jg"
in
asm3:
if
get_bytes(cur
+
0x14f
-
5
,
5
)
=
=
b
"\xE9\x37\xFF\xFF\xFF"
:
print
(f
"found pattern-7 at: {hex(cur)}"
)
nop(cur,
0x14f
)
cur
+
=
0x14f
continue
m1
=
re.match(r
"mov +\[ebp\+var_.+\], *1"
, asm1)
m2
=
re.match(r
"mov +\[ebp\+var_.+\], *5"
, asm2)
asm3
=
generate_disasm_line(cur
+
0xc8
,
0
)
m3
=
re.match(r
"mov +\[ebp\+var_.+\], *2"
, asm3)
if
m1
and
m2
and
m3:
if
get_bytes(cur
+
0x198
-
5
,
5
)
=
=
b
"\xE9\xFE\xFE\xFF\xFF"
:
print
(f
"found pattern-8 at: {hex(cur)}"
)
nop(cur,
0x198
)
cur
+
=
0x198
continue
m1
=
re.match(r
"mov +\[ebp\+var_.+\], *20h"
, asm1)
m2
=
re.match(r
"mov +\[ebp\+var_.+\], *6Dh"
, asm2)
asm3
=
generate_disasm_line(cur
+
0x5c
,
0
)
m3
=
re.match(r
"cmp +\[ebp\+var_.+\], *3"
, asm3)
if
m1
and
m2
and
m3:
if
get_bytes(cur
+
0xf7
-
5
,
5
)
=
=
b
"\xE9\x58\xFF\xFF\xFF"
:
print
(f
"found pattern-9 at: {hex(cur)}"
)
nop(cur,
0xf7
)
cur
+
=
0xf7
continue
m1
=
re.match(r
"and +\[ebp\+var_.+\], *0"
, asm1)
if
m1
and
get_bytes(cur
+
0xe
,
2
)
=
=
b
"\xEB\x0D"
and
get_bytes(cur
+
0xc6
,
5
)
=
=
b
"\xB9\x00\x04\x00\x00"
:
asm3
=
generate_disasm_line(cur
+
0x136
-
6
,
0
)
if
re.match(r
"mov +\[ebp\+var_.+\], *eax"
, asm3):
print
(f
"found pattern-10 at: {hex(cur)}"
)
nop(cur,
0x136
)
cur
+
=
0x136
continue
m1
=
re.match(r
"mov +\[ebp\+var_.+\], *3"
, asm1)
m2
=
re.match(r
"mov +\[ebp\+var_.+\], *2"
, asm2)
if
m1
and
m2
and
get_bytes(cur
+
0x4c
,
2
)
=
=
b
'\x73\x34'
:
if
get_bytes(cur
+
0x82
-
2
,
2
)
=
=
b
"\xEB\xBE"
:
print
(f
"found pattern-13 at: {hex(cur)}"
)
nop(cur,
0x82
)
cur
+
=
0x82
continue
cur
+
=
get_item_size(cur)
start_ea
=
0x028ADA1C
end_ea
=
0x028E5FC1
deobfus(start_ea, end_ea)
del_items(start_ea,
0
, end_ea)
create_insn(start_ea)
add_func(start_ea)
不过在其他 6 个函数上用的效果不是很好,因为其他函数中还有许多 call 无用 API 的模式没有考虑。它们肯定都可以通过模式识别进行定位并去除,考虑到未知的工作量,赛中就没有再写下去了。脚本放在这里,希望能起到抛砖引玉的作用。
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
def
dec1(cipher: bytes)
-
> bytes:
plain
=
list
(cipher)
tbl
=
bytes.fromhex(
"b466efcad9ebb6423614b123b5abd400b0bb96e430a87e5e872daa0147a03dd2dae185f5ff0cfdad07aff2c8739446fce77f1570baf3085f0aa38d1fe6056dc44d31881799c6b26b831c80db6927fac22eec4b2f62a4d339bc6a4a8633bf929144b9cdacf6976ce9906554747609e249f0f9a2139a1632f4823f6f290b5a22b39c4e68d0c1e041ae6428d5048f9f78cc1d180d675be5487b19edd7dd55590e258e2c4012601e10bdc571f851c721c01b45e83ba1f76e2b8cb7d60fde35892a1a7d95d1723ca53411b8525c75ee9bf1fba96179c9203ec337817ccb5798dcbe243a586302d8ea4f43849d064c9efee3a7a68a0356938b7ace385326cfdf775d50"
)
pp
=
b
"0123456789ABCDEF"
*
8
ee
=
bytes.fromhex(
"3031157034f3365f3839418843994546307f32703435365f38394142439945b23031323334f3363738a34188434445b23031323334f336373839418543994546303132703435365f38a34142434445b2303132703435363738a3414243444546307f323334f3365f3839418843994546307f32333435363738394142434445b2"
)
idxs
=
[]
for
i
in
range
(
len
(ee)):
if
ee[i] !
=
pp[i]:
idxs.append(i)
cc
=
list
(pp)
for
idx
in
idxs:
cc[idx]
=
tbl[pp[idx]]
rr
=
bytes.fromhex(
"0b3a177e1fc61b4a70304b8958ad0560115632373b7020731c1a5b55059e658c232e150c31cf3507288173885e5c76ba2200731d2ab0130124117b8501a47d0f3c250b7470021c4617a5434146434ebf2122256d2b101f1c17967a7f00030c096326535653985b2e47bac803d60ed8e597d281868bf4f3f0ebe6a2a7aaabb449"
)
for
i
in
range
(
len
(cc)):
plain[i] ^
=
cc[i] ^ rr[i]
for
idx
in
idxs:
plain[idx]
=
tbl.index(plain[idx])
return
bytes(plain)
def
dec2(cipher: bytes)
-
> bytes:
plain
=
list
(cipher)
tbl
=
bytes.fromhex(
"38393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637716e66655e61696b5d64676f5c606a7063685b6d5f626c8788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff72737475767778797a7b7c7d7e7f80818283848586"
)
rr
=
bytes.fromhex(
"f6b0c1702bb6869da6bcba77bde9b92f51db99a5efa3a6d4b8b2bcc0c781342b14dd80ccd0a3e8c0e7c0f79a198205f8b46e99fe90e4ca51afb5e498ca74df8488615077606bf6758083411c1369ac087036514d500731f9b5a9b3efeee95eda7ddf9a71a7c3a6d1deddac03f60de8e65f8c918c97970fd1e3dea2d5db962af9"
)
cc
=
list
(bytes.fromhex(
"680567cabc021234390d1ed230593e9cc250360d412f2e553e2e386c711999bb8f646b9c500264121a186ac43ec4222d93415f434746dd02370b7402256ad50455bf8f97818915916565a6f4fad443f8868aefa6a5fcf10159470c16141db429977f1142703e7e7940727203b2288f6a2ff41971056669f0183c5c4013ae0458"
))
for
i
in
range
(
0x20
):
cc[
0x20
+
i], cc[
0x60
+
i]
=
cc[
0x60
+
i], cc[
0x20
+
i]
for
i
in
range
(
len
(plain)):
plain[i] ^
=
cc[i] ^ rr[i]
for
i
in
range
(
0x20
):
plain[
0x20
+
i], plain[
0x60
+
i]
=
plain[
0x60
+
i], plain[
0x20
+
i]
rr
=
bytes.fromhex(
"680567cabc021234390d1ed230593e9cc250360d412f2e553e2e386c711999bb8f646b9c500264121a186ac43ec4222d93415f434746dd02370b7402256ad50455bf8f97818915916565a6f4fad443f8868aefa6a5fcf10159470c16141db429977f1142703e7e7940727203b2288f6a2ff41971056669f0183c5c4013ae0458"
)
pp
=
bytes.fromhex(
"5a69aef84e591d6a7a3a3ef22d6b781f40e463b16a23265316102e227058189d727d445b60503301225206f32b2f0bab7353224a7b2f15072e1b0efe746200706d765af221511a661d763636333033ae707174eb7a43191a1d450f08757071763294020102075d0e4db0bd78a3c8a59ac660d0d1daa7f5f6e1ecd7d0dfd8c958"
)
cc
=
list
(pp)
for
i
in
range
(
len
(plain)):
cc[i]
=
tbl[pp[i]]
for
i
in
range
(
0x40
):
cc[i], cc[
0x80
-
i
-
1
]
=
cc[
0x80
-
i
-
1
], cc[i]
for
i
in
range
(
0x20
):
cc[i], cc[
0x40
+
i]
=
cc[
0x40
+
i], cc[i]
for
i
in
range
(
len
(cc)):
plain[i] ^
=
cc[i] ^ rr[i]
for
i
in
range
(
0x20
):
plain[i], plain[
0x40
+
i]
=
plain[
0x40
+
i], plain[i]
for
i
in
range
(
0x40
):
plain[i], plain[
0x80
-
i
-
1
]
=
plain[
0x80
-
i
-
1
], plain[i]
for
i
in
range
(
len
(plain)):
plain[i]
=
tbl.index(plain[i])
return
bytes(plain)
def
dec3(cipher: bytes)
-
> bytes:
plain
=
list
(cipher)
tbl
=
bytes.fromhex(
"c4189868c047179a23f21a2f75ffd837eb1c7d1861cdf1b74914c18590e1616d7bd4f82307d23443325c3c1aeddff337e4ae04e36d2506bd4ea1f351bd3f8ca1974465b774ac094bdb56552fe61bfc579daa9b47710921084a979b12601de096438c39b57b9bfe9e0e196ceb9a9632a14c5c7e3291bd9017d0db023a8f002eb2"
)
for
i
in
range
(
len
(plain)):
plain[i]
=
(plain[i]
-
0x80
) &
0xFF
for
i
in
range
(
0x40
):
plain[i], plain[
0x80
-
i
-
1
]
=
plain[
0x80
-
i
-
1
], plain[i]
ret
=
[
0
]
*
128
for
i
in
range
(
len
(tbl)):
ret[(
0x75
+
i)
%
128
]
=
plain[i] ^ tbl[i]
for
i
in
range
(
0
,
len
(ret),
2
):
ret[i], ret[i
+
1
]
=
ret[i
+
1
], ret[i]
return
bytes(ret)
def
dec4(cipher: bytes)
-
> bytes:
plain
=
list
(cipher)
pp1
=
bytes.fromhex(
"a53f0c50366abda69abc3ecf6f580d6be2286767b4b24360f7cdf44e9c88f5931131d090a4b71fd9e1e0957144ed5f7dbc2ceceece0a5291bf6db45b822f9587c5954189bf76d9d7bf713f0aa36ceeb414f393794788f7754208923f11de80144e78c441def8bb74decb3a47247b014001990f031fb08b788c3512a3361749d3"
)
cc1
=
bytes.fromhex(
"a642115b4c77f1b5fdba36cb428a409f17f2309fdea03474e6d0f7519f8bf8961434d393a7ba22dce4e3987447f05876b525e5e7c7034b8ab866ad547b289082c0903c84ba71d4d2ba6c3a059e67f5bb1bfa9a804e8ffe7c490f994618e587144e78c441def8bb74decb3a472483094809a1170b27b89380943d1aab3e0c3ec8"
)
dis
=
[]
for
i
in
range
(
len
(pp1)):
dis.append((cc1[i]
-
pp1[i]) &
0xFF
)
for
i
in
range
(
len
(plain)):
plain[i]
-
=
dis[i]
plain[i] &
=
0xFF
return
bytes(plain)
def
dec5(cipher: bytes)
-
> bytes:
plain
=
list
(cipher)
tbl
=
bytes.fromhex(
"d5a04a5de8a503a8dd2d980a4d8f901234023d5545b73f2cbabc07c70186df532961253e09217b85b60895300bb09e6bdbf9af51844950d210ebac2b48c56a74cdfd1d314bd6f3b381367e9c582f4c6c0513635a419b387c6519d047c4927a6fefb15783271a71d8fa2ae142a28ceaff166400561e374328ab06c9c3d3a614aeb5e6969a9d5f2615f223a7a34e8772ec208059a440f70ce7bb33ede2ee0f8eb20e3c916824754660a17932b8738b76d11fda8d22f00dc011c2e0665ed79ffe88dc7d8aca4404d417c61b94f654694f6de5be3b6ecbf18278f4def5bd2ece67c835ad7752c17fb99339f8e418bfd9cfb489cc5c1cfcaa3a7062fb5be3a99997e9"
)
pp
=
bytes.fromhex(
"9620b6c3418b71c2a79c5d17937f210d436589b31ebb52c12e256660a46e84450c62a3b21370e5b91e840e67b2db5c2cb2cda71df65066990dcc285847021d46dc20489d6664cb3b66a2aca58ed8aa5ec75bedb54cec97d3361233f3ba7f15454cab44fd67625e1e67f6acb3099a2d812d3c2c0a85c2a4b540c507b86a4d6ac6"
)
cc
=
bytes.fromhex(
"1e76d27f22bf0ba060c447584fa9b895954c4a32bdc046d036cd250181466efc2f002f48486ec74947015bcc5249878f274d2cfb1ab6a9b9a362ca9cff8f586ac125846ea7c2acf7c225d7662ca5b39e5387ca66b8687d953a4d09b09436291f92e9a38ace7ce6cdd1ba7464e488dc9118143ec808ec822e4438538100d068b3"
)
for
i
in
range
(
len
(cipher)):
plain[i] ^
=
pp[i] ^ cc[i]
for
i
in
range
(
0x80
):
plain[i]
=
tbl.index(plain[i])
ret
=
[]
for
i
in
range
(
0x30
,
-
1
,
-
0x10
):
for
j
in
range
(
0xF
,
-
1
,
-
1
):
ret.append(plain[i
+
j])
ret
+
=
plain[
0x40
:]
return
bytes(ret)
def
dec6(plain: bytes)
-
> bytes:
p
=
bytes.fromhex(
"cf00fa1ac6497c69840b0c74e6d8c2ad50e23957b7b581e678aac75be30e61d895f5d38858be754f4dcf567f9f1cf0cc89fed6aee83cf43e20c8c8fadbc6f2cbd16eca9559b795199d171848be19fa92a30f49b7dc3ec2f54599d28e29a38546bc459e3b969792d0fb06532ac838a4c8fd72055c12d398bbd1f5ad497a5a831b"
)
c
=
bytes.fromhex(
"5a125abad541706a858bf87f4354c5ab409259b7e73511f6589a87ab23de41f885c5d2855fbf7a4d44df76ef7fec30fc005fe6ee885cb41e60e8880a1b16d2ebe11efa65eabc97298c061940be6770a8132f0907acaedbc505dbf2e563b7ad50eec6ee66e6f7b240eb0603bad868f498ed52956c62f3a8cbe1863b497658ae6b"
)
tbl
=
[p[i] ^ c[i]
for
i
in
range
(
len
(p))]
return
bytes([tbl[i] ^ plain[i]
for
i
in
range
(
len
(plain))])
def
dec7(cipher: bytes)
-
> bytes:
tbl1
=
bytes.fromhex(
"588d51e8d4d9a5c53094c6bab325c238a4c8aaf74e2e603b3ab2a975a12316fb64e42478322631434bbcb8ac639b7e871b42b59e612a866e4cd2355ad6e9b91db77fa8537bd7de799a745f0bf001ade24a3d98651e6cd8dbabe5442221cb507615565c2972896d418c8e19e1919df2063f1a7d978a8392dc77f936cf48a0c78214e3963984b188284611afa352fe10f457f1e0ca547ca27049a72db6d090da7a67c3bd1cf6f52b9308691359624feaced3eceb5ed10e04204d0f8bbbc9bf03059ccc40dfef853e3cf3ffd50a272fee8f6a1ffd955d817355dde75b6f18c4ae450d689fc012edcd0c33f8fc2c003747bee634a666b0b49971806b07fac1170209"
)
tbl2
=
bytes.fromhex(
"35b3a22a08d483add97fb6c277933814aa1341488d79eca0f6529df8a64d30fa6124b557658ef9f0d1c3c41acd252f676aa44c17686682c7cc6343e987dd8cb2ea3f7cfc6d115db8b1bd562cc186b044056236a8399427ae7b80df73e5e233e3d3cba7859b9991d0006921e66e9806372b8bf42e95a3cf0c7119530410c96b3aee1b88e12397d6f2d54fe4be4270ffe8de5c7db9f126a9843bced2bcc6d83d501c81db2d6045493e587692c512fb9c54ba070290ef477e75af18bb51f5209a9631349f599e46bfa1ca89014a5a1f1e5bf78fb7d7fe5ee01528e7dcda725f55030d64744b29c04e78ab40226f1d09f3a516c8fd6cac8a0fed0a3c327a0b0eebb4"
)
tbl3
=
bytes.fromhex(
"7f9458886cfd2dafe88538c7287bebeeb925894fd2053a0cde8ffccb65ad45c959e12b2f4372c381db8eab010677075e74bc03628c543d3718e279840a307e2e83f95746d15b1a1f116820a76495710b5627a350bbc102e035b582d333ca4a0eef26f413b786acc83ed8759d233b934ca15ab6a0048b8a551922be61e69690c099c69ed7603241f087e9aa175f7c4b1b0d40ffb34269e410faa9d62cf5edbad9480f4ef378d014f7a66eaea870669a52801d34366b5da4ecdf0891ce9c4992a221cc2a6df8bd514d6ae55ce767b0f2f12412989b29b4b197fbc453cdda44e3dd1e6f31dc3cc576ead5f673c28d3f1ccf477aa50039fe7db215d4b863bf9f1609"
)
tbl4
=
bytes.fromhex(
"4f8a646ddee94796105c220be55999d3319533ff1821ab3d2d78291e7758844db99ff851357d2b666ec2b15e2cdc5fd742ae98371fe2439cd94bcadfec9761398334676345366270243f877e467ca203d47394a41da6bb1add8cebd6d8be93feb419a832002a0a11c94ced28f3fc8ea0a1f675c0ce0754fbb512ea914e9dc7746014ac8f385ac152501c539bf1c4e36a4a41b2e8e19071b3cc0c57f9d2ada523bd7615effdbcf5af85dae068f4c8fa69d5256b273b891655db9ee448b69aee80f7170406b0921bcfbf6f86727bf05db713ba050f01e6aa2fc35b7a026ccda32ea9c53c568882e78d3e8120cb0d79f244653a260830a7b84940d07fc6d18b0e09"
)
tbl5
=
b
'\x1d\xbcs,\xdb\x81\xe3\x04\x06U\x8dF\xfcQ\x83\x00G\x14v-C\xf8\xc6\x10l\x11\x1c\xc0\x96V\x99\xbd\xd7\xeb\xa8\t\xc4=\x0ci\xea\xfd.j\xbf\x947!\x0fo(\x1f\xa7\x1bg6\x13\xd9\xff\xe8d0?\xf4q+\x8c\\p\'[email protected]\xa0z#\xcct\x871\xc1DN\x80&c\x07\x12W\x91<`h|w\xb7\x84\xae\x9c\xc9\xc2\xd0\xc3\x97\xf1B%y$\xc8\x02\xca/\xe4\xf0Or\x92\x0b\xfb\xa3n\xe7\x1eT\xc7\xa4J\xe0\xd5\x86\xb1\xf7\x8bY\xd2\x89\xf5\x08E\n:\x93\xd4\xd6}\xf9{\x85\x9d\xfe\xd3"L;~\xbe\xab\xb0\xb9\xa9\x88\xa6\xda\xbb\xf6\x1a\x05\xde\x18>\x8e\xb4\xfa\xba\xb3\xb8\xb6k\x0eK5\xcb\xec\xdc\x17\x8f \xf2*eb\x82\xf3\xa2\xcf^\xb5\xe6\xce\x9ff\xe9PR\xef[\x9e\xdd\x8a\xe2Iau\xed8\xd8\xd1\xe1)\x15\x98ZS\x01\xa5M\xcd\xc5\x90]\r9\x7f4\xdf_\x16\x03\xee\xa1\xad\x9b\xaf\xb23X\xe5\x19HA\xaa\x95\xac\x9ax'
tbl6
=
b
'V\xd6x\xdc\x8fs\xcf\x8e\x0b\x14\xaa\xfa?=\xc0\xf1)\xde\x8b:t\xb1n\x8cH\xc5\xc4R\xdd.\xd76yD\x7f\xe1\xc1\x99\xd4\x9a\xd8h\xa52WC\x17\xa2\xdf\x87\x82\xf8\xe6\xe7\xb5\x004\xb2\xc9\rX\xaeK\xad\xc3\xc7\x88\x91\n\x051dz>Mb\x06m\xa4\xc6\xe3Bji\xa3\xcc\xb0\x92a\xbf\x8a!Q\x07\xa7-&A\x10\x08\x19\xe2\x1ckr\xca\xb4\x18\x94U\xdaJ\xf3Y^"\x0cE\xbe\[email protected]}\xd0]*\xf2\x0eO/\xcd\x90\x03\x97\xff<\x968\x15\x80\xec\x0f\xc2\x1b\xb3\xeb\x9b~I\xaf{g\x9d$\x86\tf\xf7\\;\xd3\xfd\x04o\x1f\xd9\xb8\xa8ev\x8d\x95\xbb\xb9l\xb7\xee\x01\xf4 `\x1au\xf65\x89%\xbd\x11\x83,\xbcF\xd5\xcb\xab(w\'\xd2\xc8\xe0\xb6N\xd1\x98\xe9\xcep\xe4P+\xe8\xa1#\xa6\xfe\xedS\x9c\xa9\x127Z[\x81\xbaLT\xf9\x9e\xdb3\xea\x939\x1d\x02qc\x16\x85\x1e\x9f|\xac\xf0\xf5\x84\xef\xa00\xe5\x13_\xfc'
tbl7
=
b
' ;\xec\xbe\xb6\x87\x85\x9fS\xefW\xe0\xc3\x01\xf8:\xe7AKr)\x0bl\x04y\xfc\x18\xb4g\xce\xf0\x0eZ4\x9e\xf6\x94\xacXo\xf3\xc42\x8aU\x9c\x07\xb0e\xe3\x9bRQ\xc7\xddc\xa9\x12\x0f\x95\x80Y\x1a\xcf{0\xa8\xab1/a\x16\x1cMi"p\xcbu<\xd3t\x91\xf1O\xa5\xe2\xfd\xbd\x11m6+\xaa\xd5\x90\xe4\x8d\xda\xb8\xa2\xaf\x1d\x98\x1f\x88*I\x82x\x99\xebGf\xca?\xa6J&\xdfD\x7f\x13\xa4\xb1\x02z\xc9\x9d\x00\xd6^\xbaC\xc2\x03\xff(5\xbcdq\xdc\xa3[\xd4\xee\x83\xf7F-k}\xaeb\xd9\xa7,\xc8\r\xa1\x8ej\xe8`n\[email protected]%h\xf4\xb7\xb3w\xc18\xc0\xd8\xd1\xfe\xb9\'\xbfE]=\x19\xf5\xcc9\xde\x81\x9a3\xc5s\x15\\P\x89N\xa0!$\xdb\xbbV\x17_\xad\xf2\x8c\x8f\x96\x97\xe5T\x86\t\x1bB\x10H\xb5\xf9~|\x05\xd7>\x067\xe6\x93\xfa\xe9v\n\x1e\xed\x0c.\xcd\xfb\x08\xea\x84\x92\xd0\xc6L\xe1#\xd2\x14\x8b'
plain
=
list
(cipher)
tbls
=
[tbl1, tbl2, tbl3, tbl4, tbl5, tbl6, tbl7]
for
tbl
in
tbls[::
-
1
]:
for
i
in
range
(
len
(plain)):
plain[i]
=
tbl.index(plain[i])
return
bytes(plain)
target
=
bytes([
121
,
23
,
66
,
107
,
59
,
80
,
122
,
227
,
70
,
208
,
222
,
78
,
36
,
167
,
138
,
106
,
105
,
208
,
2
,
6
,
240
,
39
,
36
,
189
,
192
,
187
,
227
,
30
,
9
,
163
,
151
,
48
,
60
,
182
,
235
,
104
,
144
,
9
,
208
,
234
,
17
,
242
,
196
,
96
,
165
,
203
,
195
,
252
,
69
,
251
,
92
,
83
,
192
,
128
,
58
,
153
,
89
,
111
,
47
,
84
,
74
,
217
,
14
,
106
,
52
,
222
,
210
,
236
,
175
,
74
,
11
,
164
,
138
,
182
,
250
,
147
,
31
,
4
,
16
,
68
,
238
,
228
,
214
,
158
,
244
,
69
,
18
,
77
,
55
,
60
,
240
,
17
,
248
,
200
,
68
,
118
,
99
,
16
,
115
,
45
,
104
,
215
,
157
,
47
,
195
,
132
,
42
,
182
,
204
,
181
,
55
,
97
,
79
,
15
,
22
,
188
,
187
,
140
,
83
,
39
,
238
,
119
,
170
,
31
,
156
,
194
,
24
,
222
])
decs
=
[dec1, dec2, dec3, dec4, dec5, dec6, dec7]
for
func
in
decs[::
-
1
]:
target
=
func(target)
print
(target.decode())