吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4039|回复: 46
上一主题 下一主题
收起左侧

[CTF] 2025腾讯游戏安全竞赛 PC客户端安全 初赛WP

  [复制链接]
跳转到指定楼层
楼主
Tkazer 发表于 2025-3-31 18:24 回帖奖励
本帖最后由 Tkazer 于 2025-4-2 12:18 编辑

2025 腾讯游戏安全技术竞赛 PC客户端安全 初赛WP

前言

这也是本菜鸡第一次参加该比赛,之前是有看过前几年比赛的WP,感觉难度不小,这次来尝试一下,由于是纯CTF类型,做起来还算顺手,不过也是遇到不少问题。经过半天的奋战最后还是解了出来,综合体验下来收获还是不少的。

R3分析

将ACEFirstRound.exe放入IDA分析,在main函数可以看到一个虚表,根据里面各个函数内容,将每个虚表函数都重新命名为对应功能。

发现是运行了ACEDriver驱动,与r3程序之间进行通信。

尝试动调发现没办法,发现程序退出,根据CheckRemoteDebuggerPresent的交叉引用发现一个反调试函数。

找该函数的交叉调用,发现是这边启了一个线程来启动反调试。

在该函数这边进行条件断点,修改rip,让代码直接执行到函数结束处,跳过中间反调试相关代码,即可绕过反调试。

动调分析,然后这边输入flag要求是以"ACE_"开头,然后去掉前面这四个字符,首先进行Base58加密,然后再将数据倒转。这边Base58是变表,和标准不一样,提取得:abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789

与"sxx"进行循环xor。

最后通信发送到ACEDriver,命令码是0x154004。

至此R3层分析完毕。

R0分析

IDA载入ACEDriver.sys,发现有几个消息的Callback,但是跳转过来发现有混淆和花指令。

该驱动的混淆和花指令都是一个类型的,花指令是最基础的。

以下图为例子:

对41e9按u再跳过e9字节按c还原,即可pass花指令。

然后截图处是一块,将地址计算完进行jmp,计算出来实际就是jmp到下面pop处,说明这一段是无用的,可以直接将push到pop全部nop即可。其他地方都和这地方混淆差不多类型,都直接跳过花指令后nop即可。

但有一种比较特殊,并不是跳转到下面邻近代码处,而是jmp到其他代码处,观察push和底下pop寄存器是否一致就可以判断是哪一种类型,该种就得手动计算地址然后写jmp。

手动去除大部分混淆后,就可以看到几个回调的里面代码,MessageNotifyCallback里面的代码如下:

进入几层call就可以看到这边就是判断命令码执行,下面就是接收R3发送来的密文数据。

进入call发现就是关键处,unk_140004064那边就是flag密文,使用的是tea加密,key是['A','C','E','6'],然后边加密边判断密文是否相等。

查看tea函数的交叉调用,发现有其他地方有出现。

在第四个call处,发现一个函数传入了tea加密的函数地址,然后进行了一系列变换,应该是对tea函数本体进行了修改。

将该函数代码和相关数据进行提取,对tea函数字节进行本地模拟操作。

