文章目錄
- 1. 工具
- 2. 介面抓包
- 3. 引數解密程序
- 4. 解密方法整理重構
- 5. 腳本實作
- 6. 總結
1. 工具
- Fiddler 抓包工具
- 手機(與PC統一局域網)
- Chrome瀏覽器
- Postman
2. 介面抓包
打開fiddler軟體,在Tools > Options 按以下設定:

設定連接資訊,注意這里的埠是后面手機連接要用的:

在cmd命令列查看PC的IP地址:

手機連接到和PC相同的網路,并設定代理:

然后接下來從Fiddler里就可以抓取到手機端的請求了,預約入口這里使用【深圳疾控】公眾號,請求程序如下:

下面就是查找的程序,找出對我們有用的請求并且分析,從下網上找:
1. 社康資訊介面
這個介面可以查詢社康串列,回傳資訊包括社康ID,社康名稱,可打疫苗廠商,社康地址,當前狀態等資訊,

2. 獲取深圳區串列
這個介面回傳的區代碼后面會有用,用來查詢這個區的號源:

3. 獲取疫苗廠商串列
這個介面是獲取疫苗廠商串列資訊,其中重要的資料是corpCode – 廠商代碼,

4. 獲取token介面
這個介面也可以不用分析,因為token很長時間不會過期,可以直接抓包拿到就可以,一般在請求頭就可以找到,

5. 獲取用戶資訊介面
這個介面回傳真實用戶資訊,也包含token,

6. 查看當前社康這天每個時間段的號源情況
restSurplus 大于0表示有號,下面箭頭指的說明9:30-10:00有1個號:

7. 預約介面
這里引數就包含了社康資訊還有token一些引數,下節分析,

8. 查看預約結果資訊
預約成功后,查看詳細預約資訊,

3. 引數解密程序
通過上一步分析,可以把有用的介面都撈出來了,接下來就是分析引數,然后用Postman來模擬請求,只有請求成功了才算真的分析清楚了,那么引數分析在那里分析方便呢?當然是瀏覽器啦,這里教大家一個小技巧,可以在Chrome上除錯微信頁面,
有小伙伴可能要問了,為什么是除錯微信頁面呢,其實公眾號里面嵌入的是H5頁面,因為我發現了有一個請求回傳的是網頁:

用這個請求地址在Chrome瀏覽器訪問頁面試一下(記得帶上引數),結果是這樣的:

哦~ 原來預約界面就是H5頁面,如此就簡單多了,誰說預約只能在手機上的,這不PC也可以嗎?
那么除錯起來是不是很方便呢,Fiddler抓包現在就可以不用了,開始用Chrome整吧,這里提一下不要覺得加密的引數太多就怕了,一般網站加密方法是一樣的,只要破了一個其他的就都破了,就以獲取社康串列資訊這個介面來看:
首先最簡單的是能看到請求地址:https://xgsz.szcdc.net/crmobile/outpatient/nearby
請求方式:POST
然后可以看到請求頭里有一些加密的引數,還有Form-Data里也有一個params是加密的:

經過使用Postman模擬請求,篩選出Header中的token、appid、otn、ybm是必須的,token是后臺傳過來的(后面分析),appid是固定的,所以重要的是otn、ybm這倆引數,因為加密了,下面就來看看加密方法,先搜索ybm:

搜到這個js中這里正是設定header的地方,剛好ybm、otn是用的同一種加密方式,先看看加密方法的引數,這里c,p是上面生成的,后面是固定的字串,在上面打個斷點再重繪一下,可以查出上面的方法是啥:
這里的c=u()是回傳的當前時間戳的相關字串:

p是d(e,c)得來的,e是token,c就是上面的時間戳相關引數,d方法是字串拼接:

接下來看看加密函式Object(_t.b)是啥,控制臺先看下,是個函式:

除錯進去看看:

額,這就不用多說了吧,一個是加密函式,一個是解密函式,引數都是傳進來的,上面分析好了,接下來分析i方法是回傳什么:

這個就是加密函式了,但是最后回傳一個new ybzl.SM4(l)是什么鬼,感情這個方法只是處理引數而已,額,不急,我們進去看看:

好家伙!直接進去了bundle.min.js 里面都是演算法啊,除錯里面的太復雜了,我放棄了,但是我發現一件事:

