android-app-100-wp
0x00
    之前一直没做过真正的apk的题目,今天遇到了。首先有:

    在网上搜了搜,直接用jadx反编译,得到:


    查了一下,Build.SERIAL这个方法被弃用了,使用手机试了一下,一直显示:

    直接看wp,师傅们说发现有native方法之后,看到代码里有System.loadLibrary("adnjni");,可以猜测到IsCorrect函数定义在了这里面,用ida打开后的确有adnjni.so这样一个文件,发现IsCorrect函数:

    猜测要与这个字符串比较,试一试,发现:

    还是不行,猜测是那个弃用方法的问题,换个mumu模拟器,得到:

0x01
    仔细分析函数流程:

- 得到int processObjectArrayFromNative与int this.a.d,之后计算processObjectArrayFromNative+this.a.d+空格转字符串的md5值。
- 遍历对上述结果转化成stringBuffer然后输出。
    分析this.a.processObjectArrayFromNative函数,可以简化为:
| 12
 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
 
 | v3 = -1661035768v25 = 0
 v22 = 0
 while True:
 while True:
 while True:
 while v3 <= -1303766071:
 v3 = 2063008300
 if v3 > 441419317:
 break
 v3 = 1800572839
 if not v25:
 v3 = 441419318
 
 if v3 > 867851767:
 break
 v3 = 1405326207
 if v3 <= 1405326206:
 break
 if v3 == 1405326207:
 v26 = v22
 v3 = 867851768
 elif v3 == 1800572839:
 v22 = 92060626
 v3 = 441419318
 else:
 v22 = 0
 v3 = -18897425
 v25 = 1
 print(v26)
 
 
 | 
    因此可以写脚本:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;
 
 public class Test {
 public static void main(String []args) {
 int v1 = 114366;
 int v26 = 92060626;
 String str = String.valueOf(v1 + v26) + " ";
 try {
 MessageDigest messageDigest = MessageDigest.getInstance("MD5");
 messageDigest.update(str.getBytes());
 byte[] digest = messageDigest.digest();
 StringBuffer stringBuffer = new StringBuffer();
 for (byte b : digest) {
 stringBuffer.append(Integer.toString((b & 255) + 256, 16).substring(1));
 }
 System.out.println(stringBuffer.toString());
 } catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
 }
 
 }
 }
 
 
 | 
0x02
    看别的师傅的frida脚本:
| 12
 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
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 
 | import frida, sys
 
 def on_message(message, data):
 if message['type'] == 'send':
 print("[*] {0}".format(message['payload']))
 else:
 print(message)
 
 
 jscode = """
 setImmediate(function () {
 Java.perform(function () {
 console.log("start");
 //so层hook
 //导出函数
 //var exports = Module.enumerateExportsSync("libadnjni.so");
 //for(var i=0;i<exports.length;i++){
 //    send("name:"+exports[i].name+"  address:"+exports[i].address);
 // }
 var str = Java.use("java.lang.String");
 //遍历模块找基址
 // Process.enumerateModules({
 //     onMatch: function (exp) {
 //         send(exp.name)
 //         if (exp.name == 'libadnjni.so') {
 //             send('enumerateModules find');
 //             send(exp.name + "|" + exp.base + "|" + exp.size + "|" + exp.path);
 //             send(exp);
 //             return 'stop';
 //         }
 //     },
 //     onComplete: function () {
 //         send('enumerateModules stop');
 //     }
 // });
 
 //通过模块名直接查找基址
 //var soAddr = Module.findBaseAddress("libadnjni.so");
 var soAddr = Module.findBaseAddress("libmedia_jni.so");
 send("soAddr:" + soAddr);
 
 var parray=0x48c+1;
 var pcorrect=0x74c+1;
 //   hook导出函数 通过函数名
 
 //Module.findExportByName 找到的函数地址无效
 // var farray=Module.findExportByName("libadnjni.so", "Java_com_example_ctf2_MainActivity_processObjectArrayFromNative")
 // send("findExportByName farray() by Module.findExportByName:" +farray);
 var farray=new NativePointer(soAddr).add(parray);
 //NativePointer   简写ptr
 send("findExportByName farray() by ptr:" +farray );
 
 Interceptor.attach(farray, {
 onEnter: function (args) {
 var s = Java.cast(args[2], str);
 send("array()  jstring:" + s );
 },
 onLeave: function (retval) {
 send("array() return:" + retval);
 }
 });
 
 //   hook导出函数 通过函数名
 // var fcorrect=Module.findExportByName("libadnjni.so", "Java_com_example_ctf2_MainActivity_IsCorrect");
 // send("findExportByName correct()  by Module.findExportByName:" +fcorrect );
 var fcorrect=new NativePointer(soAddr).add(pcorrect);
 send("findExportByName correct()  by ptr:" +fcorrect );
 Interceptor.attach(fcorrect, {
 onEnter: function (args) {
 var s = Java.cast(args[2], str);
 send("fcorrect() jstring:" + s );
 },
 onLeave: function (retval) {
 send("fcorrect() return:" + retval);
 }
 });
 
 });
 });
 """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 process = frida.get_usb_device().attach(2164)
 script = process.create_script(jscode)
 script.on('message', on_message)
 print('[*] Running test')
 script.load()
 sys.stdin.read()
 
 
 
 '''
 [*] Running test
 start
 [*] soAddr:0xcd562000
 [*] findExportByName farray() by ptr:0xcd56248d
 [*] findExportByName correct()  by ptr:0xcd56274d
 [*] array()  jstring:Serial Number
 [*] array() return:0x0
 [*] fcorrect() jstring:Serial Number
 [*] fcorrect() return:0x0
 
 
 [*] array()  jstring:ef57f3fe3cf603c03890ee588878c0ec
 [*] array() return:0x57cbbd2
 [*] fcorrect() jstring:ef57f3fe3cf603c03890ee588878c0ec
 [*] fcorrect() return:0x1
 '''
 
 | 
    没跑出来,主要是没找到libadnjni.so,很奇怪。
知识点1:
- 常见的安卓逆向工具 
- jadx-gui。方便的jadx工具,可以直接反编译apk。 
知识点2:
    frida 是一款基于 python+javascript 的 hook 框架,可运行在 android、ios、linux、win等各个平台,主要使用的动态二进制插桩技术。
    插桩技术是指将额外的代码注入程序中以收集运行时的信息,可分为源代码插桩 SCI 和二进制插桩 BI。
知识点3:adb(android debug)使用
    配置查看:https://blog.csdn.net/yi_rui_jie/article/details/115462824
    链接mumu模拟器:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | adb connect 127.0.0.1:7555 # 7555为mumu模拟器端口号adb disconnect 127.0.0.1:7555 # 断开连接
 adb shell # 进入shell
 cat /proc/cpuinfo # adb查看电脑cpu架构
 getprop ro.product.cpu.abi # 查看模拟器cpu架构
 adb push file /data/local/tmp/ # 将文件push 进手机的指定目录下
 adb -s emulator-5554 shell # 多个设备进入某一指定设备
 su # 切换获取手机的root权限
 adb forward tcp:27042 tcp:27042 # 进行端口转发(新打开一个cmd)
 adb forward tcp:27043 tcp:27043 # 进行端口转发(新打开一个cmd)
 frida-ps -U # 查看手机启动的进程(查看到则运行成功,frida安装完毕!)
 frida-ps -U -a # 不仅输出进程名称,还输出进程的Identifier
 frida -U -f 进程的Identifier -l xx.js # 将xx.js注入到进程中
 adb devices # 查看adb连接的设备
 linux 在命令的后面加一个 & 的作用是在后台执行
 
 |