本帖最后由 黑骑士 于 2020-7-31 22:49 编辑
头信息smail文件前三行
- .class <访问权限> [关键修饰字] <类名>;
- .super <父类名>;
- .source <源文件名>
复制代码.class指令表示当前的类名,类的访问权限是public,类名是Lcom/example/mark/myfirstapp/MainActivity,类开头的L是遵循Dalvik字节码的相关约定,表示后面跟随的字符串是一个类 .super指定了当前类所继承的父类 .source指定了当前类的源文件名 接口.implements <接口名>
类型#- V void
- Z boolean
- B byte
- S short
- C char
- I int
- J long
- F float
- D double
- L java类
- [ 数组
复制代码变量存放在寄存器中,寄存器采用v和p来命名,v表示本地寄存器,p表示参数寄存器。寄存器为32位,支持任何类型,其中long,double是64位,使用两个相邻的寄存器。 [x表示一维数组,x代表基本类型,如[I代表int[],[[x代表二维数组。
Java语言存在大量对象,java.lang.String表示为Ljava/lang/String;,分号一定要加上。 静态字段
(1)静态字段
- #static fields
- .field <访问权限> static [修饰关键字] <字段名>:<字段类型>
复制代码 (2)实例字段
- #instance fields
- .field <访问权限> static [修饰关键字] <字段名>:<字段类型>
复制代码 方法定义
- #direct/virtual methods ----注释,直接方法(direct methods)指的是该类中定义的方法,虚方法(virtual methods)指的是从父类中继承的方法或者实现的接口方法。
- .method <访问权限> [修饰关键字] <方法原型> ----方法原型描述了方法的名称、参数和返回值
- <.registers> ----指定了方法中寄存器的总数,这个数量是参数和本地变量总和
- [.param] ----方法的参数
- [.prologue] ----指定了代码的开始处,混淆过的代码可能去掉了该指令
- [.line] ----此处代码在源代码中的行号
- <.local> ----使用这个指定表明方法中非参寄存器
- <代码体>
- .end method
复制代码 常用指令
- move v0,v3 把v3寄存器的值移动到寄存器v0上
- const-string v0, "admin" 把字符串"admin"赋值给v0寄存器
- invoke-super 调用父函数
- invoke-static 调用静态函数
- invoke-direct 调用函数
- input-object 对象赋值
- iget-object 调用对象
- new-instance 创建实例
- return-void 函数返回void
复制代码 if判断
- if-eq vA, VB, cond_** 如果vA等于vB则跳转到cond_**。相当于if (vA==vB)
- if-ne vA, VB, cond_** 如果vA不等于vB则跳转到cond_**。相当于if (vA!=vB)
- if-lt vA, VB, cond_** 如果vA小于vB则跳转到cond_**。相当于if (vA<vB)
- if-le vA, VB, cond_** 如果vA小于等于vB则跳转到cond_**。相当于if (vA<=vB)
- if-gt vA, VB, cond_** 如果vA大于vB则跳转到cond_**。相当于if (vA>vB)
- if-ge vA, VB, cond_** 如果vA大于等于vB则跳转到cond_**。相当于if (vA>=vB)
- if-eqz vA, :cond_** 如果vA等于0则跳转到:cond_** 相当于if (VA==0)
- if-nez vA, :cond_** 如果vA不等于0则跳转到:cond_**相当于if (VA!=0)
- if-ltz vA, :cond_** 如果vA小于0则跳转到:cond_**相当于if (VA<0)
- if-lez vA, :cond_** 如果vA小于等于0则跳转到:cond_**相当于if (VA<=0)
- if-gtz vA, :cond_** 如果vA大于0则跳转到:cond_**相当于if (VA>0)
- if-gez vA, :cond_** 如果vA大于等于0则跳转到:cond_**相当于if (VA>=0)
复制代码 注解
- #annotations
- .annotation [注解属性] <注解类名>
- [注解字段 = 值]
- .end annotation
复制代码 smail插桩
虽说是老生常谈的东西了,稍微记录一下,我觉得最重要的就是寄存器的问题了,如果需要额外的寄存器,要在smali函数的最前面将寄存器数量增加到需要的数量。
在smali代码中,寄存器有两种表示方式,一种是v命名法,一种是p命名法。在v命名法中,从v0开始依次表示局部变量和参数。在p命名法中,从p0开始表示参数,从v0开始表示局部变量。以p命名法为例,在smali函数的开头,.locals n则表示可以使用v0到vn-1表示局部变量,因此如果插桩的时候需要额外的寄存器,则将.locals n 表示为.locals n+1就可以在插桩的代码中使用vn了。
#黑骑士技术QQ1994091497,培训火热扩招中
|