闲来无事系列-雨课堂抓包发包玩法(娱乐向)

今天开心的玩游戏,突然发来通知,增加了一门课程,打开一看,噢,原来是雨课堂

其实,本来通过多开挂机的方式,完成了大部分的课程了,但是,还是想探究一下,这个原理,于是乎,留了几节课,用来实验。

 

为什么要这么玩呢,因为很久之前(非本次),某网站的长达几个小时的视频,通过python伪造请求,可以做到10s看完,非常有意思

这个网站的视频逻辑是不断发包请求

但是每个包的请求的视频点,不得超过太长时间,否则失效。以下为破解代码

import requests
import random
import time
import math
courseId = "****"
videoId = "****"
longtime = 1000
viewUUID = "****"
cs = {
        "_fecdn_":"1",
        "gr_user_id":"****",
        "****_gr_session_id":"****",
        "grwng_uid":"****",
        "****":"true",
        "UniqueKey":"****",
        "lebanban_auth":"****",
        "fb_auth":"****",
        "****_gr_last_sent_sid_with_cs1":"****",
        "****_gr_last_sent_cs1":"****",
        "****_gr_cs1":"****",
        "JSESSIONID":"****"
    }
hs = {
        "Host":"www.****.com",
        "Connection":"keep-alive",
        "Accept":"application/json, text/javascript, */*; q=0.01",
        "X-Requested-With":"XMLHttpRequest",
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4139.0 Safari/537.36 Edg/84.0.516.1",
        "Content-Type":"application/x-www-form-urlencoded",
        "Origin":"https://www.****.com",
        "Sec-Fetch-Site":"same-origin",
        "Sec-Fetch-Mode":"cors",
        "Sec-Fetch-Dest":"empty",
        "Referer":"https://www.****.com/course/introduction/"+courseId+".shtml",
        "Accept-Encoding":"gzip, deflate, br",
        "Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
    }

monitor = {
    "courseId":courseId,
    "videoId" : videoId,
    "resourceType":"0",
    "currentSec":0,
    "viewUUID":viewUUID,
    "bufferTime":0
    }

end = math.floor(longtime * 60)
for c in range(1,end+5,5):
    tranceId = (str(time.time()*1000)[:13]+str(random.randint(10,99)))[-11:];
    monitor["currentSec"] = c
    monitor["bufferTime"] = random.randint(1,99)
    url = "https://www.****.com/learn/common/playstatistics.json?traceId=" + tranceId
    rsp = requests.post(url,headers=hs,cookies=cs,params=monitor)
    print(rsp.text)

回归正题,一起来了解一下雨课堂的情况。

反手就是打开 fiddler,点开课程抓包看看情况。

(远不止这些包)

每次请求,和得到的回包,都用notepad++记录一下,以便于之后,通过请求获取具体的课堂信息等

除了分析了300多行,想了解一下,每个包的目的等。

首先,我先教大家使用notepad++里面,好用的js和json的格式自动排版工具

JSTool和JSON Viewer。。。。。JSON Viewer可以一键将json格式化

至于JSTool,好羞愧啊,刚开始,有些参数没有弄明白,我直接去后台扒JS看了,emmmmmm,乱七八糟的(混淆了),放弃了。

 

接下来,我将具体说明每个请求和每个包的作用(*为手动马赛克)

先放上感觉没有用的包。

#获取学校信息(暂时没啥作用,因为返回来的包,没什么有价值的东西)
GET https://****.yuketang.cn/edu_admin/get_custom_university_info/?current=1 

GET https://****.yuketang.cn/edu_admin/get_custom_university_info/?host_name=****.yuketang.cn&no_loading=true&term=latest&uv_id=0000

#导出列表(暂时没用)
GET https://****.yuketang.cn/edu_admin/display_data_dashboard/export_list/?no_loading=true&page_size=10&page=1
#回包
{"msg": "", "data": {"exporting_count": 0, "page_size": 0, "task_list": []}, "success": true}

回包含有我需要的参数的包。

