开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 3833|回复: 7
收起左侧

[图文资料] 某uniapp 加密逆向

[复制链接]
结帖率:91% (10/11)
发表于 2022-7-22 16:50:48 | 显示全部楼层 |阅读模式   湖南省怀化市
本帖最后由 ximenlang666 于 2022-7-22 17:05 编辑
  今天看到了问答区的这一篇求助帖https://bbs.125.la/forum.php?mod=viewthread&tid=14738238&highlight=UNI%2Bapp闲的没事打开瞅了一眼,分享一下我的解密思路,说的不好,各位大哥也不要喷!  首先我们抓个包
   抓包.png


   可以看到这里我们的提交数据是被加密过了的, 提交参数名是:encrypt_data

    压缩包图.png

打开apk文件可以看到是一个uniapp框架的  我们知道,uniapp他发包是在java发包,加密一般是在 app-services.js  这个文件里面 ,我们可以直接打开这个js文件


js.png


  这里我用Notepad++打开的,搜索 encrypt_data  一共有三处地方 :

encrypt_data: (0, s.encrypt)(JSON.stringify(c), "api")
switch (void 0 !== e.data.data && e.data.data.encrypt_data && o && (l = JSON.parse((0, s.decrypt)(e.data.data.encrypt_data, c))), n.code)


这里我们可以看到 第一处的encrypt_data  是调用了s对象下面的一个encrypt方法 ,encrypt这玩意翻译过来就是加密的意思,我们可以找一下这个s是从哪儿来的;


var s = a("e40f");


这不就是webpack吗,a是webpack的分发器,传了模块名进去;我们直接在js文件里面搜索e40f,找到他模块所在的地方;


[JavaScript] 纯文本查看 复制代码
 e40f: function (e, t, a) {
                "use strict";
                Object.defineProperty(t, "__esModule", {
                    value: !0
                }),
                t.encrypt = n,
                t.decrypt = r;
                var s = i(a("bffd"));
                function i(e) {
                    return e && e.__esModule ? e : {
                    default:
                        e
                    }
                }
                function n(e, t) {
                    var a = o(t),
                    i = c(t),
                    n = s.default.enc.Utf8.parse(i),
                    r = s.default.enc.Utf8.parse(a),
                    l = s.default.AES.encrypt(e, n, {
                        iv: r,
                        mode: s.default.mode.CBC,
                        padding: s.default.pad.Pkcs7
                    });
                    return l.toString()
                }
                function r(e, t) {
                    var a = o(t),
                    i = c(t),
                    n = s.default.enc.Utf8.parse(i),
                    r = s.default.enc.Utf8.parse(a),
                    l = s.default.AES.decrypt(e, n, {
                        iv: r,
                        padding: s.default.pad.Pkcs7
                    });
                    return l.toString(s.default.enc.Utf8)
                }
                function o() {
                    var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "web",
                    t = e.toUpperCase(),
                    a = l("ymd") + t,
                    i = s.default.MD5(a).toString();
                    return i.substr(8, 16)
                }
                function c() {
                    var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "web",
                    t = e.toUpperCase(),
                    a = t + l("ymd"),
                    i = s.default.MD5(a).toString();
                    return i.substr(8, 16)
                }
                function l(e) {
                    var t = new Date,
                    a = t.getFullYear(),
                    s = t.getMonth() + 1,
                    i = t.getDate(),
                    n = t.getHours() < 10 ? "0" + t.getHours() : t.getHours(),
                    r = t.getMinutes() < 10 ? "0" + t.getMinutes() : t.getMinutes(),
                    o = t.getSeconds() < 10 ? "0" + t.getSeconds() : t.getSeconds();
                    return s >= 1 && s <= 9 && (s = "0" + s),
                    i >= 0 && i <= 9 && (i = "0" + i),
                    n >= 0 && n <= 9 && (n = "0" + n),
                    r >= 0 && r <= 9 && (r = "0" + r),
                    o >= 0 && o <= 9 && (o = "0" + o),
                    -1 != e.indexOf("y") && (e = e.replace("y", a)),
                    -1 != e.indexOf("m") && (e = e.replace("m", s)),
                    -1 != e.indexOf("d") && (e = e.replace("d", i)),
                    -1 != e.indexOf("h") && (e = e.replace("h", n)),
                    -1 != e.indexOf("i") && (e = e.replace("i", r)),
                    -1 != e.indexOf("s") && (e = e.replace("s", o)),
                    e
                }
            },




