jidesheng6 发表于 2020-3-18 21:13

记录一次对学校网课平台的分析

本帖最后由 jidesheng6 于 2020-3-19 00:05 编辑

# 为什么写这篇文章?

- **更多的是记录这次分析过程,尽管很简单**
- **网课真的挺烦人,学的东西也没啥用处**

---

## 我是怎么做的-刷网课时长 AND 刷课程点击

**首先来看一下学校网课平台的页面,很简陋【因为隐私问题网站不会在这篇帖子中展示,包括任何出现的人名等信息】:**







**一开始我是想尝试分析一下登录的【登录的我分析了最后,但是没有成功,后面会提到他的登录流程】,看页面那么简陋,就去看看课程那边抓包能不能抓到啥吧,刚进到下面这个页面我就有点愣住了:


不知道他的判断机制是什么,看到这个PDF文件的小箭头我就打算用Jquery选择器选一下这个next执行一个click动作吧:

发现他是可以的,于是就了个循环,来执行这个操作,自己看到页数就可以了,最开始调试就是不用代码获取,自己写死了:**

```JavaScript
var a;
for(a=0;a<10;a++)
{
      $("next").click();
}
```

**等我执行完再返回课程列表看学过的课,我发现他是这样的:

仔细想了一下,难道说看完就可以了吗,我都没有仔细看,于是我又点进去了一个文件,但是这次我没有看,直接返回,发现系统显示我已经学完了,那我就明白了:点进去=学过
按照这样来说的话:只要我们在当前课程页面把所有的PDF文件都点击一次不就可以了吗【其实我第一次没有想到这个问题,我接下来是去分析了视频来着】,
后来又去看了一下视频,发现视频也是这样,但是后台如果记录下来怎么办呢,因为视频是有播放时长的,你当前播放到哪里他都是有记录的。
之前有看过别人写的文章,里面提到有些视频通过后台提交当前播放位置来记录所学位置,所以我打开了调试器查看我们学校是不是也是这样来判断的:





点击播放没多久,在调试器中就出现了一条新的请求,于是看一下是什么东西:

在图中我注意到一个很显眼的参数:timepoint,字面翻译过来叫做时间点,于是我就看了一下当前视频播放到哪里了**






**上图可以看到,大概是2秒,但是我也不确定,又等了会儿,出现了新的请求,比之前多了几秒,这里不放图片了哈,发现是和当前播放位置对应起来的
所以猜测这条URL携带的timepoint就是提交给服务器当前用户视频播放的位置,于是我放在浏览器中进行请求,返回结果和后台自动发送的返回是一样的,
同时这个也让我注意到了一个细节:在刚才的请求中,比较关键的就是课程ID和当前的文件ID,在请求参数中没有发现任何用来鉴别用户的参数【我自己没有系统学过这些服务器认证用户的知识,后来查资料知道的,那个cookie中的jessionid就是客户端和服务器保持联络的玩意,用那个鉴别用户】,所以我猜测,也许不需要进行登录模拟了,直接把头部cookie带上说不定就可以了,过期了大不了我再获取一次

之后返回刷新可以看到网课的上次保存时间【这个图很早了,这个方法好像失效了,刚才没成功,找了个以前成功的来凑着看】,可以看到记录的时间可以随便更改


但是目前是失效了,后来无聊的时候又想到了用JavaScript控制不就可以了吗,设置当前进度条位置:**

```JavaScript
var e = document.getElementById("example_video_1_html5_api")
e.currentTime=1000
```

**也是可以的
我原本以为我做完这些我课就可以不用管了,当我回到课程主页看到这个的时候心态有点崩了:

