前言

前两天发小让找一下有没有可以刷课的平台或者软件,找遍论坛和网络也没有找到关于此学院的信息。
无奈,只能自己上手了。
本文应该可能只适用于河南大学继续教育网络平台

某大学继续教育平台刷课分析

QQ五笔截图未命名.png

分析

首先网络平台,最关键的就是有一个向服务器提交数据观看时间的请求,综合此情况,那么就开始抓取请求。
以我当前浏览器搜狗浏览器为例,在课程页面按F12键,调出开发者工具,点击NetWork,勾选住PreserveLog(持续日志或译为保留日志)。
点击课程平台,在第一次点击之时是不会有请求信息的,这个在稍候解析JS文件的时候说明。
播放之后再次点击一次需要观看的课程,这个时间首先就出现了请求了。

某大学继续教育平台刷课分析

2.png

先来看一下updstatus中的这个请求。

某大学继续教育平台刷课分析

3.png

请求地址:

[POST]http://henu.cjnep.net/lms/web/timing/updstatus

请求头:

Cookie: _csrf=xxxx; Hm_lvt_fc82d39d0aabdf72237c051c09b9428e=1577847473; PHPFRONTSESSID=xxxxx; contact=%5B%7B%22id%22%3A%221%22%2C%22teacher_name%22%3A%22%5Cu5e73%5Cu53f0%5Cu4f7f%5Cu7528%5Cu54a8%5Cu8be21%22%2C%22qq_number%22%3A%222924134909%22%7D%2C%7B%22id%22%3A%222%22%2C%22teacher_name%22%3A%22%5Cu5e73%5Cu53f0%5Cu4f7f%5Cu7528%5Cu54a8%5Cu8be22%22%2C%22qq_number%22%3A%221283346554%22%7D%5D; noticeNumber=19; Hm_lpvt_fc82d39d0aabdf72237c051c09b9428e=1577848743

其中关键的参数我已经用xxxx为代替。
请求内容:

userId=xxxx&courseId=xxxx&scoId=27463&historyId=272631&addTime=5&totalTime=1149.619955¤tTime=1008.187626&hasCheckOne=false&hasCheckTwo=false&hasCheckThree=true&firstUpdate=false

userIdcourseId用xxx代替,其中userId身份证号做为判断依据,scoId为当前观看地址中的itemidhistoryId为历史ID,addTime为增加的时间,totalTime为总时间,currentTime为当前播放时间,hasCheckOnehasCheckTwohasCheckThreefirstUpdate为判断,于本文测试无用,暂不自多说。

Cookie中的信息自不必多说,这个为自己的登陆信息。咱们首先在伪造的请求则是请求中的内容。

相同的请求测试一下。

某大学继续教育平台刷课分析

4.png

状态为-1,出现了错误。那么说明还是有着验证的,如何寻找到验证呢?
接下来开始寻找关键的JS代码段,来查看JS代码,寻找可能存在的验证。

关键字

关键字为updstatus,为什么选择updstatus,可以看上面的请求地址中,他的文件为updstatus,所以咱们来寻找播放页面所有的JS文件里面,哪个文件包含了updstatus

某大学继续教育平台刷课分析

5.png

可以看到在地址中:https://cc9.mynep.com.cn/open/player/jobplayer.js。

存在了updstatus关键字,下载下来这个文件。

某大学继续教育平台刷课分析

6.jpg

JS代码段:

        updateStatus: function(finished) {                if (st_updating) return;                //if (!finished && Job.conf.lastViewedTime == 0) return; //时间点为0时不提交                st_updating = true;                var obj = {};                obj.userId = Job.conf.userId;                obj.courseId = Job.conf.courseId;                obj.scoId = Job.conf.scoId;                obj.historyId = Job.conf.historyId;                //obj.addTime = Job.conf.updInterval;//新增学习时间,单位秒                if (Job.conf.updStime) {                        var stime = (new Date()).getTime();                        var diff_time = Math.min((stime - Job.conf.updStime) / 1000, Job.conf.updInterval);                        if (diff_time < 0) diff_time = 0;                        Job.conf.updAddTime += diff_time;                        Job.conf.updStime = stime;                }                obj.addTime = Math.floor(Job.conf.updAddTime);//新增学习时间,单位秒                Job.conf.updAddTime -= obj.addTime;                obj.totalTime = Job.conf.totalTime;                if (finished) {                        obj.finished = 1;                        obj.currentTime = 0;                } else {                        obj.currentTime = Job.conf.lastViewedTime;//当前时间,可用来更新最后一次访问时间,学习到达最远时间点等                }                obj.hasCheckOne = Job.conf.hasCheckOne;                obj.hasCheckTwo = Job.conf.hasCheckTwo;                obj.hasCheckThree = Job.conf.hasCheckThree;                obj.firstUpdate = Job.conf.firstUpdate; //第一次提交时,更新,用于统计学习次数                Job.conf.firstUpdate = false;                $.ajax(Job.conf.updStatusUrl, {type: 'POST', data: obj, dataType: 'xml'}).done(function(xml) {                        console.log('update status');                        if (xml) {                                var status = Number($(xml.documentElement).find('>status').text());                                if (status == -1) {                                        Job.player.pause();                                }                                if (!Job.conf.historyId) {                                        var historyId = Number($(xml.documentElement).find('>historyId').text());                                        if (historyId) Job.conf.historyId = historyId;                                }                                window.onUpdstatus && window.onUpdstatus(status);                        }                }).always(function() {                        st_updating = false;                });        }

网站的程序员很贴心啊,还给我备注上了。

基本这个JS代码段看的也是半懂不懂,但大概意思是可以看出来了。

userId=xxxx&courseId=xxxx&scoId=27463&historyId=272631&addTime=5&totalTime=1149.619955¤tTime=1008.187626&hasCheckOne=false&hasCheckTwo=false&hasCheckThree=true&firstUpdate=false

上文所说的这些参数都有涉及。其中最关键的属historyId、和addTime

obj.addTime = Math.floor(Job.conf.updAddTime);//新增学习时间,单位秒
if (!Job.conf.historyId) {        var historyId = Number($(xml.documentElement).find('>historyId').text());        if (historyId) Job.conf.historyId = historyId;        }        window.onUpdstatus && window.onUpdstatus(status);        }

addTime为新增的时间,但如果返回正确的话,那么会根据这个时间来相应的增加时间。
再然后重点的是historyId参数。
首先

var historyId = Number($(xml.documentElement).find('>historyId').text());