js逆向案例-cookie反爬之akamai_2.0-上

admin 2024年12月5日16:57:44评论31 views字数 8807阅读29分21秒阅读模式
js逆向案例-cookie反爬之akamai_2.0-上

大家好,我是十一姐,一个分享爬虫相关知识点的程序猿

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上
提示!本文章仅供学习交流,严禁用于非法用途,文章如有不当可联系本人删除!
目录
js逆向案例-cookie反爬之akamai_2.0-上

由于本篇完整文章长达1.4w字,所以将分成三篇文章发布

本篇文章为目录到目录内容

视频操作晚些出可以关注b站时一十一姐

虽然大多数网站已经更新到3.0了,但是算法函数差不多,且存在2.0的cookie可以过3.0,那么我们先分析2.0的逆向流程,有时间再更新3.0的流程

本文仅供学习交流,选择了风控较低的网站逆向学习

本文章发布日距离研究时隔1月多,可正常响应

一、网址及目标数据

1、网站:https://www.dhl.com/cn-zh/home/tracking/tracking-supply-chain.html?submit=1&tacking-id=1232343

2、目标:爬取这个接口的数据 https://www.dhl.com/utapi?trackingNumber=1232343&language=zh&requesterCountryCode=CN&source=tt ,即如下图片内容的展示

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

3、直接模拟请求这个接口,响应状态码403,有反爬,目标让这个接口请求状态码响应返回200,且拿到响应文本内容js逆向案例-cookie反爬之akamai_2.0-上

二、分析接口反爬点(akamai执行过程)

1、utapi的请求方式与请求链接:get请求,参数为固定值,无反爬加密值

js逆向案例-cookie反爬之akamai_2.0-上

2、请求头:无疑似反爬加密值

js逆向案例-cookie反爬之akamai_2.0-上

3、请求头cookie:有个_abck的cookie可能是反爬参数,包括其它ak_bmsc、bm_sz、bm_sv的cookie

js逆向案例-cookie反爬之akamai_2.0-上

4、_abck的cookie:由WDsB接口链接响应头set-cookie返回

js逆向案例-cookie反爬之akamai_2.0-上

5、_abck的cookie:详细看下WDsB接口 , 发现是POST请求,请求参数有个加密值sensor_data

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

6、ak_bmsc、bm_sz的cookie,由首页请求链接响应返回

js逆向案例-cookie反爬之akamai_2.0-上

这两个cookie直接get请求首页响应返回的, 同时它还返回了个_abck的cookie,但和我们目标utapi接口的cookie并不是同一个

js逆向案例-cookie反爬之akamai_2.0-上
from curl_cffi import requestsurl = "https://www.dhl.com/cn-zh/home/tracking/tracking-supply-chain.html?submit=1&tacking-id=1232343"response = requests.get(url, impersonate="chrome124", timeout=10)res_cookies = dict(response.cookies)print(response, res_cookies)

7、bm_sv的cookie,由下面这个json链接返回

js逆向案例-cookie反爬之akamai_2.0-上

我们测试下如下代码,发现这3个ak_bmsc、bm_sz、bm_sv的cookie值我们都拿到了

js逆向案例-cookie反爬之akamai_2.0-上
from curl_cffi import requestsurl = "https://www.dhl.com/cn-zh/home/tracking/tracking-supply-chain.html?submit=1&tacking-id=1232343"response = requests.get(url, impersonate="chrome124", timeout=10)res_cookies = dict(response.cookies)print(response, res_cookies)url = "https://www.dhl.com/global/dhl/news-alerts.gnf.json"response = requests.get(url, impersonate="chrome124", cookies=res_cookies, timeout=10)res_cookies = dict(response.cookies)print(response, res_cookies)

8、虽然前面两个接口请求也拿到了_abck的cookie,但是带入cookie请求utapi接口请求,并不能响应状态码200,且在步骤4和步骤5我们分析得到,是由WDsB的接口返回的_abck的cookie才有用

js逆向案例-cookie反爬之akamai_2.0-上

9、同时我们发现WDsB这个接口请求了2次,第一次是GET请求,第二次是POST请求,

js逆向案例-cookie反爬之akamai_2.0-上

10、且第一次get请求的WDsB接口返回的内容是js内容,

js逆向案例-cookie反爬之akamai_2.0-上

11、第二次Post请求的WDsB接口返回的内容是success:true,这个似乎是验证cookie :_abck是否正确的,所以我们接下来的目标也是拿到WDsB响应是success后的cookie: _abck

