逆向分析与登录某统一身份认证平台

# 一点基础的逆向,就是分享出来给大家娱乐借鉴一下

一、请求分析

直接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)

四、注意

做一个文明的人!不用技术做坏事喔!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值