免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
内容参考于:图灵Python学院
本人写的内容纯属胡编乱造,全都是合成造假,仅仅只是为了娱乐,请不要盲目相信。
工具下载:
链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd=6tw3
提取码:6tw3
复制这段内容后打开百度网盘手机App,操作更方便哦
上一个内容:18.安卓逆向-frida基础-调试实战2
上一个内容里,进一步编写了FridaHook算法的脚本,上一个内容只写了HOOK MD5算法的Update方法,它可以得到明文数据,本次接着继续
首先是MD5加密完之后的数据
首先编写下图红框里的代码,然后运行,让它报下图蓝框里的错误,从而得到它有哪些参数
效果图:
完整的hook md5脚本代码
function bytesToHex(arr) { var str = ""; for (var i = 0; i < arr.length; i++) { var tmp = arr[i]; if (tmp < 0) { tmp = (255 + tmp + 1).toString(16); } else { tmp = tmp.toString(16); } if (tmp.length == 1) { tmp = "0" + tmp; } str += tmp; } return str; } function bytesToBase64(e) { var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var r, a, c, h, o, t; for (c = e.length, a = 0, r = ''; a < c;) { if (h = 255 & e[a++], a == c) { r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4), r += '=='; break } if (o = e[a++], a == c) { r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), r += base64EncodeChars.charAt((15 & o) << 2), r += '='; break } t = e[a++], r += base64EncodeChars.charAt(h >> 2), r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6), r += base64EncodeChars.charAt(63 & t) } return r } function bytesToString(arr) { if (typeof arr === 'string') { return arr; } var str = '', _arr = arr; for (var i = 0; i < _arr.length; i++) { var one = _arr[i].toString(2), v = one.match(/^1+?(?=0)/); if (v && one.length == 8) { var bytesLength = v[0].length; var store = _arr[i].toString(2).slice(7 - bytesLength); for (var st = 1; st < bytesLength; st++) { store += _arr[st + i].toString(2).slice(2); } str += String.fromCharCode(parseInt(store, 2)); i += bytesLength - 1; } else { str += String.fromCharCode(_arr[i]); } } return str; } function main() { Java.perform(function () { // 有些app没有 ByteString,如果没有需要我们自己用Python或js写转换,这个百度一搜一大堆 var ByteString = Java.use("com.android.okhttp.okio.ByteString") var MessageDigest = Java.use('java.security.MessageDigest') function toUtf8(data){ return ByteString.of(data).utf8(); } /** * hook Update 方法获取明文数据 * */ MessageDigest.getInstance.overload('java.lang.String').implementation = function (str) { console.log('算法名:',str) return this.getInstance(str) } MessageDigest.update.overload('byte').implementation=function (str) { console.log(`byte算法入参:${str}`) return this.update(str) } MessageDigest.update.overload('java.nio.ByteBuffer').implementation=function (str) { console.log(`java.nio.ByteBuffer算法入参:${str}`) return this.update(str) } MessageDigest.update.overload('[B').implementation=function (str) { // [B是字节需要转成字符串我们人才认识,toUtf8方法可以把字节转换文字(文字指的是字母、数字、中文、英文) console.log(`update.overload('[B')[B算法入参:${toUtf8(str)}`) return this.update(str) } MessageDigest.update.overload('[B', 'int', 'int').implementation=function (str, a1, a2) { console.log(`'[B', 'int', 'int算法 入参1:${str},入参2:${a1},入参3:${a2}`) return this.update(str, a1, a2) } /** * hook digest 方法获取加密之后的数据 * */ MessageDigest.digest.overload().implementation=function () { var res = this.digest() console.log(`digest.overload()返回值:${bytesToHex(res)}`); console.log(`digest.overload()bytesToHex返回值:${bytesToHex(res)}`); console.log(`digest.overload()bytesToBase64返回值:${bytesToBase64(res)}`); return res } MessageDigest.digest.overload("[B").implementation=function (arr) { console.log(`digest.overload("[B")入参:${bytesToString(arr)}`); var res = this.digest(arr); console.log(`digest.overload("[B")bytesToString返回值:${bytesToString(res)}`); console.log(`digest.overload("[B")bytesToHex返回值:${bytesToHex(res)}`); console.log(`digest.overload("[B")bytesToBase64返回值:${bytesToBase64(res)}`); return res } }) } main()
然后使用上方的脚本去找一个真实的app试一试,通过抓包的方式不通过逆向的方式找它的明文,如下图对app抓的包
然后下图红框位置有一个哈希算法,它的值就是MD5,然后试一试我们的Frida Hook脚本能不能得到它
然后运行Frida hook脚本,然后来到app里刷新界面,效果如下图,可以正常hook得到算法
然后下图蓝框是它要加密的数据,红框是加密完的数据,下图蓝框和红框之间有很多东西,这可能是因为MD中调用了其它方法,也被我们hook了,所以会打印多余的
然后通过在线的MD5加密工具验证,正常
然后对数据进行拆分,如下图的拆分
上图里经过多次调用接口发现 C50GIK6GDhQNjtMRVRoQbwxVovXCX8DU 是不变的,所以它可能是用来加密用的钥匙,是写死的,然后我们也对它写死
Python代码测试
首先来到Charles(青花瓷),然后选中参数,然后右击,选择Copy cURL Request
然后百度搜索 curl request 转Python代码 在线 这个关键字,如下图红框,它可以给我们生成Python代码,复制粘贴之后改改就行了
import hashlib import time import requests headers = { 'Host': '', 'os': 'android', 'appversion': '10.2.1', 'rmt-device-id': '30F1CB8DE4DD5B232D9465BBD71C57EC8F65FC80', 'rmt-hash': 'c5ca34fe9d02fb642273df676c8fff39', 'rmt-request-time': '1728311097476', 'rmt-device-type': 'android', 'rmt-build': '1002100', 'rmt-app-version': '10.2.1', 'rmt-app-id': '9', 'user-agent': 'okhttp/4.11.0', } _ts = str(int(time.time() * 1000)) params = { 'list_version': '', 'classid': '3378', 'appid': '9', 'page': '1', } headers['rmt-request-time'] = _ts pa = "C50GIK6GDhQNjtMRVRoQbwxVovXCX8DUv5" def md5s(param): md5 = hashlib.md5() md5.update(param.encode()) return md5.hexdigest() hash = md5s(pa+"android"+headers['rmt-request-time']+headers['rmt-device-id']+headers['rmt-hash']) headers['rmt-hash'] = hash response = requests.get('', params=params, headers=headers) print(response.text)
这样可以不用逆向就可以得到想要的东西了