他有一个学习的总时长,我当时的时间是32分钟,规定的两门课一门是240分钟还有一门是230分钟,一开始天真的想用Fidder更改这边显示的时间,然后等他把数据一起交给服务器,现在看起来有点傻,等我能看到时间的时候服务器就已经知道我有多久了,到时候也是不会把本地这个带上去,带的根本不是这里的,应该是我在学习页面多久他就给服务器提交我在的时间,于是我就想,这样说来是不是也和视频时长一个原理呢。
于是打开一个PDF,继续抓包【因为PDF没有播放时长什么的】,打开PDF之后开启网络抓包,等待了一会儿第一条包出现:





又等了一会儿,发现有多条数据包在发送,时间好像还是挺有规律的,不管三七二十一,我也不知道是不是,用python写一个小demo试试看就知道了**

```python
#--* coding:utf-8 --*
import requests,time
'''
网课刷时长脚本
/@author:jidesheng
/
'''
CourseHeartUrlList = ["url?playStatus=false&isResourcePage=true&courseVersionId=4db484e151c74cf486cb641f43d79d2a&activityId=01c34bcf2e1e11ea85dd005056b13345&type=1&isStuLearningRecord=2&token="
                      ,"url?playStatus=false&isResourcePage=true&courseVersionId=8398e23855d44cbdbe60109e52e54121&activityId=0a69188c2cf711ea85dd005056b13345&type=1&isStuLearningRecord=2&token="]
'''
/@CourseHeartUrlList中存放的是个人Heart链接列表,自行替换
OneUrl = CourseHeartUrlList
TwoUrl = CourseHeartUrlList
UserCookieDict = {"Cookie":"JSESSIONID="}
'''
/@UserCookieDict中Cookie:后面是自己的cookie值否则无法正常刷时长,也需要自己获取替换
'''
'''
/@下面开始进行网课刷课
'''
while 1:
    try:
      time.sleep(1)
      ResponeText1 = requests.get(OneUrl,headers=UserCookieDict).json()
      ResponeCode1 = ResponeText1["code"]
      ResponeText1 = requests.get(TwoUrl,headers=UserCookieDict).json()
      ResponeCode2 = ResponeText1["code"]
      ifResponeCode1 != "SUCCESS" or ResponeCode2 != "SUCCESS":
            print(u"Cookie可能过期,请及时更新")
            break
      else:
            print(u"执行无异常,正在执行中...")
    except:
      continue
    '''
    /@使用捕获异常防止发生假性网络中断导致脚本异常结束
    '''
`
```

**[上面的代码是我后来完善的结果,在测试中发现只需要携带cookie的jsessionid就可以了,过期重新获取一次就行],测试了能有一小时,每次时间都在变化,有次能证明这个就是提交给服务器进行在线时长统计的接口了。
现在回到上面说过的“点进去=学过”,我分析了一下单门课程页面:

所有的pdf文件类名都是“activity doc”,所有的视频文件类名都是“activity video”


    所以我们只要写一条JavaScript语句,获取这些类的数量,进行循环点击就可以了**

```JavaScript
var x = document.getElementsByClassName("activity doc")//获取所有activity doc类
var l = x.length//获取其数量
for(var n=0;n<l;n++)
{
    x.click()//集合中每一项进行点击
}
```

**只要像上面一样在Console控制台中输入就可以进行全部点击了,当然浏览器可能会有一丢丢卡,最后在随便一个标签页右键关闭其他标签刷新一下就能看到结果了,视频也是同理,doc换成video就可以了**

------

## 登录分析 AND 答案的获取

**在写了一段时间之后感觉每次重新获取Cookie好像挺麻烦的,于是就想着,进行模拟登陆,使用session持续连接不就没那么麻烦了吗,也不用登录什么的,还能获取一些基本信息[网课学习时长,有没有新的作业布置什么的],【当然啦,登录只是进行了分析,没有成功实现,技术不到家】**
**照例使用调试器进行网络抓包,看看他的登录流程是什么样子的


重新登录了一遍,发现一条带有login字样的URL,看了一下请求,是post请求,携带的参数如上图,有用户名,加密的密码,验证码,还有一个固定的参数,
要是明文还好说,不用分析那么多,现在只能在里面搜搜看有没有UserPassword这个字符串了,因为要从客户端把密码加密,一定要获取输入框里面的内容,所以就一定可以搜得到,去抓js的包,一个文件一个文件的搜搜看,如下图所示,jQuery,layer,这种文件一般不用看了,是些库文件,里面没有我们想要的
最后我在head.js文件中找到了Userpawword:


我们接着往下看


图中开发人员注释的很清楚,首先获取了加密公钥然后把传来的密码进行RSA加密,获取加密公钥的地址是:/user/getRSAPublicKey+当前时间戳,我们看看能不能在调试器中找到这个文件,然后根据他的构造方式来生成一个,和提交过去的密码进行比对,来验证我们的想法



我们在XHR中找到了这个地址,打开看一下



**


我们回到之前的js代码中看一下,有一个data.publicKeyStr,先不管这个是啥意思,我们可以看到在获取公钥那边有一个字符串也是publicKeyStr,所以推测这个就是公钥了,
于是我们准备在控制台中进行验证









虽然我们可以看到密码不是完全一样的【每次公钥都是不同的】但是长得差不多,既然这样就要来试试看模拟登陆了**

**我们还要一个验证码,来看看验证码的接口:


上面就是验证码的接口,可是python里面怎么用RSA呢,我也不会。。。百度了一份别人写好的,自己改了改**

```python
#--* coding:utf-8 --*
import requests,time,base64,subprocess
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as pkc#不知道为什么这么写
#安装的模块: pycryptodome
def GetRsaKey(Password="285912"):
    SchoolCourseNetHost = "jsou.cn/"
    RsaPublicUrl = SchoolCourseNetHost + "jxpt-web/user/getRSAPublicKey?date=" + str(int(time.time()))
    RsaJsonInfo = requests.get(RsaPublicUrl).json()
    PublicKey = "-----BEGIN PUBLIC KEY-----\n" + RsaJsonInfo["publicKeystr"] + "\n-----END PUBLIC KEY-----"
    RsaKey = RSA.importKey(PublicKey)
    RsaEn = pkc.new(RsaKey)
    Raw_Password = Password
    EnPassword = base64.b64encode(RsaEn.encrypt(Raw_Password))
    return EnPassword
