目标网站:aHR0cDovL3R2Lmh6d2RkLmNuLw==
注意:此网站有反调试,第一:开发者工具不能通过F12快捷键打开(可以通过菜单打开),第二:需要将开发者工具设置为独立窗口,否则网页都会自动关闭。
一、无限Debugger
通过堆栈可以看到
这个 debugger 是由 constructor 构造的,所以可以直接对其进行重写覆盖,代码如下:
(()=>{
Function.prototype.__constructor = Function.prototype.constructor;
Function.prototype.constructor = function(){
if(arguments && typeof arguments[0]==='string'){
if("debugger"===arguments[0]){
return
}
return Function.prototype.__constructor.apply(this,arguments);
}
}
})()
也可以使用 Reres 或是 Fiddler 进行替换,相关内容可以自行百度
二、逆向分析
通过观察浏览器发出的请求,很轻松就能锁定上图中的这个 analysis.php 的请示,它的参数就是我们需要解析的视频页面url,我们看下它的响应
下面的url一眼就能看出是经过加密的,咱们的重点就是找到这个url 的解密方法,上面的 abc()函数很奇怪,作了处理,一般正常页面突然出现一段特别处理的函数内容,这就叫做此地无银三百两,把代码放到console里运行一下,可以看到
整理一下,加上注释:
function abc(){
var _pr = $('meta[name="viewport"]').attr('id').replace('vod_',''); //取网页源码meta[name="viewport"]的id值
var _pu = $('meta[charset="UTF-8"]').attr('id').replace('vod_',''); //取网页源码meta[charset="UTF-8"]的id值
var _puArr = [];
var _newArr = [];
var _code = '';
for(var i=0;i< _pu.length; i++){
_puArr.push({ 'id':_pu[i], 'text': _pr[i] });
}
//对密钥重新进行排序
_newArr = _puArr.sort(PAR.compare("id")); //PAR.compare
for(var i=0;i< _newArr.length; i++){
_code+=_newArr[i]['text'];
}
config.url = PAR.secret(config.url, _code, true); //PAR.secret
}
function abc()这个函数先是取了两个id的值,然后通过 PAR.compare 函数进行排序,最后又使用 PAR.secret 的函数进行了不知道什么运算,那我们先搜索这两个函数,找到这里:
这个JS 是经过加密混淆的,有能力的小伙伴可以使用AST进行还原,要么就进行手工还原,我们的目的很明确,就是搞清楚这个compare 和 secret 两个函数到底在干嘛,然后把它们扣取出来。具体过程可以到B站看详细讲解,compare函数可以直接扣取,对里面的_0x15b4进行一下处理就可以用,secret函数其实就是一个 md5 + aes 加解密的函数,几个函数搞清楚就可以上PYTHON了。
三、梳理逻辑Python实现
整体逻辑很简单,将需要解析的视频页面URL作为参数提交到
然后从返回数据中提取两个id值,以及加密的config.url
再调用函数abc(id1,id2)获取code
调用函数secret(config.url,code)进行aes解密,获得最终url明文地址;
整个逻辑清楚了,写代码部分应该算是最最简单的环节了
完整Python代码:
# -*- coding: utf-8 -*-
# @Author: Null119
# @Desc: { 某vip在线解析 }
# @Date: 2022/03/02 12:59
import requests,execjs,urllib3,re,base64,hashlib
from Crypto.Cipher import AES
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
ctx = execjs.compile(open('./abc.js').read())
def md5(str):
return hashlib.md5(str.encode(encoding='UTF-8')).hexdigest()
def aesCbcDecode(content,key, iv,pkcs=5):
try:
key_bytes = bytes(key, encoding='utf-8')
iv = bytes(iv, encoding='utf-8')
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
aes_encode_bytes = base64.b64decode(content)
aes_decode_bytes = cipher.decrypt(aes_encode_bytes)
result = str(aes_decode_bytes, encoding='utf-8')
if pkcs==7:
result = pkcs7unpadding(result)
except:
pass
else:
return result
def pkcs7unpadding(text):
try:
length = len(text)
unpadding = ord(text[length - 1])
return text[0:length - unpadding]
except Exception as e:
pass
def secret(url,code):
code=md5(code)
iv=code[0:16]
key=code[16:]
return aesCbcDecode(url,key,iv,7)
def getVIP(url):
nurl='https://jx.parwix.com:4433/player/analysis.php?v=%s' % (url)
html=requests.get(nurl,verify=False).text
id=re.findall('id="vod_(.*?)"',html)
enurl=re.search('"url": "(.*?)"',html).group(1)
evstr='abc("'+id[0]+'","'+id[1]+'")'
code = str(ctx.eval(evstr))
print('解析地址:',secret(enurl,code))
if __name__ == '__main__':
url='https://v.qq.com/x/cover/mzc00200jtxd9ap/e0042tbl57y.html'
getVIP(url)
abc.js代码:
function abc(id1,id2){
var _pr = id1;//$('meta[name="viewport"]').attr('id').replace('vod_','');
var _pu = id2;//$('meta[charset="UTF-8"]').attr('id').replace('vod_','');
var _puArr = [];
var _newArr = [];
var _code = '';
for(var i=0;i< _pu.length; i++){
_puArr.push({ 'id':_pu[i], 'text': _pr[i] });
}
_newArr = _puArr.sort(compare("id"));
for(var i=0;i< _newArr.length; i++){
_code+=_newArr[i]['text'];
}
return _code
}
function compare(_0x209a13) {
return function(_0x4490c6, _0x47bde8) {
return _0x4490c6[_0x209a13] - _0x47bde8[_0x209a13];
}
}
详细视频地址:
https://www.bilibili.com/video/BV1VU4y1f7PU/
评论(3)
不错学习了
你真厉害,向优秀大佬低头
博主,解析更新了播放器,能否在出一期视频 提供学习,对着你的视频研究了下新的播放器 全新写法,完全不知道怎么下手,jx.parwix.com:4433/player/?url=
接口地址