首页
社区
课程
招聘
[原创] 看雪·2024 KCTF 大赛 第三题 绝境逢生 WriteUP
发表于: 2024-8-20 14:32 5770

[原创] 看雪·2024 KCTF 大赛 第三题 绝境逢生 WriteUP

2024-8-20 14:32
5770

又是一个周末,又是一道题~

封面

由于反混淆的脚本出了点状况,截至本WriteUP发布,还是没修完BUG。。

拿到题目,我们稍微调试分析可以发现

x64dbg代码截图

这些大幅增加了静态分析的难度。程序还实现了多种反调试技术,如检测调试器等,让动态调试也有些许麻烦。

这里基本上直接人工整理代码,我们可以知道大概算法,随后得到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截图。

IDA分析截图

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直播授课

收藏
免费 6
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
// // 统计代码