首页
社区
课程
招聘
[原创]一套自定义 Token 算法逆向分析:设备指纹、变种 SHA、HMAC 与双重 AES 加密链路
发表于: 23小时前 535

[原创]一套自定义 Token 算法逆向分析:设备指纹、变种 SHA、HMAC 与双重 AES 加密链路

23小时前
535

这不是一套单纯的“参数签名算法”,而是一条把业务参数、设备指纹、时间戳、随机扰动和多层加密混合在一起的 Token 生成链路。

在很多移动端或接口安全场景里,Token 并不是简单地由几个参数做一次 HMAC 就结束了。
有些方案会把设备信息、时间戳、随机数、自定义编码逻辑、标准密码学算法和非标准扰动算法混合在一起,构造出一条复杂的签名与加密链路。

本文分析的就是这样一套算法。

它的特点很明显:

从工程视角看,这套算法的复杂度明显高于常见的“参数排序 + HMAC”模式。
从逆向和迁移视角看,它真正难的地方,往往也不是 AES 或 HMAC,而是那些“看起来像标准算法、实际上已经被改造过”的细节,加上ollvm 和vmp 更让人想原地飞升。

如有侵权请联系我下架

如果只看结果,这套算法的目标很简单:生成一个最终的 Token 字符串

但在内部,它实际上分成了四大部分:

最终 Token 的结构大致如下:

整套算法的输入主要可以分成两类。

最核心的业务参数通常是登录信息,例如:

这部分主要参与签名计算。

它决定的是:当前这个 Token 是为谁生成的、用于什么业务请求。

另一部分是设备相关信息,例如:
包名

这些参数不会简单明文拼接,而是先被编码成一个二进制块。
这个二进制块会同时进入:

也就是说,设备信息不是“装饰字段”,而是这套算法的核心组成部分。

这一层可以理解成“设备指纹封装层”。
它不是标准 JSON、XML,也不是普通的 URL 编码,而是一套自定义二进制封装逻辑。
编码流程大致如下

所有设备参数先按 key 排序,保证顺序稳定。

每个 key 在写入时,会额外叠加一个随机高字节。
这意味着即使 key 本身固定,最终写入值也带有一定随机性。

每个 value 的字符不是直接写入,而是逐字节做 nibble 级别变换,再写入 value 区。

编码后的 key 和 value 会被分别拼接,形成主体数据。

在主体前面还会加上一段固定头、随机字节,以及一些固定零填充区。

然后从固定偏移位置开始,对后续内容执行一次自定义 Murmur Hash。

最后把算出的 Hash 写回到固定位置。
这样就得到一个最终的设备参数二进制块。
这个数据块既是后续签名的一部分,也是设备密文生成的原始输入。

签名部分是这套方案最容易误判的地方。
表面上看它包含 HMAC,但实际上 HMAC 只是其中一个环节。

完整流程大致如下。

首先构造一个 signatureVector。

它不是单一业务字符串,而是把下面几类信息混合起来:

可以近似理解为:

这里的时间戳也不是直接十进制字符串,而是经过:

之后才参与拼接。

接下来会对 signatureVector 做一次 SHA 运算。
但这里的关键在于:它不是标准 SHA-256

这一步被改造过的地方包括:

这意味着,哪怕算法名字看起来像 SHA-256,也不能直接替换成标准库。
这一步输出的是 32 字节摘要。

摘要不会整体参与下一步,而是:

也就是只使用中间的一部分内容作为后续输入。
这种“摘要后再截取”的做法,会进一步增加复现时的细节敏感度。

将上一步得到的截断字符串作为输入,再执行一次标准 HMAC-SHA256。
这一阶段使用固定 HMAC Key。
也就是说,标准密码学组件确实存在,但它是建立在一套自定义摘要处理之后的。

HMAC 结果转成大写十六进制后,再在前面拼接固定前缀:

然后只取前固定长度字节,形成新的待处理向量。

这一段待处理向量不会直接输出,而是会进入一套自定义混淆流程。

其思路是:

这一层主要由以下操作构成:

最终得到签名密文段。

除了签名之外,设备参数编码块本身还会被单独加密,生成最终 Token 中的另一大段内容。

可以把它理解成:设备密文段生成链路。

原始设备参数块首先进入 zlib 压缩。

这里的目的不仅是缩短长度,更重要的是打散原始结构,让明文特征不再直接可见。

压缩完成后,不会立刻进入 AES,而是先做一轮链式异或变换。

这一过程的特点是:

因此它比普通异或更复杂,也更难从局部观察规律。

这一步非常有特点。
算法会读取某个尾字节的低 4 位,并据此决定进入哪条分支。

不同分支中可能出现的操作包括:

换句话说,这里不是一条固定算法,而是一套多态扰动机制。

完成多态扰动后,数据会先做 16 字节对齐,然后执行第一层 AES:

使用固定 Key 和固定 IV。

第一层 AES 结束后,并不会直接输出,也不会立刻 Base64。
而是会遍历每个字节,对最低位做一次翻转处理。
这一步并不是标准密码学流程,而是额外插入的一层位级扰动。

