2024寒假某研修模拟学习思路分析
本帖最后由 pwp 于 2024-2-4 00:02 编辑1、点击立即报名:
发现两个post,咱也不知道哪个post有啥用,都模拟一下:
import requests
url = "https://elearning-train-gateway.ykt.eduyun.cn/v3/spi/trains/action_rules?current_train_id=ee0d68b5-6a9d-441b-97dc-d52bfdfece83&action=access&need_verify_audit=true"
headers = {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9",
"authorization": "MAC id=\"7F938B205F876FC39BD5FD64A3C6E3CBBC682E5F9A58550F6BD9431CE859CF308D8C762D1AFFBAFECC7CF21AF76E4BDB127\",nonce=\"1706953412553:K218AKFG\",mac=\"RdDeqkQbGgPgWGleCn2JiYbFsQo6zknDjZx2sE=\"",
"cache-control": "no-cache",
"pragma": "no-cache",
"sdp-app-id": "e5649925-441d-4a53-b525-51a2f1c4e0a8",
"sec-ch-ua": "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site"
}
response = requests.get(url, headers=headers)
print(response.text)
import requests
url = "https://elearning-train-gateway.ykt.eduyun.cn/v2/spi/trains/ee0d68b5-6a9d-441b-97dc-d52bfdfece83/actions/async_joins"
headers = {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9",
"authorization": "MAC id=\"7F938B205F876FC39BD5FD64A3C8216721E3CBB2C0F6BD9431CE859CF308D8C762D1AFFBAFECC7CF21AF41C4BDB127\",nonce=\"1706953412840:CAPWS9EJ\",mac=\"HhPbxhQ0Psggvvpg1YYioggaJ3Pc/tUfaNGe0Zfepqs=\"",
"cache-control": "no-cache",
"content-type": "application/x-www-form-urlencoded",
"pragma": "no-cache",
"sdp-app-id": "e5649925-441d-4a53-b525-51a2f1c4e0a8",
"sec-ch-ua": "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site"
}
data = None
response = requests.post(url, headers=headers, data=data)
print(response.text)
能够模拟立即报名的前提是信息完整度100%。
前后端分离项目逆向成也Authorization,败也Authorization,首当其冲的是解决Authorization。
如上面代码片段所示,headers 中的Authorization是直接复制浏览器出来的,具体他是怎么产生的呢?
因为学历太低,根本不知道怎么形成的,只有暴力搜索:
这个函数好复杂,鼠标摆上去一个一个查看是什么意思:
e是一个链接 "https://uc-gateway.ykt.eduyun.cn/v1.1/users/452596678222?with_ext=true&session_id=637ec2d0-17bf-4108-b602-2a55xxxxxxcd"
t是get
n感觉是登录后的一系列参数:xxxxxxxxxxxx
进入这个函数,还有个Ge函数,是骡子是马溜出来看看:
根本看不懂!
真的费力,这不,He(i)和Ze(e, s, t, o)又是啥,javascript没学过,还带那么多参数,想想都可怕,要不,问问AI?
先解决He(i)
function He(e) {
return (new Date).getTime() + parseInt(e, 10) + ":" + Ne(8)
}
function Ze(e, t, n, r) {
var o = f.parse(e)
, i = t + "\n" + n.toUpperCase() + "\n" + o.relative + "\n" + o.authority + "\n";
return ee.HmacSHA256(i, r).toString(ee.enc.Base64)
}
差Ne函数,
function Ne(e) {
for (var t = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""), n = "", r = 0; r < e; r++)
n += t;
return n
}
再来
哦哦,原来是这个意思。
用python模拟出来:
import random
import time
def Ne(e):
t = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
n = ""
for i in range(e):
n += t
return n
def He(i):
timestamp = int(time.time())
return str(timestamp) + str(i) + ":" + Ne(8)
好了,解决完He(i),准备来解决Ze(e, s, t, o),
先看看这个函数是神马意思:
哦哦,原来是这个意思。
那么,就来下断点,运行,看看到底是啥。运行到此处的时候,鼠标摆上去,咋变量不显灵了?
一看log发现还有限制,这些蛛丝马迹可能就是后面能否模拟自动学习的关键,给截个图摆着:
重新运行到此处,感觉思路足见清晰:
成也Authorization,败也Authorization,20楼有大老说这个他也搞过,并不能模拟出来,我想这里就被套路了。
(因截图泄漏个人账号数据,择日重新上传
本帖最后由 pwp 于 2024-2-4 18:26 编辑
这个diff我是搜了好久才搜到他生成的地方,大家搜索的时候可以不再慢慢去找diff了,直接搜索t.saveToken函数就行了,这个函数原型如下,
t.saveToken = function(e, t) {
return e && !e.diff && (e.diff = e.server_time ? wt()(e.server_time).toNumber() - wt()().toNumber() : 0),
this._tokenStorage.set("token", JSON.stringify(e), void 0, t),
e
}
这个函数咋看也看不懂,让ai帮我们换一种写法并解释:
t.saveToken = function(e, t) {
if (e && !e.diff) {
e.diff = e.server_time ? wt()(e.server_time).toNumber() - wt()().toNumber() : 0;
}
this._tokenStorage.set("token", JSON.stringify(e), void 0, t);
return e;
}
这段代码是一个名为saveToken的函数,它接受两个参数:e和t。函数的作用是将一个包含令牌信息的对象e保存到本地存储中,并返回该对象。首先,函数会检查对象e是否存在且不包含diff属性。如果满足条件,它会计算diff的值并将其添加到对象e中。diff的值是通过将服务器时间(e.server_time)转换为数字并与当前时间相减得到的。接下来,函数使用this._tokenStorage.set()方法将对象e以JSON字符串的形式保存到本地存储中,键为"token",过期时间为t。最后,函数返回保存后的对象e。
这wt()又是啥,点进去后长这样:function V(e) {
var t = e.url
, n = e.headers
, r = e.data
, o = void 0 === r ? "{}" : r
, i = e.method
, s = void 0 === i ? "GET" : i
, a = e.isProxy
, c = void 0 === a || a;
n = K(K({}, F), n),
n.Host = z(t).host,
null === o["org_name"] && delete o["org_name"];
var u = {
$headers: n,
$body: o,
$method: s
}
, d = "$proxy=proxyhttp&bodys=".concat(encodeURIComponent(JSON.stringify(u)));
return c && (t += (t.indexOf("?") >= 0 ? "&" : "?") + d),
t = t.replace("?&", "?"),
new Promise((function(e, n) {
Z(t, {
prefix: "nd_uc_sdk_".concat(+(new Date).getTime())
}, (function(t) {
var r = arguments.length > 1 && void 0 !== arguments ? arguments : {};
if (t)
return "string" === typeof t ? void n(new L(t)) : void n(t);
var o = r.$status >= 200 && r.$status < 300 || 304 === r.$status || W(r);
if (o)
if (void 0 === r.$body && (r.$body = {}),
N()(r.$body))
e(r.$body);
else
try {
e(JSON.parse(r.$body))
} catch (_o) {
n(new L("UCSDK/SERVER_ERROR"))
}
else if (!1 === o && N()(r.$body))
n(r.$body);
else
try {
n(JSON.parse(r.$body))
} catch (_o) {
n(new L("UCSDK/SERVER_ERROR"))
}
}
))
}
))
}
问ai他说:这段代码是一个名为V的函数,它接受一个包含请求信息的对象作为参数。该函数的作用是发送一个HTTP请求,并返回一个Promise对象。 请注意,上述代码中的wt()函数未提供定义,因此无法确定其具体实现。
越搞越糊涂,没办法,直接执行这个函数看看是啥:
看起来是一个时间戳啊为了验证我的猜想我给他转换一下:而这个时间,视乎在哪里看见过:
我为了猜测他们是什么意思,我尽然无底线地运行了无限次:
最终和程序猿想到一块去了:服务器时间-当前时间。
服务器时间又哪里来的呢,其实就是登录成功后来的,为了验证我的猜想,我给他刷新了看,果不其然:
真的是啊,那所有参数都搞定了,就来模拟吧。
模拟前,需要注意的是,这里有个耿,大于5分钟就会弹出错误提示,小伙伴们自己测试吧!!!
经过多次测量求平均值,发现这地方在1120左右,估计就是登录成功到给这个参数赋值所需要的时间,
两时间做和差积商是我的短板,我就将这个时间差设为(1000,1200)。
用python模拟这些过程得:
def Ne(e):
t = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
n = ""
for i in range(e):
n += t
return n
def He(i):
timestamp = int(time.time())
return str(timestamp) + str(i) + ":" + Ne(8)
def Ze(e, t, n, r):
parsed_url = urlparse(e)
o_relative = parsed_url.path + '?' + parsed_url.query# 路径+参数
o_authority = parsed_url.netloc# 域名
# i = t + "\n" + n.toUpperCase() + "\n" + o.relative + "\n" + o.authority + "\n";
i = (t + '\n' + str.upper(n) + '\n' + o_relative + '\n' + o_authority + '\n').encode('utf-8')
# # Calculate HMAC SHA256
signature = hmac.new(r.encode(), i, digestmod=hashlib.sha256).digest()
# # Encode the signature in Base64 format
return base64.b64encode(signature).decode('utf-8')
def Ge(e):
t = 'GET' #t = arguments.length > 1 && void 0 !== arguments ? arguments : "GET"
r = access_token #r = n.accessToken
o = mac_key_decrpyt #o = n.macKey
i =random.randint(1000,1200) #i = n.diff
s = He(i)
a =Ze(e,s,t,o)
c = f'MAC id="{r}",nonce="{s}",mac="{a}"'
#c = 'MAC id="'.concat(r, '",nonce="').concat(s, '",mac="').concat(a, '"');
return c
e = 'https://uc-gateway.ykt.eduyun.cn/v1.1/users/45259xxxxxxx?with_ext=true&session_id=8da6f745-071f-4317-8d87-axxxxxxxxxxx'
t = 'GET'
n = logininfo
def getMACAuthorizationHeaders(e):
r = Ge(e)
return r
Authorization = getMACAuthorizationHeaders(e)
print('Authorization:', Authorization)
这东西解决了,我认为就没啥难度了。
接下来应该就是获取专题id,获取专题列表,看视频,提交参数了。
如果您耐心地看到这里,相信后面您也会了。
但为了有始有终,话不多说,继续开干。
打开这个页面,好多请求,发现可疑链接train_courses.json。看他返回数据,果不其然,和网页显示的一模一样啊:
激动之余,赶紧码代码:
import requests
url = "https://s-file-2.ykt.cbern.com.cn/teach/api_static/trains/2024hjpx/train_courses.json"
headers = {
"accept": "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9",
"cache-control": "no-cache",
"pragma": "no-cache",
"sec-ch-ua": '"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site",
}
referrer = "https://basic.smartedu.cn/training/2024hjpx"
referrer_policy = "no-referrer-when-downgrade"
response = requests.get(url, headers=headers, timeout=10)
print(response.json())
return response.json()
绝对奈斯!
fulls.json好像和页面有很多关联的数据:
而链接里面的这个数据视乎又来自这个json,那就好办了吧:
本帖最后由 Pwaerm 于 2024-2-4 13:33 编辑
document.querySelector("video").dispatchEvent(new Event("ended")) Pwaerm 发表于 2024-2-3 18:24
不晓得为啥子,说我违规了。 希望楼主这一贴坚持住。
里面敏感的网址我都替换了
认真阅读论坛规则再说 function Encrypt(t,authority,relative,key) {
var n = "GET";
var i = t + '\n' + n + '\n' + relative + '\n' + authority + '\n';
return CryptoJS.HmacSHA256(i,key).toString(CryptoJS.enc.Base64);
}
function Fe(e) {
return (new Date).getTime() + parseInt(e, 10) + ':' + Ze(8)
};
function Ze(e) {
for (
var t = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
n = '',
r = 0;
r < e;
r++
) n += t;
return n
};
关键代码就这些了 前面扣个crypto-js直接调用就可以了 东西不错要是有成品就好了! 你这是雪中送炭啊,坐板凳围观中。。。。 插眼,等待完成 插眼,等待完成
{:301_999:}
不晓得为啥子,说我违规了。 希望楼主这一贴坚持住。
里面敏感的网址我都替换了 正好需要!坐等! sai609 发表于 2024-2-3 18:47
认真阅读论坛规则再说
嗯嗯。
可能是某个地方的域名没替换完,现在帖子被删除了,自己也检查不到了。
向楼主学习,玩python 学习一下