工具
JEB动态调试
添加debug权限 android:debuggable="true"
1 |
|
手机开启开发者模式,允许USB调试,使用adb
1 |
|
运行JEB
1 |
|
搜索定位,文字或者控件ID,也可以直接再bytecode 环绕搜索(JEB已经把apk转换成一份smali)
定位到对应smali代码,转换成Java代码方便查看,Java那边也可以通过解析反找smail,cmd+B 下断点,双击可以调到函数声明,交叉引用(x)可以引用函数的地方。
debug
会弹出
使用这些代码跳转,和debug调试
数据类型不一定对需要修改类型看到正确的值
frida
监控和修改APP行为,适合临时调试的场景
安装服务端
检查CPU版本
1 |
|
https://github.com/frida/frida/releases 最新的下载,试着装一下看看是否适配,frida-server开启后,模拟器是否正常,打开点击app之类。可以查看到Frida server与Frida-tools对应关系。如果最新可以用,pip就不指定版本
根据abi和服务器类型,选择下载frida-server-15.2.2-android-x86.xz
1 |
|
安装客户端
1 |
|
helloworld
1 |
|
在AndroidMainfest.xml里面查看想控制的activity。或者使用MT
拿到activity name
- hook相同方法
1 |
|
签名
signapk 源码 com/android/signapk/sign.java
对APK签名后会有个META-INF里面有三个文件
-
MANIFEST.MF
对Apk中的每个文件(除了这三个文件外)做一次算法(SHA-1数据摘要+Base64编码),保存到MANIFEST.MF文件中,Name是文件路径
-
CERT.SF
对MANIFEST.MF整个文件做一次算法(数据摘要+Base64编码),然后放到SHA-1-DIgest-Manfest
然后对MANIFEST.MF文件中每个条目做一次算法(数据摘要+Base64编码),在保存
-
CERT.RSA
对CERT.SF文件做用私钥计算出签名,将签名和包含公钥内容存档到CERT.RSA中
如果apk内容被篡改,必然会引起这些文件的变动。因为安装APK时候会做签名校验,没有签名的私钥也不能仿造签名,所以必须重签名。
so
why
- java处理音视频效率低,在数据运算和实时渲染游戏上面
- 无法直接操作硬件
- 无法调用本地C库,so可以,也有丰富的C/C++库支持
- Java容易被反编译,加密代码用C/C++写
JNI(java native interface)让java和其他语言做交互。
语言的交互主要解决数据类型的转换,JNI就是规范。Java只和JNI交互,JNI和其他语言交互。
NDK里面有个头文件jni.h,定义了数据的映射关系,数据转换的函数和调用java的函数等。
java程序执行时候,jvm通过JNI来调用库文件里面的C代码。C是运行在linux进程中执行的,而java跑在jvm上面
JNI注册
- 静态注册函数 ,在IDA Export可以搜索
- 必须遵循注册规则
- 名字过长
- 第一次调用需要搜索,影响效率
1 |
|
-
动态注册
- 需要我们手动建立联系,增加了代码量但提高效率
- 允许自己定义函数名字
通过 RegisterNatives 方法手动完成 native 方法和 so 中的方法的绑定,这样虚拟机就可以通过这个函数映射表直接找到相应的方法了。
以JNI_OnLoad为入口,调用env->RegisterNatives(调用类,注册方法methods,methods个数)
methods 是JNINativeMethod类型的
1
2
3
4
5// Java层方法名,(方法参数)返回值 ,so对应函数指针(目标) static const JNINativeMethod nativeMethod[] = { {"text", "(Ljava/lang/String;)I", (void *) native_text}, {"static_text", "(Ljava/lang/String;)I", (void *) native_staic_text} };
找到对应的so函数名字
IDA
linux 下的elf文件(.elf .so )
lib 通常对应设备abi(CPU架构类型)
- arm64-v8a arm64
- armeabi-v7a arm32
- x86 32
- x86_64 64
逆向分析时选择32-bit IDA分析32位程序,64-bit IDA 分析64位程序。
view 介绍
Exports
优先看,供Java调用的函数表,crtl+F搜索
IDA-VIEW
空格展开看汇编地址
- B 跳转指令
- BL 带返回的跳转指令
- BLX 带返回和状态切换的跳转指令
- BX 带状态切换的跳转指令
Pseudocode
通常取地址参数就是返回值,F5抓换位伪C代码,参数个数或类型可能错误,逻辑靠谱。可以通过TAB切换去
解决偏移
parse jni.h
遇到类似的问题,导入失败
删掉对应行数,删除jni.h的两个导包#include <stdint.h>
和 #include <stdarg.h>
即可
实在不行,把第一个参数改成**_JNIEnv ** NewStringUTF Cstring 转成Jstring
Hex view
- 修改汇编
- 查看一些明文
左边是地址偏移值,内存字节,内存字符串
1 |
|
string view
查看so出现的字符串
IDA静态
IDA 动态
找到dbgsrv目录,里面有android_server
免root执行andoid_server
通过Android Studio的Device File Explorer upload到对应的应用目录下,adb是没有权限push文件进去
1 |
|
IDA
先打开app,再attach
开始debug, 按F9让程序执行
modules,先搜索so名字,再搜方法名
双击进入定位到函数汇编位置,F5转伪代码,与静态时候看到差别很大,IDA为了效率无法看清,双开IDA动静结合看伪代码,定位断点位置
IDA view
断点触发PC值 就是当前地址, x1寄存器,
- arm 32位R0~R3前四个寄存器放函数参数,R0还会放函数返回值,再多参数放到栈 ,SP是栈顶寄存器地址
- arm 64位R0~R7前八位放函数参数,其他和32位一样。
追踪寄存器的值
可能遇到的问题
-
android_server 报错
可能会遇到的问题
1
2
3./android_server socket: Operation not permitted
app 的androidmanfest.xml需要添加网络权限
1
<uses-permission android:name="android.permission.INTERNET"/>
-
android_server位数和设备不一致,IDA报错
1
2Create segment (12C00000-42C00000, sel 00000000): Illegal segment bitness.
ida位数和server不一致,IDA报错
1
2Incompatible debugging server: address size is 8 bytes, expected 4
-
attach app 没开, IDA报错
1
Bogus or irresponsive remote server
思路
-
抓包
- 清除缓存,有可能重新安装,或者新建模拟器
- 保留完整抓包,deviceid 之类
-
搜索
- 连接URL ,URL/发送参数,算法关键字
-
log输出,JEB 主要是获取值,R.id
-
hook xposed frida (不用担心修改apk内容,带壳hook,不需要还原相关算法,可能写在so混淆)
-
so黑盒可以单独直接调用so,但是so层有可能会调用Java层代码
-
主动hook
手机端相当于hook了,通过参数,调用手机端对应算法。(app挂,多手机端)