前言
(此篇就是玩玩,有想要再深入学习逆向的小伙伴,还请自行寻找资料,切勿再私信破解app,一律不回,谢谢)
因为疫情的缘故上学期在学校出校门需要用到请假软件,(虽然还是想吐槽一下,但还是算了吧)随之也就出现了各种假 假条软件,有部分需要收费。秉承能白嫖坚决不掏钱的原则,别问为什么,问就是穷。正好现在放假闲来无事就搞它一波,本人也是菜鸡一枚,仅仅来分享下逆向过程跟经验,大佬看看就好,如若能给点方向给点建议,那再好不过。(手动狗头)本篇文章只是来说一说我这个小白的逆向入门之路,仅用来学习交流之用!!!!帮助那些和我类似的小伙伴理解逆向,欢迎有此爱好的小伙伴交流、互相学习。废话不多说,进入正题:
(PS:文中所说的软件在文末)
First 查壳
首先就是对apk进行查壳,未加密就直接下一步了
嗯…应该是未加密的吧?有点不确定就再从MT管理器上面瞅瞅
显示未加固,那就直接进行下一步
Second 反编译
既然是没有壳,那就用AndroidKiller进行反编译
但是用AndroidKiller也有个问题,就是再进行反编译过程中会卡在“反编译源码”,这个也没关系,关闭重新开一次软件就可,至于解决方法,在吾爱破解论坛也有介绍,有兴趣的可以去找找看。源码的问题可以用dex2jar解决,源码只是配合smali文件理解,破解还是要改smali文件。
接下来找个安卓机,实测一下软件,发现点击“请假”会跳出“请激活再使用!”的提示。
好滴,这就是一个突破口,先将刚才提示的文本转为Unicode编码。“请激活再使用!”转Unicode编码也就是“\u8bf7\u6fc0\u6d3b\u518d\u4f7f\u7528\uff01”。在回到AndroidKiller中进行全文件搜索
哦吼!找到一个JS文件,咱先瞅瞅里边都是啥,对文件进行搜索,先定位看看具体在哪儿
看搜索结果有6处,额(⊙o⊙)…看不懂JS咋办捏,猜!!仔细看着六处搜索结果,每三个各包含在一个activation: function (),并且都有 success: function (t)、fail: function (t),不妨大胆尝试一下修改这两个模块。不过到这儿也就大致猜到了,软件页面内容其实就是web页面,使用JavaScript添加交互行为(不知道表达的对不对)下面看下源码:
activation: function () {
var e = this;
(this.activationCode = !1),
t.callFunction({
name: "logincardkey",
data: { cardkey: this.cardkey },
success: function (t) {
var n = t.result.code,
i = (t.result.msg, e);
if (0 == n) {
var s = t.result.expireDate,
a = new Date(s.replace(/-/g, "/")).getTime(),
r = Date.now(),
o = a - r;
o > 0
? i.sub()
: uni.showToast({
icon: "none",
duration: 3e3,
title: "\u8bf7\u6fc0\u6d3b\u518d\u4f7f\u7528\uff01",
});
} else
uni.showToast({
icon: "none",
duration: 3e3,
title: "\u8bf7\u6fc0\u6d3b\u518d\u4f7f\u7528\uff01",
});
},
fail: function (t) {
uni.showToast({
icon: "none",
duration: 3e3,
title: "\u8bf7\u6fc0\u6d3b\u518d\u4f7f\u7528\uff01",
}),
i("log", t.result, " at pages/addLeave/addLeave.vue:340");
},
});
},
sub: function () {
var t = this;
if (
"" != this.name &&
"" != this.sflx &&
"" != this.xjgz &&
"" != this.type &&
"" != this.startDate &&
"" != this.startTime &&
"" != this.endDate &&
"" != this.endTime &&
"" != this.reason &&
"" != this.address &&
"" != this.cc &&
"" != this.phone &&
"" != this.oneCheckTime &&
"" != this.applyDate &&
"" != this.applyTime &&
"" != this.oneCheckStatus &&
"" != this.oneCheck &&
"" != this.countDate &&
"" != this.oneCheckDate &&
"" != this.oneCheckIdea
)
if (
this.startDate != this.endDate ||
this.startTime != this.endTime
)
if (this.reason.length < 2)
this.toast(
"\u8bf7\u5047\u539f\u56e0\u4e0d\u80fd\u5c11\u4e8e10\u5b57",
"none"
);
else if (
"" == this.twoCheck ||
("" != this.twoCheckDate &&
"" != this.twoCheckTime &&
"" != this.twoCheckStatus &&
"" != this.twoCheckIdea)
)
if (
"" == this.threeCheck ||
("" != this.threeCheckDate &&
"" != this.threeCheckTime &&
"" != this.threeCheckStatus &&
"" != this.threeCheckIdea)
)
if ("" == this.threeCheck || "" != this.twoCheck) {
var e = {};
new Date();
(e["name"] = this.name),
(e["type"] = this.type),
(e["xjgz"] = this.xjgz),
(e["sflx"] = this.sflx),
(e["startDate"] =
this.startDate + " " + this.startTime),
(e["endDate"] = this.endDate + " " + this.endTime),
(e["countDate"] = this.countDate),
(e["reason"] = this.reason),
(e["phone"] = this.phone),
(e["address"] = this.address),
(e["cc"] = this.cc),
(e["oneCheck"] = this.oneCheck),
(e["oneCheckDate"] =
this.oneCheckDate + " " + this.oneCheckTime),
(e["oneCheckStatus"] = this.oneCheckStatus),
(e["oneCheckIdea"] = this.oneCheckIdea),
(e["twoCheck"] = this.twoCheck),
(e["twoCheckDate"] =
this.twoCheckDate + " " + this.twoCheckTime),
(e["twoCheckStatus"] = this.twoCheckStatus),
(e["twoCheckIdea"] = this.twoCheckIdea),
(e["threeCheck"] = this.threeCheck),
(e["threeCheckDate"] =
this.threeCheckDate + " " + this.threeCheckTime),
(e["threeCheckStatus"] = this.threeCheckStatus),
(e["threeCheckIdea"] = this.threeCheckIdea),
(e["fourCheck"] = this.fourCheck),
(e["fourCheckDate"] =
this.fourCheckDate + " " + this.fourCheckTime),
(e["fourCheckStatus"] = this.fourCheckStatus),
(e["fourCheckIdea"] = this.fourCheckIdea),
(e["viewChakan"] = this.viewChakan),
(e["viewHuangse"] = this.viewHuangse),
(e["viewsqXujia"] = this.viewsqXujia),
(e["state"] = this.state),
(e["applyDate"] =
this.applyDate + " " + this.applyTime),
(e["imgFile"] = this.imgFile),
(e["imgFiles"] = this.imgFiles),
i(
"log",
this.imgFile,
" at pages/addLeave/addLeave.vue:425"
),
this.leaves.push(e),
i(
"log",
this.leaves,
" at pages/addLeave/addLeave.vue:427"
),
uni.setStorage({
key: "todaySchoolLeaves",
data: t.leaves,
success: function () {
t.toast("\u63d0\u4ea4\u6210\u529f", "success"),
setTimeout(function () {
uni.navigateBack({ delta: 1 });
}, 1600);
},
fail: function () {
t.toast(
"\u63d0\u4ea4\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5",
"none"
);
},
});
} else
this.toast(
"\u5982\u6709\u4e09\u7ea7\u5ba1\u6279\uff0c\u4e8c\u7ea7\u5ba1\u6279\u5fc5\u586b",
"none"
);
else
this.toast(
"\u8bf7\u5c06\u4e09\u7ea7\u5ba1\u6279\u4eba\u5ba1\u6279\u4fe1\u606f\u586b\u5199\u5b8c\u6574",
"none"
);
else
this.toast(
"\u8bf7\u5c06\u4e8c\u7ea7\u5ba1\u6279\u4eba\u5ba1\u6279\u4fe1\u606f\u586b\u5199\u5b8c\u6574",
"none"
);
else
this.toast(
"\u5f00\u59cb\u65e5\u671f\u4e0d\u80fd\u7b49\u4e8e\u7ed3\u675f\u65e5\u671f",
"none"
);
else
this.toast(
"\u8bf7\u5c06\u5fc5\u586b\u4fe1\u606f\u586b\u5199\u5b8c\u6574",
"none"
);
}
接下来就是改啊,首先看success这个函数,里面也做了一个判断,不符合条件就显示要激活的提示,就先改它:
o > 0
? i.sub()
: uni.showToast({
icon: "none",
duration: 3e3,
title: "\u8bf7\u6fc0\u6d3b\u518d\u4f7f\u7528\uff01",
})
此处做出判断跳转到下面sub()的函数,咱先给他把判断结果做一下调换,再往下看还有个else的跳转,这个就是前面所提到的突破口——“请激活再使用!”,结合前面 if 成功的跳转,那就把else跳转结果改为i.sub(),现在success函数就改完了,接着开整fail()函数,根据success的结果来看,最终是要跳转到sub()这个函数,按理来说应该可以直接修改跳转到sub(),但还没有去尝试,索性直接将success()的内容直接替换到fail()里。这一组就算是改完了,还剩下一组,改的方法跟这个一样,改完收工。
Third 打包、签名
改完之后就是打包签名,然后安装,测试一下修改的结果
现在就来安装测试一下,重新点击“请假”,哦吼吼吼吼!!进去了,也就是说破解完成,搞完收工。
Forth 总结
本人才学浅薄,见笑见笑,本次破解并没有涉及到smali文件,盲猜源码是一些校验算法之类的,本次只涉及到安卓的一些资源文件,其实并不需要反编译,只需要修改再签名即可,在手机上直接用MT管理器进行替换就可以完成。OK,到现在该说的基本说完了,再来说说逆向,逆向的本意是对自身进行挖掘,好填补一些难以发现的漏洞、不足,增加安全性。在座的各位要做一个遵纪守法的好孩子哦,千万不要试图挑战法律!!!!
AndroidKiller_v1.3.1链接: https://download.csdn.net/download/weixin_43811041/14907645