逆向实战(4)-微信 创见小程序 反编译 解包 接口签名参数研究

本次主要分析对象网址(base64):5b6u5L+h5bCP56iL5bqP77ya5Yib6KeBICjljY7liJvor4HliLjlrqLmiLfmnI3liqHlubPlj7Ap
在这里插入图片描述

一、工具准备
1、Fiddler(抓包)
2、微信(小程序)
3、KillWxapkg(反编译、解包、解密)
4、微信开发者工具(小程序代码调试)
4、PyCharm(逆向代码调试)

二、Fiddler抓包
在这里插入图片描述
三、反编译小程序 解包
1、找到目标小程序的包
在这里插入图片描述
打开文件夹,然后上一级目录Applet下,这些长长的一串就是打开过的小程序文件,全部删掉,重新打开我们要弄的小程序,就会出现一个文件夹,这个文件夹下就有小程序的包
在这里插入图片描述
在这里插入图片描述
2、解包

  • 用 KillWxapkg 程序进行解包,下面是用法
    在这里插入图片描述

  • 执行命令:KillWxapkg_1.1.0_windows_amd64.exe -id=wx797d2853220c468c -in “F:\test_files\149” -out “F:\test_files\new_149” -restore -pretty

  • wx797d2853220c468c 小程序的id

  • F:\test_files\149 需要解包的目录

  • F:\test_files\new_149 解包后的的文件输出目录
    在这里插入图片描述

  • 这是没有解包的样子
    在这里插入图片描述

  • 这是解包后的样子
    在这里插入图片描述

ok,非常完美,后面就是到微信开发者工具里面运行这个小程序进行调试了

四、调试小程序

  • 因为我们用工具反编译的时候不能全部都编译出来,所以加载后会有很多地方报错,需要哪里报错点哪里进行解决
    1、导入项目
    在这里插入图片描述
    2、先把右上角详情-本地设置-去掉一些勾选,如下:
    在这里插入图片描述
    我们可以看到模拟器启动失败,这是因为编译的不完全导致的,需要一步步解决
    3、调试项目
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    现在报的是另一个错误,缺少组件,这些组件对于我们来说都没用,我们找到对应的地方删掉就好了
    在这里插入图片描述
    删除
    在这里插入图片描述
    继续报另一个json文件里面没有组件,继续定位到位置,删除
    在这里插入图片描述
    一直报错一直删,根本停不下来,完全停不下来,继续删。。。。。。。
    在这里插入图片描述
    这开发者视乎有自己的想法啊
    在这里插入图片描述
    终于不报异常错误了,并且小程序的底部出现了正常的图标,下面就可以进行调试了

五、加密入口分析
1、通过刷新首页,可以看到所有接口都带有签名,我们只要找到生成签名的方法,就可以得到sign的值了
在这里插入图片描述
2、全局搜sign=,可以筛选出三个位置出现url拼接了签名,这就有可能是我们要研究的地方;全部打上断点,进行调试
在这里插入图片描述
3、通过测试发现这边打上三个断点在调试之后虽然生成了签名,但是最终和服务器校验的时候是失败的,并且服务器返回禁止访问
在这里插入图片描述
说明这三个地方的都不对,我们换个搜索条件sign: ,发现只有一个关键字出现sign: d,这个感觉就是获取签名的方法了,打上断点,刷新调试一下;
在这里插入图片描述
4、关键位置下断点,多次跳过断点发现c就是我们要传的参数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个c参数传的不就是一个翻页数据吗,那我们就只需要把这些代码扣下来缺啥补啥就行了

var c = a.data,
    l = (0, n.getTime)(),
    d = (0, n.getSign)("CJ", c),
    g = o();

var data = t(t({}, c), {}, {
    time: l,
    sign: d
})

三、扣代码阶段
1)、a.data先用 {limit: 20, page: 1} 进行调试;n.getTime 就是o ;n.getSign 就是getSign

o = function () {
    return Date.parse(new Date) / 1e3
}

getSign = function (t) {
    var c = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {},
        a = e(e({}, c), {}, {
            time: "".concat(o())
        }),
        i = Object.keys(a).sort().reduce((function (e, t) {
            return "".concat(e).concat(a[t] ? "&".concat(t, "|").concat(a[t]) : "")
        }), ""),
        u = {
            CJ: "".concat(n.CJ_KEY).concat(i),
            WORK: "".concat(n.WORK_KEY).concat(i)
        };
    return (0, r.hexMD5)(u[t])
}
var c = {limit: 20, page: 1},
    l = (0, o)(),
    d = (0, getSign)("CJ", c),
    g = o();

var data = t(t({}, c), {}, {
    time: l,
    sign: d
})

2)、执行js后报 “e is not defined”,我们一步步跟进取,把所有报错的都扣下来

o = function () {
    return Date.parse(new Date) / 1e3
}

function ownKeys(e, r) {
    var t = Object.keys(e);
    if (Object.getOwnPropertySymbols) {
        var o = Object.getOwnPropertySymbols(e);
        r && (o = o.filter((function (r) {
            return Object.getOwnPropertyDescriptor(e, r).enumerable
        }))), t.push.apply(t, o)
    }
    return t
}

function _typeof(o) {
    return module.exports = _typeof = "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
    }, _typeof(o)
}