其實這里會把這個函式輸出到window物件上,這就好辦了,不跟你玩了,直接把這個js檔案下載下來,直接用,哈哈哈~
4. 解密方法整理重構
經過了上面的分析,我自己寫出了加密和解密的方法,如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="bundle.min.js"></script>
<script>
/**
* 1 獲取疫苗廠商 token
* 2 獲取區域串列 token appid
* 3 獲取社康資訊 token appid otn ybm params
* 4 獲取時間段疫苗數量 token appid otn ybm params
* 5 獲取用戶資訊 token appid
* 6 預約 token appid reservationtoken Content-Type json引數
* 7 查看預約資訊 token appid reseId(預約成功回傳)
*/
// 加密解密方法
function i(t, e) {
t = t || "di6N7eCJYFp3kB4Q,!@#$%&*",
e = e || "u1r8jNhz07N7Zkn0";
var n = t.split(",")
, i = n // r()(n, 2)
, a = i[0]
, o = i[1]
, s = a.split("");
o.split("").map(function(t, e) {
s[e + e + 1] = t
}),
s = s.join("");
var l = {
key: s,
mode: "cbc",
iv: e,
cipherType: "base64"
};
return new ybzl.SM4(l)
}
// otn ybm 加密
function u() {
return (Date.now().toString() + (1e6 * Math.random().toFixed(6)).toString()).padEnd(19, "0")
}
function d(t, e) {
if (!t || !e)
return "";
var n = t.substring(0, 5)
, i = t.substring(5, 10)
, a = t.substring(10, 12)
, o = t.substring(12);
return n + e.substring(0, 14) + i + e.substring(9, 10) + a + e.substring(16, 17) + o
}
// token獲取在下面介紹
var token = "xxx";
var c = u(), p = d(token, c);
var ybm = i("1EzrokKlK2pFuEIT,~@#^%&*", "4h0VXhpqwWy89xBk").encrypt(c)
var otn = i("1EzrokKlK2pFuEIT,~@#^%&*", "4h0VXhpqwWy89xBk").encrypt(p)
console.log(ybm);
console.log(otn);
// params 加密
let params = {
areaCode: "440309", // 區號
bactCode: "5601", // 新冠疫苗編號,不用改
corpCode: "", // 疫苗廠商代碼
numPerPage: 10, // 每頁顯示記錄數
outpMapLatitude: "", // 地圖緯度
outpMapLongitude: "",// 地圖經度
outpName: "", // 社康名稱
pageNum: 1 // 頁數
}
let res = i("016BhmYAk7Oi1ajM,~@#^%&*","4h0VXhpqwWy89xBk").encrypt(JSON.stringify(params));
console.log(res);
// 從H5頁面加密的引數中解密出 appId token reservationtoken cardNo
let uri = "hYAPOVzzgsPD8XXKeSRfCIO2zdSKobI6YQFdzDUWwORNYoT1MDCf......."; // H5地址加密部分
var true_params = i(undefined, undefined).decrypt(uri);
console.log(true_params)
// appId=xxx&token=xxx&cardNo=xxx&reservationToken=xxx&vaccineCode=
</script>
</body>
</html>
因涉及個人隱私,中間的引數我沒有貼真實的回傳結果,請自行測驗,
5. 腳本實作
引數破解完后,最后一步就是實作自動化預約了,預約流程:

具體實作下面給個例子,因為現在號源也比較多,所以沒有寫腳本,需要的自己修改一下就行了:
# -*- coding: utf-8 -*-
import requests, time, copy
from urllib.parse import parse_qs, urlencode, urlparse
token = ""
appid = ""
otn = ""
ybm = ""
reservationtoken = ""
baseHeaders = {
# "Cookie": findCookie,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1326.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x63010200)"
}
# 獲取疫苗余量
def getRest():
rest_url = "https://xgsz.szcdc.net/crmobile/reservationStock/timeNumber"
params_1 = "4517CL5iSqYrVthaOYxxxxxxxxxx" # 先加密好
rest_headers = copy.deepcopy(baseHeaders)
rest_headers["token"] = token
rest_headers["appid"] = appid
rest_headers["otn"] = otn
rest_headers["ybm"] = ybm
rest_data = {
"params": params_1
}
rest_res = requests.post(rest_url, json=rest_data, headers=rest_headers).json()
return rest_res
# 預約
def save():
post_url = "https://xgsz.szcdc.net/crmobile/reservation/saveAppointment"
data = {
"reusId": "6068111xxxxxxxxxxx", # 用戶的reusId 固定
"depaId": "1698A7F4-CA7B-9FDA-FC3C-48DEE401491B", # 社康ID (第1個請求獲取)
"corpCode": "80", # 廠商代碼
"date": "2021-06-13", # 日期
"ouatId": "831", # 時間段ID (第2個請求獲取)
"vaccCodes": "5601" # 新冠疫苗code
}
post_headers = copy.deepcopy(baseHeaders)
post_headers["token"] = token
post_headers["appid"] = appid
post_headers["reservationtoken"] = reservationtoken
post_headers["Content-Type"] = "application/json"
rest_res = requests.post(post_url, json=data, headers=post_headers).json()
return rest_res
6. 總結
這個抓取介面花了兩次,第一次抓完后第二天官方就修改了引數,把原來的明文改為加密的了,后來又抓了一遍,通過引數的解密程序,大家會學會如何去分析、除錯、并重構它,結果無所謂,主要是分析程序,希望能幫到大家,
點贊支持下,謝謝~
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/287188.html
標籤:其他
上一篇:哈希表底層探索
