腾讯滑块vData_VMP分析
成品解决方案联系v:cjh-18888
原文http://www.zhuoyue360.com/jsnx/53.html
1. 环境搭建
不太好拿实际的网站来做实战,所以使用Wampserver64 + html
来搭建测试站, 需要本地html文件的可以联系QQ 2625112940. 验证码识别,图像识别,安卓逆向相关的朋友也可以联系我.
2. 分析
vData使用了JS-VMP的技术哈.至于JSVMP是啥?请参考下面这篇文章
给"某音"的js虚拟机写一个编译器 https://bbs.pediy.com/thread-261414.htm
1. 定位
vData
包在cap_union_new_verify
这儿,我们使用查看调用堆栈
的方式去找位置.
看到send
.打断点.看看数据是啥
然后把a.data
拿出来,发现并没有vData相关的东西?
what? 一般情况下不应该都是在send之前就组完包了吗? 怎么都到了send还没有加上vData
呢?
2. 补环境
此时读者可以继续跟下去,你就会进到vm-slide.e201876f.enc.js
文件.可以说它几乎是没法跟踪的,更别提算法还原了. so,这里使用补环境的方式来弄.
关注点getElementById
,
[V8]get,[object XMLHttpRequest],open,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object XMLHttpRequest],send,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementById,function getElementById() { [native code] }
[V8]get,[object Window],top,[object Window]
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementsByTagName,function getElementsByTagName() { [native code] }
[V8]get,[object Window],navigator,[object Navigator]
[V8]get,[object Navigator],userAgent,Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Version/8.0(Rs) Chrome/94.0.4606.71 Safari/537.36
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object XMLHttpRequest],autoHttp,
由于这里没有全局hook出来,这里手动给他注下代码.
document.getElementById = new Proxy(document.getElementById, {
apply: (target,ctx,args)=>{
let value = Reflect.apply(target,ctx,args);
console.log('apply', args, value);
return value;
}
});
日志如下:
[V8]get,[object XMLHttpRequest],open,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object XMLHttpRequest],send,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementById,function () { [native code] }
[V8]apply|slideBg|null
[V8]get,[object Window],top,[object Window]
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementsByTagName,function getElementsByTagName() { [native code] }
[V8]get,[object Window],navigator,[object Navigator]
[V8]get,[object Navigator],userAgent,Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Version/8.0(Rs) Chrome/94.0.4606.71 Safari/537.36
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object XMLHttpRequest],autoHttp,
发现,getElementById是找浏览器中有没有slideBg
.我们去浏览器找找看.
发现是存在的哈,存在我们就创建一个id为slideBg
的img
let img = document.createElement('img');
img.id = "slideBg";
document.body.appendChild(img)
日志
[V8]get,[object XMLHttpRequest],open,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object XMLHttpRequest],send,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementById,function () { [native code] }
[V8]get,[object HTMLImageElement],toString,function toString() { [native code] }
[V8]apply|slideBg|[object HTMLImageElement]
[V8]get,[object HTMLImageElement],src,
[V8]get,[object Window],top,[object Window]
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementsByTagName,function getElementsByTagName() { [native code] }
[V8]get,[object Window],navigator,[object Navigator]
[V8]get,[object Navigator],userAgent,Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Version/8.0(Rs) Chrome/94.0.4606.71 Safari/537.36
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object XMLHttpRequest],autoHttp,
再调试,发现要获取src
,通过hook的方式再次断下.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vlwqjqj6-1634887028842)(G:\blog_img\image-20211022143712475.png)]
看看src是个啥.其实就是图片验证码的img
let img = document.createElement('img');
img.id = "slideBg";
img.src = "https://t.captcha.qq.com/hycdn?index=1&image=937314008038564608?aid=1600000223&sess=s0ipTulqaOqk9Zr9mkbKPy0JQ29X-B9J9_CMprHOmxRFOlIzbuGMp7sup2cPoBRotaiEYfNR5iTjpbWMd4BRySwr7JoOayjVE9Ko5ILxEO7KfpCjRyCq2GtNhjgYjo_YZnHo05Wt4wXLmMIxLJDdDXHgO3qXuUFXYu1lUCpnN-vCgQrMkY1WnZXKpFS7-zAUrVb9qg-ffnKHJwbJBvd0GuQH_RWw-qqwBKi2skfWEH2C0aRofqx8fLQW69BYTi3fBBlL3z3yUO60TcrdfdSzakZmS2eZ_WJDRj&sid=6857193806836801537&img_index=1&subsid=3"
document.body.appendChild(img)
调试看日志, 这回到了top
[V8]get,[object XMLHttpRequest],open,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object XMLHttpRequest],send,function w(){var A=p.slice(0);A[0]=[this],A[1]=[arguments],A[2]=[w];for(var C=0;C<Q.length&&C<arguments.length;C++)0<Q[C]&&(A[Q[C]]=[arguments[C]]);return __TENCENT_CHAOS_VM(K,m,U,A,E,F,Y,c)}
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementById,function () { [native code] }
[V8]get,[object HTMLImageElement],toString,function toString() { [native code] }
[V8]apply|slideBg|[object HTMLImageElement]
[V8]get,[object HTMLImageElement],src,https://t.captcha.qq.com/hycdn?index=1&image=937314008038564608?aid=1600000223&sess=s0ipTulqaOqk9Zr9mkbKPy0JQ29X-B9J9_CMprHOmxRFOlIzbuGMp7sup2cPoBRotaiEYfNR5iTjpbWMd4BRySwr7JoOayjVE9Ko5ILxEO7KfpCjRyCq2GtNhjgYjo_YZnHo05Wt4wXLmMIxLJDdDXHgO3qXuUFXYu1lUCpnN-vCgQrMkY1WnZXKpFS7-zAUrVb9qg-ffnKHJwbJBvd0GuQH_RWw-qqwBKi2skfWEH2C0aRofqx8fLQW69BYTi3fBBlL3z3yUO60TcrdfdSzakZmS2eZ_WJDRj&sid=6857193806836801537&img_index=1&subsid=3
[V8]get,[object Window],top,[object Window]
[V8]get,[object Window],document,[object HTMLDocument]
[V8]get,[object HTMLDocument],getElementsByTagName,function getElementsByTagName() { [native code] }
[V8]get,[object Window],navigator,[object Navigator]
[V8]get,[object Navigator],userAgent,Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Version/8.0(Rs) Chrome/94.0.4606.71 Safari/537.36
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://rsv8.com/resouce/vDate.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object HTMLScriptElement],src,https://t.captcha.qq.com/vm-slide.e201876f.enc.js
[V8]get,[object XMLHttpRequest],autoHttp,
对top打断点.
浏览器下:
我们的环境:
所以我们需要修改top.补充环境方式:
Object.defineProperty(window,'top',{
get:function(){
return {};
}
});
接着看日志中的getElementsByTagName
. 继续hook, 关系的是script
, 在hook代码中加个debugger, 进去看看
document.getElementsByTagName = new Proxy(document.getElementsByTagName, {
apply: (target,ctx,args)=>{
let value = Reflect.apply(target,ctx,args);
console.log('apply', args, value);
debugger;
return value;
}
});
[V8]apply|script|[object HTMLScriptElement],[object HTMLScriptElement]
看到这里其实就是在获取我们的script
标签
我们看看真正的浏览器上有多少个script.
11个,我们把它获取出来
let scripts = ["","","","","","","","https://t.captcha.qq.com/tdc.js?app_data=6857198026746343424&t=28740867?t=1634883410","https://captcha.gtimg.com/1/tcaptcha-slide.fd5f5cd0.js",""];
for (let i = scripts; i < scripts.length; i++){
let script = document.createElement('script')
script.src = scripts[i];
document.body.appendChild(script);
}
然后再拦截一下xhr请求的数据.vData
出现了.
aid=1600000223&protocol=https&accver=1&showtype=popup&ua=TW96aWxsYS81LjAgKExpbnV4OyBBbmRyb2lkIDguMDsgUGl4ZWwgMiBCdWlsZC9PUEQzLjE3MDgxNi4wMTIpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85NC4wLjQ2MDYuODEgTW9iaWxlIFNhZmFyaS81MzcuMzY%253D&noheader=0&fb=1&aged=0&enableAged=0&enableDarkMode=0&grayscale=1&clientype=1&sess=s0-IJwliNz11BFO_2VSjLia0__WOz70-tMf05e7hssmPIdQYV9s76NMyXMPvVXoo6pjzA366lIBAs9DIZJ11wVaLFmaB1mU0p4mJN_OXl-AVz98JVhZbxbDRwRTqZaxZcwp-iILOXvDnCtwjYUOkBR8X1oYu4pxdOauLWYmo0i9VeXZSPV82BZJ56mzuXc78li88BqSjEg--RmFVWByd6d_XkuYTghsGVPgCjXAumhn4AJWe26oZ2rEMMfaWhkzF-5tS-rscmOe3jEHjZ3RSM-F3Ae_XGo8lPm&fwidth=0&sid=6857181222991794176&wxLang=&tcScale=1&uid=&cap_cd=&rnd=928880&prehandleLoadTime=13&createIframeStart=1634879403746&subsid=2&cdata=0&ans=151%2C60%3B&vsig=&websig=&subcapclass=&pow_answer=edb0bb5d24fa85d3%23303&pow_calc_time=8&collect=tcge6Vy%2FnGtaEHQWYCBgEpgpQeTo2neVmClB5Ojad5VtXbxm8Z8kD1uIQOFlLcsoUCQcBu0iaDmWvvimVZWXVJa%2B%2BKZVlZdUGjV8n1rg06d3b5gUbCJ7w6yfLuIcIX%2FLrJ8u4hwhf8vwxYHSUbi491n69E4Jju1S8MWB0lG4uPdZ%2BvROCY7tUglKgfHZQFHYkpg5gCvLjGpT%2FlDk2WRpO1n69E4Jju1S8MWB0lG4uPdqB1BkdjdoMQyCy0m7LluVL2wspnbALEXBTZyKs4tTj%2BdcXg61zHP44hhzIznYS90E%2BB0%2BttgvObYPkkCAHj1vWje3Ti%2BPPPmIQCodklvbgj6YsAXRT2H3aj%2FRMbNWRgCWvvimVZWXVJa%2B%2BKZVlZdUpCJVnt9sVeRSMSQTdIynQ2jB3F89NM8oVaqd81jG4QXvIUYv1poj6hDgatsUlh9VPXdEe%2BPyxycN1hif%2FSh84Z9cNTJkmNLX8Nokkbo3p2uDqd1flFGftdY5Fcq2IudI4%2FsIXByipvm83no55K0ROW2VUyMVRYYyZ2sTby30efG8vcjbxvZcpS550lLFBl8H3kWlW2eQ%2B6%2Fy6pUBv4aFcgIkgYc3VNfAt92sJM2uRxf4gpYdbIKcSqGR%2BfbsrP0wV9cibCzHyn6YId7R4i%2B1z8eaYphBIf%2FztEcoxsupwjCcWIz5tFcE1BJngJA%2BQSsWVPCSgnDy5dVd86VArTtfGyS1%2FdObsTWtBIiEbZqQaNl0PN2qRMHpL5gmXZlAoZt8bR5LsBYne5lq9RD9ohMCL1Opjqdszh7mrA0vVG3H9vYzlRcdnExJjmukF%2FfiIQu5UrxJalrJLkClLn6mxLssbpvPUKfRIE2%2FDIdKMIDnUw%2BWHJpwLHfA5%2FUJgu2xdNQ51V7w%2F55kLHbQiGVHMHkqV6%2BGHg7EZftE0CiQXSo5z3phRsg93j8TetFiBq9Rb8YlDpcOLWVpJZdXh21oDKt%2FssQrqcMaUXT7aJhoBTunr9%2B%2FC6kyG2dA3oudT1DNAQki%2BsKN9EJU98Su7Jn4UuPnUidjxuDrCk%2FhC2tInAF%2BURgMKOYUZWN2j6LEaV%2B92ACwc2VUnBz8vcKjNwTjq80x2lAp7U4UWmYy51D2jYii9%2BrMkVoQ7NOfmYaFOOooKwMNkTajH%2BvmYz1169yzXQzhRHBeMou2Vl0CFmN4TI%2BtiwnzROtr4P41j5uS2%2Bi54CaRvBEo7JYxokNPQk%2Fzu0bv7irD%2FIpHatMH81rBm20lRpEDegQNCPBzKmk5pWYJyrvAyteqPAaEZtE0Qlxna9zQaIhZjp4QYztWdLLs1RLBvXtZumdn0cD1CLKJvx%2FIGPSyBfWJg3HsO64kRAtmDDuUZo0b7s8w7kDs2omNxQh548zj4r7TI5iNZXruU2l2Oi7YVgzjvoCJemUT36FS2Odbnkg8I6qHCVlMbUUr%2BTK9wKM0JJWolnsPbCWx9LiGGs1CJbH0uIYazUKECVAuceTbTIpy6xxb1N%2FihAlQLnHk20yKcuscW9Tf4uWQwp1ytYExOdFdjsgrzTRXlld3q%2FrKzIpy6xxb1N%2FihAlQLnHk20yg9kDO7xpH5gTw5%2BJpHRyrlBHlYd2wSf6%2FzyAV4JMRn4OgVswu9WwIAdkJ3ehjaYq5tLj6D4hxInWxufsaXQ9bCS09WMhVUcOXlQv8padEFcvX9IWQKfhnQ5mLiklTbRYncs3%2B4Q0kYuBnvwLm1KpdWG2vmDbiLCkWBVqXZzavRA%3D%3D&tlg=1752&fpinfo=&eks=w%2BvgfjAqDBahHOElk5GjDmh6Ag2X8B2ZC2HbL8NGhEA4WFaM85PQ3NJbk3vkEyeNWJJqNfIhqR0Mh4lL7dq9WuicQoLNkPwrGW5yDymlWgXRK94kuIg%2FqzhSqMJUyswBZEPsR25qrkEzjVkz5F29AmACSqVRp%2BN48o2MiaOyIRndOcd0Ct2bCOSV2avZV%2FNJmB%2By2zWdfVUbvsIQllETeE%2Bkk4QXN5GxbZfnaBpFPtosUmK6p%2BZskA%3D%3D&nonce=eda1152f11f1daf0&vlg=0_0_1&vData=orxe*6-anzMcijlbsiamaUg1c3d5ZNdoMyMKvHr-mw0GK6vfm-hH*IZd0M1uupeWIBRwaATB1kT1763_XNfB_*5Fjq8wNoMPhCpodTOnXwk0twVlWCgdCWapS66lKFvtNo*vcCU4JtKDTydM7aTU9XYY&vData=Ru9GrK6OtZ1zKF5uKe*L_ST3nJVwoJ2FmPWzxtwlbcX1K38DEj1Xx3AzX_7m9mB60X18DQsclqREAVBNGL52iGuphlhmT6EyAmdechAXZIcY
3. 完结.
对于JSVMP的加密,个人是不建议对其算法进行还原的, 吃力不讨好的工作. 补环境才是上好的选择~