1. 抓包并且hook
1.1 登录请求抓包charles + 系统代理就可以抓包
charles + 系统代理就可以抓包
POST /market-activity/register/intention?appid=38741001&did=c69583270de11ab95119c90cff96c59f&noncestr=69fc49&svs=v3×tamp=1734095423&sign=a9be61f92bdee069d00b34e2415443332211a27fc0604a9d4b2fe3d972af0137 HTTP/1.1
Auth-Token:
User-Agent: AndroidSDKbuiltforarm64 android 9 7.59.0 2.0
token: 477c33c6-2f38-4363-a670-314393b47c1b
AKC-MODEL: AndroidSDKbuiltforarm64
AKC-OS: android
AKC-OS-VERSION: 9
AKC-APP-VERSION: 7.59.0
AKC-APP-API-VERSION: 2.0
AKC-APP-BUILD-VERSION: 75900
AKC-DID: c69583270de11ab95119c90cff96c59f
AKC-APP-CHANNEL: 2005
applicationId: com.aikucun.akapp
x-auth-token:
live-channel: 20
dtdToken: 675c3035o69t16VHDZSesSmuU0Saf7ahv6rlEk13
app2H5Token:
uid:
subUid:
APP-LOGIN-CHANNEL: akcApp
app-request-id: 3ed72013807d4df9a7896c6ad9a47e0e
PAGE-NAME: %E7%99%BB%E5%BD%95
TRACKER-SESSION-ID: 2a99dad141359a53
APP-USER-TYPE: 6
Content-Type: application/json; charset=UTF-8
Content-Length: 134
Host: zuul.aikucun.com
Connection: Keep-Alive
Accept-Encoding: gzip
{"smsChecking":false,"channelApp":"akapp","mobile":"13122223333","channel":"2005","deviceId":"358240051111110","channelPattern":"app"}
我们本次主要分析这个sign
1.2 frida检测
附加frida,发现秒退,这个时候我们已经是魔改的fridaGitHub - taisuii/rusda: 对frida 16.2.1的patch并且更换端口了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | (base) r@R aikucun % frida -H 127.0.0.1:12345 -f com.aikucun.akapp ____/ _ | Frida 16.2.1 - A world-class dynamic instrumentation toolkit| (_| |> _ | Commands:/_/ |_| help -> Displays the help system. . . . object? -> Display information about 'object'. . . . exit/quit -> Exit. . . .. . . . More info at https://frida.re/docs/home/. . . .. . . . Connected to 127.0.0.1:12345 (id=socket@127.0.0.1:12345)Spawned `com.aikucun.akapp`. Resuming main thread! [Remote::com.aikucun.akapp ]-> Process terminated[Remote::com.aikucun.akapp ]->Thank you for using Frida!(base) r@R aikucun % |
hook 一下dlopen
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function hookdlopen() { var dlopen = Module.findExportByName(null, "dlopen"); var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext"); Interceptor.attach(dlopen, { onEnter: function (args) { var path_ptr = args[0]; var path = ptr(path_ptr).readCString(); console.log("[dlopen:]", path); }, onLeave: function (retval) { } }); Interceptor.attach(android_dlopen_ext, { onEnter: function (args) { var path_ptr = args[0]; var path = ptr(path_ptr).readCString(); console.log("[dlopen_ext:]", path); }, onLeave: function (retval) { } });} |
在 libmsaoaidsec.so 处退出,app没有结束,frida被杀掉了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | (base) r@R aikucun % frida -H 127.0.0.1:12345 -f com.aikucun.akapp -l hook.js ____/ _ | Frida 16.2.1 - A world-class dynamic instrumentation toolkit| (_| |> _ | Commands:/_/ |_| help -> Displays the help system. . . . object? -> Display information about 'object'. . . . exit/quit -> Exit. . . .. . . . More info at https://frida.re/docs/home/. . . .. . . . Connected to 127.0.0.1:12345 (id=socket@127.0.0.1:12345)Spawned `com.aikucun.akapp`. Resuming main thread! [Remote::com.aikucun.akapp ]-> [dlopen_ext:] /system/framework/oat/arm64/org.apache.http.legacy.boot.odex[dlopen_ext:] /data/app/com.aikucun.akapp-Gqd0OXL0bAt7H-zUkRSKuA==/oat/arm64/base.odex[dlopen_ext:] /data/app/com.aikucun.akapp-Gqd0OXL0bAt7H-zUkRSKuA==/lib/arm64/libc++_shared.so[dlopen_ext:] /data/app/com.aikucun.akapp-Gqd0OXL0bAt7H-zUkRSKuA==/lib/arm64/libmarsxlog.so[dlopen_ext:] /data/app/com.aikucun.akapp-Gqd0OXL0bAt7H-zUkRSKuA==/lib/arm64/libmmkv.so[dlopen_ext:] /data/app/com.aikucun.akapp-Gqd0OXL0bAt7H-zUkRSKuA==/lib/arm64/libmsaoaidsec.soProcess terminated[Remote::com.aikucun.akapp ]->Thank you for using Frida!(base) r@R aikucun % |
1.3 过检测
这个检测其实就是在加载so的时候,创建了检测线程,具体的话可以分析libmsaoaidsec.so的 .init_proc函数
那么其实已经有很多网友分析过这个了,hook__system_property_get函数寻找hook时机,找到创建线程的地方然后把它替换掉固然是个好方法
不过这里直接粗暴一点,hook pthread_create,只要是在libmsaoaidsec.so里面创建的线程,我们统统替换掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | function replace(addr) { Interceptor.replace(addr, new NativeCallback(function () { console.log(`replace ${addr}`) }, 'void', []));}function hook_pthread_create(soname) { let replaces = []; // 用来记录已经替换的函数偏移 // int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); let pthread_create = Module.findExportByName("libc.so", "pthread_create"); if (!pthread_create) { console.log("pthread_create not found in libc.so"); return; } Interceptor.attach(pthread_create, { onEnter: function (args) { let start_routine = args[2]; let libmsaoaidsec = Process.findModuleByAddress(start_routine); if (libmsaoaidsec && libmsaoaidsec.name === soname) { if (!replaces.includes(start_routine.toString())) { let libmsaoaidsec_addr = libmsaoaidsec.base; let func_offset = start_routine.sub(libmsaoaidsec_addr); console.log("The thread function offset address in libmsaoaidsec.so(" + libmsaoaidsec_addr + ") is " + func_offset); console.log("replace: " + func_offset); replaces.push(start_routine.toString()); replace(start_routine) } } } });} |
成功过掉检测,一共两处线程创建的地方:0x175f8和0x16d30,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | (base) r@R aikucun % frida -H 127.0.0.1:12345 -l hook.js -f com.aikucun.akapp ____/ _ | Frida 16.2.1 - A world-class dynamic instrumentation toolkit| (_| |> _ | Commands:/_/ |_| help -> Displays the help system. . . . object? -> Display information about 'object'. . . . exit/quit -> Exit. . . .. . . . More info at https://frida.re/docs/home/. . . .. . . . Connected to 127.0.0.1:12345 (id=socket@127.0.0.1:12345)Spawned `com.aikucun.akapp`. Resuming main thread! [Remote::com.aikucun.akapp ]-> replace 0x7b6b55a5f8replace 0x7b6b559d30[Remote::com.aikucun.akapp ]-> |
这个检测在很多app中都是存在的,这个方式在其他app中不一定适用
2. 算法还原
2.1. java层
无套路定位到
2.2. so层
无套路,可读性非常高,都是字符串拼接

这个digest函数是调用的java层进行加密的

2.3 算法还原
获取加密参数以及sha256 的参数,结果一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | function hook() { if (Java.available) { console.log("Java hook start") Java.perform(function () { let MXSecurity = Java.use("com.mengxiang.arch.security.MXSecurity"); MXSecurity["signV3"].implementation = function (url, nonceStr, timestamp, body) { console.log(`MXSecurity.signV3 is called: url=${url}, nonceStr=${nonceStr}, timestamp=${timestamp}, body=${body}`); let result = this["signV3"](url, nonceStr, timestamp, body); console.log(`MXSecurity.signV3 result=${result}`); return result; }; let LoginModel = Java.use("com.aikucun.akapp.business.login.model.LoginModel"); LoginModel["authCode"].implementation = function (phoneNum, userid, type, rcsTraceId, captchaToken) { console.log(`LoginModel.authCode is called: phoneNum=${phoneNum}, userid=${userid}, type=${type}, rcsTraceId=${rcsTraceId}, captchaToken=${captchaToken}`); let result = this["authCode"](phoneNum, userid, type, rcsTraceId, captchaToken); console.log(`LoginModel.authCode result=${result}`); return result; }; let MessageDigest = Java.use("java.security.MessageDigest"); MessageDigest.digest.overload("[B").implementation = function (input) { const byteArray = Java.array('byte', input); // 将 byte[] 转换为字符串 let plaintext = ''; for (let i = 0; i < byteArray.length; i++) { plaintext += String.fromCharCode(byteArray[i] & 0xff); } if(plaintext.indexOf("38741001") != -1){ console.log("[+] MessageDigest.digest(byte[]) called"); console.log("Plaintext: " + plaintext); } // 调用原始方法 return this.digest(input); }; }); } else { console.log("Java.available is false") }}var hook_num = 0function replace(addr) { Interceptor.replace(addr, new NativeCallback(function () { console.log(`replace ${addr}`) hook_num = hook_num + 1 if (hook_num >= 2) { hook() } }, 'void', []));} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | (base) r@R aikucun % frida -H 127.0.0.1:12345 -l hook.js -f com.aikucun.akapp ____/ _ | Frida 16.2.1 - A world-class dynamic instrumentation toolkit| (_| |> _ | Commands:/_/ |_| help -> Displays the help system. . . . object? -> Display information about 'object'. . . . exit/quit -> Exit. . . .. . . . More info at https://frida.re/docs/home/. . . .. . . . Connected to 127.0.0.1:12345 (id=socket@127.0.0.1:12345)Spawned `com.aikucun.akapp`. Resuming main thread! [Remote::com.aikucun.akapp ]-> The thread function offset address in libmsaoaidsec.so(0x7b6b5e4000) is 0x175f8replace: 0x175f8The thread function offset address in libmsaoaidsec.so(0x7b6b5e4000) is 0x16d30replace: 0x16d30replace 0x7b6b5fb5f8replace 0x7b6b5fad30Java hook startMXSecurity.signV3 is called: url=https://zuul.aikucun.com/akucun-base-data-new/base/address/selectAddrVersion?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=3d0f39&svs=v3×tamp=1734184260, nonceStr=3d0f39, timestamp=1734184260, body=[+] MessageDigest.digest(byte[]) calledPlaintext: appid=38741001&svs=v3&noncestr=3d0f39×tamp=1734184260&secret=04fdc5e4d9c7420e896ee92b17c68e9f&url=https://zuul.aikucun.com/akucun-base-data-new/base/address/selectAddrVersion?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=3d0f39&svs=v3×tamp=1734184260MXSecurity.signV3 result=5c927464497d321ac3ff49d817cc571d696da21e828ea75bdc9e3465af8a17aeMXSecurity.signV3 is called: url=https://m.xiangdian.com/api/mshop/mshop-aggr-prod/outer/common/bwl/isHitByBatch?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=22f096&svs=v3×tamp=1734184260, nonceStr=22f096, timestamp=1734184260, body=398a40be5a2a6a5a742f35b1b606277a[+] MessageDigest.digest(byte[]) calledPlaintext: appid=38741001&svs=v3&noncestr=22f096×tamp=1734184260&secret=04fdc5e4d9c7420e896ee92b17c68e9f&url=https://m.xiangdian.com/api/mshop/mshop-aggr-prod/outer/common/bwl/isHitByBatch?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=22f096&svs=v3×tamp=1734184260&398a40be5a2a6a5a742f35b1b606277aMXSecurity.signV3 result=bd809e352277f9357b436ed424a8fd62b546f415e7f9e7875a05bda5aa5f6704MXSecurity.signV3 is called: url=https://m.xiangdian.com/api/mshop/mshop-aggr-prod/outer/v1/material/create/createAuth?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=9908c3&svs=v3×tamp=1734184261, nonceStr=9908c3, timestamp=1734184261, body=37a6259cc0c1dae299a7866489dff0bd[+] MessageDigest.digest(byte[]) calledPlaintext: appid=38741001&svs=v3&noncestr=9908c3×tamp=1734184261&secret=04fdc5e4d9c7420e896ee92b17c68e9f&url=https://m.xiangdian.com/api/mshop/mshop-aggr-prod/outer/v1/material/create/createAuth?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=9908c3&svs=v3×tamp=1734184261&37a6259cc0c1dae299a7866489dff0bdMXSecurity.signV3 result=1181b2330a12f04c2501193430b50712d6f0187a2f87eaf0fe861016e2e1f6a7MXSecurity.signV3 is called: url=https://zuul.aikucun.com/appconfigmgt/api/v1/download/config?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=32a49b&svs=v3×tamp=1734184263, nonceStr=32a49b, timestamp=1734184263, body=2288e58e8bda39d24cb10b10af923d50[+] MessageDigest.digest(byte[]) calledPlaintext: appid=38741001&svs=v3&noncestr=32a49b×tamp=1734184263&secret=04fdc5e4d9c7420e896ee92b17c68e9f&url=https://zuul.aikucun.com/appconfigmgt/api/v1/download/config?appid=38741001&did=8e72f37ab5db201b91de47172047e760&noncestr=32a49b&svs=v3×tamp=1734184263&2288e58e8bda39d24cb10b10af923d50MXSecurity.signV3 result=4d9b7d406b6ce2e44dc602b8c83a49b4b20ec944bea69d72aae3790249ed7127 |