打开浏览器,进入学习通登录页面。F12——随便输入账号密码点击登录——网络——fanyalogin–负载,这里发现uname和password使用了加密手段进行加密。

尝试搜索password了解使用什么加密手段。
这里找到了一个encryptByAES()函数,看起来像是加密方式,第一个参数为密码,第二个参数为密钥。

点击进去,跳转到源代码界面。看到了像是密钥的字符串transferKey = "u2oh6Vu^HWe4_AES"

为了验证密钥是否真实,再次搜索encryptByAES,找到它加密的方法。

同样点进去,在加密方法的返回值return处下个断点。

点击登录,发现已经断下来了,F9,单步走。


到这已经证实了猜想。下面复现一下它的加密过程,将encryptByAES的方法复制到在线js运行工具里调试。在原来的基础上加上一句代码调用它的方法,console.log(encryptByAES('123','u2oh6Vu^HWe4_AES'));
function encryptByAES(message, key){
let CBCOptions = {
iv: CryptoJS.enc.Utf8.parse(key),
mode:CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
};
let aeskey = CryptoJS.enc.Utf8.parse(key);
let secretData = CryptoJS.enc.Utf8.parse(message);
let encrypted = CryptoJS.AES.encrypt(
secretData,
aeskey,
CBCOptions
);
return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}
console.log(encryptByAES('123','u2oh6Vu^HWe4_AES'));


此时发现报错了运行不了,提示CryptoJS未定义。回去源代码处,查到它在哪里会有CrytoJS,找到了之后点进去。


点进来发现代码好多,不方便分析,干脆直接全部复制下来,放到原来encryptByAES方法的上面,再次点运行,发现没有报错,运行结果也与实际一致。

同样,可以将解密的function放到js中运行,为了方便,可以用python进行加解密的复现。
import base64
from Crypto.Cipher import AES

AESKEY = 'u2oh6Vu^HWe4_AES' # 密钥
AESIV = 'u2oh6Vu^HWe4_AES' # 和KEY保持一致即可

class AESTool:
def __init__(self):
self.key = AESKEY.encode('utf-8')
self.iv = AESIV.encode('utf-8')

def pkcs7padding(self, text):
"""
明文使用PKCS7填充
"""
bs = 16
length = len(text)
bytes_length = len(text.encode('utf-8'))
padding_size = length if (bytes_length == length) else bytes_length
padding = bs - padding_size % bs
padding_text = chr(padding) * padding
self.coding = chr(padding)
return text + padding_text

def aes_encrypt(self, content):
"""
AES加密
"""
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# 处理明文
content_padding = self.pkcs7padding(content)
# 加密
encrypt_bytes = cipher.encrypt(content_padding.encode('utf-8'))
# 重新编码
result = str(base64.b64encode(encrypt_bytes), encoding='utf-8')
return result

def aes_decrypt(self, content):
"""
AES解密
"""
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
content = base64.b64decode(content)
text = cipher.decrypt(content).decode('utf-8')
return self.pkcs7padding(text)

if __name__ == '__main__':
a = AESTool() #实例化一个对象
username=a.aes_encrypt(input('用户名:')) #调用classAESTool里的aes_encrypt方法
pwd=a.aes_encrypt(input('密码:'))
aes_username = username #这里传一下值给另一个变量,待会要用到
aes_pwd = pwd
print('加密后的用户名:'+aes_username)
print('加密后的密码:'+aes_pwd)
加密后结果一致。

那么如何使用python实现学习通登录呢?先看看正常登录成功发送的表单。

利用python的requests构造请求,编写的完整代码如下。
import base64

from Crypto.Cipher import AES

AESKEY = 'u2oh6Vu^HWe4_AES' # 密钥
AESIV = 'u2oh6Vu^HWe4_AES' # 和KEY保持一直即可

class AESTool:
def __init__(self):
self.key = AESKEY.encode('utf-8')
self.iv = AESIV.encode('utf-8')

def pkcs7padding(self, text):
"""
明文使用PKCS7填充
"""
bs = 16
length = len(text)
bytes_length = len(text.encode('utf-8'))
padding_size = length if (bytes_length == length) else bytes_length
padding = bs - padding_size % bs
padding_text = chr(padding) * padding
self.coding = chr(padding)
return text + padding_text

def aes_encrypt(self, content):
"""
AES加密
"""
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# 处理明文
content_padding = self.pkcs7padding(content)
# 加密
encrypt_bytes = cipher.encrypt(content_padding.encode('utf-8'))
# 重新编码
result = str(base64.b64encode(encrypt_bytes), encoding='utf-8')
return result

def aes_decrypt(self, content):
"""
AES解密
"""
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
content = base64.b64decode(content)
text = cipher.decrypt(content).decode('utf-8')
return self.pkcs7padding(text)

if __name__ == '__main__':
a = AESTool() #实例化一个对象
username=a.aes_encrypt(input('用户名:')) #调用classAESTool里的aes_encrypt方法
pwd=a.aes_encrypt(input('密码:'))
aes_username = username #这里传一下值给另一个变量,待会要用到
aes_pwd = pwd
print('加密后的用户名:'+aes_username)
print('加密后的密码:'+aes_pwd)

import requests
session = requests.session()
headers = {
"Host": "passport2.chaoxing.com",
"Connection": "keep-alive",
"Content-Length": "248",
"sec-ch-ua": "\"Chromium\";v=\"106\", \"Microsoft Edge\";v=\"106\", \"Not;A=Brand\";v=\"99\"",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"sec-ch-ua-mobile": "?0",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.52",
"sec-ch-ua-platform": "\"Windows\"",
"Origin": "https://passport2.chaoxing.com",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Dest": "empty",
"Referer": "https://passport2.chaoxing.com/login?fid=&newversion=true&refer=https://i.chaoxing.com",
"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",
"Cookie": "fid=23194; route=52ffa9af7a380e114204ed76732d509c; JSESSIONID=F7C40528A60B7D04420D26319385CD5A; source=\"\""
}
url = "https://passport2.chaoxing.com/fanyalogin"
data = {
"fid": "-1",
"uname": aes_username,
"password": aes_pwd,
"refer": "http%3A%2F%2Fi.chaoxing.com",
"t": "true",
"forbidotherlogin": "0",
"validate": "",
"doubleFactorLogin": "0",
"independentId": "0"
}
session.headers = headers
response = session.post(url, headers=headers, data=data)
print('登陆中......')
print(response.text)
print(response)
到这里已经成功登录了!!!