// tea函数原字节
unsigned char tea[149] = {
    0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48,
    0x89, 0x78, 0x20, 0x41, 0x55, 0x4C, 0x8B, 0xEA, 0x8B, 0x1A, 0x45, 0x33, 0xDB, 0x8B, 0x7A, 0x04,
    0x4C, 0x8B, 0xC1, 0x8B, 0x72, 0x08, 0x8B, 0x6A, 0x0C, 0x44, 0x8B, 0x09, 0x41, 0x8D, 0x53, 0x20,
    0x44, 0x8B, 0x51, 0x04, 0x41, 0x8B, 0xCA, 0x45, 0x8D, 0x9B, 0xB9, 0x79, 0x37, 0x9E, 0xC1, 0xE9,
    0x05, 0x41, 0x8B, 0xC2, 0x03, 0xCF, 0xC1, 0xE0, 0x04, 0x03, 0xC3, 0x33, 0xC8, 0x43, 0x8D, 0x04,
    0x13, 0x33, 0xC8, 0x44, 0x03, 0xC9, 0x41, 0x8B, 0xC9, 0x41, 0x8B, 0xC1, 0xC1, 0xE9, 0x05, 0xC1,
    0xE0, 0x04, 0x03, 0xCD, 0x03, 0xC6, 0x33, 0xC8, 0x43, 0x8D, 0x04, 0x0B, 0x33, 0xC8, 0x44, 0x03,
    0xD1, 0x48, 0x83, 0xEA, 0x01, 0x75, 0xBD, 0x41, 0x5D, 0x48, 0x8B, 0x5C, 0x24, 0x08, 0x48, 0x8B,
    0x6C, 0x24, 0x10, 0x48, 0x8B, 0x74, 0x24, 0x18, 0x48, 0x8B, 0x7C, 0x24, 0x20, 0x45, 0x89, 0x08,
    0x45, 0x89, 0x50, 0x04, 0xC3
};

unsigned char P_0[0x1000]{};

unsigned char xmmword_140004000[16] = {
    0x58, 0x41, 0x8B, 0xC9, 0x41, 0x8B, 0xC1, 0xC1, 0xE0, 0x04, 0xC1, 0xE9, 0x05, 0x33, 0xC8, 0x41
};

unsigned char xmmword_140004010[16] = {
    0x8B, 0xC3, 0x48, 0xC1, 0xE8, 0x0B, 0x41, 0x03, 0xC9, 0x83, 0xE0, 0x03, 0x41, 0x8B, 0x44, 0x85
};

unsigned char xmmword_140004020[16] = {
    0x00, 0x41, 0x03, 0xC3, 0x33, 0xC8, 0x44, 0x03, 0xD1, 0x48, 0x83, 0xEA, 0x01, 0x48, 0xB8, 0x00
};

unsigned char xmmword_140004030[16] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

unsigned char dword_140004040[4] = {
    0x00, 0x75, 0x02, 0xFF
};

unsigned char word_140004044[2] = {
    0xE0, 0xFF
};

unsigned char byte_140004046[2] = {
    0xE1, 0x00
};

unsigned char qword_140004048[8] = {
    0x50, 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00
};

unsigned char dword_140004050[4] = {
    0x00, 0x00, 0x00, 0xFF
};

unsigned char byte_140004054[1] = {
    0xE0
};

DWORD64 qword_1400041E0 = 0;
DWORD dword_1400041E8 = 0;
BYTE byte_1400041EC = 0;

// 对tea函数修改的函数
void __fastcall sub_14000A35B(__int64 a1)
{
    int n64; // ebx
    char* v3; // rdx
    int i; // ecx
    unsigned __int64 v5; // rax
    char* v6; // rdx
    int j; // ecx
    unsigned __int64 v8; // rax
    char* v9; // rdx
    unsigned __int64* v10; // rcx
    unsigned __int64 v11; // r8
    unsigned __int64 v12; // rax
    unsigned __int8 CurrentIrql; // dl
    unsigned __int64 v14; // rcx
    unsigned __int64 v15; // rax
    unsigned __int64 v16; // rax

    n64 = 0;

    v3 = (char*)&xmmword_140004020 + 15;
    for (i = 0; i < 64; i += 8)
    {
        v5 = (unsigned __int64)(a1 + 119) >> i;
        *v3++ = v5;
    }
    v6 = (char*)&xmmword_140004030 + 9;
    for (j = 0; j < 64; j += 8)
    {
        v8 = (unsigned __int64)(a1 + 52) >> j;
        *v6++ = v8;
    }
    v9 = (char*)&qword_140004048 + 3;
    v10 = (unsigned long long*)P_0;
    memcpy(P_0, xmmword_140004000, 16);
    memcpy(P_0 + 16, xmmword_140004010, 16);
    memcpy(P_0 + 16 * 2, xmmword_140004020, 16);
    memcpy(P_0 + 16 * 3, xmmword_140004030, 16);
    *((DWORD*)P_0 + 16) = *(DWORD*)dword_140004040;
    *((WORD*)P_0 + 34) = *(WORD*)word_140004044;
    *((BYTE*)P_0 + 70) = *(BYTE*)byte_140004046;
    v11 = (unsigned __int64)P_0;
    do
    {
        v12 = v11 >> n64;
        n64 += 8;
        *v9++ = v12;
    } while (n64 < 64);

    qword_1400041E0 = *(DWORD64*)(a1 + 86);
    dword_1400041E8 = *(DWORD*)(a1 + 94);
    byte_1400041EC = *(BYTE*)(a1 + 98);
    *(DWORD64*)(a1 + 86) = *(DWORD64*)qword_140004048;
    *(DWORD*)(a1 + 94) = *(DWORD*)dword_140004050;
    *(BYTE*)(a1 + 98) = *(BYTE*)byte_140004054;
}

