# 一点基础的逆向,就是分享出来给大家娱乐借鉴一下
一、请求分析
直接F12打开开发者工具,在账号密码处输入账号和密码,错的就行,不能直接登录了,那就不好分析了。然后在捕获的请求里找到请求登录的,带有login关键字的。
然后看请求的参数。
username :输入的账号,明文
password:密码,但是被加密了
captcha,_eventId,cllt,dllt,lt:有的固定,有的为空
execution:好长一大串,看着也是密文,好吓人啊。
所以我们只需要搞定password和execution就行。
二、逆向过程
1.password
直接在全局搜索里搜索password关键字,然后在可疑的地方打上断点,如果看不出来哪里可疑也没事,只是工作量大点,抱着良好的心态,每一个地方都打上断点,总可能有一个地方是。
打完断点,再输入错误的账号密码,点击登录,欸嘿,这就断住了(就是和代码断点调试一样)。
$("#saltPassword").val(encryptPassword($(LOGIN_PASSWORD_ID).val(), $("#pwdEncryptSalt").val()));
有一点小基础就是val()方法就是取这个元素的值,LOGIN_PASSWORD_ID).val()就是你输入的密码,$("#pwdEncryptSalt").val()是一个salt值,全局搜索发现,这个值是网页返回的。所以破案了——密码加密就是用了一个encryptPassword方法和一个salt。
我们直接进入encryptPassword方法内部。
function encryptPassword(n, f) {
try {
return encryptAES(n, f)
} catch (c) {}
return n
}
这里有一个try和catch,请问我们逆向扣代码的时候需要这个错误校验么?如果这还能走到catch那的话就说明你前面的构造就不对,还得练!眼尖的可能已经看出来了,其实就是走了一个AES算法。
继续进入encryptAES方法内部。
function encryptAES(n, f) {
return f ? getAesString(randomString(64) + n, f, randomString(16)) : n
}
哟!还套了一层!这时候有的小伙伴会问看不懂这个return 后面的语句,其实这个三元表达式你看不懂完全没关系。接下来就是扣代码的过程了。先把encryptAES复制到脚本,然后先写死n和f作为参数传入。
function encryptAES(n, f) {
return f ? getAesString(randomString(64) + n, f, randomString(16)) : n
}
password = '123456'
salt = 'ay01P1VDyXZwnZ2v'
encryptpassword = encryptAES(password, salt)
console.log(encryptpassword)
点击运行之后肯定会报错,因为现在getAesString等都是没有的,然后它报什么东西没有,我们就去搜,然后复制过来就好!补充完整就是——
function getAesString(n, f, c) {
f = f.replace(/(^\s+)|(\s+$)/g, "");
f = CryptoJS.enc.Utf8.parse(f);
c = CryptoJS.enc.Utf8.parse(c);
return CryptoJS.AES.encrypt(n, f, {
iv: c,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString()
}
var $aes_chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"
, aes_chars_len = $aes_chars.length;
function randomString(n) {
var f = "";
for (i = 0; i < n; i++)
f += $aes_chars.charAt(Math.floor(Math.random() * aes_chars_len));
return f
}
function encryptAES(n, f) {
return f ? getAesString(randomString(64) + n, f, randomString(16)) : n
}
password = '123456'
salt = 'ay01P1VDyXZwnZ2v'
encryptpassword = encryptAES(password, salt)
console.log(encryptpassword)
然后就会发现CryptoJS这个东西未定义,要扣么?这其实是直接用nodejs的库就行了
var CryptoJS = require('crypto-js')
完整的代码就是
var CryptoJS = require('crypto-js')
function getAesString(n, f, c) {
f = f.replace(/(^\s+)|(\s+$)/g, "");
f = CryptoJS.enc.Utf8.parse(f);
c = CryptoJS.enc.Utf8.parse(c);
return CryptoJS.AES.encrypt(n, f, {
iv: c,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString()
}
var $aes_chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"
, aes_chars_len = $aes_chars.length;
function randomString(n) {
var f = "";
for (i = 0; i < n; i++)
f += $aes_chars.charAt(Math.floor(Math.random() * aes_chars_len));
return f
}
function encryptAES(n, f) {
return f ? getAesString(randomString(64) + n, f, randomString(16)) : n
}
password = '123456'
salt = 'ay01P1VDyXZwnZ2v'
encryptpassword = encryptAES(password, salt)
console.log(encryptpassword)
2.execution
在全局搜索execution,你猜怎么着!就是网页返回的值!所以execution就用个正则匹配或者是用bs4直接提取就行!
三、使用python进行模拟登录
1.得到pwdEncryptSalt和execution
pwdEncryptSalt和execution都是请求返回的,所以我们可以先用一个请求得到一组数据,然后再构造新的正确的请求。
def get_pwdEncryptSalt_execution(username):
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Origin": "https://ids.ynu.edu.cn",
"Referer": "https://ids.ynu.edu.cn/authserver/login?service=https%3A%2F%2Fehall.ynu.edu.cn%3A443%2Flogin%3Fservice%3Dhttps%3A%2F%2Fehall.ynu.edu.cn%2Fnew%2Findex.html"
}
cookies = {
"route": "your_route",
"JSESSIONID": "your_JSESSIONID",
"org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE": "zh_CN",
"happyVoyage": "your_happyVoyage"
}
url = "https://ids.ynu.edu.cn/authserver/login"
params = {
"service": "https%3A%2F%2Fehall.ynu.edu.cn%3A443%2Flogin%3Fservice%3Dhttps%3A%2F%2Fehall.ynu.edu.cn%2Fnew%2Findex.html"
}
data = {
"username": username,
"password": "Fvv7VNtivaLLCrSpVirOnBwSMpB1BL1QU7piaSRqUDGHg%2Bb%2Bsw9IsDXbO9cIwZ%2BbYtXBHgggOHu0PmHvINMqCIN0iUKgJfDD%2Fqjnd2hz9es%3D",
"captcha": "",
"_eventId": "submit",
"cllt": "userNameLogin",
"dllt": "generalLogin",
"lt": "",
"execution": ""}
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
soup = BeautifulSoup(response.text, 'html.parser')
pwdEncryptSalt = soup.find('input', {'id': 'pwdEncryptSalt'})['value']
execution = soup.find('input', {'name': 'execution'})['value']
return pwdEncryptSalt, execution
这里我省略了请求里的execution,但是需要粘贴的时候必须自己加上,否则校验不成功,返回的就不是正确的数据了。
2.调用JS文件得到加密结果
由于加密算法较为简单,也可以考虑直接全部转换为python语言进行编写,此次展示的是python调用库运行js代码的方法。因为使用了crypto-js,所以在新的路径下使用时会报错Cannot find module 'crypto-js',此时只需要在该路径下在终端安装,使用命令npm install crypto-js(前提是你配置好了node环境)就可以了!
def get_encrypt_password(password,pwdEncryptSalt):
import execjs
with open('网上办事服务大厅.js', 'r', encoding='utf-8') as file:
js = file.read()
node = execjs.compile(js)
return node.call('encryptAES', password, pwdEncryptSalt)
3.构造登录结构
def login(username, EncryptPassword, execution):
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "https://ids.ynu.edu.cn",
"Referer": "https://ids.ynu.edu.cn/authserver/login?service=https%3A%2F%2Fehall.ynu.edu.cn%3A443%2Flogin%3Fservice%3Dhttps%3A%2F%2Fehall.ynu.edu.cn%2Fnew%2Findex.html",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
}
cookies = {
"route": "your_route",
"JSESSIONID": "your_JSESSIONID",
"org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE": "zh_CN",
"happyVoyage": "your_happyVoyage"
}
url = "https://ids.ynu.edu.cn/authserver/login"
params = {
"service": "https%3A%2F%2Fehall.ynu.edu.cn%3A443%2Flogin%3Fservice%3Dhttps%3A%2F%2Fehall.ynu.edu.cn%2Fnew%2Findex.html"
}
data = {
"username": username,
"password": EncryptPassword,
"captcha": "",
"_eventId": "submit",
"cllt": "userNameLogin",
"dllt": "generalLogin",
"lt": "",
"execution": execution
}
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
print(response.cookies)
4.主函数
def main():
username = 'your_username'
pwd = 'your_password'
pwdEncryptSalt, execution = get_pwdEncryptSalt_execution(username)
EncryptPassword = get_encrypt_password(pwd, pwdEncryptSalt)
login(username, EncryptPassword, execution)
四、注意
做一个文明的人!不用技术做坏事喔!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!