之后再执行第二层 AES:

这一层使用另一组固定 Key 和 IV。
所以设备数据实际上经历了两层 AES,而且中间还夹着一层非标准位翻转处理。

第二层 AES 后,算法还会再做一次逐字节最低位翻转。

这个细节很容易在迁移时被忽略,但只要漏掉一次,最终密文就会完全不一致。

经过上述全部步骤后,结果再做 Base64 编码,得到最终的设备密文段。

到这里,算法已经得到两段最重要的数据:

再配合时间戳片段和固定头尾,就得到最终 Token。

结构如下:

固定前缀
用于标记这类 Token 的版本或类型。

时间戳片段
提供时效性信息,也间接参与签名一致性。

select
来自签名处理中间过程的提取值,可以看作一个小型控制标记。

签名密文段
负责将业务参数、设备参数和时间戳绑定在一起。

设备密文段
负责封装和隐藏设备指纹信息。

固定后缀
作为格式尾标识。

从设计角度看,这套算法有几个非常明显的特点。

常见接口签名可能只是:

而这里实际包含:

这是一种明显的“多层混合式方案”。

设备参数不仅参与最终密文,而且直接参与签名向量构造。
这意味着:

同样的业务参数,在不同设备参数下会得到不同 Token。

因此它天然带有较强的设备绑定特征。

时间戳并不是简单地附加在末尾,而是深入参与了:

所以它属于典型的时效型 Token,不适合长期复用。

参数编码过程中存在随机内容,例如:

key 的高字节扰动

固定头之后的随机字节

这说明即使业务输入一致,输出也不一定逐次完全相同。

这类算法最难处理的,不一定是完全陌生的自定义逻辑,而是那些“长得像标准实现”的部分。
例如:

这类实现最容易让人在迁移时掉坑。

如果把它实现成 Java 项目,比较合理的结构一般是:

参数对象层
统一管理:

等业务和设备字段。

参数编码层

负责把设备参数组装成原始二进制块,并计算回填自定义 Hash。
Hash 层
负责:

自定义 Murmur Hash

自定义 SHA

加密工具层
负责:

总入口服务层

统一暴露一个总方法,例如:

由这个入口把全部步骤串起来,直接返回最终 Token。

如果用一句话概括,它就是:

将业务参数和设备参数先编码成二进制块,再结合时间戳构造签名向量,通过自定义 SHA 与 HMAC 生成签名密文,同时对设备数据进行压缩、多态扰动和双阶段 AES 加密,最后拼接成一个具备设备绑定和时效特征的 Token。

这类算法真正难的地方,从来不只是“用了什么密码学算法”,而是:

参数如何编码

在迁移、重写、逆向分析或跨语言复现时,真正决定结果能否一致的,通常就是这些最容易被忽略的细节。

也正因为如此,这类 Token 方案往往看上去只是“签名 + 加密”,真正拆开后才会发现:
它其实是一套经过多层封装和扰动的复合算法链路。

测试通过性
图片描述
图片描述
图片描述
图片描述

000x_ + 时间戳片段 + select + 签名密文段 + 设备密文段 + _xxxxx_
000x_ + 时间戳片段 + select + 签名密文段 + 设备密文段 + _xxxxx_
{"loginId":"xxxxxxxx"}
{"loginId":"xxxxxxxx"}
javaDataString + "&0xxxx_" + kvPair + "&" + timestampHex
javaDataString + "&0xxxx_" + kvPair + "&" + timestampHex
xxxxxx + HMAC_HEX
xxxxxx + HMAC_HEX
AES/CBC/NoPadding
AES/CBC/NoPadding
AES/CFB/NoPadding
AES/CFB/NoPadding
000x_
+ 时间戳片段
+ select
+ 签名密文段
+ 设备密文段
+ _xxxx_
000x_
+ 时间戳片段
+ select
+ 签名密文段
+ 设备密文段
+ _xxxx_
XXXAPI.XXXX(payload)
XXXAPI.XXXX(payload)

这不是一套单纯的“参数签名算法”,而是一条把业务参数、设备指纹、时间戳、随机扰动和多层加密混合在一起的 Token 生成链路。


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 22小时前 被一只笨猫编辑 ,原因:
收藏
免费 46
支持
分享
412????????
最新回复 (12)
雪    币: 3288
活跃值: (3100)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
111111111111
22小时前
0
雪    币: 2639
活跃值: (7219)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
666
22小时前
0
雪    币: 4
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
感谢分享
21小时前
0
雪    币: 6
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
感谢分享
21小时前
0
雪    币: 730
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
,666
12小时前
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
感谢分享
5小时前
0
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
666
4小时前
0
雪    币: 390
活跃值: (1398)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
9
感谢分享
4小时前
0
雪    币: 212
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
66
4小时前
0
雪    币: 155
活跃值: (4246)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
感谢分享 
3小时前
0
雪    币: 260
活跃值: (450)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
66
1小时前
0
雪    币: 0
活跃值: (1511)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
666
1小时前
0
游客
登录 | 注册 方可回帖
返回