js逆向案例-cookie反爬之akamai_2.0-上

12、既然WDsB的第一次内容是js内容,我们需要找下它的js链接是哪里来的

js逆向案例-cookie反爬之akamai_2.0-上

13、我们在首次首页请求的响应文本里面找到了WDsB接口js链接的由来

js逆向案例-cookie反爬之akamai_2.0-上

14、从首页请求取js链接的url,我们多次运行发现js链接url是动态变化的

js逆向案例-cookie反爬之akamai_2.0-上
from curl_cffi import requestsimport reurl = "https://www.dhl.com/cn-zh/home/tracking/tracking-supply-chain.html?submit=1&tacking-id=1232343"response = requests.get(url, impersonate="chrome124", timeout=10)res_cookies = dict(response.cookies)print(response, res_cookies)js_url = 'https://www.dhl.com' + re.search('type="text/javascript"  src="(.*?)">', response.text).group(1)print(js_url)

15、同时我们在网页上也能发现无法再次找到WDsB的接口链接,而是换成了其它的,也就是说js链接动态变化,同时可以自行观察的js文件内容混淆的也是动态变化的,不变的是算法加密逻辑

js逆向案例-cookie反爬之akamai_2.0-上

16、为了后面方便分析同一份js代码,我们需要保存一份首页的html文件,然后用overrides或者fiddler替换html的方法,保证始终分析的是同一份js代码,方便扣代码算法逻辑 ,这里直接鼠标右击首页接口Override content

js逆向案例-cookie反爬之akamai_2.0-上

17、由于步骤16我们固定了首页html,所以接下来我们的js请求链接也会同时固定,不再动态变化,从步骤5我们知道是post请求的那个WDsB链接能返回我们需要的_abck的cookie,所以要成功模拟那个接口请求,那么就要分析这个接口需要的请求参数sensor_data

js逆向案例-cookie反爬之akamai_2.0-上

18、通过xhr断点定位sensor_data的生成位置,如图我们打上xhr断点,清缓存后,刷新网页,看到了zfT的参数包含sensor_data

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

三、逆向分析参数sensor_data

1、定位sensor_data的生成位置可以通过xhr断点拦截js链接 , 如图我们定位到了sensor_data的生成即zfT

js逆向案例-cookie反爬之akamai_2.0-上

2、而zfT是由FIT拼接而成 ,这里的FIT就是sensor_data

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

3、搜索FIT=发现有12个匹配到,可疑位置打上断点清缓存再次刷新网页

js逆向案例-cookie反爬之akamai_2.0-上

4、第一次断住的位置是,FIT=0,这是初始赋值的地方

js逆向案例-cookie反爬之akamai_2.0-上

5、同时FIT最后生成的位置在这里,也就是从初始到这里的中间流程就是FIT的生成流程

FIT = jr(jr(jr(jr(jr(jr(jr(jr(jr(jr(MxT, wxT), ZfT[AA()[Lc(Dq)].apply(null, [Vt, Br(Uc), x8])]), wxT), O2T[zB]), wxT), O2T[Uc]), wxT), Vg), wxT), FIT);
js逆向案例-cookie反爬之akamai_2.0-上

6、怎么扣FIT生成值,要么倒着扣,要么正着扣,继续调试,会发现第二次断点断在了这里,简单分析了下,M2T是60位数组,然后和其它几个似乎是拼接起来的

js逆向案例-cookie反爬之akamai_2.0-上

四、扣js算法代码加密详细步骤

