Android逆向
AndroidKiller安装
AndroidKiller/cfgs目录下的injectcode换成新的injectcode;
新建文件夹AndroidKiller/apktool,将apktool.jar拷贝进去;
打开AndroidKiller,在主页/配置/Java,中配置jdk;
打开AndroidKiller,在Android/APKTOOL管理器中配置apktool.jar。
dalvik字节码
.java
编译成 .class
在编译成 .dex
最后反编译得到 samli
文件。
dx.jar:将.class打包.dex
dx --dex --output=Decrypt.dex com/yijinda/demo/Decrypt.class
Baksmali.jar:将.dex反编译成smali
java -jar baksmali.jar -o smali_out/ classes.dex
Samli.jar:将.smali打包成.dex
java -jar smali.jar smali_out/ -o classes.dex
dalvik字节码类型对应java:
Dalvik → java
B byte
C char
S short
I int
J long
F float
D double
Z boolean
V void
L java类类型
[ 数组类型
寄存器的命名法:
v:局部变量寄存器 v0-vn 参数寄存器 vn-vn+m
p:参数寄存器p0 -pn 变量寄存器 v0-vn
p0没有被定义成参数,那么它代表this
字段:
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
字段格式:包名/类名;->字段名称:字段类型;
方法:
Lpackage/name/ObjectName;->MethodName (III) Z
包名/类名;->方法名(参数):返回值类型
dalvik指令
格式:
基础字节码-名称后缀/字节码后缀 目的寄存器 源寄存器
格式解释:
名称后缀是wide,表示数据宽度为64位
字节码后缀是from16,表示源寄存器为16位
字节码后缀是16,表示目的寄存器和源寄存器都为16位
目的寄存器始终在源寄存器前面
目的寄存器的取值范围是v0-v255
源寄存器的取值范围是v0-v65535
A/B/C/D/E/F/G/H代表一个4位的数值
AA/BB/CC/DD/EE/FF/GG/HH代表一个8位的数值
AAAA/BBBB/CCCC/DDDD/EEEE/FFFF/GGGG/HHHH代表一个16位的数值
13种dalvik指令:
1、空操作指令:
nop
2、数据操作指令:
move(-wide/-object/-result/-result-object/-result-wide/-exception)
move(-wide/-object)/from16
move(-object)/16
object是对象的意思-为对象赋值。
move指令的三种作用:赋值;move-result接收方法返回操作;处理异常。
3、返回指令(重点):
return-void(表示方法的放回值为空)
return(表示方法的反回值为32位非对象类型的值)
return-wide(表示方法的反回值为64位非对象类型的值)
return-object(表示方法的反回值为对象类型的值)
4、数据定义指令(重点):定义程序中用到常量
const(-wide/-string/-class)
const/4(数值符号扩展为32位)
const/16(数据符号扩展为64位)
const(-wide)/16
const(-wide)/32
const(-wide)/high16
5、实例操作指令:
check-cast(类型转换)
instance-of(检查)
new-instance(新建)
6、数组操作指令:
array-length(获取数组长度)
new-array(新建数组)
filled-new-array(定义数组并初始化)
filled-new-array/range(定义数组并初始化/指定取值范围)
filled-array-data(数组元素取值与赋值)
7、异常指令:
throw
8、跳转指令(重点):
goto 紧跟一个标签直接跳转到标签所在位置
packed-switch(有规律)、sparse-switch(无规律)
if-eq(等于)/if-ne(不等于)
if-lt(小于)/if-le(小于等于)
if-gt(大于)/if-ge(大于等于)
if-eqz(等于零)/if-nez(不等于零)
if-ltz(小于0)/if-lze(小于等于0)
if-gtz(大于0)/if-gez(大于等于0)
9、比较指令(cmp):
大于(1)/等于(0)/小于(-1)=>cmpg、cmp
大于(-1)/等于(0)/小于(1)=>cmpl
10、字段操作指令:
普通字段=>iget(读)/iput(写)
静态字段=>sget(读)/sput(写)
get(读):从后往前读
put(写):从前往后走
11、方法调用指令(重点):
invoke-virtual(调用实例的虚方法) Java当中的普通方法
invoke-super(调用实例的父类/基类方法)
invoke-direct(调用实例的直接方法) 调用java当中的构造方法
invoke-static(调用实例的静态方法)
invoke-interface(调用实例的接口方法)
12、数据转换指令:
neg-数据类型=>求补
not-数据类型=>求反
数据类型1-to-数据类型2=>将数据类型1转换为数据类型2
13、数据运算指令:
add/sub/mul/div/rem 加/减/乘/除/模
and/or/xor 与/或/非
sh1/shr/ushr 有符号左移/有符号右移/无符号右移
实战案例技巧
1、修改bean里get的int值:
//原smali代码
return v0
//修改后
const v0, 0x1
return v0
2、修改判断条件,判断条件取反:
//原smali代码
if-eqz v1, :cond 4
//修改后
if-nez v1, :cond 4
3、DDMS使用
/sdk/tools/
目录下双击 monitor.bat
即可。
4、Log日志插入
AndroidKiller中,右键/插入代码/Log信息输出。
但是注意:locals 要大于0 ,不能在等于零的地方插桩。在 .prologue
之后插入。
5、栈跟踪和方法抛析
AndroidKiller中,右键/插入代码/StackTrace栈跟踪。然后调用顺序是从下往上。
Traceview的使用,查看调用,可以看到Parents和Children。
6、JEB2的静态分析动态调试
7、AS+smalidea插件动态调试
安装本地插件: File/Settings/Plugins/
。设置AndroidManifest文件中 android:debuggable="true"
。然后在 File/Import Settings
中导入Smali代码。右击项目中的smali Mark Directory as/Sources Root
。配置远程调试,菜单栏 Run/Edit Configurations
添加Remote,配置name、port、classpath。
获取PID:adb shell ps
查找注册机PID。
转发:adb forward tcp:你设置的端口号 jdwp:你的PID号
。
adb常用命令
monkey测试
adb shell monkey -p 包名 -v 次数
启动adb、关闭adb
adb start-server
adb kill-server
获取手机的系统版本
adb shell getprop ro.build.version.release
清除apk的数据和缓存
adb shell pm clear 包名
安装和卸载apk
adb install 文件路径
adb uninstall 包名
电脑和手机文件互传
adb push C:\Users\win\Desktop\xx.png /sdcard
adb pull /sdcard/xx.png C:\Users\win\Desktop
查看保存app错误日志
adb logcat *:E | grep "包名" > 电脑路径 //mac
adb logcat *:E | find "包名" > 电脑路径 //win
获取当前app包名和当前页面名(⼿机打开对应app)
adb shell dumpsys window windows | grep mFocusedApp //mac
adb shell dumpsys window windows | findstr mFocusedApp //win
log获取app的包名和activity名称
adb logcat | grep START //mac
adb logcat | findstr START //win
然后点击app
关闭app后,获取app启动时间
关闭app
adb shell am start -W 包名/启动名
adb shell am start -W com.xxx.xxx/.LaunchActivity
//TotalTime: app⾃身启动时间,WaitTime: 系统启动应⽤时间
Appium
官⽹: www.appium.io,
Appium是由nodejs的express框架写的Http Server,Appium使⽤WebDriver的json wire协议,来驱动Apple系统的UIAutomation库、Android系统的UIAutomator框架。
ARM汇编指令
1.跳转指令
B 无条件跳转
BL 带链接的无条件跳转。LR和pc会变。
BX 带状态切换的无条件跳转 根据目标地址最低位切换状态(arm/thumb)。T和pc会变。
BLX 带链接和状态切换的无条件跳转。LR、T、pc会变。
B loc_地址
BEQ,BNE
2.存储器与寄存器交互数据指令(核心)
存储器(主存,内存)
寄存器中放的数据:可以是字符串,可以是数,也可以是一个地址,它可以放各种类型的数据
存储地址单元:地址(如0x00004000)与地址中存在的值
LDR:从存储器中加载数据到寄存器 ← Load
LDR R8,[R9,#4] R8为待加载数据的寄存器,加载值为R9+0x4所指向的存储单元 R8=*(R9+4)
STR:将寄存器的数据存储到存储器 → Store
STR R8,[R9,#4] 将R8寄存器的数据存储到R9+0x4指向的存储单元 *(R9+4)=R8
LDM:将存储器的数据加载到一个寄存器列表 →
LDM R0,{R1-R3}将R0指向的存储单元的数据依次加载到R1,R2,R3寄存器
STM:将一个寄存器列表的数据存储到指定的存储器 ←
PUSH:将寄存器值推入堆栈 压栈--》
POP:将堆栈值推出到寄存器 出栈 《--
SWP:将寄存器与存储器之间的数据进行交换
SWP R1, R1 [R0] 将R1寄存器与R0指向的存储单元的内容进行交换
堆,队列:数据结构,栈是竖的,后进先出,且只能从栈顶依次填入数据
3.数据传送指令
MOV:将立即数或寄存器的数据传送到目标寄存器 ←
MOV R0, #8 R0=8
4.数据算术运算指令
←
ADD,SUB,MUL,DIV
有符号,无符号运算;带进位运算
5.数据逻辑运算指令
与:AND
或:ORR
异或:EOR
移位:实质是乘,除,类似于小数点移位,但相反。小数点左移,数变小;右移变大。
但逻辑移位,左移变大,右移变小,且按2的倍数进行,因为是2进制。
LSL:逻辑左移←
LSR:逻辑右移←
LSL R0,R1,#2 R0=R1*4
LSR R0,R1,#2 R0=R1*2
6.比较指令
CMP:比较
CMP R0 #0 R0寄存器中的值与0比较
标志位:如z位,这个都可以在动态调试时,寄存器窗口看到
7.其他指令
协处理器指令:SWT (切换用户模式)
伪指令:DCB
8.寄存器寻址方式
立即寻址:MOV R0,#1234 R0=0X1234
寄存器寻址:MOV R0,R1 R0=R1
寄存器移位寻址:MOV R0,R1,LSL #2 R0=R1*4
寄存器间接寻址:LDR R0,[R1] 将R1寄存器中的值作为地址,取出地址中的值赋予R0
寄存器间接基址偏移寻址:LDR R0,[R1,#-4]将R1寄存器的值-0x4的值作为地址,取出地址中的值给R0
对 int a=0;
这一句简单高级语言的汇编理解,首先会开辟一个内存存储单元,然后把0x0这个数放入R0寄存器,然后再把R0寄存器的数据放入内存存储单元。所以:
MOV R0,#0
STR R0,[R11,#0x14+var_20]
IDA工具
IDA Pro工具介绍:交互式反汇编器,是典型的递归下降反汇编器。
导航条:
蓝色 :表示常规的指令函数
黑色 :节与节之间的间隙
银白色 :数据内容
粉色 :表示外部导入符号
暗黄色: 表示ida未识别的内容
IDA主界面:
IDA View三种反汇编视图:文本视图、图表视图、路径视图
Hex View 十六进制窗口
Struceures 结构体窗口
Enums 枚举窗口
Imports 导入函数窗口
Exports 导出函数窗口
Strings 字符串窗口
IDA常用功能及快捷键:
空格键:切换文本视图与图表视图
ESC:返回上一个操作地址
G:搜索地址和符号
N:对符号进行重命名
冒号键:常规注释
分号键:可重复注释
Alt+M:添加标签
Ctrl+M:查看标签
Ctrl+S:查看段的信息
代码数据切换
C=>代码 D=>数据 A=>ascii字符串 U=>解析成未定义的内容
X:查看交叉应用
F5:查看伪代码
Alt+T:搜索文本
Alt+B:搜索十六进制
IDA动态调试
将dbgsrv/android_server
push到手机。
adb push ...\dbgsrv\android_server data/local/tmp
查看是否成功并给权限:
adb shell
su
cd data/local/tmp
ls
如果改名字,android_server可以运行: mv android_server as ab
如果想改端口号,可以运行: ./android_server -p端口号
chmod 777 android_server
新打开cmd,端口转发:
adb forward tcp:端口号 tcp:端口号
安装apk
打开ddms(红色甲壳虫)
挂起程序:
adb shell am start -D -n 包名/.类名
打开IDA,Debugger -> Attach -> Remote ARMLinux/Android debugger
设置:
127.0.0.1 端口
不用输入密码
选择app进程即可使用了。
设置 Debugger -> Debugger options
勾选:
Suspend on process entry point
Suspend on thread start/exit
Suspend on library load/unload
执行命令:
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=端口号
ddms的红色甲壳虫自动变成了绿色
点击IDA左上角运行。
等待so库加载,在IDA模块中找到该so库,在so库中找方法 jni_onload
(动态注册) 或者 java开头的方法
(静态注册)。f2下断点,f9运行。
加密算法
散列函数:用于数据完整性校验
MD 消息摘要算法
SHA 安全散列算法
MAC 消息认证算法
CRC 循环冗余校验算法
对称加密算法:加密密钥==解密密钥。
DES
DESede/3DES/Triple DES
AES
TEA
DEA
PBE
非对称加密算法:
加密密钥!=解密密钥
公钥==>对外公开
私钥==>对外保密
私钥加密==>公钥解密
公钥加密==>私钥解密
DH 密钥交换算法
基于因子分解
RSA 数据加密/解密 数字签名
基于离散对数
ElGameal 数据加密/解密 数字签名
DSS数据签名标准=>DSA 数字签名
ECC 椭圆曲线加密算法
数字签名
私钥==>签名
公钥==>验证
单向认证
双向认证
RSA
DSA
ECC+DSA==>ECDSA 椭圆曲线数字签名算法
认证/鉴别服务
数据完整性服务
抗否认性服务
数字证书
消息摘要算法
对称加密算法
非对称加密算法
数字签名
鉴别/认证
数据保密性
数据完整性
抗否认性
证书管理
KeyTool
构建自签名证书
构建CA签发证书
OpenSSL
根证书
服务器证书
客户端证书
密钥库==>管理私钥
数字证书==>管理公钥
加密/解密
签名/验证
X.509
服务器数字证书