小结
有了这么多优秀的开发工具,可以做出更高质量的Android应用。
当然了,“打铁还需自身硬”,想要写出优秀的代码,最重要的一点还是自身的技术水平,不然用再好的工具也不能发挥出它的全部实力。
在这里我也分享一份大佬自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。
总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
var offset = ptr(addr).sub(idaBase); // Calculate offset in memory from base address in IDA database
var result = baseAddr.add(offset); // Add current memory base address to offset of function to monitor
console.log('[+] New addr=' + result); // Write location of function in memory to console
return result;
}
开始解密jsc文件,这我用的傻瓜是解密方式,只要填写密钥就行了,一个软件自动搞定。
![](https://img-blog.csdnimg.cn/0657ec6a8ef44f21b75059684aee424a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_18,color_FFFFFF,t_70,g_se,x_16)
解密后的一个压缩包,打开压缩包把文件拖出来即可。
![](https://img-blog.csdnimg.cn/eb4337b2bace4775b6a1680d4f6bc4b8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_6,color_FFFFFF,t_70,g_se,x_16)
打开文件,搜索m-urlencoded;charset=utf- 定位到发送Http 请求处。
![](https://img-blog.csdnimg.cn/4630dcc8e66041cf9bc85eacf931c016.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_20,color_FFFFFF,t_70,g_se,x_16)
发现是 aesEncryptString 数据加密,同时也发现了 HttpEncryptKey,那我们就把HttpEncryptKey 打印出来。
这我就偷懒一下,直接添加到http请求头里面,从抓包里就能看到密钥了。
![](https://img-blog.csdnimg.cn/8768f10d08a342fbb50316fbd41f85e4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_20,color_FFFFFF,t_70,g_se,x_16)
选择**新加密** ,把.js文件加密回jsc文件,替换原文件。
![](https://img-blog.csdnimg.cn/81e7355e9d1f47e98842da5639869609.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_17,color_FFFFFF,t_70,g_se,x_16)
效果图,得到aes加密的密钥了。
我顺便也打印了一下**POST数据**,Content-params: {"ChannelID":"0"}
![](https://img-blog.csdnimg.cn/bf31bbc2efaa4efa9023d4a215ff2a00.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_13,color_FFFFFF,t_70,g_se,x_16)
那我就去测试一下密钥是否正确,测试结果完全一致
![](https://img-blog.csdnimg.cn/5d8ae009f00e4e02a1972acc6b7298ec.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_16,color_FFFFFF,t_70,g_se,x_16)
那我就去看看如何解密。
搜索 aesEncryptString 下面就是解密方法 aesDecryptString
![](https://img-blog.csdnimg.cn/a608aef98c7e4fa8904feb1cc92f3e4e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_20,color_FFFFFF,t_70,g_se,x_16)
在搜索 aesDecryptString,找到http数据返回处,调用了aesDecryptString,解密数据密钥也是用的 t.Config.HttpEncryptKey,说明是和加密的一样。
![](https://img-blog.csdnimg.cn/3fadba7beece4815ba3dcf5e87359f11.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_20,color_FFFFFF,t_70,g_se,x_16)
测试解密返回数据,也成功了,这样我们的第一步①就完成了。
![](https://img-blog.csdnimg.cn/c53a6ec64a794d38a7b728e47fdb3880.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_18,color_FFFFFF,t_70,g_se,x_16)
解密部分js代码
var i = function() {
function t() {}
t.randomAesKeyBuffer = function() {
return n(16);
};
t.randomAesIvBuffer = function() {
return n(16);
};
t.stringToBuffer = function(t) {
for (var e = [], o = t.length, n = 0; n < o; n++) e[n] = t.charCodeAt(n);
return new Uint8Array(e);
};
t.bufferToString = function(t) {
for (var e = “”, o = Array.from(t), n = 0, r = o.length; n < r; n++) e += String.fromCharCode(o[n]);
return e;
};
t.aesEncryptString = function(t, e) {
if (e.length > 0) {
var o = by.CryptoJS, n = o.enc.Utf8.parse(t), r = o.enc.Utf8.parse(e);
return by.CryptoJS.AES.encrypt(r, n, {
mode: o.mode.ECB,
padding: o.pad.Pkcs7
}).toString();
}
return “”;
};
t.aesDecryptString = function(t, e) {
var o = by.CryptoJS, n = o.enc.Utf8.parse(t), r = o.AES.decrypt(e, n, {
mode: o.mode.ECB,
padding: o.pad.Pkcs7
});
return o.enc.Utf8.stringify®.toString();
};
t.aesEncryptBuffer = function(t, e, o) {
var n = by.CryptoJS, i = n.lib.WordArray.create(t), a = n.lib.WordArray.create(e), s = n.lib.WordArray.create(o);
return r(n.AES.encrypt(s, i, {
iv: a,
mode: n.mode.CBC,
padding: n.pad.ZeroPadding
}).ciphertext);
};
t.aesDecryptBuffer = function(t, e, o) {
var n = by.CryptoJS, i = n.lib.WordArray.create(t), a = n.lib.WordArray.create(e), s = n.lib.WordArray.create(o), c = n.enc.Base64.stringify(s);
return r(n.AES.decrypt(c, i, {
iv: a,
mode: n.mode.CBC,
padding: n.pad.NoPadding
}));
};
t.rsaEncryptWithPublicKey = function(t) {
var e = by.forge.pki.publicKeyFromPem(“-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEA3svz/3o/IBJGL3Lml5zH1jTpey+Z1fZraHF5dOj0FA1f8eJM7naE\ncO4tDuIgbICXfNW4Ln+hTi33EMzulpZpehigYFd9aPinJ6ynhNXE4BL/2NauYIRq\nvTy+72PtL4gswT0l0tWWbCX2yNco0G8J4fk92ZivuO+/osTtmYLMmNJ/hjPi4u86\njRtLkoSQ+6X55OJmLA1enWiu5hxDQQtue3Yw96Wo7fUJh8BnTBw7lTUwTHJhadoK\nt6mJqQfv0DnnHaOERkwxNgL/c6u04R2ruywyKrC5aaFRqZRrGA3zthUZS5K3/YLq\nU8tf+UBiBI1hEyroAWe8Q8/syBJ0cYOCOQIDAQAB\n-----END RSA PUBLIC KEY-----”), o = this.bufferToString(t), n = e.encrypt(o);
return this.stringToBuffer(n);
};
t.hex_md5 = function(t) {
var e = by.CryptoJS;
return e.MD5(t).toString(e.enc.Hex);
};
t.LogTag = “[CryptoTool]”;
t.strEncryptKey = “thndwdhbqdyydsy5”;
return t;
}();
\>>>>彩蛋<<<<
细心的人可能已经发现,密钥是保存在 t.Config.HttpEncryptKey,Config关键字,说明是保存到某地方的,那就再挖一挖吧。
正好在assets 目录下找到一个GameConfig.config文件,
![](https://img-blog.csdnimg.cn/56c68f8879cd424484b9e15d8ec48cf0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_12,color_FFFFFF,t_70,g_se,x_16)
打开文件发现是加密的
![](https://img-blog.csdnimg.cn/da5fc6684c8c465cb8c7a65e5b250a74.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_15,color_FFFFFF,t_70,g_se,x_16)
那就在js文件里面找找看,有没有解密的密钥,搜索GameConfig.config
![](https://img-blog.csdnimg.cn/5724826655624b749f8598e69d0e5942.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaW9zIGFuZCBBbmRyb2lk,size_19,color_FFFFFF,t_70,g_se,x_16)
找到下面关键代码 aesDecryptString
cc.loader.load({
url: e,
type: "text" },
function(e, o) {
//关键解密密钥 strEncryptKey 已找到是 thndwdhbqdyydsy5
var n = i.CryptoTool.aesDecryptString(i.CryptoTool.strEncryptKey, o);
r = JSON.parse(n);
by.extend("by", "Config", r);
});
t.loadConfig = function(t) {
if (void 0 == by.Config) {
var e = “”;
if (cc.sys.isNative) e = cc.path.join(r.default.pkgInsideRootPath, “GameConfig.config”); else {
e = globalThis.location.origin + globalThis.location.pathname;
var o = globalThis.location.search, n = “TestChannel”;
if (“” != o) {
var a = o.substr(1, o.length).split(“&”);
a && (n = a[0]);
}
e += n + “.config”;
}
cc.loader.load({
url: e,
type: “text”
}, function(e, o) {
if (e) t(e); else {
var n = i.CryptoTool.aesDecryptString(i.CryptoTool.strEncryptKey, o), r = JSON.parse(n);
最后
在此为大家准备了四节优质的Android高级进阶视频:
架构师项目实战——全球首批Android开发者对Android架构的见解
附相关架构及资料
往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
)]
往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!