int main()
{
    // 修改tea加密函数代码字节
    sub_14000A35B((long long)tea);
    system("pause");
        return 0;
}

编译使用IDA动调,并按c分析tea数组处的代码,发现分成了三块,手动将三块合并到一块代码,并修复部分跳转的地址,即可得到完整的代码。

合并完的代码如下:

反编译得到修改后的魔改tea加密

即可编写得到对应的解密代码:

void tea_decrypt(unsigned int* Input, int* Key)
{
    unsigned int v6 = Input[0];
    unsigned int v8 = Input[1];
    unsigned int sum = 0;
    // sum从32开始
    sum = (-0x61C88647) * 32;

    for (int i = 0; i < 32; i++) 
    {
        v8 -= (sum + Key[(sum >> 11) & 3]) ^ (v6 + ((v6 << 4) ^ (v6 >> 5)));
        v6 -= (sum + v8) ^ (Key[0] + (v8 << 4)) ^ (Key[1] + (v8 >> 5));
        sum += 0x61C88647;
    }

    Input[0] = v6;
    Input[1] = v8;
}

进行对unk_140004064密文解密即可,不过注意一点,这边是从-1处开始判断,也就是unk_140004064-4处开始是密文。

提取出来就是42的DWORD数据,和上面的判断数值对应上了。

解密

#include <iostream>
#include <Windows.h>

// 魔改tea解密函数
void tea_decrypt(unsigned int *Input, int *Key)
{
    unsigned int v6 = Input[0];
    unsigned int v8 = Input[1];
    unsigned int sum = 0;

    sum = (-0x61C88647) * 32;

    for (int i = 0; i < 32; i++)
    {
        v8 -= (sum + Key[(sum >> 11) & 3]) ^ (v6 + ((v6 << 4) ^ (v6 >> 5)));
        v6 -= (sum + v8) ^ (Key[0] + (v8 << 4)) ^ (Key[1] + (v8 >> 5));
        sum += 0x61C88647;
    }

    Input[0] = v6;
    Input[1] = v8;
}

// flag密文
unsigned int enc[42] = {
    0x0EC367B8, 0xC9DA9044, 0xDA6C2DEB, 0x88DDC9C3, 0x32A01575, 0x231DD0B4, 0x4B9E8A74, 0xD75D3E74,
    0xEAAB8712, 0xE704E888, 0xE01A31AC, 0xECAE205C, 0xA7BE7467, 0x0C6252A3, 0x1AEFEC4E, 0xC40DED44,
    0xC3C842CC, 0xDE4A0C0E, 0x7C24F3FC, 0x8FB8D001, 0x11153E6E, 0x530ED15C, 0xF4214811, 0xBEB517E0,
    0x63F91634, 0x4D96F8A5, 0xFE23EAC8, 0x2C607ADF, 0xCC43D85C, 0xFF186C5B, 0x8763E1A5, 0x9187BD58,
    0x87D1069B, 0xD7878D7B, 0x836E6B68, 0x55A0C63F, 0xD979FDB3, 0x3E524DEE, 0x7AB35C82, 0xA2F4DA8D,
    0x1708BA4C, 0x710653E6};

