近日,瞬犀安全技术团队发现了一组针对游戏账号与登录态的窃取样本。报告记录的运行链从 cli2update2.exe 启动开始:程序下载并加载 pz2.bin,随后持续检查 Steam、QQ、WeGame/TGP 等客户端进程;发现目标后,进入对应采集分支,并将获取的数据发送到外部服务器。
样本在后台按周期调度多个业务分支,采集路径因平台而异:WeGame/TGP 分支涉及目标进程内存读取及 DLL 注入相关行为;QQ 分支读取账号与 clientkey,借助正常登录跳转链路获取 Cookie;Steam 分支解析 JWT 载荷并读取账号相关数据。报告记录了采集数据向外部地址发送的行为。
• 账号接管风险:账号标识和登录凭据一旦外泄,攻击者可能尝试未授权登录,造成账号控制权丢失。
• 登录态滥用风险:Cookie、令牌等会话材料可能绕过单纯的密码验证,在有效期内被用于冒用会话。
• 游戏资产与关联账户风险:账号失控可能进一步影响虚拟资产、绑定邮箱及其他关联服务。实际是否发生损失,需要结合账户日志和设备取证确认。
• 隐蔽采集风险:分支按目标进程和状态条件触发,且通过内存加载、进程访问等方式运行,单看磁盘文件或单条告警可能无法还原完整链路。
cli2update2.exe 是这条链路的前置程序。本节以 cli2update2_dump_SCY.exe 的脱壳程序代码为依据,地址均对应当前脱壳项目。
解码字符串和获取外网地址
下载并动态加载pz2.bin
网络请求1:
网络请求2:
网络请求3:
网络请求4:
网络请求5:
程序从易语言模块入口 fn_EYuyanMain0(0x1002922D)进入初始化流程,创建运行库和全局对象后,通过 fn_StartMonitorThread(0x1000103B)启动后台线程。
线程经 fn_MonitorThreadEntry 进入 fn_MonitorLoop(0x10001079),循环执行 fn_CheckTargetsAndDispatchPayloads(0x100010AA),每轮约等待 2 秒。
主调度围绕是否已处理过对应业务决定后续操作:micc 尚未尝试下载时,下载并启动;Steam 采集状态允许时,检查目标并采集;Trxa 尚未尝试执行且发现 WeGame/TGP 时,依次下载执行两份载荷;QQ 尚未尝试启动采集时,检查进程并创建采集线程。下文按各项业务分别展开,公共字符串解码集中放在后面说明。
这种编排用于阅读和后续补充分析;主函数的真实调用顺序仍以以下逻辑树为准,Steam 检查先于 micc、QQ 和 Trxa 处理。
fn_CheckTargetsAndDispatchPayloads的函数逻辑如下:
标志位名 | 地址 | 置位条件及含义
g_micc_download_attempted | 0x10045A4D | 为 0 时先置 999,再尝试下载、落地启动 micc.bin;不依赖目标进程是否存在
g_qq_collector_start_attempted | 0x10045A51 | 为 0 且找到 QQ.exe(PID > 1)时,先置 999,再尝试创建 QQ 采集线程
dword_10045A55 | 0x10045A55 | 为 0 时置 999
g_trxa_dispatch_attempted | 0x10045A59 | 为 0 且找到 WeGame/TGP 目标(最终 PID > 1)时,先置 999,再依次下载、内存加载两份 Trxa 载荷
这些标志表示对应业务是否已经尝试处理。
这里有两类不同的重试行为:QQ 或 WeGame/TGP 进程未找到时,对应的 g_qq_collector_start_attempted、g_trxa_dispatch_attempted 保持 0,下轮还会检查;一旦满足进程条件并置位,即使线程创建、下载或 PE 加载失败,这个调度函数也不会再尝试该分支。WeGame 查找仅在 PID < 1 时回退到 tgp_daemon.exe,最终是否进入载荷分支则判断 PID > 1。
Steam 不由上述三个 attempted 标志控制,每轮仍会调用其检查函数。Steam 子流程另有状态重置逻辑,用于重新判断进程和窗口是否满足采集条件。
主调度检查 g_micc_download_attempted。为 0 时,先将其设为 999,再调用 fn_DownloadDropAndRun(0x10008142)。该函数接收主流程传入的加密地址,解码后请求 d1dK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8W2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6e0p5I4y4W2)9K6b7e0V1#2x3e0N6Q4x3V1k6E0K9h3y4U0i4K6u0W2j5X3W2F1i4@1f1K6i4K6R3H3i4K6R3J5
响应长度大于 5000 字节时,程序生成六个随机小写字母组成的名称,将下载内容写入宿主 EXE 所在目录,设置隐藏属性,再调用 CreateProcessA 启动。
▌落地启动中的关键操作
目录由 fn_RuntimeGetHostDirectory(0x1002B5F0)取得,其内部使用 GetModuleFileNameA(NULL, ...) 获取宿主 EXE 路径,再去掉文件名。写文件、设置属性和创建进程分别由对应的运行库包装函数完成。
后续经分析micc.bin:与盗号业务无关,故在此不做进一步展示.
fn_CheckSteamAndCollect 分析:
fn_CollectSteamTokensAndSend 分析:
循环获取 steam.exe / steamchina.exe 的pid
调用fn_ReadRemoteText获取到JwtPayload:
传入 fn_DecodeJwtPayload(0x10005A35)。该函数把文本按点号分成三段,Base64 解码中间载荷段并返回 JSON 文本。
随后,从 JSON 中取得 iss 字段,与解码得到的 steam 字符串比较
获取steam的steamui模块的基址
请求6c1K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8W2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6e0t1K6z5q4)9K6b7e0f1J5x3e0u0Q4x3V1k6H3P5W2)9J5k6i4c8^5N6q4!0q4z5q4)9^5c8g2!0n7y4#2!0q4y4g2)9^5c8W2)9&6y4W2!0q4y4g2)9^5x3g2)9^5c8W2!0q4y4#2!0m8y4#2!0n7b7W2!0q4y4#2)9&6b7g2)9^5y4q4!0q4y4g2!0m8c8W2)9^5y4W2!0q4y4W2)9&6y4W2)9^5y4H3`.`.
解码偏移密文:1194E85
获取steam账号信息
向服务器发送获取到的steam数据
网络请求1:
网络请求2:
这一分支从 g_trxa_dispatch_attempted 开始判断。为 0 表示尚未尝试分发执行 Trxa;随后检查 wegame.exe,仅在查找结果小于 1 时改查 tgp_daemon.exe。最终 PID 大于 1,才把标志设为 999,进入两份载荷的下载执行流程。
1. 判断是否需要下载执行
2. 两份载荷的下载顺序
主流程先查找 wegame.exe,未找到时再检查 tgp_daemon.exe;目标存在后,请求以下两份文件:
下载地址 | 后续处理
565K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8W2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6e0p5I4y4W2)9K6b7e0V1#2x3e0N6Q4x3V1k6f1M7Y4S2S2i4K6g2X3j5h3c8V1M7X3g2K6M7K6y4Q4x3X3g2T1K9h3^5`. | 将响应交给内存 PE 加载器
6fbK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8W2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6g2)9J5b7g2)9J5b7g2)9J5b7g2)9J5k6e0p5I4y4W2)9K6b7e0V1#2x3e0N6Q4x3V1k6f1M7Y4S2S2i4K6u0W2j5X3W2F1 | 将响应交给内存 PE 加载器
3. 下载后在当前进程内加载执行
两份下载响应经 fn_LoadDownloadedPe(0x100086A2)传入 fn_MemLoadPE0(0x100086C0)。继续进入加载器,可以看到完整的手工映射过程。
程序先检查 MZ 和 PE 标记,按映像大小分配内存,再复制头部和各节。当实际加载地址与首选基址不同,加载器遍历重定位表修正地址;随后解析导入模块和函数,设置节属性,最后调用被加载 DLL 的入口函数。
3. 下载后在当前进程内加载执行相关逆向分析截图
4. 动态加载Trxa_address3.bin 分析
分析其脱壳版本 Trxa_address3_dump_SCY.dll,当前 IDA 加载基址为 0x701F0000。模块在 DLL 初始化时创建工作线程,随后进入 WeGame/TGP 的凭据采集流程。
入口调用树如下:
[招生]科锐逆向工程师培训(2026年11月13日实地,远程教学同时开班, 第57期)