-
-
[原创] 看雪·2024 KCTF 大赛 第三题 绝境逢生 WriteUP
-
发表于: 2024-8-20 14:32 5770
-
又是一个周末,又是一道题~
由于反混淆的脚本出了点状况,截至本WriteUP发布,还是没修完BUG。。
拿到题目,我们稍微调试分析可以发现
这些大幅增加了静态分析的难度。程序还实现了多种反调试技术,如检测调试器等,让动态调试也有些许麻烦。
这里基本上直接人工整理代码,我们可以知道大概算法,随后得到SN即可,下面放出加密脚本和大致算法流程,如果有误请在评论区提出。
SN分5小节,每小节计算大致如下
Name与8位的特定数组字节加,之后循环与i,table1,table2按字节xor,最后将其看作两个dword量,进行xor 0x506。然后进行base编码,再对编码结果进行加密(process_data),得到的就是第1小节SN。第3小节类似该流程
第2小节为Name进行CRC后,xor 0xffffffff,之后减去第1小节SN的开头4字节,然后加0x1000,最后xor 第1小节SN开头的4字节。第4小节类似,不过这里要对第2小节CRC,然后not即可(最终结果用十六进制的文本值,如21ECFFFF)。
第5小节为DES部分,要求解密结果下列计算的值,既等于Name进行base编码后进行CRC,然后对其结果xor 0xffffffff后的文本值。
如下是第一小节和第三小节会用到的算法脚本。其中input_values输入BASE编码的值即可,输出既为SN。
对于DES部分,不再过多阐述,这里可以直接去修改算法逻辑和数据来实现加密和解密。如果要逆向该部分算法的话,要注意置换那边是3bytes的左移和右移。
早期选择用x64dbg+脚本来处理混淆,效果一般。
后期采用IDAPython配合各类第三方库,效果还好,但是脚本调试到最后有各种bug,这里就先给出处理了部分混淆后的IDA截图。
整体算法结构和反调试相关部分勉强能看,如果想要更细致的反混淆,那就需要花费漫长的时间了。
带着混淆直接分析起来会比较麻烦,还是得想办法处理掉混淆后看起来会好很多,不然分析算法会非常头疼。
主要难点还是前面的加密算法和后面被修改过的DES的分析,以及如何处理反调试等。
对于反调试,本题实现了包括IsDebuggerPresent、NtSetInformationThread、ZwQueryInformationThread等API检测,以及时间检测等技术。可以通过修改调试器行为、Hook相关API等方式绕过。感兴趣的可以自行搜索,我这边测试用插件可以绕过。
def
inv_process_data(const_list, input_data):
temp
=
[
0
]
*
6
temp[
3
], temp[
2
], temp[
1
], temp[
0
]
=
input_data
pos
=
0
temp[
2
]
=
(temp[
2
]
+
const_list[pos]) &
0xFFFFFFFF
pos
+
=
1
temp[
0
]
=
(temp[
0
]
+
const_list[pos]) &
0xFFFFFFFF
pos
+
=
1
for
_
in
range
(
5
):
temp[
4
], temp[
3
], temp[
2
], temp[
1
], temp[
0
]
=
temp[
3
], temp[
2
], temp[
1
], temp[
0
], temp[
3
]
calculation
=
((
32
*
temp[
3
]) ^
3
)
*
temp[
3
] &
0xFFFFFFFF
shift_val
=
((calculation <<
4
) | (calculation >>
28
)) &
0xFFFFFFFF
temp[
4
]
=
shift_val
calculation
=
((
32
*
temp[
1
]) ^
3
)
*
temp[
1
] &
0xFFFFFFFF
shift_val
=
((calculation <<
4
) | (calculation >>
28
)) &
0xFFFFFFFF
temp[
5
]
=
shift_val
temp[
0
] ^
=
temp[
4
]
calculation
=
temp[
0
] &
0xFFFFFFFF
temp_val
=
(
0x20
-
temp[
5
]) &
0x1F
temp[
0
]
=
((calculation >> temp_val) | (calculation << (temp[
5
] &
0x1F
))) &
0xFFFFFFFF
temp[
0
]
=
(temp[
0
]
+
const_list[pos]) &
0xFFFFFFFF
pos
+
=
1
temp[
2
] ^
=
temp[
5
]
calculation
=
temp[
2
] &
0xFFFFFFFF
temp_val
=
(
0x20
-
temp[
4
]) &
0x1F
temp[
2
]
=
((calculation >> temp_val) | (calculation << (temp[
4
] &
0x1F
))) &
0xFFFFFFFF
temp[
2
]
=
(temp[
2
]
+
const_list[pos]) &
0xFFFFFFFF
pos
+
=
1
temp[
3
]
=
(temp[
3
]
+
const_list[pos]) &
0xFFFFFFFF
pos
+
=
1
temp[
1
]
=
(temp[
1
]
+
const_list[pos]) &
0xFFFFFFFF
return
list
(
reversed
(temp[:
4
]))
a_constant_list
=
[
0x7796B480
,
0x77A446B0
,
0x77972020
,
0x779769B0
,
0x77A44730
,
0x77A447F0
,
0x77975790
,
0x77A44870
,
0x779725B0
,
0x779769B0
,
0x77A44780
,
0x77A447F0
,
0x779AD4F0
,
0x77A44870
]
input_values
=
[
0x6952754A
,
0x30695130
,
0x00000000
,
0x00000000
]
result
=
inv_process_data(a_constant_list, input_values)
for
number
in
result:
hex_str
=
format
(number,
'08x'
)
reversed_str
=
' '
.join([hex_str[i:i
+
2
]
for
i
in
range
(
0
,
len
(hex_str),
2
)][::
-
1
])
print
(reversed_str.upper(), end
=
' '
)
def
inv_process_data(const_list, input_data):
temp
=
[
0
]
*
6
temp[
3
], temp[
2
], temp[
1
], temp[
0
]
=
input_data
pos
=
0
temp[
2
]
=
(temp[
2
]
+
const_list[pos]) &
0xFFFFFFFF
pos
+
=
1
temp[
0
]
=
(temp[
0
]
+
const_list[pos]) &
0xFFFFFFFF
pos
+
=
1
for
_
in
range
(
5
):
temp[
4
], temp[
3
], temp[
2
], temp[
1
], temp[
0
]
=
temp[
3
], temp[
2
], temp[
1
], temp[
0
], temp[
3
]
calculation
=
((
32
*
temp[
3
]) ^
3
)
*
temp[
3
] &
0xFFFFFFFF
shift_val
=
((calculation <<
4
) | (calculation >>
28
)) &
0xFFFFFFFF
temp[
4
]
=
shift_val
calculation
=
((
32
*
temp[
1
]) ^
3
)
*
temp[
1
] &
0xFFFFFFFF
shift_val
=
((calculation <<
4
) | (calculation >>
28
)) &
0xFFFFFFFF
temp[
5
]
=
shift_val
temp[
0
] ^
=
temp[
4
]
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课