Cubic Zone

超星尔雅网课平台反作弊机制的探究 (3) - 实现

在上一篇文章中, 我们注意到播放器的一个对外接口 getPlayState()

尝试在视频播放时调用此函数, 返回值为 1. 暂停视频后再次调用, 返回值为 2

可以用此函数判断视频播放是否暂停. 简单的用户脚本代码如下:

function getPlayer() {
    var _frame1 = window.document.querySelector("iframe");
    var _frame2 = _frame1.contentWindow.document.querySelector("iframe");
    return _frame2.contentWindow.document.querySelector("object");
}

function init() {
    var player = getPlayer();
    if (player.getPlayState() !== 1) {
        // if the video has not started, do not enable auto start
        // video metadata should be loaded by player in advance
        setTimeout(init, 1000);
        console.log("Video metadata not loaded. Please click start button.");
        return;
    }
    setInterval(function () {
        try {
            if (player.getPlayState() !== 1)
                player.playMovie();
        } catch (e) {

        }
    }, 1000);
    console.log("Auto play enabled");
}

setTimeout(init, 5000);

OK, 这样我们就解决了视频暂停的问题. 为了达到更好的易用性, 下一步, 我们可以使用 Selenium + WebDriver 模拟鼠标的悬停动作, 从题库中提取对应题目信息模拟鼠标点击进行答题, 如此循环往复: 播放视频 -> 回答视频任务点 -> 播放完视频 -> 回答章节测验 -> 下一章. 由于尔雅平台并没有进行鼠标位置等信息的监测, 因此本方法和手工刷课在服务器端观察到的的操作高度一致, 且无需进行额外的代码编写.

更进一步, 我们可以通过抓取页面信息获取以及计算出 multimedia/log/xxxxxx 接口的 post 参数, 直接向服务器提交播放进度.

GET https://mooc1-1.chaoxing.com/knowledge/cards HTTP/1.1

从该接口返回的 HTML 文本中, 我们可以找到如下数据:

var mArg = "";

try{
    mArg = {"attachments":[{"headOffset":788000,"jobid":"xxx","otherInfo":"nodeId_xxx","isPassed":true,"property":{"jobid":xxx,"switchwindow":"true","size":xxx,"fastforward":"true","hsize":"116.15 MB","module":"insertvideo","name":"[hidden].mp4","mid":"xxx","type":".mp4","objectid":"xxx","_jobid":xxx},"mid":"xxx","playTime":46000,"type":"video","objectId":"xxx"}],"defaults":{"fid":"xxx","knowledgeid":xxx,"clazzId":xxx,"cardid":xxx,"isFiled":0,"state":0,"reportUrl":"https://mooc1-1.chaoxing.com/multimedia/log","userid":"xxx","courseid":xxx,"reportTimeInterval":60,"subtitleUrl":"https://mooc1-1.chaoxing.com/richvideo/subtitle","initdataUrl":"https://mooc1-1.chaoxing.com/richvideo/initdatawithviewer"},"control":true};
}catch(e){
}

uParse(".ans-cc",null,mArg);

可以看出我们所需要获取任务点题目和上传进度的参数都包含在此段代码中.

继续查看请求, 找出获取章节测验的接口:

GET https://mooc1-1.chaoxing.com/work/doHomeWorkNew HTTP/1.1

以及提交接口:

POST https://mooc1-1.chaoxing.com/work/addStudentWorkNewWeb HTTP/1.1

最后从侧边栏中获取到下一节课的 clazzIdchapterId 等参数, 从而完成自动章节切换. 由于此脚本过于邪恶, 因此在此不会放出具体实现代码, 但根据上述的分析完全可以自行开发.

对尔雅网课平台的分析和自动脚本的构想就到此为止了. 最后切记: 闷声发大财!