本篇文章作者ius,本文属i春秋原创奖励计划,未经许可禁止转载
原文地址:https://bbs.ichunqiu.com/thread-63786-1-1.html

某安信登录机制逆向分析

我们先随意输入账号密码进行测试

image-20240105222707586
image-20240105222707586

点击登录后出现极验滑块

image-20240105155536009
image-20240105155536009

极验三代水平不高,直接秒。

image-20240105160252840
image-20240105160252840

滑块请求成功之后,会向该链接请求公钥https://user.skyeye.qianxin.com/api/v1/encrypt/public-key

image-20240105155648767
image-20240105155648767

查看我们的登录请求

image-20240105155946141
image-20240105155946141

发现请求是XHR,先用XHR断个点

image-20240105155933517
image-20240105155933517

断住之后逐步跟栈

image-20240105161940048
image-20240105161940048

找到key_iv的位置

image-20240105160622604
image-20240105160622604

f是请求来的公钥

image-20240105161902818
image-20240105161902818

r=s(),进入s函数,随机生成的

image-20240105161705319
image-20240105161705319

image-20240105162031991
image-20240105162031991

s = function() {
            for (var e = "", a = 0; a < 32; a++)
                e += Math.floor(16 * Math.random()).toString(16);
            return e
        }

然后进入l函数查看,简单的加密,把f替换成crypto即可

image-20240105162058606
image-20240105162058606

b是个 RSA 对象,原型链存放着加密方法 此处使用的是JSEncrypt

image-20240105162922106
image-20240105162922106

直接用nodejs实现

image-20240105203424759
image-20240105203424759

密码加密

image-20240105185024165
image-20240105185024165

image-20240105171337946
image-20240105171337946

把代码抠出来,运行,一模一样

image-20240105222837524
image-20240105222837524

参数都解决完了,整理一下代码

image-20240105202202166
image-20240105202202166

运行测试看看

image-20240105222959444
image-20240105222959444

登录成功

image-20240105202347721
image-20240105202347721

总体来说,该网站登录流程比较简单,水平不高。


下面附上代码:

const crypto = require("crypto-js");
window = global
const NodeRSA = require('jsencrypt');

function short() {
    for (var e = "", a = 0; a < 32; a++)
        e += Math.floor(16 * Math.random()).toString(16);
    return e
}

function password(e, a) {
    var c = a.substring(0, 16);
    a = crypto.enc.Utf8.parse(a),
        c = crypto.enc.Utf8.parse(c),
        e = "string" === typeof e ? e : JSON.stringify(e);
    var t = crypto.AES.encrypt(e, a, {
        iv: c,
        mode: crypto.mode.CBC,
        padding: crypto.pad.Pkcs7
    });
    return t.toString()
}

function key_iv(e, a) {
    var c = a.substring(0, 16);
    a = crypto.enc.Utf8.parse(a),
        c = crypto.enc.Utf8.parse(c);
    var t = {
        key: crypto.enc.Base64.stringify(a),
        iv: crypto.enc.Base64.stringify(c)
    };
    t = JSON.stringify(t)
    var aa = new NodeRSA()
    aa.setPublicKey(e);
    return aa.encrypt(t)
}
import json
import execjs
import requests

account="11111111111"
password="111111"

headers = {
  'Accept': 'application/json, text/plain, */*',
  'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
  'Cache-Control': 'no-cache',
  'Connection': 'keep-alive',
  'Cookie': 'next=http%3A//forum.***.net/btlogin%3FredirectPath%3Dhttps%3A//forum.***.net/; wzws_sessionid=gjA1NjM4N6Bll33vgTljMWNlMoAyNDA4OjgyMTU6NzIxOToxZTUwOjk1ZDpkYjhlOjhlYzk6ODgzZA==; User-Center=3e7f3775-4f57-46d8-91ec-91adcb46b0bd; User-Center=3e7f3775-4f57-46d8-91ec-91adcb46b0bd',
  'Pragma': 'no-cache',
  'Referer': 'https://user.skyeye.***.com/user/sign-in?next=http://forum.***.net/btlogin?redirectPath=https://forum.butian.net/',
  'Sec-Fetch-Dest': 'empty',
  'Sec-Fetch-Mode': 'cors',
  'Sec-Fetch-Site': 'same-origin',
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
  'sec-ch-ua-mobile': '?0',
  'sec-ch-ua-platform': '"Windows"'
}
def get_pem():
    url = "https://user.skyeye.***.com/api/v1/encrypt/public-key"
    response = requests.request("GET", url, headers=headers)
    return response.json()["public_key"]