1、开始扣js代码,我们先逆着扣js代码,如图手动解混淆还原如下,当前我们差FIT的由来

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上
function get_sensor_data(){    // var zfT = (EM(typeof BA()[zd(HA)], 'undefined') ? BA()[zd(RO)].apply(null, [tB, lA]) : BA()[zd(mV)](f9T, tg))[S1()[MA(ld)](nh, Q0)](FIT, AA()[Lc(fD)](wp, FA, wB));    // (true ? '{"sensor_data":"': BA()[zd(mV)](f9T, tg))['concat'](FIT, '"}');    var zfT = '{"sensor_data":"' ['concat'](FIT, '"}');    return zfT}

2、由目录三的步骤5我们知道FIT最后的生成位置,手动解混淆还原如下,其中wxT是分号,现在我们还差O2T、Vg、FIT的由来

js逆向案例-cookie反爬之akamai_2.0-上
//  FIT = jr(jr(jr(jr(jr(jr(jr(jr(jr(jr(MxT, wxT), ZfT[AA()[Lc(Dq)].apply(null, [Vt, Br(Uc), x8])]), wxT), O2T[zB]), wxT), O2T[Uc]), wxT), Vg), wxT), FIT);// jr(jr(jr(jr(jr(jr(jr(jr(jr(jr(2, wxT), 0), wxT), O2T[zB]), wxT), O2T[Uc]), wxT), Vg), wxT), FIT)// "2" + ';' + 0 + ';' + O2T[0] + ';' + O2T[1] + ';' + Vg + ';' + FIT;
js逆向案例-cookie反爬之akamai_2.0-上
function get_sensor_data(){    FIT = "2" + ';' + 0 + ';' + O2T[0] + ';' + O2T[1] + ';' + Vg + ';' + FIT;    var zfT = '{"sensor_data":"' ['concat'](FIT, '"}');    return zfT}get_sensor_data()

3、全局搜索O2T =  , 搜索定位到如下var O2T = fTT || g4() ,其中fTT是undefined ,说明O2T = 是g4()函数,进入到g4()函数

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

4、发现g4()函数如下,手动解混淆换下如下,其中有些常量我们这里写死了固定值,后续可能还需要多次比对验证常量是固定值;同时这里我们发现它取了document.cookie['bm_sz'],所以我们改成传参的形式

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上
function g4(bm_sz) {    var gJ = 8888888,        qp = 7777777; // 写死固定值    var J5 = [gJ, qp];    var GQ = bm_sz    var Aq = Xm['decodeURIComponent'](GQ)["split"]('~');    if (Aq["length"] >= 4) {        var kq = Xm["parseInt"](Aq[2], 10);        var m0 = Xm["parseInt"](Aq[3], 10);        kq = Xm['isNaN'](kq) ? gJ : kq;        m0 = Xm["isNaN"](m0) ? qp : m0;        J5 = [kq, m0];    }    var nG;    return nG = J5, nG;}

5、验证下g4()函数传入相同的bm_sz,出参是否相同,出参相同,g4()函数无误

js逆向案例-cookie反爬之akamai_2.0-上

6、现在还差Vg和FIT的由来

js逆向案例-cookie反爬之akamai_2.0-上
function get_sensor_data(bm_sz){    var O2T = g4(bm_sz);    FIT = "2" + ';' + 0 + ';' + O2T[0] + ';' + O2T[1] + ';' + Vg + ';' + FIT;    var zfT = '{"sensor_data":"' ['concat'](FIT, '"}');    return zfT}var bm_sz = '5FED1A3F67960E11A9FA43C5BE5B3468~YAAQnuBb2taNz2qSAQAATkERlBmfh1YIrwFk3EYaAGiyZsj3sgNaTicXx28L7Ys8mj7OSUlSg+qSvsCJLZszM3bkYX6sSVSoaYDdRACRU8OCIZ2oyKI1GZ30I6XfsfbGhfEwGzBQCozr0pJf9mAGqOcvlNdw2M8forrU4ScI/PWYsMh1UrBxrUpQSHvqEQ+bZTKibFCNCuWX0J2ePdW30WZiDvPgCASbHBypI5Yvkb1Bj82h66RHPStFogRHtNFSI8s5tOtzR/p2OpTSWVwWIACO0kKpXpI+Xz7rK2N4ivZxqC0F49DSIkK7djh3q6p3/rHcuxNVeH9l7ReOiX06fq5kHEfvrQPPPQBKANsxeY+4colUWJgbb8JPjxYeAA6EH4ChjkSl1/EPvOtkhqMxl9vTpDCPaBTKsx//EPkte57rnzqT8Zt7BtLDN7Rk47rou/jSO81mY25eHnA=~4337970~427345'console.log(get_sensor_data())

7、全局搜索Vg =  , 搜索定位到如下,手动解混淆还原后,发现v8() - czT在动态变化,这是因为v8()是当前时间戳,czT也是时间戳,它是一个时间差值;Vg值正常大概是'26,0,0,2,10,0' , 这里计算的全是函数执行的时间差值,有几个0的我也直接写死了(但是但是如果后面过不掉的话,我们需要和源代码保持一致的逻辑,把这些时间差的逻辑再加回来)

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上
// var Vg = BA()[zd(sr)].apply(null, [C2, gV])[S1()[MA(ld)](nh, MsT)](cR(v8(), czT), S1()[MA(v6)](Zq, Gd))[S1()[MA(ld)].apply(null, [nh, MsT])](J2T, S1()[MA(v6)](Zq, Gd))[S1()[MA(ld)](nh, MsT)](YfT, S1()[MA(v6)](Zq, Gd))[S1()[MA(ld)](nh, MsT)](tNT, S1()[MA(v6)](Zq, Gd))[S1()[MA(ld)](nh, MsT)](kXT, S1()[MA(v6)](Zq, Gd))[S1()[MA(ld)](nh, MsT)](U3);// var Vg = ""["concat"](cR(v8(), czT), ",")["concat"](J2T, ",")["concat"](YfT, ",")["concat"](tNT, ",")["concat"](kXT, ",")["concat"](U3);//  var Vg = "" ["concat"](v8() - czT, ",")["concat"](0, ",")["concat"](0, ",")["concat"](tNT, ",")["concat"](kXT, ",")["concat"](0);

J2T差值是0

js逆向案例-cookie反爬之akamai_2.0-上

YfT差值是0

js逆向案例-cookie反爬之akamai_2.0-上

U3差值是0

js逆向案例-cookie反爬之akamai_2.0-上

8、现在还差czT、tNT、kXT、FIT的由来

js逆向案例-cookie反爬之akamai_2.0-上
function v8() {    if (Xm["Date"]["now"] && typeof Xm["Date"]["now"]() === 'number') {        return Xm["Date"]["now"]();    } else {        return +new(Xm["Date"])();    }}function get_sensor_data(bm_sz){    var O2T = g4(bm_sz);    var Vg = "" ["concat"](v8() - czT, ",")["concat"](0, ",")["concat"](0, ",")["concat"](tNT, ",")["concat"](kXT, ",")["concat"](0);    FIT = "2" + ';' + 0 + ';' + O2T[0] + ';' + O2T[1] + ';' + Vg + ';' + FIT;    var zfT = '{"sensor_data":"' ['concat'](FIT, '"}');    return zfT}var bm_sz = '5FED1A3F67960E11A9FA43C5BE5B3468~YAAQnuBb2taNz2qSAQAATkERlBmfh1YIrwFk3EYaAGiyZsj3sgNaTicXx28L7Ys8mj7OSUlSg+qSvsCJLZszM3bkYX6sSVSoaYDdRACRU8OCIZ2oyKI1GZ30I6XfsfbGhfEwGzBQCozr0pJf9mAGqOcvlNdw2M8forrU4ScI/PWYsMh1UrBxrUpQSHvqEQ+bZTKibFCNCuWX0J2ePdW30WZiDvPgCASbHBypI5Yvkb1Bj82h66RHPStFogRHtNFSI8s5tOtzR/p2OpTSWVwWIACO0kKpXpI+Xz7rK2N4ivZxqC0F49DSIkK7djh3q6p3/rHcuxNVeH9l7ReOiX06fq5kHEfvrQPPPQBKANsxeY+4colUWJgbb8JPjxYeAA6EH4ChjkSl1/EPvOtkhqMxl9vTpDCPaBTKsx//EPkte57rnzqT8Zt7BtLDN7Rk47rou/jSO81mY25eHnA=~4337970~427345'console.log(get_sensor_data())

9、全局搜索发现tNT、kXT分别是函数FIT = Sw(AZ, [FIT, O2T[Uc]]);执行的时间差值 FIT = Vk(FIT, O2T[kV[rh]]);的时间差值

js逆向案例-cookie反爬之akamai_2.0-上
    // 函数时间差    var tNT = v8();    FIT = Sw(AZ, [FIT, O2T[1]]);    tNT = v8() - tNT;    var kXT = v8();    FIT = Vk(FIT, O2T[0]);    kXT = v8() - kXT;

10、网页上调试执行时间差[tNT,kXT]大致是[1, 4]

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

11、所以[tNT,kXT]大致是[1, 4]这里的值我又暂时写死了

js逆向案例-cookie反爬之akamai_2.0-上

12、同理,czT也是初始的时间戳,然后执行了一大串逻辑函数后到了Vg计算函数运行时间差,多次调试发现这个v8() - czT时间差值差不多是25~30之间

js逆向案例-cookie反爬之akamai_2.0-上

13、所以这里我们也给了个随机值,这样步骤8的czT、tNT、kXT、FIT的由来,只剩FIT的由来不清楚了

js逆向案例-cookie反爬之akamai_2.0-上

14、我们继续研究,进入Vk函数

js逆向案例-cookie反爬之akamai_2.0-上

15、Vk函数手动解混淆还原如下,右侧截图里面有成var zl = (qS >> 8) & 65535;

js逆向案例-cookie反爬之akamai_2.0-上

16、其中 Vk里面还有些变量Kq 、IW需要补充上

var Kq = new (Xm[S1()[MA(sv)].apply(null, [ht, JG])])(lM);var Kq = new (Xm['Array'])(127)var IW = "";
js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

17、传入相同的参数,检验Vk函数输出结果一致,Vk函数无误 ,可以发现Vk函数是将明文加密的一个流程

js逆向案例-cookie反爬之akamai_2.0-上

18、继续进入到Sw函数里面

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

19、手动解混淆还原如下,传入相同的参数,验证结果输出一致,Sw52无误

js逆向案例-cookie反爬之akamai_2.0-上

20、继续往上研究,手动解混淆如下

js逆向案例-cookie反爬之akamai_2.0-上
FIT = jr(jr(jr(jr(jr(LzT, lIT), HPT), B2T(E4(FIT), Qt)), HPT), FIT);FIT = LzT + lIT + HPT + (E4(FIT)^24) + HPT + FIT;FIT = jr(jr(jr(jr(nmT, HPT), nmT), HPT), FIT);FIT = "2" + HPT + "2" + HPT + FIT;

21、现在还差LzT 、lIT 、E4、 HPT 、FIT的由来

js逆向案例-cookie反爬之akamai_2.0-上

22、LzT搜索定位如下,这里的扣代码算法逻辑和前面步骤一样,手动解混淆还原验证,如下2张图

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

23、lIT还原如下,其中这里写死了个值,后面如果换版本需要留意是否一样, 留意变化

js逆向案例-cookie反爬之akamai_2.0-上

24、E4函数如下

js逆向案例-cookie反爬之akamai_2.0-上

25、HPT先定义了个字符串,然后HPT = zg(M2T, 2, false);  

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

26、我们还发现,zg这个函数传入的M2T参数,它是一个60位的数组,包含了一些环境信息,这里我们先写死M2T,后面逐个研究由来

js逆向案例-cookie反爬之akamai_2.0-上

27、手动解混淆zg函数还原如下,传入相同的参数,验证结果输出不一致,因为函数本身里面有很多随机数,所以这个问题不大,后面如果过不了风控,我们再回来对比研究

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上

28、补完上面的内容后,这个时候我们已经能生成sensor_data了,如下

js逆向案例-cookie反爬之akamai_2.0-上

29、其中在扣js代码中,我们写死了一些值,后面如果过不了接口,还得回来反复核对,现在我们还剩M2T这个60位数组的研究, 到目前为止,整个加密算法200多行,重点是60位数组的生成逻辑

js逆向案例-cookie反爬之akamai_2.0-上

30、M2T在这里开始生成

js逆向案例-cookie反爬之akamai_2.0-上

31、我们把上面的代码整理下,得到下面的内容,然后逐步分析M2T的各个数组的值的来源

js逆向案例-cookie反爬之akamai_2.0-上

32、从60位数组里面再次还原下,发现近一半的是固定变量可以直接写死,剩下的需要研究的变量的由来有29个,我们需要一一研究由来,大多数是环境检测ua、屏幕尺寸、页面的input信息、请求页面地址/canvas/wbgl/字体指纹/陀螺仪/事件/鼠标轨迹/函数运行时间差

js逆向案例-cookie反爬之akamai_2.0-上

33、把要研究的变量单独拧出来,发现其它值似乎一直是固定的,有5个特别长的在动态变化,我们先研究这5个看看能不能出结果

js逆向案例-cookie反爬之akamai_2.0-上

本篇文章同款调试的html与js文件在知识星球,无成品代码

The End~ 进群交流扫码加vx

js逆向案例-cookie反爬之akamai_2.0-上
js逆向案例-cookie反爬之akamai_2.0-上
The End~ 更多爬虫交流可加入星球学习
js逆向案例-cookie反爬之akamai_2.0-上

原文始发于微信公众号(逆向OneByOne):js逆向案例-cookie反爬之akamai_2.0-上

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月5日16:57:44
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   js逆向案例-cookie反爬之akamai_2.0-上https://cn-sec.com/archives/3471249.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息