好,找到模块了,下面有一个 加密方法和一个解密方法,t.encrypt = n,t.decrypt = r; 所以说我们的s.encrypt 他就是我们的n方法;我们看一下n方法;


                function n(e, t) {
                    var a = o(t),
                    i = c(t),
                    n = s.default.enc.Utf8.parse(i),
                    r = s.default.enc.Utf8.parse(a),
                    l = s.default.AES.encrypt(e, n, {
                        iv: r,
                        mode: s.default.mode.CBC,
                        padding: s.default.pad.Pkcs7
                    });
                    return l.toString()
                }

我们看到这个应该是知道了,他就是一个aes加密,还有他的模式和填充,aes是对称加密,所以说我们拿到他的key和iv是可以解密的;


我们看一下他的key和iv是什么玩意;经常搞这种的朋友应该知道,这路的n就是我们的key,r就是iv; n(key)是在这里赋值的:n=s.default.enc.Utf8.parse(i)  ;  


这个s其实就是CryptoJS这个加密库,s.default.enc.Utf8.parse(i)是用来从UTF8编码解析出原始字符串;所以说,我们要找到这个i, i = c(t);

这里的i是通过c这个方法返回的,穿进去的t是我们调用s.encrypt这个方法的第二个参数,(0, s.encrypt)(JSON.stringify(c), "api") ;


我们的第二个参数就是这个“api”,所以说我们需要先把c方法拿出来;

[JavaScript] 纯文本查看 复制代码
   function c() {
                    var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "web",
                    t = e.toUpperCase(),
                    a = t + l("ymd"),
                    i = s.default.MD5(a).toString();
                    return i.substr(8, 16)
                }



var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "web" 这三目运算不多讲了,反正你记住,不是“api”就是“web”,;


t = e.toUpperCase();把我们的参数到大写,a = t + l("ymd"), a=参数+l(“ymd”);这个l方法就是取得今天的年月日


QQ截图20220722163627.png

a=参数+l(“ymd”)   就是 a="API20220722"; s.default.MD5(a).toString();  把a md5加密,return i.substr(8, 16)  返回加密结果的第九位到第十六位,就是我们的key ;


这里我拿到的key是:“3ff7e48790b97ded”;key拿到了还有我们的iv;a = o(t), iv是通过o方法,穿进去的参数是一样的,我们看一下o方法;


[JavaScript] 纯文本查看 复制代码
function o() {
                    var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "web",
                    t = e.toUpperCase(),
                    a = l("ymd") + t,
                    i = s.default.MD5(a).toString();
                    return i.substr(8, 16)
                }



这个o方法就是里面md5加密的参数相加顺序倒过来了一下 l("ymd") + t,c方法是 t+l("ymd") ,我这边加密的结果是:“b9a844d493688f67”;

所以说我们的key:3ff7e48790b97ded,iv:b9a844d493688f67,我们拿去解密测试一下;

QQ截图20220722164952.png


好结果出来了;;



结帖率:32% (6/19)

签到天数: 6 天

发表于 2024-1-10 09:13:32 | 显示全部楼层   贵州省黔东南苗族侗族自治州
很不错的样子,支持,支持
回复 支持 反对

使用道具 举报

发表于 2022-8-4 15:01:02 | 显示全部楼层   浙江省杭州市
浪总又秒了, 太强了666666666666
回复 支持 反对

使用道具 举报

签到天数: 1 天

发表于 2022-7-22 21:30:18 | 显示全部楼层   黑龙江省哈尔滨市
回复 支持 反对

使用道具 举报

签到天数: 8 天

发表于 2022-7-22 21:27:45 高大上手机用户 | 显示全部楼层   四川省资阳市
学习学习
回复 支持 反对

使用道具 举报

结帖率:89% (17/19)

签到天数: 1 天

发表于 2022-7-22 19:15:30 | 显示全部楼层   湖北省咸宁市
太牛了浪牛学习学习
回复 支持 反对

使用道具 举报

结帖率:60% (15/25)

签到天数: 25 天

发表于 2022-7-22 18:31:34 | 显示全部楼层   江苏省苏州市
学习了,这个比较简单
回复 支持 反对

使用道具 举报

结帖率:100% (4/4)

签到天数: 3 天

发表于 2022-7-22 18:18:37 | 显示全部楼层   浙江省衢州市
浪总又秒了, 太强了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 诚聘英才| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 800073686,邮箱:800073686@b.qq.com
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表