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.陌生关键字

二、定义/声明

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    #接口函数的调用

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。
  • 全面分析,在最简单的地方修改。
  • 数据分析,可以制造条件产生不同的数据,然后对比。
分类: smali

0 条评论

发表回复

您的电子邮箱地址不会被公开。