0


【VX小程序逆向】房*下小程序pseusign参数分析

目录

请求包分析

使用 Charles 软件进行抓包,详细过程就不细说了,直接贴上抓包结果

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)

经过来回删除恢复参数的方式,得出 pseusign 参数尤为重要,直接分析小程序代码。

获取小程序代码

之前写过一篇 [小程序逆向]PC端VX小程序代码提取 来获取小程序的代码,不过后面在使用 wxappUnpacker 接包的时候出了问题,会提示以下错误

TypeError: subPackage.pages is not iterable

不过又发现了一个新工具 unveilr ,使用过程也很简单,简单演示下

前提还是需要使用 PC微信小程序包解密工具 对在 PC 端拿到的小程序文件进行解密,参考上述文章即可。

直接使用 NPM 安装(首先电脑上得确保安装 NodeJS)

# npm
npm i unveilr -g
# yarn
yarn global add unveilr

unveilr --help
# 简称
uvr -h
# 当 'unveilr' 不是内部或外部命令,也不是可运行的程序或批处理文件。
# 尝试在命令前面加一个 npx, 例如:
npx unveilr --help

在对小程序文件进行解密后直接使用

unveilr /path/to/wxapkg/dir/

就可以获取到源文件了。

还有很多使用实例具体参考unveilr 文档。

运行小程序

使用微信小程序开发工具导入解包后的代码,直接编译运行,会得到以下错误信息

[插件 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":"__APP__"}},
"plugins":{},

:::

继续编译允许,继续报错,内容如下

WAServiceMainContext.js?t=wechat&s=1681204008944&v=2.30.3:1 TypeError: _typeof3 is not a function

解决办法,找到

@babel/runtime/helpers/typeof.js

,把下面内容替换到文件中

function_typeof2(o){"@babel/helpers - typeof";return(_typeof2 ="function"==typeof Symbol &&"symbol"==typeof Symbol.iterator ?function(o){returntypeof 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;

继续编译运行,通过了。

分析代码

直接全局搜索

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

函数生成,跟进

h

来看下

functionh(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 =newDate(e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate(), e.getUTCHours(), e.getUTCMinutes(), e.getUTCSeconds()),

r =newDate(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)newRegExp("("+ a +")").test(t)&&(t = t.replace(RegExp.$1,1=== RegExp.$1.length ? o[a]:("00"+ o[a]).substr(String(o[a]).length)));return t

}(newDate,"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 进行调试

var i = a.vars.headerSgin;
a.vars

则声明在

app.js

是一个常量对象,那么

headerSgin

headerSgin: {encodeNumber: "101",password: "4f0c6725d917f8fe4e2791921187fd7d",miversgin: "p"}
c = n;
n

为函数的第 2 个参数,是一个对象,多调试几次就知道是接口的请求参数

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

为函数的第 1 个参数,是一个 URL 地址

var u = i.encodeNumber,
u

= 101

s = i.password,
s

= 4f0c6725d917f8fe4e2791921187fd7d

g=function(e, t){var n =newDate(e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate(), e.getUTCHours(), e.getUTCMinutes(), e.getUTCSeconds()),
            r =newDate(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)newRegExp("("+ a +")").test(t)&&(t = t.replace(RegExp.$1,1=== RegExp.$1.length ? o[a]:("00"+ o[a]).substr(String(o[a]).length)));return t
        }(newDate,"yyyyMMddhhmmss"),

这块代码就是取当前时间然后转化格式,

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 合并为一个对象

h = Object.keys(f);
h

f

对象的所有

key

的数组

h.sort((function(e, t){return e.toLowerCase().localeCompare(t.toLowerCase())}));

h

数组中的元素全部转小写

var d ="";
h.forEach((function(e){
d +="&".concat(e,"=").concat(f[e])})), d = d.substr(1);

声明一个空字符串

d

,然后把

h

中的元素全部使用

&

拼接起来

var p = r.hex_md5("".concat(d).concat(s));
o ="".concat(l).concat(p)

d

和之前的

s

拼接起来使用 md5 加密之后,在和

l

拼接,结果就出来了

o

= “p10120230411175542fab22e3db8c2d5a523289a398d920647”

部分最终代码

functiongetSign(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 =newDate(e.getUTCFullYear(), e.getUTCMonth(), e.getUTCDate(), e.getUTCHours(), e.getUTCMinutes(), e.getUTCSeconds()),
            r =newDate(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)newRegExp("("+ a +")").test(t)&&(t = t.replace(RegExp.$1,1=== RegExp.$1.length ? o[a]:("00"+ o[a]).substr(String(o[a]).length)));return t
    }(newDate(),"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));

完整代码

关注公众号【

趣码周

】回复

ftx

即可获得。

关注我们

微信公众号:【

趣码周


本文转载自: https://blog.csdn.net/baoshuowl/article/details/130090419
版权归原作者 mankvis 所有, 如有侵权,请联系我们删除。

“【VX小程序逆向】房*下小程序pseusign参数分析”的评论:

还没有评论