js逆向之猿人学-反混淆刷题平台第十八题(jsvmp)
内容分析:
- 题目要求:抓取这5页的数字,计算加和并提交结果
- 接口分析: F12,点击第二页,这里我们能看到有三个请求参数:page、t、v。一看就能知道,page:页码,t:时间戳,v:加密参数。所以这题我们的目的就是最找到这个v是怎么生成的即可。
点击圈中的地方,如下图所示:
直接跳转到了发送请求的位置,我们能看到727行,这里有个data参数,然后在729行有个data=data.data。大概猜一下这里应该就是已经拿到数据了,为了验证下,我们直接在727,729打上断点,然后点击下一页看看。如下图所示,这里就已经拿到数据了,但这不是我们想要的,我们需要分析在这个之前怎么生成加密参数v的。
这里拿到数据是在cback这个函数之中的,所以我们直接在这里直接在724行和751行打上断点。重新点击下一页,发现最后会跳到如下图所示:(这里就是本题的重点)
在上图这两个地方打上断点,然后释放断点。
这里我们能看到一个可疑的东西(圈起来的部分),这里就可以猜测一下加密参数v通过AES进行加密的,接下我们根据这个进行分析。首先hook一下AES,hook代码如下:(提示:如果第一遍没有hook上的,重新走一遍流程)
aes_encrypt_old = _[1][0]['CryptoJS']['AES']['encrypt']
_[1][0]['CryptoJS']['AES']['encrypt']=function(a,b,c,d,e){
debugger;
var a = aes_encrypt_old(a,b,c,d,e);
console.log(a.toString())
debugger;
return a;
}
释放断点之后,这里就出来结果了,我们一次按照上图圈住的部分,在console中打印出结果
_[1][0]['CryptoJS'].enc.Utf8.stringify(a) // text
_[1][0]['CryptoJS'].enc.Utf8.stringify(b) // key
_[1][0]['CryptoJS'].enc.Utf8.stringify(c.iv) // iv
这里能看到key和iv的结果是一致的,text就是待加密文本,接下我们就一一分下这里的text、key、iv是如何生成的。之后直接跳回到上一步,如下图所示:
可以看到加密函数就是从这里被hook到的,接下来我们在这里加入一个日志断点,输出所有从这里经过的内容。
接下来就是重新走一遍过程,点击下一页,释放断点,这里就会打印出如上图所示的一些内容,我们从这里开始分析,之前我们发现key和iv是一致的,那么我们只需要分析这个值怎么来的就行,可以从圈住的第一行开始看,首先生成了一个13位的时间戳,之后将这个时间戳变成了10位的,然后将这个时间戳转为16进制(此步骤要做两次),生成了两个16进制值,将这两个值相加,就得到了key和iv
再来分析怎么得到待加密文本的,这里看下上图圈出来的部分,可以看到生成了一个数组,数组里面有5个参数,然后将这五个参数转成了一个字符串,圈出的第二个部分,可以看成
"2"+"|"+ "796m215,796m215,796m215,796u215,796u215"
经过多次验证,这里会发现这个 “2” 其实就是页码数。好了,接下来只剩下这组数据了。此时我们的断点应该释放了,将鼠标在页面中滑动,会发现console面板中还在不断输出内容,如下图所示:
有没有发现生成的这些数组和上面待加密文本的内容差不多,这个其实是你的鼠标轨迹,接下来我们验证一下。重新进行上面Hook之前的步骤即可。
看上图我圈出来的部分,这里mouses的参数,这个就是鼠标轨迹。
到这里为止整个过程都分析完成了,那么结合起来就是如下步骤:
1.生成一个13位时间戳 -> t = Date.now()
2.将13位时间戳转成10位的时间戳 t = Math.round(t/1000)
3.将这个10位的时间戳转成16进制(需要做两遍),然后将两个值相加 -> key = iv = t.toString(16) t.toString(16)
4.获取到鼠标轨迹 mouses = ['825m199', '825m199', '825m199', '825u199', '825u199']
5.转成字符串 mouses_str = mouses.jion()
6.将当前页码数与"|"以及生成的鼠标轨迹字符串相加 text = "page" +"|" + mouses_str
7.使用AES加密对待加密文本进行加密
接下来我们来根据这个步骤实现一下:
先走一遍流程,拿到跟网页一样的参数,如下图所示:
这里最后的结果:
t:1645164744
text:'2|800m312,800d312,800m312,800m312,800u312'
key、iv:620f38c8620f38c8
v: 'TPX1Cm7JNb419NS7+GYNvn2YUo2DQUxG6LoyujSBjNSSiW5vKX6BLXzSJcF9u4fx'
下面我们拿这些参数验证一下:
const CryptoJS = require("crypto-js");
function AESencrypt(data, key, iv) { //key,iv:16位的字符串
var key1 = CryptoJS.enc.Utf8.parse(key);
var iv1 = CryptoJS.enc.Utf8.parse(iv);
return CryptoJS.AES.encrypt(data, key1, {
iv: iv1,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();
}
t = 1645164744
page = 2
var key = iv = t.toString(16) + t.toString(16)
data = page.toString() + "|" + "800m312,800d312,800m312,800m312,800u312"
res = AESencrypt(data, key, iv)
console.log(res) // -> TPX1Cm7JNb419NS7+GYNvn2YUo2DQUxG6LoyujSBjNSSiW5vKX6BLXzSJcF9u4fx
最后验证成功,与请求时生成的参数一致,到这里这题就完成了。
欢迎关注公众号:【时光python之旅】 (在这里你能学到我的所见、所闻、所思、所学)
- 点赞
- 收藏
- 关注作者
评论(0)