target: https://www.hfhuizhan.com
data encryption

response descryption

search
notice Promise.then, so search interceptors in Search tab

enter

request data encryption
check out At, we got requestInterceptors


def enc_data(s):
key = "$shanghaidianqi$".encode("utf-8")
iv = "2023050814260000".encode("utf-8")
aes = AES.new(
key=key,
mode=AES.MODE_CBC,
iv=iv
)
raw = pad(s.encode('utf-8'), 16)
b = aes.encrypt(raw)
return base64.b64encode(b).decode()
s = "/prod-api/hfhz-pavilion/back/pto/pavilion/getLatestExhibition=undefined"
data = enc_data(s)
print(data) # ‘U1tYc6MIt/gPHlztiOuAHBEmV/vYxyFhT9c7gcRpTPFaRxJuAR11Xb1wSxhtqaZYYGjQv2sTrXalXeryqwEeSiEX5WlU7516ov1dcUr978w=’
params = {
'data': data,
}
response = requests.get(
'https://www.hfhuizhan.com/prod-api/hfhz-pavilion/back/pto/pavilion/getLatestExhibition',
params=params,
headers=headers,
)
response decryption
enter the interceptors At, got this function

but dont click cr while mouse hanging over it, its asychronous so it will enter a wrong function. at this situation, single step debugger is not suitable

just click cr and notice its above that function

remember: When the code is the same as that framed by the orange box in the figure, it indicates the feature of asynchronous execution.
At this point, do not perform single-step debugging. Consider the case as await a task.
Jt.sent receive the response value of it’s last step :ot.clone().text()
set breakpoints at return ... below case x, use this button to debug
![]()
if you want to jump from case 0 to case 3, different cases, use this button. but in the case block, single step debug is OK.
Jt.next = 3 means its next task is in the case 3 block. the result of ot.clone().next() cant be found in the block case0, you must step into case 3 Jt.sent to retrive its value.

after mr(), kt can be parsed by Json, so mr may be the decrypt function
boom

from Crypto.Cipher import AES
# from Crypto.Util.Padding import pad, unpad
import base64
s = "too long..."
key = "$shanghaidianqi$".encode("utf-8")
iv = "2023050814260000".encode("utf-8")
aes = AES.new(
key=key,
mode=AES.MODE_CBC,
iv=iv
)
b = aes.decrypt(base64.b64decode(s))
print(b.decode("utf-8"))
pure js
var jt = {}; // pay attention to this kind of format
jt.a = require("crypto-js"); // jt.a.enc.Utf8.parse
var Zt = "$shanghaidianqi$";
var Vt = "2023050814260000";
var sr = function(Xe) {
Xe = JSON.stringify(Xe); // add this line to transform py dict to string
var ot = jt.a.enc.Utf8.parse(Zt)
, Kt = jt.a.enc.Utf8.parse(Vt)
, kt = jt.a.AES.encrypt(Xe, ot, {
iv: Kt,
mode: jt.a.mode.CBC,
padding: jt.a.pad.Pkcs7
});
return JSON.stringify({
data: kt.toString()
}); // return JSON
}
var mr = function(Xe) {
var ot = jt.a.enc.Utf8.parse(Zt)
, Kt = jt.a.enc.Utf8.parse(Vt)
, kt = jt.a.AES.decrypt(Xe, ot, {
iv: Kt,
mode: jt.a.mode.CBC,
padding: jt.a.pad.Pkcs7
})
, yr = kt.toString(jt.a.enc.Utf8);
return JSON.parse(yr.toString());
}
import json
import requests
import execjs
f = open("binhu.js", mode="r", encoding="utf-8")
js_code = f.read()
f.close()
js = execjs.compile(js_code)
url = "https://www.hfhuizhan.com/prod-api/hfhz-exhibition/back/exhibition/listExhibitionNotPage"
# its api is different with what i've been working for that's not the point though
ming_data = {
"yyyyMM": "2024-11"
}
ret = js.call("sr", ming_data)
# my_headers = {...}
resp = requests.post(url, data=ret, headers=my_headers)
ming = js.call("mr", resp.text) # it can trigger UnicodeDecodeError. dont konw why :(
print(ming)
