目标网站:aHR0cDovL3R2Lmh6d2RkLmNuLw==
注意:此网站有反调试,第一:开发者工具不能通过F12快捷键打开(可以通过菜单打开),第二:需要将开发者工具设置为独立窗口,否则网页都会自动关闭。

一、无限Debugger

debugger

通过堆栈可以看到

constructor构造器

这个 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里运行一下,可以看到

此地无银300两

整理一下,加上注释:

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作为参数提交到

https://jx.parwix.com:4433/player/analysis.php

然后从返回数据中提取两个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/

本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习使用,请在下载后24小时内删除,严禁商用。若由于商用引起版权纠纷,一切责任均由使用者承担。