最近RCS-TEAM倚天实验室加入了几位安全方向的大神,其中就有Android逆向工程工程师。今天要跟大家分享的就是Android逆向技术。
I 0x1Android 移动安全与逆向介绍
Android 移动安全逆向方面,逆向首先要看懂代码,Android4.4之前一直使用的是 Dalivk虚拟机,而Smali是用于Dalivk的反汇编程序的实现。
Smali 支持注解,调试信息,行数信息等基本Java的基本特性,可以说是很接近Java编译再JVM上的中间语言,一般用来做Android程序的逆向工程。
I 0x2Android 移动安全与逆向之Smali基础语法总结
1.Smali文件结构
一个Smali文件对应的是一个Java的类,更准确的说是一个.class文件,如果有内部类,需要写成ClassName$InnerClassA,ClassName$InnerClassB...这样的形式
2.基本类型
类型关键字/标识符 | 对应Java中的类型说明 |
V | void,只能用于返回类型 |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long(64 bits) |
F | float |
D | double (64 bits) |
I 0x3Smali 指令集
指令集 : smali指令大全
Dalvik 指令在调用格式上模仿了C语言的调用约定.Dalvik 指令的语法与助词符有如下特点:
参数采用从目标( destination )到源( source )的方式
根据字节码的大小与类型不同,一些字节码添加了名称后缀以消除歧义 > > * 32 位常规类型的字节码未添加任何后缀。> > * 64 位常规类型的字节码添加-wide后缀 > > * 特殊类型的字节码根据具体类型添加后缀。它们可以是-boolean、-byte、-char、-short、-int、-long、-float、-double、-object、-string、-class、-void 之一
根据字节码的布局与选项不同,一些字节码添加了字节码后缀以消除歧义。这些后缀通过在字节码主名称后添加斜杠“ / ”来分隔开
在指令集的描述中,宽度值中每个字母表示宽度为 4 位
例如这条指令 move-wide/from16 vAA , vBBBB
move 为基础字节码( base opcode )。标识这是基本操作
wide 为名称后缀( name suffix )。标识指令操作的数据宽度( 64 位)
from16 为字节码后缀(opcode suffix )。标识源为一个 16 位的寄存器引用变量。
vAA 为目的寄存器。它始终在源的前面,取值范围为 vo-v255 。
vBBBB 为源寄存器。取值范围为 vo-v65535 。
Dalvik 指令集中大多数指令用到了寄存器作为目的操作数或源操作数,其中 A/B/C/ D/E/F/G/H 代表一个 4 位的数值,可用来表示 0 一15的数值或 vo 一 v15 的寄存器,而 AA / BB / CC / DD / EE / FF / GG / HH 代表一个 8 位的数值,可用来表示 0 一 255 的数位或 v0 一 v255 的寄存器, AAAA/BBBB / CCCC / DDDD / EEEE / FFFF / GGGG / HHHH 代表一个 8 位的数值,可用来表示 0 一 65535 的数值或 vo 一 v65535 的寄存器。
I 0x4Smali 空指令
nop 值为00,用来代码对齐,无用处
I 0x5Smali 数据操作指令
数据操作指令为move,move指令的原型为move destination,source 或 move destination , move 指令根据字节码的大小与类型不同,后面会跟上不同的后缀.
-
move vA , vB 将 vB 寄存器的值赋给 vA 寄存器,源寄存器与目的寄存器都为 4 位.
-
move vA , vB 将 vB 寄存器的值赋给 vA 寄存器,源寄存器与目的寄存器都为 4 位.
-
move / from 16 vAA , vBBBB 将 vBBBB 寄存器的值赋给 vAA寄存器,源寄存器为16 位,目的寄存器为 8 位.
-
move / 16 vAAAA , vBBBB 将 vBBBB 寄存器的值赋给 vAAAA 寄存器,源寄存器与目的寄存器都为 16 位.
-
move-wide vA , vB 为 4 位的寄存器对赋值.源寄存器与目的寄存器都为 4 位.
-
move-wide/from16 vAA , vBBBB 与 move-wide/16 vAAAA , vBBBB 实现与move-wide相同
-
move-object vA , vB 为对象赋值.源寄存器与目的寄存器都为4位.
-
move-object/from16 vAA , vBBBB 为对象赋值,源寄存器为 16位,目的寄存器为8位.
-
move-object/16 vAAAA,vBBBB 为对象赋值源寄存器与目的寄存器都为 16 位.
-
move-result vAA 将上一个 invoke 类型指令操作的单字非对象结果赋给 vAA 寄存器.
-
move-result-wide vAA 将上一个invoke类型指令操作的双字非对象结果赋给 vAA 寄存器
-
move-result-object vAA 将上一个 invoke 类型指令操作的对象结果赋给 vAA 寄存器.
-
move-excecption vAA 保存一个运行时发生的异常到 vAA 寄存器.这条指令必须是异常发生时的异常处理器的一条指令.否则的话,指令无效.
I 0x6Smali 返回指令
返回指令指的是函数结尾时运行的最后一条指令.它的基础字节码为retum,共有以下四条返回指令.
return-void表示函数从一个void方法返回.
return vAA表示函数返回一个32位非对象类型的值,返回值寄存器为8位的寄存器vAA.
return-wide vAA表示函数返回一个64位非对象类型的值.返回值为8位的寄存器对vAA.
return-object vAA表示函数返回一个对象类型的值.返回值为8位的寄存器vAA.
I 0x7Smali 数据定义指令
数据定义指令用来定义程序中用到的常量、字符串、类等数据.它的基础字节码为const.
#+X 表示它是一个常量数字,+X 表示它是一个相对指令的地址偏移,kind@X 表示它是一个常量池索引值。
const/4 vA,#+B 将数值符号扩展为32位后赋给寄存器vA
const/16 vAA,#+BBBB将数值符号扩展为32位后赋给寄存器vAA.
const vAA,#+BBBBBBBB 将数值赋给寄存器vAA.
const/high16 vAA,#+BBBB0000 将数值右边零扩展为32位后赋给寄存器vAA
const-wide/16 vAA,#+BBBB 将数值符号扩展为64位后赋给寄存器对vAA
const-wide/32 vAA.#+BBBBBBBB 将数值符号扩展为64位后赋给寄存器对vAA
const-wide vAA,#+BBBBBBBBBBBBBBBB 将数值赋给寄存器对vAA.
const-wide/high16 vAA,#+BBBB000000000000 将数值右边零扩展为64位后赋给寄存器对vAA
const-string vAA,string@BBBB 通过字符串索引构造一个字符串并赋给寄存器vAA.
const-string/jumbo vAA,string@BBBBBBBB 通过字符串索引(较大)构造一个字符串并赋给寄存器vAA.
const-class vAA,type@BBBB 通过类型索引获取一个类引用并赋给寄存器vAA
const-class/jumbo vAAAA,type@BBBBBBBB 通过给定的类型索引获取一个类引用并赋给寄存器vAAAA.这条指令占用两个字节,值为ox00ff(Android4.0中新增的指令)
I 0x8Smali 锁指令
锁指令多用在多线程程序中对同一对象的操作.Dalvik指令集中有两条锁指令.
monitor-enter vAA 为指定的对象获取锁.
monitor-exit vAA 释放指定的对象的锁.
I 0x9Smali 实例操作指令
与实例相关的操作包括实例的类型转换、检查及新建等
check-cast vAA,type@BBBB 将vAA寄存器中的对象引用转换成指定的类型,如果失败会抛出ClassCastException异常.如果类型B指定的是基本类型,对于非基本类型的A来说,运行时始终会失败.
instance-of vA,vB,type@CCCC 判断vB寄存器中的对象引用是否可以转换成指定的类型,如果可以vA寄存器赋值为1,否则vA寄存器赋值为0.
new-instance vAA,type@BBBB 构造一个指定类型对象的新实例,并将对象引用赋值给vAA寄存器,类型符type指定的类型不能是数组类
check-cast/jumbo vAAAA,type@BBBBBBBB 指令功能与check-cast vAA,type@BBBB相同,只是寄存器值与指令的索引取值范围更大(Android4.0中新增的指令)
instance-of/jumbo vAAAA,vBBBB,type@CCCCCCCC 指令功能与 instance-of vA,vB,type@CCCC”相同,只是寄存器值与指令的索引取值范围更大(Android4.0中新增的指令)
new-instance/jumbo vAAAA,type@BBBBBBBB 指令功能与new-instance vAA,type@BBBB 相同,只是寄存器值与指令的索引取值范围更大(Android4.0中新增的指令).
I 0x10Smali 数组操作指令
数组操作包括读取数组长度、新建数组、数组赋值、数组元素取值与赋值等操作。
array-length vA,vB 获取给定vB寄存器中数组的长度并将值赋给vA寄存器,数组长度指的是数组的条目个数。
new-array vA,vB,type@CCCC 构造指定类型(type@CCCC)与大小(vB)的数组,并将值赋给vA寄存器。
new-array/jumbo vAAAA,vBBBB,type@CCCCCCCC 指令功能与上一条指令相同,只是寄存器与指令的索引取值范围更大(Android4.0中新增的指令)
filled-new-array {vC,vD,vE,vF,vG},type@BBBB 构造指定类型(type@BBBB)与大小(vA)的数组并填充数组内容。vA寄存器是隐含使用的,除了指定数组的大小外还制订了参数的个数,vC~vG是使用到的参数寄存器序列
filled-new-array/range {vCCCC, … ,vNNNN},type@BBBB 指定功能与上一条指令相同,只是参数寄存器使用range字节码后缀指定了取值范围,vC是第一个参数寄存器, N=A+C-1。
filled-new-array/jumbo {vCCCC, … ,vNNNN},type@BBBBBBBB 指令功能与上一条指令相同,只是寄存器与指令的索引取值范围更大(Android4.0中新增的指令) fill-array-data vAA, +BBBBBBBB 用指定的数据来填充数组,vAA寄存器为数组引用,引用必须为基础类型的数组,在指令后面会紧跟一个数据表
arrayop vAA,vBB,vCC 对vBB寄存器指定的数组元素进入取值与赋值。vCC寄存器指定数组元素索引,vAA寄存器用来寄放读取的或需要设置的数组元素的值。读取元素使用 aget类指令,元素赋值使用aput指令,根据数组中存储的类型指令后面会紧跟不同的指令后缀,指令列表有aget、 aget-wide、aget-object、aget-boolean、aget-byte、aget-char、aget-short、aput、 aput-wide、aput-boolean、aput-byte、aput-char、aput-short。
~点赞加关注学习更多安全知识~
原文始发于微信公众号(小白嘿课):【逆向工程】Android逆向Smali语法(一)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论