首页
社区
课程
招聘
[原创]anti-token 纯算法分析
发表于: 15小时前 581

[原创]anti-token 纯算法分析

15小时前
581

本文基于AI分析 anti-token,不得不感慨AI确实强大。

测试环境

它对应 Java Native 方法:

其中:

com.xunmeng.pinduoduo.secure.DeviceNative.info2是一个动态注册的jni方法,通过Hook RegisterNatives,得到函数偏移0x1cfac,以及库名为 libpdd_secure.so

image-20260706103328915

0x1CFAC 就是一个 native 方法入口。它接收 Java 传入的 Context 和一个 long 值,然后返回一个 Java String

IDA 反编译出来的原型是:

把 JNI 语义补上后更容易理解:

参数含义:

这个函数做了控制流扁平化。

image-20260703094956937

正常代码可能长这样:

但反编译中会看到大量类似代码:

这里的 i 是状态机变量。大量随机整数只是混淆后的状态编号,不是业务数据。分析时不要跟着这些数字走,而要抓住真正的调用和数据流:

混淆后大概798行

image-20260706095121854

让AI帮我们分析规则,并编写去控制流平坦化脚本,去除后逻辑就比较清晰了。

image-20260706100510564

IDA底部python 执行命令

本节把主流程涉及的关键子函数一并列出,保留能证明执行逻辑的核心语句,并把 IDA 临时变量名改成更容易理解的名字。

image-20260706135538737

关键调用顺序可以还原为:

对应主函数中的关键证据:

Hook 验证:

整体逻辑:

此函数用于 C 字节指针/字符串 -> slot

该函数证明了 record slot 的内部布局:slot[0] 是 tag,slot+1 是 payload,slot+520 是 payload 长度,slot+524 是 record 长度。

伪代码:

如调用write_bytes_record(slot, 2, "google", 6) 会构造成这样的slot

该函数先把整数转成指定长度的大端字节,再复用 record slot 格式。

整数 value -> 大端 bytes -> slot

伪代码:

它调用的 sub_17FC74 可以简化为:

slot 布局和上面是一样的:

如sdk版本,我的是34,这个是整数型。

这个函数用于把 Java 字符串写入 slot,或者把字符串转整数后写入固定长度 payload。

Java jstring -> 根据 mode 决定按字符串写,还是按整数写 -> slot

tag32:

可还原为:

tag33:

可还原为:

该函数负责 tag1 到 tag11 的主要系统属性。

伪代码:

对应反编译能看到连续的:

Hook 验证,1697AC和169840,slot结构体为:

image-20260703164712740

该函数读取 /system/build.prop 的文件状态,取其中一个时间字段写成 4 字节整数。

伪代码:

对应反编译核心:

Hook 验证:1230768000时间戳转换后是2009-01-01 08:00

image-20260703170141067

image-20260703170235796

image-20260703170542992

该函数负责 tag13 到 tag28,多数来自 TelephonyManager

伪代码:

对应反编译核心包括:

Hook 验证tag 18、21、22 、23:

image-20260703170934497

该函数把三路检测结果 OR 到一起,然后写 tag31。

伪代码:

对应反编译核心:

Hook 验证为0,这里也能看出来,假如用unidbug调的话,java stack trace可能会为1,导致风控的存在。

image-20260703171012827

该函数通过 JNI 调 Java 侧 UUID 逻辑,最后把 Java 字符串拷贝到 native 缓冲区。

主函数上是直接保存的,没有调用1697ac或者169840创建slot。

image-20260703171325740

伪代码:

主函数随后把它作为 tag34 record 使用:

这与主函数里写全局 tag34 slot 的逻辑一致:

主函数里先统计所有 record 的 record_len,再 malloc(raw_len),最后把 slot 转成连续 TLV。

image-20260703171636580

上面的逻辑执行完成后,他还会补上tag 32、33、34到raw packet。32和33的获取方式后面会提到。

image-20260703172611774

伪代码:

对应主函数证据:

下面补充本次 hook 样例值和 raw_packet 写入形态。

raw_packet 中每个 record 的写法固定为:

例如 tag2 的 payload 是字符串 google

依次对所有record转换,再按照tag大小,进行排序拼接。

组装后会传入 0x181980进行压缩,对此函数入参和出参分别打印一下 (UUID和设备信息 敏感信息打码了)

image-20260706092653189

raw_packet包的数据

image-20260706092118237

这个函数的作用是把 native 的 raw_packet 复制到 Java byte[],再调用压缩逻辑,返回 gzip 后的 byte[]。

伪代码:

对应反编译核心:

注意:主函数传入该函数的是压缩前明文:

所以 hook 这个函数入口可以直接拿到完整 raw_packet

结合AI分析

image-20260706092537186

gzip压缩实际上是ByteArrayOutputStream + GZIPOutputStream

image-20260706092926511

该函数完成最终封装。

伪代码:

对应反编译核心:

info2_aes_cbc_encrypt_zero_iv 又能证明 IV 为 0:

aes函数 入参和出参

image-20260706093537784

Base64 函数 info2_base64_encode 使用标准字母表,并在剩余 1 或 2 字节时写 = padding。

Hook 验证:

image-20260706094815896

这个函数生成的原始数据叫 raw_packet。它由很多条小记录组成,每条记录就是一个 tag

可以把它理解成一个表:

每条 record 写进 raw_packet 时,格式是:

说明:

例如 payload 为 8 字节的 tag32,record 长度就是:

在拼包前,native 先把每条 record 放进固定大小的临时槽位。

槽位大小是:

布局可以还原为:

相关 helper:

所有 record 拼好后,会形成 raw_packet

当前版本号固定为:

所以包头的前 4 字节是小端序:

body_len 是后面所有 record 的总长度,不包含前 6 字节 packet header。

伪代码:

把混淆状态机去掉后,函数可以简化成下面这个流程:

真实 native 里分成几个阶段:

函数里有几组重要全局变量:

缓存存在的原因:

刷新条件大致是:

如果不需要刷新,本次调用只补充动态字段:

反编译关键点:

含义:

如果 timestamp_ms = 0x0000019f1cb27649,payload 就是:


[内核课程]《Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

上传的附件:
收藏
免费 0
打赏
分享
最新回复 (12)
雪    币: 158
活跃值: (5091)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习。
13小时前
0
雪    币: 7722
活跃值: (24839)
能力值: ( LV12,RANK:550 )
在线值:
发帖
回帖
粉丝
3
看看
13小时前
0
雪    币: 109
活跃值: (410)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
666
13小时前
0
雪    币: 9124
活跃值: (7517)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享
13小时前
0
雪    币: 8992
活跃值: (4625)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
感谢分享
13小时前
0
雪    币: 859
活跃值: (1250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
6
12小时前
0
雪    币: 859
活跃值: (1250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
6
12小时前
0
雪    币: 859
活跃值: (1250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
6
12小时前
0
雪    币: 4504
活跃值: (6977)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
10
6
10小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
6
9小时前
0
雪    币: 88
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
6
9小时前
0
雪    币: 158
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
66
2小时前
0
游客
登录 | 注册 方可回帖
返回