// tea解密key
int key[4]{'A', 'C', 'E', '6'};

int main()
{
    // 42个数据,2个2个进行tea解密
    for (int i = 0; i < 42; i += 2)
    {
        tea_decrypt((unsigned int *)((DWORD64)enc + i * 4), key);
    }
    // 输出42个解密后数据
    for (int i = 0; i < 42; i++)
        printf("%X ", enc[i]);
    return 0;
}

Out

33 28 13 0 2D 16 40 41 13 2A 12 4F 45 4B 1F 14 39 49 3B 34 3A 26 3B 19 24 2B 22 5 4C E 0 4C 3B 4 2B 1D 5 39 16 22 3D B

CyberChef

xor('sxx') -> Reverse -> Base58 Decode(换表)

密文:We1C0me!T0Z0Z5GamESecur1t9*CTf

Flag

flag{ACE_We1C0me!T0Z0Z5GamESecur1t9*CTf}

2025腾讯游戏安全技术竞赛-PC客户端安全-初赛.zip

159.92 KB, 下载次数: 24, 下载积分: 吾爱币 -1 CB

PC附件

免费评分

参与人数 26吾爱币 +20 热心值 +22 收起 理由
zpbooks + 1 + 1 我很赞同!
LionJee + 1 我很赞同!
lin5789 + 1 热心回复!
biggeryellow + 1 + 1 我很赞同!
mch624774 + 1 + 1 我很赞同!
ioyr5995 + 1 + 1 我很赞同!
ztw36343153 + 1 + 1 我很赞同!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
yzlyyds + 1 + 1 热心回复!
52PJ658 + 1 我很赞同!
GGhostG + 1 + 1 我很赞同!
gaosld + 1 + 1 谢谢@Thanks!
InfiniteBoy + 1 + 1 用心讨论,共获提升!
笨笨家的唯一 + 1 + 1 我很赞同!
zhiyuckt + 1 我很赞同!
52pj3344 + 1 大佬啊 看都看不懂
ApollosLegends + 1 + 1 我很赞同!
lwGoodChinese + 1 我很赞同!
PoJieDaWang123 + 1 我很赞同!
坐照 + 1 + 1 谢谢@Thanks!
Tgxmy + 1 我很赞同!
RakanLi + 1 我很赞同!
yur0 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
akb848 + 1 + 1 我很赞同!
5m10v3 + 1 用心讨论,共获提升!
SeanDcitonary + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
SfbjZxc 发表于 2025-4-5 16:10
本帖最后由 SfbjZxc 于 2025-4-5 18:18 编辑

纯新手一个,想请教一下大佬,这个在win10 22H2的虚拟机当中不能加载sys该怎么处理啊,提示环境不对。已经关闭了windows defender、vbs、hyper了。
沙发
SeanDcitonary 发表于 2025-3-31 21:32
3#
mw26973 发表于 2025-3-31 21:37
4#
cgh740 发表于 2025-4-1 02:05
厉害,这种没有几年的沉淀,分析难度很大。
5#
AisakaMai 发表于 2025-4-1 07:50
膜拜大佬
6#
qlh520 发表于 2025-4-1 09:42
依然神傲
7#
坐照 发表于 2025-4-1 10:39

不明觉厉!
8#
Cyh777 发表于 2025-4-1 11:23
不明觉厉!
9#
springOfSummer 发表于 2025-4-1 11:38
大佬厉害,学习啦!
10#
RielCcc 发表于 2025-4-1 11:45
连初赛看起来就已经很有难度了,有原题附件可以发出来动手试试吗
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-25 00:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表