def VerCode():
    VerCodeUrl = "pt-web/user/getImage?type=1"
    CodePicByte = requests.get(VerCodeUrl).content
    with open("ver.jpg","wb") as f:
      f.write(CodePicByte)
    subprocess.Popen("ver.jpg",shell=True)
    vercodetext = raw_input("请输入看到的验证码:").replace(" ","")
    return vercodetext
def loginMain():
    login_url = "http://web/user/login"
    #h = {"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"}
    da = {"userName":"202","userPassword":GetRsaKey(),"userLoginPicCode":VerCode(),"checkpic":1}
    print(requests.post(login_url,data=da))
    #print(type(da))

loginMain()

```

**[结果就是上面的代码得到cookie是没有用的,验证码识别做起来麻烦,而且这也就是个小demo就直接肉眼识别好了],所以这个是放弃了,登录分析到这里也就结束了**

**接下来说一下答案的获取,答案的获取我也是一次无聊看了一下作业的源代码发现里面有答案的**

**首先来到作业的页面看一下源代码:**
**我们可以在开头不远处看到一大串JavaScript代码,而且里面有很多中文:**







**仔细观察发现还和题目有点像,可以肯定就是答案了,接着我们把她拿去格式化**



**然后拿回本地看一下**



**看到一个correAnswer,我对这个词比较敏感,以前在kfc上班的时候考试,在家就抓包找答案,答案字样也是这个单词,所以就可以肯定这个就是答案啦
满分截图:**




## 突破签名限制 AND 补交作业

**这个是我今天刚发现的,根据以上协议我做了个刷网课的工具,从最初的1.0(py)已经更新到了4.0(exe),所以在签名里面给个地址给大家下载,结果就给我提示这个:**




**于是我就想突破这个签名限制,于是迅速定位到签名标签**




**判断长度什么的应该是由JavaScript来控制完成的,所以在里面搜索这个id名称**




**从上图我们可以看到,这里有一条判断个性签名的长度,超过20他就弹出提示。**

**最开始我是想在这个页面里面直接修改逻辑然后让他执行,然而结果就是:不可以,因为这个页面已经渲染完成了,怎么改都没用。**

**那就用Fidder来改,首先拦截全部,然后再刷新一次页面:**




**点击刚才那个页面,选择b黄色的按钮,拦截返回,在下面修改页面的逻辑,改成150【因为多次试验过150字符是服务器接收的,否则返回401】,然后点击绿色按钮运行









**取消拦截,把之前请求全部释放**






**然后再去看一下页面的逻辑,已经改成150了,这时候修改签名就没限制了,这里就不演示了。**






**既然签名也是要上传服务器然后到前台展示的,一定也是有接口,所以又看了看那段JavaScript代码,发现如下地址:**





**图中使用post请求向目标地址携带signatures参数来修改签名,试了几次也是可以的**





**接着来说一下补交作业,因为今天是18号了,我有一个作业15号就要交,但是我忘记去交了,但是去看了一眼,已经没有回复的按钮了**

**转念一想,这玩意也是提交服务器啊,不知道有没有被关,试试看吧,于是找到一个还可以回复的帖子,抓个包,抓到如下结果:**




**发现和我刚才提交的一样,所以这个就是讨论的接口地址了,再来看看他的get参数---**




**本来还想在代码里面找,看了一眼url,这个在url里面就是有的---**



**转到postman来把不能回复的帖子按照这个构造一次发个包看看---**




**成功了---**




## 结语
**到这里我的分析就结束了,其实7点多就应该完成发表的,写完了,忘记保存,拖动图片的时候不小心页面直接没了,真心想哭,哎,我也是把这段时间上网课做的事情分享出来,以后再看的时候也是别有一番风味,还请各位大佬多多指点哇,嘿嘿**

---


# 更新
**刚才发现了学校提交评论的漏洞,文本允许提交HTML的p标签,在p标签内嵌套script标签,浏览器自动闭合,可以实现XSS攻击。**

jxf269 发表于 2020-4-11 12:43

特意翻过去看了一下回帖内容,感觉没啥自以为是的行为,也没有求挂,或许你认为求教程就是求挂。
有些东西你不愿意相信,我也不能强求。
非诚勿扰刚刚开播时,我就说了,那些女的是请来做戏的,男的也是。没一个人信。电视综艺那个套路,你一个新人若是指出来了,会被领导打压的。
我工作面试时就遇到了,领导讲解了设备的工作流程,然后我说挺简单,不就是……然后领导脸黑了,这技术是他们花大代价买来的,然后还经过这些年的更新升级,却被我这个门外汉说的这么简单,还好,自己比较识趣,发现不对劲,赶紧说谢谢老总给我开后门,讲解的这么通俗易懂,让我一下领悟到厂品的精髓所在,然后大家都笑了。还好我认错及时,不然就会被扣一个不稳重、自夸的帽子。而事实就是,那东西就是那么简单。
再说一下我做现场指导的事吧,本来是老总的事,可他们临时要签个合同,就把我扔那儿了,然后第二天那边领导叫了二十多人到现场学咋操作设备,我没见过这么大阵仗(我以为一对一或者一对二),很紧张,有些懵,那边领导看出来了,安慰了几句。然后我就鼓起勇气来了,说太紧张了,其实我们设备操作挺简单,不然我们领导也不会让我这个刚入职的小兵来做这事了,为了体现有多么简单,我需要两人配合一下,一人读设备门上的操作说明,一人操作,读第二遍时大家看我手指在原理图上的走向。就这样,一套走下来,我说还有啥不明白的可以提问,然后是大家都不明白,我就说换个方式吧,你们想要我这设备干什么?好,你这要求,看操作说明第一条,大家读一下,看我的操作。好了,就这么简单。若想干这个,也是读一下,这边操作一下。原理图不用管了,那个便于理解记忆画的。咱们不会操作的,就按文字说明操作把。再不会的,我可以一对一的教。当然现场还是有人嘴里说还是不会。然后那个领导不耐烦了,人家说的这么简单,你们还不会,你们这些高才生到底要咋教,我本来也看不懂那原理、流程图,但是我识字,我操作一下给你们看,然后又用手在原理图上跟着文字走了一遍,操作完,又训了一下他们现场的人,说明都不会看,看这种说明,初中生都会操作,你们大学生就不会了,再说白了说明就在面板上,不就相当于开卷考试吗,你们可真给我长脸。好了,你们自己交流一下,再不会,来找我,我让你你回炉去。
说了这么多,其实就是想说,有些东西就是这么简单,你跟着说明来操作一通就解决了,原理啥的,你不需要深入。而有些人非得把事情复杂化。

jxf269 发表于 2020-3-19 14:28

楼主讲解的很清楚,我这个门外汉也能看懂个大概,也可以依葫芦画瓢,实现点乐趣。
有没有人出一篇js刷H5私服页游的教程啊,比如说,有些东西一天只让买5个,咱把他改成无限的,还有快速通关的,抓包破,要电脑,不值得。学一门语言,得先让他尝到甜头,他才会往深入学习。一开始说要这个那个基础的,一下就把人吓住了,开始教点简单的,容易举一反三的,让他慢慢融入这个环境,然后慢慢的引导他独立分析,然后告诉他这些有教程的,上面讲解的很清楚,他自然而然的就会去看基础教程了。比如说这个js,开始你就让学基础,肯定不乐意学,楼主这篇文章一出,就会激起我对js的兴趣,学会js居然还可以这么作弊,你若是把这教给初中生,他们肯定也会感兴趣的。

刚刚我说的H5破解,有人肯定会说人家那边有验证,破不了,这样就打击了别人学js的心情。或许正是这样,人家才会放有漏洞的版本,吸引你去破,你破解了,他再修复漏洞,然后又爆新的漏洞,然后你再寻找新的漏洞,这样如此循环,然后就成产业链了。其实一开始就可以放bug少的版本的,但若是这样做了,后期的钱从哪里来?
游戏就是这个模式,至于游戏外挂,你们真相信这些bug是自己发现的,这里面有部分bug就是内部特意透露的,必须形成产业链,不然后期维护费收不到啊。
同理,楼主说的这个学习网站,开发公司早就知道这些bug,咋修复也知道,就等着拿钱呢。

Wonshourhand 发表于 2020-3-18 21:21

看不懂,但是,n.....B

520Sakura 发表于 2020-3-18 21:24

厉害(✪▽✪)

涛之雨 发表于 2020-3-18 21:26

嘿嘿嘿。
咱是超星,我写的是油猴插件{:301_986:}
(墙裂吐槽cx的js全都是错误。。。。)

叶小白 发表于 2020-3-18 21:27

没看懂,但是好像挺牛B{:301_1000:}

SVIP9大会员 发表于 2020-3-18 21:30

厉害 收藏了 今天热心送完了 明天给你

刘留留 发表于 2020-3-18 21:31

讲的很详细,多谢分享

pwp 发表于 2020-3-18 21:49

我这个老人家最近也在学js,二话不说赶紧给个评论以资鼓励。

正己 发表于 2020-3-18 22:02

支持一下

luo_bo 发表于 2020-3-18 22:04

讲的很好,什么时候我也来搞搞我们学校的网课平台
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 记录一次对学校网课平台的分析