寄存器
在smali里的所有操作都必须经过寄存器来进行:本地寄存器用v开头数字结尾的符号来表示,如v0、 v1、v2。 参数寄存器则使用p开头数字结尾的符号来表示,如p0、p1、p2。特别注意的是,p0不一定是函数中的第一个参数,在非static函数中,p0代指“this”,p1表示函数的第一个 参数,p2代表函数中的第二个参数。而在static函数中p0才对应第一个参数(因为Java的static方法中没有this方法)
| 寄存器名称 | 功能介绍 |
|---|---|
R0-R12 | 通用寄存器,用于存储临时数据。在函数调用时,R0-R3用于存储前四个参数,其余的参数通过堆栈传递。返回值也通过R0和R1传递。 |
R13 (SP) | 堆栈指针寄存器,指向当前堆栈的顶部。 |
R14 (LR) | 链接寄存器,存储子程序的返回地址。 |
R15 (PC) | 程序计数器,指向下一条要执行的指令。 |
CPSR | 当前程序状态寄存器,保存程序的状态信息,如算术运算的结果标志、中断禁止标志等。 |
FPSCR | 浮点状态和控制寄存器,如果你在调试的代码中涉及到浮点运算,那么这个寄存器会比较重要。 |
smail及其语法
smali是Dalvik的寄存器语言,smali代码是dex反编译而来的。
简单来讲就是将java代码转化成了smail代码(类似java代码转化成python代码?)
关键字
| 名称 | 注释 |
|---|---|
| .class | 类名 |
| .super | 父类名,继承的上级类名名称 |
| .source | 源名 |
| .field | 变量 |
| .method | 方法名 |
| .register | 寄存器 |
| .end method | 方法名的结束 |
| public | 公有 |
| protected | 半公开,只有同一家人才能用 |
| private | 私有,只能自己使用 |
| .parameter | 方法参数 |
| .prologue | 方法开始 |
| .line xxx | 位于第xxx行 |
数据类型对应
| smali类型 | java类型 | 注释 |
|---|---|---|
| V | void | 无返回值 |
| Z | boolean | 布尔值类型,返回0或1 |
| B | byte | 字节类型,返回字节 |
| S | short | 短整数类型,返回数字 |
| C | char | 字符类型,返回字符 |
| I | int | 整数类型,返回数字 |
| J | long (64位 需要2个寄存器存储) | 长整数类型,返回数字 |
| F | float | 单浮点类型,返回数字 |
| D | double (64位 需要2个寄存器存储) | 双浮点类型,返回数字 |
| string | String | 文本类型,返回字符串 |
| Lxxx/xxx/xxx | object | 对象类型,返回对象 |
常用指令
| 关键字 | 注释 |
|---|---|
| const | 重写整数属性,真假属性内容,只能是数字类型 |
| const-string | 重写字符串内容 |
| const-wide | 重写长整数类型,多用于修改到期时间。 |
| return | 返回指令 |
| if-eq | 全称equal(a=b),比较寄存器ab内容,相同则跳 |
| if-ne | 全称not equal(a!=b),ab内容不相同则跳 |
| if-eqz | 全称equal zero(a=0),z即是0的标记,a等于0则跳 |
| if-nez | 全称not equal zero(a!=0),a不等于0则跳 |
| if-ge | 全称greater equal(a>=b),a大于或等于则跳 |
| if-le | 全称little equal(a<=b),a小于或等于则跳 |
| goto | 强制跳到指定位置 |
| switch | 分支跳转,一般会有多个分支线,并根据指令跳转到适当位置 |
| iget | 获取寄存器数据 |
过VIP
使用MT管理器编译dex文件后对smail代码进行修改
假设:源代码是通过 if (isvip) 的类似方法进行判断。
方案一:修改判断
直接修改if中的条件语句
方案二:强制跳转
使用goto直接跳过条件判断
方案三:修改寄存器的值
比如可以直接将isvip方法固定返回true即可
感谢:【新提醒】《安卓逆向这档事》三、初识smali,vip终结者 – 『移动安全区』 – 吾爱破解 – LCG – LSG |安卓破解|病毒分析|www.52pojie.cn