
宣告
本文章中所有內容僅供學習交流,抓包內容、敏感網址、資料介面均已做脫敏處理,嚴禁用于商業用途和非法用途,否則由此產生的一切后果均與作者無關,若有侵權,請聯系我立即洗掉!
逆向目標
-
目標:某政務服務網登錄介面
-
主頁:
aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbG9naW4vaW5kZXg= -
介面:
aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbmF0dXJhbE1hbi9sb2dpbk5v -
逆向引數:
Form Data:loginNo、loginPwd、code、requestUUID
Request Headers:token
抓包分析
本次逆向目標來源于某位粉絲的求助:

隨便輸入賬號密碼點擊登陸,抓包發現介面的 Request Headers 有個加密引數 token,Form Data 里 loginNo、loginPwd、code、requestUUID 都是經過加密處理了的,loginNo 和 loginPwd 應該就是用戶名密碼了,由于登錄前需要過一下滑動驗證碼,因此可以猜測另外兩個引數與驗證碼有關,不過僅從抓包來看,另外兩個引數類似于 uuid 的格式,不太像驗證碼的引數,


另外可以注意到登陸前,有兩次 csrfSave 和一次 verCode 的請求,正常請求成功就會回傳一個 JSON,里面有個 data 引數,后面應該是會用到的,

引數逆向
Form Data
先看 Form Data,搜索任意一個引數,比如 loginNo,很容易在 login.js 里找到加密的地方,用戶名和密碼都經過了 encrypt 這個函式進行加密,backUrl 這個值,是利用 localStorage 屬性,從瀏覽器儲存的鍵值對的資料里取的,為空也不影響,

跟進 encrypt,可以看到用到了 JSEncrypt,標準的 RSA 加密:

再看看 loginCode,直接搜索這個值,可以看到是 verCode 這個請求回傳的:


然后再看看 requestUUID,其值就是個 UUID,直接在當前檔案(login.js)里搜索,可以看到定義的地方,有個 uploadUUID() 方法,就是在設定 UUID 的值,方法里面是向一個 uploadIdentifier 的介面發送了 post 請求:


這里注意,如果你直接全域搜索 UUID 的話,還可以在 common.js 里搜索到一個方法,經過測驗,直接使用這個方法生成一個 uuid 也是可以請求通過的,這網站可能不嚴謹,不會嚴格檢測這個值,

Request Headers
Form Data 解決了,再來看看 Request Headers 里的 token 引數,由于它存在于請求頭里,所以我們可以通過 Hook 的方式來查找其生成的地方:
(function () {
var org = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
if (key == 'token') {
debugger;
}
return org.apply(this, arguments);
};
})();
這里我們也可以直接搜索 token、setRequestHeader 之類的關鍵字,很容易在 common.js 里找到,當我們點擊登陸,會有一個 csrfSave 的請求,回傳的 data 值,經過 encrypt 方法加密后就是登陸請求頭的 token 了,
這個 token 引數在很多請求中都會用到,生成方法是一樣的,都是拿 csrfSave 請求回傳的 data 經過 RSA 加密后得到的:

另外注意一點的就是,以上所有涉及到網路請求的,Cookie 都需要一個 SESSION 值,這個可以在首次訪問頁面獲取到:

登陸流程
這里我們理一下登陸的流程:
- 訪問首頁拿 Cookie 中的 SESSION 值;
- 訪問 csrfSave,拿到一個 data 值,經過 RSA 加密得到 token,攜帶 token 訪問 uploadIdentifier,拿到 uuid;
- 訪問 csrfSave,拿到一個 data 值,經過 RSA 加密得到 token,攜帶 token 訪問 verCode,拿到 code;
- 訪問 csrfSave,拿到一個 data 值,經過 RSA 加密得到 token,攜帶 token、uuid、code 和加密后的賬號密碼,訪問 loginNo 登錄,
這里第2步,也可以直接用 Python 或者 JS 生成一個 uuid,網站校驗不嚴格,也可以通過,另外可以看出這個滑塊是假的,通過代碼可以無視滑塊進行登錄,

完整代碼
GitHub 關注 K 哥爬蟲,持續分享爬蟲相關代碼!歡迎 star !https://github.com/kgepachong/
以下只演示部分關鍵代碼,不能直接運行! 完整代碼倉庫地址:https://github.com/kgepachong/crawler/
JavaScript 加密代碼
/* ==================================
# @Time : 2022-01-11
# @Author : 微信公眾號:K哥爬蟲
# @FileName: encrypt.js
# @Software: PyCharm
# ================================== */
JSEncrypt = require("jsencrypt")
function encrypt(pwd){
var key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgDq4OqxuEisnk2F0EJFmw4xKa5IrcqEYHvqxPs2CHEg2kolhfWA2SjNuGAHxyDDE5MLtOvzuXjBx/5YJtc9zj2xR/0moesS+Vi/xtG1tkVaTCba+TV+Y5C61iyr3FGqr+KOD4/XECu0Xky1W9ZmmaFADmZi7+6gO9wjgVpU9aLcBcw/loHOeJrCqjp7pA98hRJRY+MML8MK15mnC4ebooOva+mJlstW6t/1lghR8WNV8cocxgcHHuXBxgns2MlACQbSdJ8c6Z3RQeRZBzyjfey6JCCfbEKouVrWIUuPphBL3OANfgp0B+QG31bapvePTfXU48TYK0M5kE+8LgbbWQIDAQAB";
var encrypt = new JSEncrypt();
encrypt.setPublicKey(key);
var encrypted = encrypt.encrypt(pwd);
return encrypted;
}
// 測驗樣例
// console.log(encrypt("15555555555"))
Python 登錄代碼
# ==================================
# @Time : 2022-01-11
# @Author : 微信公眾號:K哥爬蟲
# @FileName: hnzww_login.py
# @Software: PyCharm
# ==================================
import execjs
import requests
cookies = {}
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
with open("encrypt.js", encoding="utf-8") as f:
js = execjs.compile(f.read())
def csrf_save():
url = "脫敏處理,完整代碼關注 GitHub:https://github.com/kgepachong/crawler"
headers = {"User-Agent": UA}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
data = https://www.cnblogs.com/ikdl/p/response["data"]
return data
def get_session():
url = "脫敏處理,完整代碼關注 GitHub:https://github.com/kgepachong/crawler"
headers = {"User-Agent": UA}
response = requests.get(url=url, headers=headers)
cookies.update(response.cookies.get_dict())
def get_uuid():
url = "脫敏處理,完整代碼關注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
uuid = response["data"]
return uuid
def ver_code():
url = "脫敏處理,完整代碼關注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
data = https://www.cnblogs.com/ikdl/p/response["data"]
return data
def login(phone, pwd, code, uuid):
url = "脫敏處理,完整代碼關注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
data = https://www.cnblogs.com/ikdl/p/{"backUrl": "",
"loginNo": js.call("encrypt", phone),
"loginPwd": js.call("encrypt", pwd),
"code": code,
"requestUUID": uuid,
"guoBanAuthCode": ""
}
response = requests.post(url=url, headers=headers, cookies=cookies, data=https://www.cnblogs.com/ikdl/p/data)
print(response.json())
def main():
phone = input("請輸入賬號:")
pwd = input("請輸入密碼:")
get_session()
uuid = get_uuid()
code = ver_code()
login(phone, pwd, code, uuid)
if __name__ == '__main__':
main()

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/415226.html
標籤:Python
