目录
smali语法:
有点类似于JNI的语法
https://blog.csdn.net/pinksofts/article/details/82791806 (讲的很详细)
https://blog.csdn.net/vrix/article/details/122165521 (数据运算)
https://blog.csdn.net/aketoshknight/article/details/118333660 (条理)
https://blog.csdn.net/yuanguozhengjust/article/details/80493963
https://blog.csdn.net/qq_34149335/article/details/82699029
https://blog.csdn.net/qq_36252044/article/details/86636885
https://blog.csdn.net/jaysong2012/article/details/41007745 (总结的很简单)
https://www.bilibili.com/read/cv25545471/ (操作指令分类)
https://blog.csdn.net/qq373432361/article/details/49557579 (语法文档查询)
https://www.cnblogs.com/caoleiCoding/p/16964552.html
一、前期基础
https://www.cnblogs.com/zhrea/p/6879941.html (快速恢复记忆)
https://blog.csdn.net/biao197/article/details/135245384
1.常见关键字
- .line N
代表其下代码还原成java代码在源文件第N行
2.陌生关键字
- check-cast:强转 (对象操作指令)
- synthetic :修饰变量的关键字,表明这个变量是编译器自己合成的,对private变量的处理。
https://www.cnblogs.com/eustoma/p/8991297.html
https://blog.csdn.net/weixin_39895096/article/details/114348724 - jumbo:相当于final关键字
二、定义/声明
1.smali数据类型
http://code.newban.cn/172.html
https://blog.csdn.net/aketoshknight/article/details/118333660(!!)
数据类型分3大类:
字符串类型数据
字节码数据
数值型数据
const-string v0 , "hello"# 定义字符串 将字符串hello赋值给v0
const-class v0,LGoActivity; # 定义字节码对象 将GoActivity.class对象赋值给v0
# 以下数据定义高位默认为符号位
const/4 v0,0x2 # 定义一个容器 最大只允许存放半字节4位数据 取值范围为 -8 and 7
const/16 v0 , 0xABCD # 定义定义一个容器 最大只允许存放16位数据 比如short类型数据 取值范围为-32768~32767
const v0 , 0xA# 定义一个容器 最大只允许存放32位数据,比如int类型数据 将数字10赋值给v0 取值范围-2147483647~2147483647
const/high16 #定义一个容器 最大只允许存放高16位数值 比如0xFFFF0000末四位补0 存入高四位0XFFFF
# const-wide 占用两个寄存器vx和vx+1, 数值必须以L结尾 否则编译不通过
const-wide/16 # 定义两个相连容器 最大只允许存放16位数据
const-wide/32 # 定义两个相连容器 最大只允许存放32位数据
const-wide # 定义两个相连容器 最大只允许存放64位数据
const-wide/high16 # 定义两个相连容器 只允许存放高16位数据
2.变量定义/声明(.field)
- .local(别名)
.local v0, "b":Ljava/lang/String; # 局部变量v0别名为b 是一个String类型 也就是 String b=v0
.local关键字用于标识变量的别名与类型,在java中,一个变量会有一个类似i/j之类的变量名,并且对应的数据类型,而smali中数据都使用寄存器存储16进制数值,不存在这样的区分。因此使用.local关键字注明该变量的别名以及类型,方便理解。
3.常量定义/声明(const)
4.类声明(.class)
5.普通函数声明(.method)
6.构造函数声明(.method)
7.静态代码块声明(.method)
三、调用/修改
1.函数调用
invoke-virtual #非私有实例函数的调用
invoke-direct #构造函数以及私有函数的调用
invoke-static #静态函数的调用
invoke-super #父类函数的调用
invoke-interface #接口函数的调用
-
函数批量传值:
invoke-direct/range
https://blog.csdn.net/LQMIKU/article/details/108968384
比如:invoke-direct/range {v0…v6},即表示v0, v1, v2, v3, v4, v5, v6为传入参数。 -
this
p0表示this
2.字段取值与赋值
https://zhuanlan.zhihu.com/p/580962131
- 普通字段读写
前缀是i的iput-type和iget-type指令用于字段的读写操作.
iput-object
- 静态字段读写
前缀是s的sput-type和sget-type指令用于静态字段的读写操作
1)复杂对象
https://www.jianshu.com/p/f9fa118153b6
https://www.cnblogs.com/lordtianqiyi/articles/15969773.html
- 数组
获取:
aget-object v2, v2, v3
获取数组v2(第二个v2)里面的第v3个元素v2(第一个v2)
设置:
aput-object v2, v0, v1
在索引为v1(0)的位置填充v2于v0
3.对象创建
4.对象赋值
move-object vx,vy
:自动对象引用从 vy 到 vx.
四、控制语句
https://www.cnblogs.com/zhen-android/p/7259434.html
https://www.cnblogs.com/lee0oo0/p/3728271.html
跳转指令
- 无条件跳转(goto)
- 分支跳转(switch)
- 条件跳转(if)
if-** - 循环
if-ge配合goto
锁指令
monitor-enter vAA: 为指定的对象获取锁.
monitor-exit vAA: 释放指定的对象的锁.
五、运算指令
- 四则运算
“binop vAA, vBB, vCC”:将vBB寄存器与vCC寄存器进行运算,结果保存到vAA寄存器。 “binop/2addr vA, vB”:将vA寄存器与vB寄存器进行运算,结果保存到vA寄存器。 “binop/lit16 vA, vB, #+CCCC”:将vB寄存器与常量 CCCC进行运算,结果保存到vA寄存器。 “binop/lit8 vAA, vBB, #+CC”:将vBB寄存器与常量CC进行运算,结果保存到vAA寄存器。
**-type
-
比较
cmpl-float -
数据转换
unop vA,vB
表示对vB寄存器的中值进行操作,并将结果保存在vA寄存器中.
五、常见指令组合
onclick+switchcase
https://www.jianshu.com/p/140740e9c8e6
switch、try-catch
https://blog.csdn.net/qq_32113133/article/details/85163277
五、 类(包括内部类)
https://blog.csdn.net/weixin_44946052/article/details/89409452 (写的挺详细)
我总结一下我的认识:
1.smali文件,先看文件的前3行的描述信息,清楚这个文件的性质(类还是内部类,谁的内部类。)
2.记住smali语法是基于寄存器的,所以原来java很直接的赋值与获取操作,都会间接通过vxxx寄存器。(记住这个规律)
3.不知道smali代码咋写时,可以写个简单的demo反编译出来。
4.写代码一定注意.locals数量的同步
5. :cond_x和:goto_0是用来是控制语句关键字,跳转的时候不要蒙蔽,可以写个简单的demo测试 。
6.不同的smali文件夹下的类可能会相互跳转,要注意。
smali常见错误总结:
-
java.lang.VerifyError: Verifier rejected class com.nx.core.wrappers.d: java.lang.reflect.Method com.nx.core.wrappers.d.a() failed to verify
我的情况是在invoke-virtual与move-result-object
插入了代码,这两句要联合使用,中间不能加代码。 -
Must be between v0 and v15, inclusive..的解决办法
https://blog.csdn.net/zihao2012/article/details/50378606
smali语法实战:
插入日志
https://www.52pojie.cn/thread-665362-1-1.html
1.最简单的实战demo
https://www.it610.com/article/4638551.htm (麻雀虽小,五脏俱全)
2.AndroidStudio调试Smali
https://blog.csdn.net/qq_41866988/article/details/127597780(极简调试)
https://blog.csdn.net/ausboyue/article/details/80189184
https://blog.csdn.net/qq_34149335/article/details/81668503 (这里我要纠正一下作者的一个观点:说app端口是8600和8700的并没有错,关键清单里debugable要设置为true,然后DDMS就会显示8700或者8600)
https://www.cnblogs.com/foundkey/p/10256984.html (不必使用adb forward tcp:10001 jdwp:26793,直接使用8600或者8700进行debug即可。)
https://www.jianshu.com/p/9843e80f5ac5
IDEAAttach前先要执行:
adb shell am start -D -n com.mosheng/com.mosheng.view.activity.AppStartPager
多次Attach报错:adb kill-server再adb start-server一下,如果还不行,重启手机。
调试技巧
充分利用step over与step into的技巧,在碰到线程时step over就不好使了,用step into可以追踪到方法,想退出step into的方法,可以step out。
3.借助工具
unicode码转中文: http://tool.chinaz.com/tools/unicode.aspx (smali里的中文都是\u码,转成中文便于理解。)
as的java2smali插件:https://www.jianshu.com/p/cdde8121c823
4. 如何拼接字符串
https://blog.csdn.net/weixin_33841503/article/details/91443117
smali与dex 、Java互转
https://www.jianshu.com/p/fb9aec070c0a (纠正一下:smali与dex互转的工具写反了)
smali与baksmali
smali与baksmali的官网下载地址:https://bitbucket.org/JesusFreke/smali/downloads/
最新用法:https://www.jianshu.com/p/b2e5da2efb22
smali反编译经验总结:
- 抓住重点方法addBookMark。
- 全面分析,在最简单的地方修改。
- 数据分析,可以制造条件产生不同的数据,然后对比。
0 条评论