【VX Mini Program Reverse】Pseusign Parameter Analysis of Room* Download Mini Program

Request packet analysis

Use Charles software to capture packets, the detailed process will not go into details, just paste the packet capture results directly

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)  

After deleting and restoring parameters back and forth, it is concluded that the pseudosign parameter is particularly important, and the applet code is directly analyzed.

Obtain the applet code (for some reason, the author of unveilr deleted the warehouse, you need to find it online)

I wrote an article [Mini Program Reverse] PC-side VX Mini Program Code Extraction to get the code of the mini program, but later when I used wxappUnpacker to receive the package, there was a problem, and the following error would be prompted

TypeError: subPackage.pages is not iterable

However, I found a new tool, unveilr , and the process of using it is also very simple. Let me demonstrate it briefly

The premise is still to use the PC WeChat mini-program package decryption tool to decrypt the mini-program file obtained on the PC side, just refer to the above article.

Install directly using NPM (first, ensure that NodeJS is installed on the computer)

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

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

After decrypting the applet file, use it directly unveilr /path/to/wxapkg/dir/to get the source file.

There are many usage examples refer to the unveilr documentation for details.

run applet

Use the WeChat applet development tool to import the unpacked code, compile and run it directly, and you will get the following error message

[插件 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)

You can roughly understand the meaning of the plug-in expiration, then just app.jsonfind pluginsand delete it, just like the following

::: code-group

"plugins": {
    
    
	"echarts": {
    
    
	"version": "2.1.1",
	"provider": "wx1db9e5ab1149ea03",
	"subpackage": "__APP__"
	}
},
"plugins": {
    
    
},

:::

Continue to compile and allow, continue to report errors, the content is as follows

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

The solution is to find @babel/runtime/helpers/typeof.jsand replace the following content into the file

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;

Continue to compile and run, and pass.

Analysis code

Direct global search pseusignto find the following code

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",

You can see pseusignthat is hgenerated by the function, follow up hto see

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

}

Mark the debugger for debugging

var i = a.vars.headerSgin;

a.varsThen declare that app.jsis a constant object, then headerSginisheaderSgin: {encodeNumber: "101",password: "4f0c6725d917f8fe4e2791921187fd7d",miversgin: "p"}

c = n;

nIt is the second parameter of the function, which is an object. After several times of debugging, you will know that it is the request parameter of the interface.

if (e.includes("?")) e.substr(e.indexOf("?") + 1).split("&").forEach((function (e) {
    
    
        var t = e.split("=");
        2 === t.length && (c[t[0]] = t[1])
      }));

eIt is the first parameter of the function, which is a URL address

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"),

This code is to take the current time and then convert the format, g= 20230411175542

l = "p".concat(u).concat(g),

l = “p” + 101 + 20230411175542 = “p10120230411175542”

f = t(t({
    
    }, c), {
    
    }, {
    
    
  micalltime: g,
  miversion: i.miversgin,
  misource: u
}),

fIt is to merge the above g, i.miversgin, u into one object

h = Object.keys(f);

han array of all for fobjectskey

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

hConvert all elements in the array to lowercase

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

Declare an empty string d, and hthen &splice all the elements in

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

dAfter splicing with the previous sand encrypting with md5, and lsplicing with , the result will come out

o= “p10120230411175542fab22e3db8c2d5a523289a398d920647”

part final code

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));

full code

Follow the official account [ 趣码周] and reply ftxto get it.

Follow us

WeChat public account: 【趣码周

おすすめ

転載: blog.csdn.net/baoshuowl/article/details/130090419