吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 865|回复: 10
收起左侧

[Web逆向] 看小白如何一步步逆向acs-token参数

[复制链接]
szh12123 发表于 2026-1-12 00:45
本帖最后由 szh12123 于 2026-1-12 00:54 编辑

本文章中所有内容仅供学习交流使用不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!若有侵权,请联系作者删除。

目标网址:aHR0cHM6Ly9ndXNoaXRvbmcuYmFpZHUuY29tLw==

最近有点无聊,就随便找了个网站玩了下逆向,找到headers中有个关键参数acs-token,一时没忍住就研究了下生成逻辑,主要是有点python基础,但java还没咋学过,属于又菜又爱玩,最后居然分析出来了;现在把分析思路整理一下交流学习,因为非专业纯爱好,如有不足还请指教;

一、先说结论,至于这些参数是如何得到的,这个后面讲;

目标参数:
acs-token:1768XXXXX6745_1768XXXXX 8101_GFl7CP…省略…zx23Z0=
分析结果:acs-token: “动态时间戳(两小时一更换)” + “_” + “当前时间戳” + “_” + “AES加密
AES加密:
key值:16位动态值(两小时一更换)
iv值:16位固定值;
加密模式:CBC
数据明文:
{"0":"61889XXXXX5217","ua":"Mozilla/5.0XXXXX537.36","url":"https://XXXXX.com/","platform":"Win32","d1":"","clientTs":1768XXXXX 5218,"version":"1.0.2.1","extra":"","odkp":0}
其中:
"0":由随机数拼接时间戳后七位;
"url": referer网址
"clientTs": 当前时间戳,与acs-token当前时间戳相同
其他都是固定值;

二、接下来就是一步步分析的过程,包括试错:

首先直接搜索acs-token,就发现了赋值代码;
1.png

然后找到getParisAcessToken()方法,给几个方法都打上断点,几轮运行最后发现getSign()生成的sign是最后的密文;
2.png

然后使用单步调试和跳过函数,跟到了这里,发现他一直在循环,S不断+1,s=9之后他就跳出去了,然后这里的文件名是acs-2108.js,果断猜测就是acs-token生成的位置,
3.png

所以我在s=9时开始单步调试,结果发现他又回到了上面所示的地方,打开调用堆栈然后发现他是个嵌套,
4.png

好家伙,这样一步一步跟不得跟到天荒地老;果断放弃,另谋出路,想到加密的关键词encrypt,搜索之后发现一个有点像加密参数的方法,
5.png

但是没有基础知识所以看不懂意思,所以咨询了AI,AI告诉我这是AES加密函数的实现,还把每个参数的意思都翻译出来了,确认这就是创建加密的地方,然后在末尾打上断点,得到了每个参数的值,
6.png

发现ciphertext、key、iv都是数组,很奇怪,想到可能是加密,又咨询了AI,AI告诉我这是 CryptoJS 的 WordArray 对象,表示加密后的字节数据,然后还贴心的写了个转换成字符串的方法,key和iv还原后都是16位的字符串,ciphertext没有解出来,只留下了一串很长的base64,其他几个参数看不太懂就先没管了;随便看了眼这时的调用堆栈,
7.png

幸好之前及时放弃,不然得跟到啥时候;然后单步之后到了这里,
8.png

这不就是明牌了吗,e是明文,t是key,n是iv还有mode啥的,虽然不知道为啥就变成这样了;然后继续单步,发现他又到了这里,我这里使用跳过,找到一个可疑的数据,有点像加密后的数据,然后又跟明文在一起,后面不小心跳出去了(当然过程中有很多次这样的不小心,才一步步逼近关键位置),发现确实就是acs-token时间戳后面跟着的密文,
9.png

现在我手里有了key、iv、密文,我就咨询AI通过三种参数进行解密,AI给了我一个尝试AES各种模式的解密代码,最后成功还原为明文,并且知道了是CBC模式,继续跟到这里的话,会发现他的拼接过程,将前两个时间戳和AES密文拼接,并且还能看到key和iv,
10.png

接下来就是研究明文的结构了,
{"0":"61889XXXXX5217","ua":"Mozilla/5.0XXXXX537.36","url":"https://XXXXX.com/","platform":"Win32","d1":"","clientTs":1768XXXXX 5218,"version":"1.0.2.1","extra":"","odkp":0}
在多次获取明文的过程中,发现"0"的值是变化的,暂时没有看出规律;"clientTs"值也是变化的,但一眼时间戳,验证一下就是当前时间,没啥好说的;其他都是固定值;
经过之前多次调试发现的规律,他总是在M-c.M-n-V几个方法中循环,于是我就认真看了这几个方法的运行流程,结果就是先是c.M()定义了个a是数组,s赋值关键数据,然后运行n()n()中主要是运行V()s.s1就是将a中数值遍历完,然后看到了V(),里面就是一系列操作然后把数据返回到s里面;最开始我以为是搞的啥加密算法,里面一抹多代码,后来AI告诉我是虚拟机 (VM) 的指令执行器;原来就是把a里面的指令数组执行一遍; 11.png

接着我们来找"0"参数的生成位置,我发现V()中很多都是n.g结尾,而n就是之前的s;所以我开始查看每次循环的s中的值,发现他都是s.gs.h值的更新,结果在这里看到了这个,
12.png

g中的值是h1和h3拼接后的值,g又刚好就是"0"的值,所以在s等于27的时候执行的代码就是拼接,那就重新调试跟着s=27的代码走一遍(后来发现直接查看a中序号27时的数组,接着查看V()中对应的case也是一样的),找到了拼接代码,
13.png

然后往前回溯就找到了h1和h3是如何生成的,从s=0开始到s=27就是生成"0"参数值的全过程,其实从s=0开始直接看s.g和s.h的值就能猜到是如何运算的,都不用去看代码,
14.png