yzm = eval(requests.get("https://www.illusory.cn/api/qianxin.php").text)

with open("1.js","r",encoding="utf-8") as f:
    file_data = f.read()
cxk = execjs.compile(file_data)
short = cxk.call("short")

pwd = cxk.call("password",password,short)
key = cxk.call("key_iv",get_pem(),short)
# exit()
url = "https://user.skyeye.***.com/api/v1/sign-in"

payload = json.dumps({
  "account": account,
  "password": pwd,
  "geetest_challenge": yzm[1],
  "geetest_validate": json.loads(yzm[0])["validate"],
  "geetest_seccode": json.loads(yzm[0])["validate"]+"|jordan",
  "next": "http://forum.***.net/btlogin?redirectPath=https://forum.***.net/",
  "custom_callback_params": {
    "redirectPath": "https://forum.***.net/"
  },
  "key_iv": key,
  "csrf_token": "1704457269##ffcf2ba524ba000e09ef4decc5bd632b7720f622"
})
headers = {
  'Accept': 'application/json',
  'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
  'Cache-Control': 'no-cache',
  'Connection': 'keep-alive',
  'Content-Type': 'application/json',
  'Cookie': 'next=http%3A//forum.***.net/btlogin%3FredirectPath%3Dhttps%3A//forum.butian.net/; wzws_sessionid=gjA1NjM4N6Bll33vgTljMWNlMoAyNDA4OjgyMTU6NzIxOToxZTUwOjk1ZDpkYjhlOjhlYzk6ODgzZA==; User-Center=3e7f3775-4f57-46d8-91ec-91adcb46b0bd; User-Center=3e7f3775-4f57-46d8-91ec-91adcb46b0bd;csrf_token=1704457269##ffcf2ba524ba000e09ef4decc5bd632b7720f622',
  'Origin': 'https://user.skyeye.***.com',
  'Pragma': 'no-cache',
  'Referer': 'https://user.skyeye.***.com/user/sign-in?next=http://forum.***.net/btlogin?redirectPath=https://forum.butian.net/',
  'Sec-Fetch-Dest': 'empty',
  'Sec-Fetch-Mode': 'cors',
  'Sec-Fetch-Site': 'same-origin',
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
  'sec-ch-ua-mobile': '?0',
  'sec-ch-ua-platform': '"Windows"'
}

response = requests.request("POST", url, headers=headers, data=payload)
res = response.json()
if res["status"]==200:
  result=requests.get(res["redirect"], headers=headers)
  print(result.cookies)
  with open('cookies.json', 'w') as cookie_file:
    json.dump(result.cookies.get_dict(), cookie_file)

自动登录都有了,顺便写个签到脚本吧

import json

import requests
from lxml import etree

session = requests.Session()
url = "https://forum.***.net/"
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,en-US;q=0.8,en;q=0.7',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Pragma': 'no-cache',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    'referer': 'https://forum.***.net/sign',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"'
}
with open('cookies.json', 'r') as cookie_file:
    cookies = json.load(cookie_file)
    session.cookies.update(cookies)
response = session.request("GET", url, headers=headers)

xx = etree.HTML(response.text)
xxx = xx.xpath('/html/head/meta[@name="csrf-token"]/@content')[0]
url = "https://forum.***.net/sign"
response = session.request("POST", url, headers=headers, data='_token='+xxx)
print(response)

完整代码请从github获取->https://github.com/xvhuan/qianxin