根据您提供的新线索——“只能正确识别三次数据,之后出现 NO_PERMISSION”——这可以说是软件逆向和验证分析中的教科书级特征。
这说明程序内部有一个计数器(Counter)机制或者服务器端有频次/权限限制。配合您之前发出的导出函数表,我们可以立刻把目标收窄。
结合这个现象,以下是最关键的两个突破口和分析思路:
🥇 怀疑点一:本地计数器与 isValid / isExpired 联动
很多程序为了提供“免费试用”或者限制本地频率,会在本地内存或配置文件里维护一个计数。
- 工作原理:每次成功识别,计数器 $+1$。当计数器 $> 3$ 时,程序不再去调用网络请求,而是直接在本地把 Token 的状态标记为失效,或者直接返回错误码。
- 重点观察函数:
?isValid@Token@PixAuth@@QEBA_NXZ (序号 128):请断点拦截这个函数。看在前三次成功时它返回什么(通常是 1),在第四次出现 NO_PERMISSION 时,它是不是提前返回了 0?
?isExpired@Token@PixAuth@@QEBA_NXZ (序号 119):同理,第四次时它是否变成了 1(强行让本地 Token “过期”)。
🥈 怀疑点二:临时 Token(Anonymous/Guest Token)的生命周期
这是更常见的一种设计:程序启动时,服务器会发给未登录/免费用户一个“临时临时凭证”(Guest Token),这个 Token 的权限极其有限,在服务器端就被设置了“只能请求3次”的硬限制。
-
工作原理:
- 前三次请求,服务器验证这个 Guest Token 发现次数没超,返回正确数据。
- 第四次请求时,服务器后端判定该 Token 次数耗尽,直接拒绝并返回
NO_PERMISSION 错误。
-
重点观察函数:
?value@Token@PixAuth@@QEBA?AVQString@@XZ (序号 241):
在 x64dbg 中给这个函数下断点。把前三次成功时的 Token 字符串复制保存下来,再看第四次失败时的 Token 字符串。
- 如果是同个 Token:说明限制在服务器端(服务器记住了这个 Token 的次数),单纯在本地改
value 没用,必须寻找它是从哪里生成的(比如登录或刷新逻辑)。
- 如果第四次 Token 变了或者没有了:说明是本地逻辑在捣鬼,切断了 Token 的获取。
🛠️ 下一步调试实战建议(如何顺藤摸瓜)
由于您已经能定位到 sigJwtFetched 和 Token::value,建议您尝试以下“降维打击”的调试步骤:
-
监控法(看数据变动):
- 在
00007FFDD72A411D(即调用 Token::value 的地方)下断点。
- 观察前三次和第四次,
rax 返回的 QString 内部指针所指向的字符串内容。如果第四次时,获取出来的 Token 变成了空字符串("")或者特定错误字符,那么罪魁祸首就在 Token::value 内部。
-
爆破测试法(验证是否为本地限制):
- 找到
?isValid@Token@PixAuth@@QEBA_NXZ 的函数入口。
- 直接将其汇编代码修改为强制返回真:
mov al, 1
ret
* 找到 `?isExpired@Token@PixAuth@@QEBA_NXZ` 的函数入口。
* 直接将其修改为强制返回假(未过期):
```assembly
xor al, al
ret
- 修改后看看能不能突破 3 次的限制。如果能,说明是本地逻辑锁死了权限;如果不能(依然提示
NO_PERMISSION),则说明这个“3次限制”是服务器端通过网络严格校验的,本地的 Token 已经彻底失效或无权了。
- 追踪
fromValue / `fromJson`:
- 如果证实是服务器限制,可以看
?fromJson@Token@PixAuth@@SA?AV1@AEBVQJsonObject@@@Z (序号 103)。这里是程序收到服务器发回的新 Token 时据此构造对象的地方,可以观察程序是在什么时候、用什么身份去向服务器申请初始 Token 的。
|