function _toPrimitive(r, t) {
    if ("object" !== _typeof(r) || null === r) return r;
    var e = r[Symbol.toPrimitive];
    if (void 0 !== e) {
        var i = e.call(r, t || "default");
        if ("object" !== _typeof(i)) return i;
        throw new TypeError("@@toPrimitive must return a primitive value.")
    }
    return ("string" === t ? String : Number)(r)
}

function toPropertyKey(r) {
    var t = _toPrimitive(r, "string");
    return "symbol" === _typeof(t) ? t : String(t)
}

function defineProperty(e, r, t) {
    return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
        value: t,
        enumerable: !0,
        configurable: !0,
        writable: !0
    }) : e[r] = t, e
}

function e(e) {
    for (var r = 1; r < arguments.length; r++) {
        var t = null != arguments[r] ? arguments[r] : {};
        r % 2 ? ownKeys(Object(t), !0).forEach((function (r) {
            defineProperty(e, r, t[r])
        })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach((function (r) {
            Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r))
        }))
    }
    return e
}

getSign = function (t) {
    var c = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {},
        a = e(e({}, c), {}, {
            time: "".concat(o())
        }),
        i = Object.keys(a).sort().reduce((function (e, t) {
            return "".concat(e).concat(a[t] ? "&".concat(t, "|").concat(a[t]) : "")
        }), ""),
        u = {
            CJ: "".concat("A8-A7-C5-89-CB-33").concat(i),
            WORK: "".concat("A8-A7-C5-89-CB-33").concat(i)
        };
    return (0, r.hexMD5)(u[t])
}

function _objectSpread2(e) {
    for (var r = 1; r < arguments.length; r++) {
        var t = null != arguments[r] ? arguments[r] : {};
        r % 2 ? ownKeys(Object(t), !0).forEach((function (r) {
            defineProperty(e, r, t[r])
        })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach((function (r) {
            Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r))
        }))
    }
    return e
}

var c = {limit: 20, page: 1},
    l = (0, o)(),
    d = (0, getSign)("CJ", c),
    g = o();

var data = _objectSpread2(_objectSpread2({}, c), {}, {
    time: l,
    sign: d
})

3)、执行js后报 “r is not defined”;r.hexMD5 这很明显是一个md5的加密并以16进制输出;我们直接导个包const CryptoJS = require(“crypto-js”); 因为CryptoJS没有直接的hexMD5功能函数,所以我们使用CryptoJS.MD5().toString() 实现最终的输出

const CryptoJS = require("crypto-js");

o = function () {
    return Date.parse(new Date) / 1e3
}

function ownKeys(e, r) {
    var t = Object.keys(e);
    if (Object.getOwnPropertySymbols) {
        var o = Object.getOwnPropertySymbols(e);
        r && (o = o.filter((function (r) {
            return Object.getOwnPropertyDescriptor(e, r).enumerable
        }))), t.push.apply(t, o)
    }
    return t
}

function _typeof(o) {
    return module.exports = _typeof = "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
    }, _typeof(o)
}

function _toPrimitive(r, t) {
    if ("object" !== _typeof(r) || null === r) return r;
    var e = r[Symbol.toPrimitive];
    if (void 0 !== e) {
        var i = e.call(r, t || "default");
        if ("object" !== _typeof(i)) return i;
        throw new TypeError("@@toPrimitive must return a primitive value.")
    }
    return ("string" === t ? String : Number)(r)
}

function toPropertyKey(r) {
    var t = _toPrimitive(r, "string");
    return "symbol" === _typeof(t) ? t : String(t)
}

function defineProperty(e, r, t) {
    return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
        value: t,
        enumerable: !0,
        configurable: !0,
        writable: !0
    }) : e[r] = t, e
}

function e(e) {
    for (var r = 1; r < arguments.length; r++) {
        var t = null != arguments[r] ? arguments[r] : {};
        r % 2 ? ownKeys(Object(t), !0).forEach((function (r) {
            defineProperty(e, r, t[r])
        })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach((function (r) {
            Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r))
        }))
    }
    return e
}

getSign = function (t) {
    var c = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {},
        a = e(e({}, c), {}, {
            time: "".concat(o())
        }),
        i = Object.keys(a).sort().reduce((function (e, t) {
            return "".concat(e).concat(a[t] ? "&".concat(t, "|").concat(a[t]) : "")
        }), ""),
        u = {
            CJ: "".concat("A8-A7-C5-89-CB-33").concat(i),
            WORK: "".concat("A8-A7-C5-89-CB-33").concat(i)
        };
    return CryptoJS.MD5(u[t]).toString()
}

function _objectSpread2(e) {
    for (var r = 1; r < arguments.length; r++) {
        var t = null != arguments[r] ? arguments[r] : {};
        r % 2 ? ownKeys(Object(t), !0).forEach((function (r) {
            defineProperty(e, r, t[r])
        })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach((function (r) {
            Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r))
        }))
    }
    return e
}

var c = {limit: 20, page: 1},
    l = (0, o)(),
    d = (0, getSign)("CJ", c),
    g = o();

var data = _objectSpread2(_objectSpread2({}, c), {}, {
    time: l,
    sign: d
})

console.log(data)

// 输出结果
{
  limit: 20,
  page: 1,
  time: 1749458130,
  sign: 'fb6ac10e0902a66cb82b89bed61b666a'
}

4)、代码扣完了,后续就是简化整合然后调用了

总结:扣js代码是一件枯燥的过程,只要我们一点一点的去分析,总会找到关键位置的,加油~~~

逆向实战(3)-雪球 金融韭菜网站研究(请求参数md5__1038加密、js混淆、逆向))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值