# 获取课堂信息
GET https://****.yuketang.cn/mooc-api/v1/lms/learn/classroom_info/?classroom_id=****&sign=****&term=latest&uv_id=****
# 回包
{
	"msg": "",
	"data": {
		"notice": false,
		"end": 1611000000000.0, #课堂的结束时间(已随机修改)
		"name": "***",
		"start": 1604000000000.0,#课堂的开始时间(已随机修改)
		"course_name": "***",
		"is_class_end": false,
		"teacher": {
			"picture": "***",
			"name": "***"
		}
	},
	"success": true
}
# 获取该课堂的章节
GET https://****.yuketang.cn/mooc-api/v1/lms/learn/course/chapter?cid=****&sign=****&term=latest&uv_id=**** HTTP/1.1

# 部分回包
"section_leaf_list": [{
				"order": 0,
				"leaf_list": [{
					"name": "Video",
					"is_locked": false,
					"start_time": ****, # 开始时间
					"chapter_id": ****, # 章节id
					"section_id": ****, # 部分id(参数可能有用)
					"leaf_type": 0,
					"id": ****, #(参数可能有用)
					"is_show": true,
					"end_time": 0,
					"score_deadline": 0,
					"is_score": true,
					"is_assessed": false,
					"order": 0,
					"leafinfo_id": **** #叶子id (参数可能有用)
				}],
				"chapter_id": ****,
				"id": ****,
				"name": "章节名称"
			}

下面这个包,几乎包含了所有的信息,大概如下

# 通过课堂名,章节名,还有sign还有university_id,获取信息
GET https://****.yuketang.cn/mooc-api/v1/lms/learn/leaf_info/****/****/?sign=****&term=latest&uv_id=****

# 回包
{
	"msg": "",
	"data": {
		"sku_id": ****, # sku_id有用
		"is_deleted": false,
		"name": "Video",
		"content_info": {
			"status": "post",
			"expand_discuss": false,
			"score_evaluation": {
				"score_proportion": {
					"proportion": 0.5
				},
				"score": 1.0,
				"id": 6,
				"name": "****"
			},
			"download": [],
			"is_score": true,
			"is_discuss": true,
			"remark": {
				"remark": ""
			},
			"cover_desc": "",
			"cover_thumbnail": "https://qn-next.xuetangx.com/****.jpg?imageView2/0/h/500",
			"media": {
				"lecturer": 0,
				"ccid": "****",
				"start_time": 0,
				"cover": "https://qn-next.xuetangx.com/****.jpg",
				"ccurl": "****",
				"duration": 0000,
				"end_time": 0,
				"live_palyback_url": "",
				"live_url": "",
				"type": "video",
				"teacher": []
			},
			"cover": "https://qn-next.xuetangx.com/****.jpg",
			"leaf_type_id": null,
			"context": "<!DOCTYPE html><html><head></head><body>\n</body></html>"
		},
		"classroom_id": "****",# classroom_id有用
		"locked_reason": null,
		"user_role": 3,
		"leaf_type": 0,
		"id": ****,
		"has_classend": false,
		"university_id": ****,# university_id有用
		"be_in_force": false,
		"score_deadline": 0,
		"course_id": ****,# course_id有用
		"user_id": ****,# user_id有用
		"is_score": true,
		"teacher": {
			"org_name": "****",
			"picture": "****",
			"name": "****",
			"department_name": "****",
			"intro": "****",
			"job_title": "****"
		},
		"is_assessed": false
	},
	"success": true
}
# 获取user基本信息
GET https://****.yuketang.cn/edu_admin/get_user_basic_info/?term=latest&uv_id=****

# 回包
{
	"msg": "",
	"login_status": true,
	"data": {
		"school_new_name": "https://qn-next.xuetangx.com/****.png",
		"year_terms": [
			{
				"year_name": "2020-2021学年",
				"terms": [
					{
						"name": "第一学期",
						"value": "202001"
					}
				]
			}
		],
		"is_email_user": false,
		"school_id": ****,
		"is_assistant_teacher": false,
		"all_year_terms": [
			{
				"year_name": "2020-2021学年",
				"terms": [
					{
						"name": "第一学期",
						"value": "202001"
					}
				]
			}
		],
		"is_only_read": false,
		"current_year_term": "202001",
		"user_number": "****",
		"platform_id": 3,
		"school_color_list": [
			"",
			""
		],
		"is_fake": false,
		"school_official_website": "http://www.tsinghua.edu.cn/publish/newthu/index.html",
		"user_info": {
			"user_id": ****,
			"avatar": "****",
			"name": "****"
		},
		"permissions": [],
		"is_auditor": false,
		"department_id": ****,
		"school_icon": "https://qn-next.xuetangx.com/****.png",
		"school_evaluation": false,
		"school_name": "****",
		"user_role": 3,
		"is_edu_support": false,
		"session_id": "****",
		"department_name": "****",
		"school_type": 1,
		"school_new_logo": "https://qn-next.xuetangx.com/****.png"
	},
	"success": true
}

这里自动跳过了暂时无用包

# 获取视频的观看进度

GET https://****.yuketang.cn/video-log/get_video_watch_progress/?cid=****&user_id=****&classroom_id=****&video_type=video&vtype=rate&video_id=****&snapshot=1&term=latest&uv_id=****

# 
{
	"****": {
		"last_point": ****, # 最近的一次
		"completed": 0,
		"first_point": ****,
		"video_length": ****,# 视频长度
		"rate": ****
	},
	"message": null,
	"code": 0,
	"data": {
		"****": {
			"last_point": ****,
			"completed": 0,
			"first_point": ****,
			"video_length": ****,
			"rate": ****
		}
	}
}

这里提一下,可以利用爬虫来获取讨论区的内容并筛选

讨论区也是学生的作业,每个人必须要评论,可以通过爬虫获取,分析,重组评论,直接发包评论(有想法,没有去实现)

# 获取评论区

GET https://****.yuketang.cn/v/discussion/v2/comment/list/****/?_date=****&term=latest&offset=0&limit=10&web=web 

# 回包

{
	"msg": "",
	"data": {
		"good_comment_list": {
			"count": 0,
			"previous": null,
			"results": [],
			"next": null
		},
		"new_comment_list": {
			"count": 64,
			"previous": null,
			"results": [
				{
					"to_user": ****,
					"liked": 0,
					"user_id": ****,
					"is_essence": 0,
					"replys": [],
					"deleted": false,
					"topic": ****,
					"classroom_id": ****,
					"ids": [
						****,
					],
					"commented": 0,
					"content": {
						"text": "****",
						"upload_images": []
					},
					"user_info": {
						"user_id": ****,
						"name": "****",
						"school_number": "****",
						"role": 5,
						"avatar": "https://qn-next.xuetangx.com/****?imageView2/1/w/100/h/100",
						"nickname": "****"
					},
					"is_top": 0,
					"create_time": ****,
					"score_status": 0,
					"is_self": 0,
					"is_praise": 0,
					"score": 0,
					"id": ****
				},

视频都在这个包,可以通过视频源地址下载(我不清楚网站有没有提供下载地址,没了解)

# 获取某视频的URL
https://****.yuketang.cn/api/open/audiovideo/playurl?_date=****&term=latest&video_id=****&provider=cc&file_type=1&is_single=0 


# 回包
!!!!大家看到wsSecret了吗,从这里可以获取,其他地方好像也可以,我记不清了
{
	"msg": "",
	"data": {
		"playurl": {
			"sources": {
				"quality20": [
					"https://ws.cdn.xuetangx.com/****-20.mp4?wsSecret=****&wsTime=****"
				], # 一个是高清的,一个是标清的,两个视频的地址
				"quality10": [
					"https://ws.cdn.xuetangx.com/****-10.mp4?wsSecret=****&wsTime=****"
				]
			},
			"group": "chinanetcenter"
		}
	},
	"success": true
}
#大家都知道, 字幕是另外加的,通过这个请求,可获得所有字幕

https://****.yuketang.cn/mooc-api/v1/lms/service/subtitle_parse/?c_d=****&lg=0 
# 下面是视频观看时发送的心跳包(!很重要,模拟观看用)
{
	"heart_data": [{
		"i": 5,
		"et": "loadstart",
		"p": "web",
		"n": "ws",
		"lob": "cloud4",
		"cp": 0,
		"fp": 0,
		"tp": 0,
		"sp": 1,
		"ts": "****",
		"u": ****,
		"uip": "",
		"c": ****,
		"v": ****,
		"skuid": ****,
		"classroomid": "****",
		"cc": "****",
		"d": 0,
		"pg": "****",
		"sq": 1,
		"t": "video"
	}, {
		"i": 5,
		"et": "seeking",
		"p": "web",
		"n": "ws",
		"lob": "cloud4",
		"cp": ****,
		"fp": 0,
		"tp": ****,
		"sp": 1,
		"ts": "****",
		"u": ****,
		"uip": "",
		"c": ****,
		"v": ****,
		"skuid": ****,
		"classroomid": "****",
		"cc": "****",
		"d": ****,
		"pg": "****",
		"sq": 2,
		"t": "video"
	}, {
		"i": 5,
		"et": "loadeddata",
		"p": "web",
		"n": "ws",
		"lob": "cloud4",
		"cp": ****,
		"fp": 0,
		"tp": ****,
		"sp": 1,
		"ts": "****",
		"u": ****,
		"uip": "",
		"c": ****,
		"v": ****,
		"skuid": ****,
		"classroomid": "****",
		"cc": "****",
		"d": ****,
		"pg": "****",
		"sq": 3,
		"t": "video"
	}, {
		"i": 5,
		"et": "playing",
		"p": "web",
		"n": "ws",
		"lob": "cloud4",
		"cp": 70,
		"fp": 0,
		"tp": 70,
		"sp": 1,
		"ts": "****",
		"u": ****,
		"uip": "",
		"c": ****,
		"v": ****,
		"skuid": ****,
		"classroomid": "****",
		"cc": "****",
		"d": ****,
		"pg": "****",
		"sq": 5,
		"t": "video"
	}, {
		"i": 5,
		"et": "pause",
		"p": "web",
		"n": "ws",
		"lob": "cloud4",
		"cp": ****,
		"fp": 0,
		"tp": 70,
		"sp": 1,
		"ts": "****",
		"u": ****,
		"uip": "",
		"c": ****,
		"v": ****,
		"skuid": ****,
		"classroomid": "****",
		"cc": "****",
		"d": ****,
		"pg": "****",
		"sq": 6,
		"t": "video"
	}]
}

还有许多包,这里就不赘述了。

既然大概的发包情况都了解了,那么,开始写代码吧,先把全局变量安排好

import requests
import random
import time
import math
import json
####################
csrftoken     = "0"
sessionid     = "0"
video_id      = "0"
classroom_id  = "0"
sign = "0"
university_id = "0"
####################
nowDate = str(int(time.time() * 1000))     # 跳动时间
theDate = str(int(time.time() * 1000))     # 全局时间
course_id = "123"             # cid
user_id = "123"               # user_id
sku_id = ""                   # sku_id
cc_id = ""                    # ccid
wsSecret = ""                 # wsSecret
####################
last_point = 0
first_point = ""
video_length = ""
heart_beat_time = 1
####################

接下来,构造请求头,cookies等json包

headers = {
    "Host"           : "0",
    "Connection"     : "keep-alive",
    "Accept"         : "application/json, text/plain, */*",
    "X-CSRFToken"    : csrftoken,
    "xtbz"           : "cloud",
    "university-id"  : university_id,
    "User-Agent"     : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
    "Sec-Fetch-Site" : "same-origin",
    "Sec-Fetch-Mode" : "cors",
    "Sec-Fetch-Dest" : "empty",
    "Referer"        : "https://0/pro/lms/" + sign + "/" + classroom_id + "/video/" + video_id,
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh-CN,zh;q=0.9"
}
heart_headers = {
    "Host": "0.yuketang.cn",
    "Connection": "keep-alive",
    "Content-Length": "881",
    "Accept": "*/*",
    "X-CSRFToken": csrftoken,
    "X-Requested-With": "XMLHttpRequest",
    "xtbz": "cloud",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
    "Content-Type": "application/json",
    "Origin": "https://0.yuketang.cn",
    "Sec-Fetch-Site": "same-origin",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Dest": "empty",
    "Referer": "https://0.yuketang.cn/pro/lms/" + sign + "/" + classroom_id + "/video/" + video_id,
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh-CN,zh;q=0.9"
}
cookies = {
    "csrftoken"     : csrftoken,
    "sessionid"     : sessionid,
    "university_id" : university_id,
    "platform_id"   : "3"
}

get_video_watch_progress = {
    "cid"         : course_id,   
    "user_id"     : user_id,  
    "classroom_id": classroom_id,
    "video_type"  : "video",
    "vtype"       : "rate",
    "video_id"    : video_id,
    "snapshot"    : "1",
    "term"        : "latest",
    "uv_id"       : university_id
}
leaf_info = {
    "sign"    : sign,
    "term"    : "latest",
    "uv_id"   : university_id
}
heart_beat = {
	"heart_data": [ # 自行构造,此为删减
        {
            "i": 5,
            "et": "heartbeat",
            "p": "web",
            "n": "ws",
            "lob": "cloud4",
            "cp": str(int(float(last_point))+ heart_beat_time * 5),
            "fp": 0,
            "tp": last_point,
            "sp": 1,
            "ts": nowDate,
            "u": user_id,
            "uip": "",
            "c": course_id,
            "v": video_id,
            "skuid": sku_id,
            "classroomid": classroom_id,
            "cc": cc_id,
            "d": video_length,
            "pg": "****",
            "sq": heart_beat_time,
            "t": "video"
	    }
    ]
}

接下来,通过GET https://0.yuketang.cn/mooc-api/v1/lms/learn/leaf_info/这个

def getInfor():# 获取信息
    url = "https://0.yuketang.cn/mooc-api/v1/lms/learn/leaf_info/" + classroom_id + "/" + video_id + "/"
    rsp = requests.get(url,headers = headers, cookies = cookies, params = leaf_info)
    jRes = json.loads(rsp.text)
    course_id = jRes["data"]["course_id"]
    user_id = jRes["data"]["user_id"]
    sku_id = jRes["data"]["sku_id"]
    cc_id = jRes["data"]["content_info"]["media"]["ccid"]
    print("详细信息查询" + str(course_id) + " : " + str(user_id) + " : " + str(sku_id) + " : " + str(cc_id))

通过模拟

def getClass():
    global heart_beat_time
    for i in range(10):
        url = "https://0.yuketang.cn/video-log/get_video_watch_progress/"
        rsp = requests.get(url,headers = headers, cookies = cookies, params = get_video_watch_progress)
        jRes = json.loads(rsp.text)
        last_point = jRes[video_id]["last_point"]
        first_point = jRes[video_id]["first_point"]
        video_length = jRes[video_id]["video_length"]
        print("第 " + str(heart_beat_time) + " 次视频进度查询" + str(last_point) + " : " + str(first_point) + " : " + str(video_length))

        nowDate = str(int(time.time() * 1000))     # 跳动时间
        url = "https://0.yuketang.cn/video-log/heartbeat/ "
        heart_beat["heart_data"][0]["ts"] = nowDate
        rsp = requests.post(url,headers = heart_headers, cookies = cookies, params = heart_beat)
        print("第 " + str(heart_beat_time) + " 次心脏:" + rsp.text)
        heart_beat_time += 1
        sleep(000000000000000000000000000000)

===============================================================

===============================================================

cookies等怎么获取呢

如果大家想了解更多这种原理等, 可以看看之前的cf活动领取器,通过抓包发包进行操作,超级方便。

还记得逆战当初出活动(貌似是爱丽丝)翻车了,通过穷举,获取红包,白嫖了好几百块的东西,233333333

 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值