先是创建一个随机数,截取序号2开始的字符串,再创建一个时间戳毫秒为单位,截取序号6开始的字符串,最后拼在一起;
至此AES明文解析完成,试着加密解密一下,完全一致;

接着还是上面的方法不断查看s的值和调用堆栈找到了key创建的过程,同时还理解了一些数组代码的操作,比如[8,3]就是把3赋值到当前值,[64,4]就是列表序号4的值减去当前值,[3,4]就是把当前值赋值给列表序号4的值;
总结就是现有一个16位的列表数值,每个数经过减法和异或运算,生成了新的数值,再由新的数值(chr)转换为对应的字符串,到这里生成逻辑就清楚了,
key_list= [(init_list - i - temp) ^ i for i in range(len(init_list))]
key =''.join([chr(i) for i in key_list])
其中temp是一个两小时更新的动态值,init_list是最初的列表值,也会更新,位置和为啥是两小时更新马上就会讲了;

接下来本应该直接找最初的16位列表值,结果我去找动态时间戳去了,导致我踩了个坑浪费了很多时间,我在不断回溯调试查看S的过程中,发现他是直接从列表中提取出来的,并没有找到生成过程,并且在不断查看调用堆栈的时候,发现这个参数一直都在,只是隐藏的比较深,
15.png

以至于我从最开始的M()都找到了参数的路径:M()-[[Scopes]]-0-n-i-r-M()-[[Scopes]]-0-n-i-m,因为在s的循环步骤里面呆了很久,所以大概知道了他的调用步骤,还有就是阅读下面这个方法,得到了启示,
16.png

这里花了很多时间,虽然最终找到了位置但是没啥用,因为他本身就存在了,于是乎我直接搜了这个时间戳,找到了关键代码,key和iv都在里面,不过是用数组的形式,包括其他一些固定参数(我觉得无关紧要就没一个一个找了),
17.png

原始key列表数值共16位:
18.png

iv固定值共16位:
19.png

至于为啥我发现是两小时一更新,因为我第二天发现解不出来了,一搜索发现原来的key值变了,我将两个js文件用Beyond一对比,发现确实有些微小差别,
20.png

然后我把目光放在了acs-2108.js?_=245575网址的参数上面,起初不知道是啥意义,跑了一遍也没发现在哪加的这个参数,问了AI他告诉我是因为浏览器会缓存文件,如果不加就默认之前的文件,数据就不会更新,也不知道是不是运气好,我用时间戳一除,整数部分刚好是7200,再一对比前后不同文件的参数变化,这不就是2小时吗;但我还是耐心去找了代码,这里也花了不少时间去一步一步跟,看他在哪一步发送了网址,结果是在过程中发现生成了clientCacheTTL: 120这样一个参数,但结果又没有这个参数,让我产生了怀疑,最终发现了关键代码,这个120就表示的是分钟数:
21.png

这样只需简单正则即可提取最新的数据列表,然后每个参数的相对位置又是固定的,这样就可以把动态时间戳、动态key、iv都提取出来,将上面的各个成果合在一起,就完成了整个加密过程,然后这里我又踩了个小坑,我发现生成的acs-token对不上,然后检查一遍参数都是相同的,最后锁定在AES明文字符串中,我发现python的字典转字符串有空格,而本身其实是没有的,于是AI给了我下面的代码去除空格,
json.dumps(params,separators=(',',':'),ensure_ascii=False)
最终运行之后完美符合,分析结束。

免费评分

参与人数 5吾爱币 +3 热心值 +5 收起 理由
liuxuming3303 + 1 + 1 谢谢@Thanks!
metoo2 + 1 + 1 用心讨论,共获提升!
yxzzz666 + 1 我很赞同!
0504yck + 1 热心回复!
buluo533 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

炫迈 发表于 2026-1-12 08:54
这种一步步跟js的功夫现在很多新人已经不愿意做了,现在大厂都喜欢用这种VM保护方式,你用AI辅助分析的方法很聪明,节省了不少时间,key两小时更新这个细节抓得很准,很多新手会忽略时间因子导致第二天代码失效,老哥建议你下次可以试试用AST去还原混淆代码,这样比手动跟堆栈快很多,还有那个字典空格问题太典型了,python的json序列化和js的JSON.stringify确实有这个坑,你的分析思路很清晰
pojiestudy 发表于 2026-1-12 08:07
xxsoul 发表于 2026-1-12 09:30
推荐楼主看看这个系列:写给开发人员的使用密码学,对以后类似的case会很有帮助
逆劫古修 发表于 2026-1-12 10:25
受教了,我也来试一试
 楼主| szh12123 发表于 2026-1-12 16:23
炫迈 发表于 2026-1-12 08:54
这种一步步跟js的功夫现在很多新人已经不愿意做了,现在大厂都喜欢用这种VM保护方式,你用AI辅助分析的方法 ...

大佬,请教AST要学些啥呀

点评

学习AST只需要一个网站: https://astexplorer.net  详情 回复 发表于 2026-1-12 21:58
 楼主| szh12123 发表于 2026-1-12 16:24
xxsoul 发表于 2026-1-12 09:30
推荐楼主看看这个系列:写给开发人员的使用密码学,对以后类似的case会很有帮助

好的,感谢
Z564493690 发表于 2026-1-12 17:22
没看出来哪里是小白了!
qvbydc 发表于 2026-1-12 17:46
好复杂呀,看到最后一点都 没有记到
涛之雨 发表于 2026-1-12 21:58
szh12123 发表于 2026-1-12 16:23
大佬,请教AST要学些啥呀

学习AST只需要一个网站:
https://astexplorer.net
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-1-13 09:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表