吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11956|回复: 36
收起左侧

[Web逆向] 用TamperMonkey脚本解析XX视频分析

  [复制链接]
5omggx 发表于 2020-1-22 14:12
本帖最后由 5omggx 于 2020-1-22 14:08 编辑

根据 ZSAIm 大神帖子 《XX视频H5解析分析过程》
进行如下请求头 ==构造②== ,

GET
/jp/dash?

得到启发,Network中搜索dash可得:
image001.png
在Response 选项卡可看到如下内容:

{"data":{"dm3u8":"https:\/\/cache.m.i???i.com\/dc\/dt\/","st":101,"…………

右键 Copy Response,到[JSON格式化网站] (https://tool.lu/js/)  对内容格式化:
image002.png
在尾部可看到视频分段信息,将格式化后的代码复制到记事本,并搜索ts相关信息,找到最后一个,可以看到:
image003.png
其中含有该视频对应的TS片段和URL参数,其中start, end 分别为片段起始时间戳和结束时间戳,找到最大的end 时间戳后,将其对应的URL start改为0 即可使用该URL获取完整TS文件。
image004.png
编写一个TamperMonkey脚本,尝试一下看能否通过 HOOK WebRequest 方式拦截该 XHR 请求:
代码如下:

// ==UserScript==
// @name         HOOK AJAX XMLRequest 调试中
// @namespace    NAMESPACE
// @version      0.1
// @description  HOOK AJAX XMLRequest
// @author       anonymous
// @match        https://www.i????.com/*
// @grant        none
// ==/UserScript==

function addXMLRequestCallback(callback){
    var oldSend, i;
    if( XMLHttpRequest.callbacks ) {
        // we've already overridden send() so just add the callback
        XMLHttpRequest.callbacks.push( callback );
    } else {
        // create a callback queue
        XMLHttpRequest.callbacks = [callback];
        // store the native send()
        oldSend = XMLHttpRequest.prototype.send;
        // override the native send()
        XMLHttpRequest.prototype.send = function(){
            // process the callback queue
            // the xhr instance is passed into each callback but seems pretty useless
            // you can't tell what its destination is or call abort() without an error
            // so only really good for logging that a request has happened
            // I could be wrong, I hope so...
            // EDIT: I suppose you could override the onreadystatechange handler though
            for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
                XMLHttpRequest.callbacks[i]( this );
            }
            // call the native send()
            oldSend.apply(this, arguments);
        }
    }
}

(function () {
    'use strict';
    addXMLRequestCallback( function( xhr ) {
            xhr.addEventListener("load", function(){
                if ( xhr.readyState == 4 && xhr.status == 200 ) {
                     console.log("HOOK > " + xhr.responseURL );
                    //if ( xhr.responseURL.includes("url") ) {
                    //    console.log(xhr);
                    //    //do something!
                    //}
                }
            });
        });
})();

注意:uBlockOrigin 之类的扩展会干扰 TamperMonkey 脚本的正常运行,在使用油猴脚本调试网站时需要关闭 uBlockOrigin。

通过 https://oktools.net/json 这个在线格式化网站格式化如下URL:https://cache.video.i???i.com/dash?tvid=113292...       得到如下结果:

image005.png

可以看到
object-->data-->program-->video[2] -->m3u8
即为我们想要的内容(m3u8):
可以通过在 Tamper Monkey 脚本中加入 debugger 然后在中断后的 console 中输入如下代码验证:

var k38=JSON.parse(xhr.responseText);
console.log(k38.data.program.video[2].m3u8);

经实测,其中video数组中,下标并不固定,需要编写一段代码搜索实际含有m3u8属性的video[?]

以下地址:

https://data.video.i???i.com/videos/vts/20200103/86/25/6222*536de.ts?start=0&end=639952&contentlength=639952&sd=0&qdv=1&qd_uid=17&
qd_tvid=1127691800&qd_vip=1&
qd_src=01010031010000000000&qd_tm=1579526642916&qd_ip=0&qd_p=0&qd_k=663&ve=&sgti=14_ddf2b06babfed178086ed9ebd16a5b9a_15
79526641369&dfp=&qd_sc=7d1c8771adf248c5a28f61677209564f&pv=0.1&cross-domain=1&stauto=1

返回JSON内容为:

{"t":"CT|??Xi-113.17.102.100","abs_speed":500,"mrc":"0","z":"qiniucdn_ct","h":"0","l":"https://qncdnct.inter.71???.com/videos/vts/20200103/86/25/6222d
e7dd4fd4.ts?key=0d4db529240&dis_k=f04f6db1759&dis_t=1579526643&dis_dz=CT-Xi&dis_st=49&src=i???.com&dis_hit=0&uuid=71116664-5e25a
9f3-25e&sgti=14_ddf2b06babfed178086ed9ebd16a5b9a_1579526641369&start=0&qd_uid=1&qd_tm=1579526642916&qdv=1&cross-domain=1&ve=&dfp=&contentlength=639952&qd_src=01010031010000000000&qd_p=0&sd=0&pv=0.1&qd_tvid=1127691800&qd_vip=1&qd_ip=
0&stauto=1&end=639952&qd_k=66553","e":"0"}

但其返回的end值并非最大的,导致使用该值下载的TS视频片段不完整,原因待查。所以,还是只有前面的方法才可以做到下载完整TS文件。

经试验,确认可以HOOK到相应的XHR请求,下步就是进一步修改脚本,使得其能够处理上述JSON并输出下载的URL:

// ==UserScript==
// @name         HOOK AJAX XMLRequest 调试中
// @namespace    NAMESPACE
// @version      0.1
// @description  HOOK AJAX XMLRequest
// @author       anonymous
// @match        https://www.i???i.com/*
// @grant        none
// ==/UserScript==

function addXMLRequestCallback(callback){
    var oldSend, i;
    if( XMLHttpRequest.callbacks ) {
        // we've already overridden send() so just add the callback
        XMLHttpRequest.callbacks.push( callback );
    } else {
        // create a callback queue
        XMLHttpRequest.callbacks = [callback];
        // store the native send()
        oldSend = XMLHttpRequest.prototype.send;
        // override the native send()
        XMLHttpRequest.prototype.send = function(){
            // process the callback queue
            // the xhr instance is passed into each callback but seems pretty useless
            // you can't tell what its destination is or call abort() without an error
            // so only really good for logging that a request has happened
            // I could be wrong, I hope so...
            // EDIT: I suppose you could override the onreadystatechange handler though
            for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
                XMLHttpRequest.callbacks[i]( this );
            }
            // call the native send()
            oldSend.apply(this, arguments);
        }
    }
}

(function () {
    'use strict';
    addXMLRequestCallback( function( xhr ) {
        xhr.addEventListener("load", function(){
            if ( xhr.readyState == 4 && xhr.status == 200 ) {
                 console.log("HOOK > " + xhr.responseURL );
                 if( xhr.responseURL.includes("dash") ){
                    //console.log(xhr.responseText);
                    var k38=JSON.parse(xhr.responseText);
                    var video=k38.data.program.video;
                    var i,vlen=video.length;

                    for(i=0;i<vlen;i++){
                        if( typeof(video[i].m3u8) != "undefined" ){
                            console.log(video[i].m3u8);
                        }
                    }

                    //debugger;
                    //do something!
                 }

            }
        });
    });
})();

打开开发者工具,在 console 窗口中找到最后一个链接,将 start改为0即可获取对应的完整 TS 片段。

免费评分

参与人数 5威望 +1 吾爱币 +10 热心值 +5 收起 理由
Hmily + 1 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
ChanCherry + 1 用心讨论,共获提升!
qsws3344 + 1 + 1 用心讨论,共获提升!
陈世界 + 1 + 1 我很赞同!
Kevin-Register + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 5omggx 发表于 2020-1-24 16:33
GalaxyMimi 发表于 2020-1-24 11:59
you-get有一个Python版本的解析,见GitHub仓库: https://github.com/soimort/you-get/blob/293252b3615ff4 ...

Python这个研究更深入点,收藏了,感谢分享。
其实发这个帖主要是用于演示TamperMonkey的使用,本帖描述的方法也可用于其他网站视频。
 楼主| 5omggx 发表于 2020-1-24 16:43
WXJYXLWMH 发表于 2020-1-23 20:44
理念很好 就是有点麻烦
建议使用 IDM最好 猫抓  VideoDownloadHelper  猎影视频下载 方便快捷

感谢分享现成的下载工具。
本帖旨在于揭示现成工具其中的技术原理,便于爱折腾人士折腾
minyun 发表于 2020-1-22 14:25
china-ray 发表于 2020-1-22 14:45
我也看不懂,纯支持!
婷心mi 发表于 2020-1-22 15:14
有用啊,多谢
Louisgn 发表于 2020-1-22 16:06
非常实用,顶一个
fytv 发表于 2020-1-22 16:53
天书一样,表示看不懂,无条件支持!
侃遍天下无二人 发表于 2020-1-22 17:55
本帖最后由 侃遍天下无二人 于 2020-1-22 18:03 编辑

我知道楼主解析的是爱奇艺的视频了,我之前一直都是靠手动下载合并的
刚刚试了一下,似乎会返回405错误,不清楚是咋回事,不过这些内容还是可以复制下来处理成m3u8文件播放的
 楼主| 5omggx 发表于 2020-1-22 18:48
侃遍天下无二人 发表于 2020-1-22 17:55
我知道楼主解析的是爱奇艺的视频了,我之前一直都是靠手动下载合并的
刚刚试了一下,似乎会返回405错误, ...

我目前未碰到过405错误。可能某些视频有别的不同设置。
ok168168 发表于 2020-1-22 22:03
厉害呀,支持一个
御龙在天 发表于 2020-1-22 22:14
不懂  帮楼主顶顶
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-26 01:00

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表