好友
阅读权限 10
听众
最后登录 1970-1-1
本帖最后由 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,就发现了赋值代码;
然后找到getParisAcessToken()方法,给几个方法都打上断点,几轮运行最后发现getSign()生成的sign是最后的密文;
然后使用单步调试和跳过函数,跟到了这里,发现他一直在循环,S不断+1,s=9之后他就跳出去了,然后这里的文件名是acs-2108.js,果断猜测就是acs-token生成的位置,
所以我在s=9时开始单步调试,结果发现他又回到了上面所示的地方,打开调用堆栈然后发现他是个嵌套,
好家伙,这样一步一步跟不得跟到天荒地老;果断放弃,另谋出路,想到加密的关键词encrypt, 搜索之后发现一个有点像加密参数的方法,
但是没有基础知识所以看不懂意思,所以咨询了AI,AI告诉我这是AES加密函数的实现,还把每个参数的意思都翻译出来了,确认这就是创建加密的地方,然后在末尾打上断点,得到了每个参数的值,
发现ciphertext、key、iv都是数组,很奇怪,想到可能是加密,又咨询了AI,AI告诉我这是 CryptoJS 的 WordArray 对象,表示加密后的字节数据,然后还贴心的写了个转换成字符串的方法,key和iv还原后都是16位的字符串,ciphertext没有解出来,只留下了一串很长的base64,其他几个参数看不太懂就先没管了;随便看了眼这时的调用堆栈,
幸好之前及时放弃,不然得跟到啥时候; 然后单步之后到了这里,
这不就是明牌了吗,e是明文,t是key,n是iv还有mode啥的,虽然不知道为啥就变成这样了;然后继续单步,发现他又到了这里,我这里使用跳过,找到一个可疑的数据,有点像加密后的数据,然后又跟明文在一起,后面不小心跳出去了(当然过程中有很多次这样的不小心,才一步步逼近关键位置),发现确实就是acs-token时间戳后面跟着的密文,
现在我手里有了key、iv、密文,我就咨询AI通过三种参数进行解密,AI给了我一个尝试AES各种模式的解密代码,最后成功还原为明文,并且知道了是CBC模式, 继续跟到这里的话,会发现他的拼接过程,将前两个时间戳和AES密文拼接,并且还能看到key和iv,
接下来就是研究明文的结构了,
{"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.s 加 1 就是将 a 中数值遍历完,然后看到了 V() ,里面就是一系列操作然后把数据返回到 s 里面;最开始我以为是搞的啥加密算法,里面一抹多代码,后来 AI 告诉我是虚拟机 (VM) 的指令执行器;原来就是把 a 里面的指令数组执行一遍;
接着我们来找 "0" 参数的生成位置,我发现 V() 中很多都是 n.g 结尾,而 n 就是之前的 s ;所以我开始查看每次循环的 s 中的值,发现他都是 s.g 和 s.h 值的更新, 结果在这里看到了这个,
g中的值是h1和h3拼接后的值,g又刚好就是"0"的值,所以在s等于27的时候执行的代码就是拼接,那就重新调试跟着s=27的代码走一遍(后来发现直接查看a中序号27时的数组,接着查看V()中对应的case也是一样的),找到了拼接代码,
然后往前回溯就找到了h1和h3是如何生成的,从s=0开始到s=27就是生成"0"参数值的全过程,其实从s=0开始直接看s.g和s.h的值就能猜到是如何运算的,都不用去看代码,
先是创建一个随机数,截取序号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的过程中,发现他是直接从列表中提取出来的,并没有找到生成过程,并且在不断查看调用堆栈的时候,发现这个参数一直都在,只是隐藏的比较深,
以至于我从最开始的M()都找到了参数的路径:M()-[[Scopes]]-0-n-i-r-M()-[[Scopes]]-0-n-i-m,因为在s的循环步骤里面呆了很久,所以大概知道了他的调用步骤,还有就是阅读下面这个方法,得到了启示,
这里花了很多时间,虽然最终找到了位置但是没啥用,因为他本身就存在了,于是乎我直接搜了这个时间戳,找到了关键代码,key和iv都在里面,不过是用数组的形式,包括其他一些固定参数(我觉得无关紧要就没一个一个找了),
原始key列表数值共16位:
iv固定值共16位:
至于为啥我发现是两小时一更新,因为我第二天发现解不出来了,一搜索发现原来的key值变了,我将两个js文件用Beyond一对比,发现确实有些微小差别,
然后我把目光放在了acs-2108.js?_=245575网址的参数上面,起初不知道是啥意义,跑了一遍也没发现在哪加的这个参数,问了AI他告诉我是因为浏览器会缓存文件,如果不加就默认之前的文件,数据就不会更新,也不知道是不是运气好,我用时间戳一除,整数部分刚好是7200,再一对比前后不同文件的参数变化,这不就是2小时吗;但我还是耐心去找了代码,这里也花了不少时间去一步一步跟,看他在哪一步发送了网址,结果是在过程中发现生成了clientCacheTTL: 120这样一个参数,但结果又没有这个参数,让我产生了怀疑,最终发现了关键代码,这个120就表示的是分钟数:
这样只需简单正则即可提取最新的数据列表,然后每个参数的相对位置又是固定的,这样就可以把动态时间戳、动态key、iv都提取出来,将上面的各个成果合在一起,就完成了整个加密过程,然后这里我又踩了个小坑,我发现生成的acs-token对不上,然后检查一遍参数都是相同的,最后锁定在AES明文字符串中,我发现python的字典转字符串有空格,而本身其实是没有的,于是AI给了我下面的代码去除空格,
json.dumps(params,separators=(',',':'),ensure_ascii=False)
最终运行之后完美符合,分析结束。
免费评分
查看全部评分
发帖前要善用【论坛搜索 】 功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。