今天突然想起刚开始学逆向的时候遇到的一个站,当时没能力解决,现在得安排一下它才行。
时间过得真快啊,转眼都差不多一年了(我还是从前那个菜鸡,没有一丝丝改变)
目标网站:aHR0cHM6Ly9hYy5xcS5jb20vQ29taWNWaWV3L2luZGV4L2lkLzYzMDE2Ni9jaWQvMQ==
一、抓包分析
可以看到,数据是以图片的形式返回的,而这个图片的网址是加密的,那就跟栈找到它生成的地方呗
文章图片
二、跟栈分析
下断点刷新页面
文章图片
可以看到imgSrcList已经有数据了,现在我们全局搜一下,看它是在哪里被赋值的
文章图片
可以看到imgSrcList是被imgobj赋值的,那接下来再搜下imgobj
文章图片
imgobj是被PICTURE赋值的,再搜下PICTURE…
文章图片
然后就追到_v了,这时候再搜_v好像也没啥东西了,细心观察会发现在PICTURE被_v赋值的上面有eval这种字眼,遇到eval的要特别留意,往往会有意想不到的惊喜。
把这个自执行函数copy下来,eval改成concole.log就能可能到内容了
文章图片
这里window.DATA和window.nonce都是未知的,像这种赋值在window上的,一般都要去源码上喵一眼,看有没有找到
文章图片
文章图片
那接下来就好办了呗,正则匹配出来然后放到那个解密函数跑一下行了
注意:
(1)window.nonce在源码上两次被赋值,第二次才是真正的window.nonce
(2)生成window.nonce的地方会检测一些环境,由于每次检测的点都是不一样的,这里建议用jsdom补环境
三、请求验证
文章图片
python代码:
import requests
import execjs
import reheaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0;
WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
}for k in range(1,10):
print("第"+str(k)+"页")
response = requests.get('https://ac.qq.com/ComicView/index/id/630166/cid/%s?fromPrev=1'%(str(k)), headers=headers)nonce_js=re.findall('] = (.*?);
',str(response.text))[1]f_str='const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`Hello world
`);
window = dom.window;
document = window.document;
XMLHttpRequest = window.XMLHttpRequest;
'+'function a(){var b='+nonce_js+';
return b}'js = execjs.compile(f_str)
nonce = js.call("a")
print("nonce: ",nonce)data=https://www.it610.com/article/re.findall("DATA = 'https://www.it610.com/article/(.*?)'",str(response.text))[0]
print("data: ",data)with open('test.js', 'r', encoding='utf-8') as f:
content = f.read()
ctx = execjs.compile(content)
result_data = https://www.it610.com/article/ctx.call('get_data', data, nonce)
for i in result_data:
print(i)
print("\n")
【html5|腾讯漫画(js逆向)】js代码:
function Base() {
_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
this.decode = function(c) {
var a = "", b, d, h, f, g, e = 0;
for (c = c.replace(/[^A-Za-z0-9\+\/\=]/g, "");
e < c.length;
)
b = _keyStr.indexOf(c.charAt(e++)),
d = _keyStr.indexOf(c.charAt(e++)),
f = _keyStr.indexOf(c.charAt(e++)),
g = _keyStr.indexOf(c.charAt(e++)),
b = b << 2 | d >> 4,
d = (d & 15) << 4 | f >> 2,
h = (f & 3) << 6 | g,
a += String.fromCharCode(b),
64 != f && (a += String.fromCharCode(d)),
64 != g && (a += String.fromCharCode(h));
return a = _utf8_decode(a)
}
;
_utf8_decode = function(c) {
for (var a = "", b = 0, d = c1 = c2 = 0;
b < c.length;
)
d = c.charCodeAt(b),
128 > d ? (a += String.fromCharCode(d),
b++) : 191 < d && 224 > d ? (c2 = c.charCodeAt(b + 1),
a += String.fromCharCode((d & 31) << 6 | c2 & 63),
b += 2) : (c2 = c.charCodeAt(b + 1),
c3 = c.charCodeAt(b + 2),
a += String.fromCharCode((d & 15) << 12 | (c2 & 63) << 6 | c3 & 63),
b += 3);
return a
}
}function get_data(data,nonce) {
var B = new Base(), T = data.split(''), N = nonce, len, locate, str;
N = N.match(/\d+[a-zA-Z]+/g);
len = N.length;
while (len--) {
locate = parseInt(N[len]) & 255;
str = N[len].replace(/\d+/g, '');
T.splice(locate, str.length)
}
T = T.join('');
_v = JSON.parse(B.decode(T));
console.log(_v.picture)
return _v.picture
}
推荐阅读
- opencv|opencv.js 之官网教程翻译加代码
- 微信小程序|微信小程序——简单饮食推荐(三)
- javascript|vue学生管理系统
- typescript|Typescript总结(三)——函数类型详解
- vue|vue基础语法
- Vue.js|VUE全家桶系列之基本知识点
- Vuejs|Vue全家桶之组件基础(二)
- Vuejs|Vue全家桶之Vue核心(一)
- Vuejs|Vue全家桶之Vue CLI入门(三)