請(qǐng)求包分析
使用 Charles 軟件進(jìn)行抓包,詳細(xì)過程就不細(xì)說了,直接貼上抓包結(jié)果
headers = {
'Host': 'miniapp.fang.com',
'pseusign': 'p10120230411162220f9a1195df01c47a6065f53b22d1c4100',
'openid': 'oxBn60ADRc6eURhDDkYReN4MjFik',
'content-type': 'application/json',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.33(0x18002129) NetType/WIFI Language/zh_CN',
'Referer': 'https://servicewechat.com/wxffbb41ec9b99a969/758/page-frame.html',
}
params = {
'appname': 'fangx',
'v': '1.3.4',
'miniplat': 'weixin',
'scene': '1027',
}
response = requests.get('https://miniapp.fang.com/pingyin/cityList', params=params, headers=headers, verify=False)
經(jīng)過來回刪除恢復(fù)參數(shù)的方式,得出 pseusign 參數(shù)尤為重要,直接分析小程序代碼。
獲取小程序代碼
由于開源倉庫已經(jīng)被作者刪除,新版本已經(jīng)商業(yè)化,這里就不再敘述。
運(yùn)行小程序
使用微信小程序開發(fā)工具導(dǎo)入解包后的代碼,直接編譯運(yùn)行,會(huì)得到以下錯(cuò)誤信息
[插件 wx1db9e5ab1149ea03] provider:wx1db9e5ab1149ea03, version:2.1.1, INVALID_LOGIN,access_token expired
插件文檔: https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx1db9e5ab1149ea03&token=&lang=zh_CN(env: macOS,mp,1.06.2303060; lib: 2.30.3)
可以大概看懂是插件過期的意思,那么就找到 app.json
的 plugins
刪除就好了,就想下面這樣
::: code-group
"plugins": {
"echarts": {
"version": "2.1.1",
"provider": "wx1db9e5ab1149ea03",
"subpackage": ""
}
},
"plugins": {
},
:::
繼續(xù)編譯允許,繼續(xù)報(bào)錯(cuò),內(nèi)容如下
WAServiceMainContext.js?t=wechat&s=1681204008944&v=2.30.3:1 TypeError: _typeof3 is not a function
解決辦法,找到 @babel/runtime/helpers/typeof.js
,把下面內(nèi)容替換到文件中
function _typeof2(o) {
"@babel/helpers - typeof";
return (_typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
return typeof o;
} : function(o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
})(o);
}
function _typeof(o) {
return "function" == typeof Symbol && "symbol" === _typeof2(Symbol.iterator) ? module.exports = _typeof = function(o) {
return _typeof2(o);
} : module.exports = _typeof = function(o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : _typeof2(o);
}, _typeof(o);
}
module.exports = _typeof;
繼續(xù)編譯運(yùn)行,通過了。
分析代碼
直接全局搜索 pseusign
找到下面代碼處
v.pseusign = h(e.url, i), o || (o = l("openid") || ""), v.openid = o, wx.request({
url: e.url,
data: "POST" === e.method ? e.data : i,
header: v,
method: e.method || "GET",
dataType: e.dataType || "json",
responseType: e.responseType || "text",
可以看到 pseusign
是由 h
函數(shù)生成,跟進(jìn) h
來看下
function h(e, n) {
var o = "",
a = getApp();
if (a) {
var i = a.vars.headerSgin;
try {
if (!n) return "";
var c = {};
if ("string" == typeof n) n.split("&").forEach((function (e) {
var t = e.split("=");
2 === t.length && (c[t[0]] = t[1])
}));
else c = n;
if (e.includes("?")) e.substr(e.indexOf("?") + 1).split("&").forEach((function (e) {
var t = e.split("=");
2 === t.length && (c[t[0]] = t[1])
}));
var u = i.encodeNumber,
s = i.password,
g = function (e, t) {
var n = new Date(e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate(), e.getUTCHours(), e.getUTCMinutes(), e.getUTCSeconds()),
r = new Date(n.setHours(e.getUTCHours() + 8)),
o = {
"M+": r.getMonth() + 1,
"d+": r.getDate(),
"h+": r.getHours(),
"m+": r.getMinutes(),
"s+": r.getSeconds(),
"q+": Math.floor((r.getMonth() + 3) / 3),
S: r.getMilliseconds()
};
for (var a in /(y+)/.test(t) && (t = t.replace(RegExp.$1, String(r.getFullYear()).substr(4 - RegExp.$1.length))), o) new RegExp("(" + a + ")").test(t) && (t = t.replace(RegExp.$1, 1 === RegExp.$1.length ? o[a] : ("00" + o[a]).substr(String(o[a]).length)));
return t
}(new Date, "yyyyMMddhhmmss"),
l = "p".concat(u).concat(g),
f = t(t({}, c), {}, {
micalltime: g,
miversion: i.miversgin,
misource: u
}),
h = Object.keys(f);
h.sort((function (e, t) {
return e.toLowerCase().localeCompare(t.toLowerCase())
}));
var d = "";
h.forEach((function (e) {
d += "&".concat(e, "=").concat(f[e])
})), d = d.substr(1);
var p = r.hex_md5("".concat(d).concat(s));
o = "".concat(l).concat(p)
} catch (e) {
o = ""
}
}
return o
}
打上 debugger 進(jìn)行調(diào)試
var i = a.vars.headerSgin;
a.vars
則聲明在 app.js
是一個(gè)常量對(duì)象,那么 headerSgin
為 headerSgin: {encodeNumber: "101",password: "4f0c6725d917f8fe4e2791921187fd7d",miversgin: "p"}
c = n;
n
為函數(shù)的第 2 個(gè)參數(shù),是一個(gè)對(duì)象,多調(diào)試幾次就知道是接口的請(qǐng)求參數(shù)
if (e.includes("?")) e.substr(e.indexOf("?") + 1).split("&").forEach((function (e) {
var t = e.split("=");
2 === t.length && (c[t[0]] = t[1])
}));
e
為函數(shù)的第 1 個(gè)參數(shù),是一個(gè) URL 地址
var u = i.encodeNumber,
u
= 101
s = i.password,
s
= 4f0c6725d917f8fe4e2791921187fd7d
g = function (e, t) {
var n = new Date(e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate(), e.getUTCHours(), e.getUTCMinutes(), e.getUTCSeconds()),
r = new Date(n.setHours(e.getUTCHours() + 8)),
o = {
"M+": r.getMonth() + 1,
"d+": r.getDate(),
"h+": r.getHours(),
"m+": r.getMinutes(),
"s+": r.getSeconds(),
"q+": Math.floor((r.getMonth() + 3) / 3),
S: r.getMilliseconds()
};
for (var a in /(y+)/.test(t) && (t = t.replace(RegExp.$1, String(r.getFullYear()).substr(4 - RegExp.$1.length))), o) new RegExp("(" + a + ")").test(t) && (t = t.replace(RegExp.$1, 1 === RegExp.$1.length ? o[a] : ("00" + o[a]).substr(String(o[a]).length)));
return t
}(new Date, "yyyyMMddhhmmss"),
這塊代碼就是取當(dāng)前時(shí)間然后轉(zhuǎn)化格式,g
= 20230411175542
l = "p".concat(u).concat(g),
l
= “p” + 101 + 20230411175542 = “p10120230411175542”
f = t(t({}, c), {}, {
micalltime: g,
miversion: i.miversgin,
misource: u
}),
f
就是把上文中的 g、i.miversgin、u 合并為一個(gè)對(duì)象
h = Object.keys(f);
h
為 f
對(duì)象的所有 key
的數(shù)組
h.sort((function (e, t) {
return e.toLowerCase().localeCompare(t.toLowerCase())
}));
對(duì) h
數(shù)組中的元素全部轉(zhuǎn)小寫
var d = "";
h.forEach((function (e) {
d += "&".concat(e, "=").concat(f[e])
})), d = d.substr(1);
聲明一個(gè)空字符串 d
,然后把 h
中的元素全部使用 &
拼接起來
var p = r.hex_md5("".concat(d).concat(s));
o = "".concat(l).concat(p)
把 d
和之前的 s
拼接起來使用 md5 加密之后,在和 l
拼接,結(jié)果就出來了
o
= “p10120230411175542fab22e3db8c2d5a523289a398d920647”
部分最終代碼
function getSign(e, n) {
var i = {
encodeNumber: "101",
password: "4f0c6725d917f8fe4e2791921187fd7d",
miversgin: "p"
};
s = i.password;
var c = {};
if ("string" == typeof n) {
n.split("&").forEach((function (e) {
var t = e.split("=");
2 === t.length && (c[t[0]] = t[1])
}));
} else {
c = n;
if (e.includes("?")) e.substr(e.indexOf("?") + 1).split("&").forEach((function (e) {
var t = e.split("=");
2 === t.length && (c[t[0]] = t[1])
}));
}
var u = i.encodeNumber;
g = function (e, t) {
var n = new Date(e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate(), e.getUTCHours(), e.getUTCMinutes(), e.getUTCSeconds()),
r = new Date(n.setHours(e.getUTCHours() + 8)),
o = {
"M+": r.getMonth() + 1,
"d+": r.getDate(),
"h+": r.getHours(),
"m+": r.getMinutes(),
"s+": r.getSeconds(),
"q+": Math.floor((r.getMonth() + 3) / 3),
S: r.getMilliseconds()
};
for (var a in /(y+)/.test(t) && (t = t.replace(RegExp.$1, String(r.getFullYear()).substr(4 - RegExp.$1.length))), o) new RegExp("(" + a + ")").test(t) && (t = t.replace(RegExp.$1, 1 === RegExp.$1.length ? o[a] : ("00" + o[a]).substr(String(o[a]).length)));
return t
}(new Date(), "yyyyMMddhhmmss");
l = "p".concat(u).concat(g);
f = _objectSpread2(_objectSpread2({}, c), {}, {
micalltime: g,
miversion: i.miversgin,
misource: u
});
h = Object.keys(f);
h.sort((function (e, t) {
return e.toLowerCase().localeCompare(t.toLowerCase())
}));
var d = "";
h.forEach((function (e) {
d += "&".concat(e, "=").concat(f[e])
})), d = d.substr(1);
var p = hs.hex_md5("".concat(d).concat(s));
o = "".concat(l).concat(p)
return o;
}
// let url = 'https://miniapp.fang.com/pingyin/cityList';
// let params = {
// 'appname': 'fangx',
// 'v': '1.3.4',
// 'miniplat': 'weixin',
// 'scene': '1027',
// }
// console.log(getSign(url, params));
完整代碼
關(guān)注公眾號(hào)【趣碼周
】回復(fù) ftx
即可獲得。文章來源:http://www.zghlxwxcb.cn/news/detail-443212.html
關(guān)注我們
微信公眾號(hào):【趣碼周
】文章來源地址http://www.zghlxwxcb.cn/news/detail-443212.html
到了這里,關(guān)于【VX小程序逆向】房*下小程序pseusign參數(shù)分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!