背景介绍

最近比较悠闲,于是没事研究了一下某东的h5st代码,2024年新鲜出炉的前端加密代码;

最大的惊喜并不是算法的复杂,在逆向破解代码的过程中,对js加密混淆有了新的认识;

于是心血来潮,回到这里,写一份研究总结,供技术交流分享。


代码分析

拿到的代码是h5st的4.3版本

使用开发者工具,显示的风格是这样的:

直接搜索关键字"h5st",整份文件里面就出现了2次,所以这里很容易找到出口。(PS:如果还有4.4版本,建议把这个关键字也加密,加大破解难度)

注意看10787行这个switch语法,在研究的过程中,这个语法出现概率非常高,它的作用就是把串行的代码用switch改变了代码的书写顺序,例如:

var a = 1;var b = a+1;var alert(b)j

加密之后就变成了:

var config = '3|1|2';var lines = config.split('|');var i = 0;switch(lines[i++]){case 1:var b = a+1;break;case 2:returnalert(b);case 3:var a = 1;break;
}

还有就是变量的混淆,总体上分为两类:

//原始代码
alert('hi');//加密后
functiona1(t,r){returnt(r)
}
functionb1(t,r){return ['','hi'][t-r];
}
a1(alert,b1(
699,698));

整个研究过程中,这些加密顶多是费点时间,要说最痛苦的,莫过于这一段:

    functionHv(t, r, n, e, o, i, u) {try{var a =t[i](u)
, c
=a.value
}
catch(t) {return voidn(t)
}
a.done
?r(c) : Kv.resolve(c).then(e, o)
}

这种不是串行的代码,类似无限递归的函数,理解起来最为费劲;

所以算法里面,最让人头痛的也是第8个关键参数,因为很难找到加密的原始字符串来源是什么。

庆幸的是,如果不是要求很高,那么可以按照它的格式,自己撰写一个,不需要去研究具体来源;

PS:如果想研究每个字段的计算过程,那么参考搜索的代码是"switch (t[kn(741, 0, p)] = t.next) "


算法总结

位置 字段名 说明 值格式 说明
1 time 时间字符串 20240131103354895 当前时间
2 fingerPrint 指纹 hnmy1t6fytuu1kt7 自定义算法,就是随机字符串删删减减,固定字符池:kl9i1uct6d
3 appId 应用编号 95cb4 业务页面的appId
4 token 令牌 tk02wad0d1bee41lMiszWWgySTRKO.. 下面这个对象的值.join('')

{
"magic": "tk",
"version": "02",
"platform": "w",
'adler32': "其它参数的校验",
"expires": "41",
"producer": "l",
"expr": "类似3+3+3+2x2的base64编码,生成sign会用到"
"cipher": "HmacSHA256结果,跟fp有关"
}

5 sgin 签名 c40d194fb4...

对请求参数进行HmacSHA256加密

加密使用的key生成算法

最初原始字符串:token + fp + timestamp + "22" + appid + "Z=<J_2";

从token中获取签名算法字符串,类似:3+3+3+2x2

数字表示用第一套加密,运算符,表示是拼接还是多种加密

6 version 算法版本 4.3 固定值
7 timestamp 毫秒时间戳 1706668434895 当前时间
8 sent 环境数据 bb7ef745bba685...

AES-128-CBC加密

原始字符串参考:

{
"sua": "Macintosh; Intel Mac OS X 10_15_7",
"pp": {},
"extend": {"wd": 0, "l": 0, "ls": 5, "wk": 0, "bu1": "0.1.9", "bu2": -1, "bu3": 43, "bu4": 0},
"random": "27_CACK7qU5",
"v": "h5_file_v4.3.3",
"fp": "xxx",
"bu1": "0.2.0"
}


测试过程

好不容易研究完准备验收

发现jd的所有接口都不验证这个参数


所以研究就到此为止了~

标签: none

添加新评论