安卓逆向学习----Dalvik汇编代码(smali语言)

这里的dalvik汇编代码值得是针对dalvik虚拟机设计的指令集,与一般的汇编代码不同

1.dalvik指令的格式

Dalvik汇编代码由一系列的dalvik指令组成,指令语法由指令位描述和格式标识来决定,这部分感觉没用先不看了,在Android4.0及之前的安卓源码Dalvik/docs目录下的instruction-formats.html可以看到具体介绍

2.相关工具

smali.jar用来将smali文件汇编为dex文件,而baksmali.jar则是用来将dex文件反汇编为smali文件,ddx.jar将dex文件反汇编为ddx文件,其语法规则与smali类似

使用方法分别为:

java -jar smali.jar -o xxx.dex  xxx.smali
java -jar baksmali.jar -o ouput/ XXX.dex
java -jar baksmali.jar -o ouput/ XXX.dex

 3.dalvik寄存器

dalvik虚拟机采用ARM架构,将一部分寄存器映射到ARM寄存器上,另一部分使用调用栈进行模拟。Dalvik的寄存器都是32位的,64位需要用两个相邻寄存器表示。寄存器编号取值范围为v0-v65535

Android SDK中有名为dalvik.bytecode.Opcodes的接口,处理字节码的函数为一个宏HANDLE_OPCODE(),每个字节码对应一个cpp文件,在其中对这个宏进行重写。

寄存器的命名有两种,v命名和p命名。一个函数有m个寄存器用于储存局部变量和隐式传入的函数引用对象,n个用于储存参数,v命名法将寄存器命名为v0~vm+n-1,而p命名法前m个寄存器仍然为v0~vm-1,储存参数的寄存器则被命名为p0~pn-1。

4.Dalvik字节码的类型、方法与字段表示方法

可以参考官网https://source.android.com/devices/tech/dalvik/dalvik-bytecode的介绍,百度了好多还是官网说的比较清楚

(1)类型:

Dalvik字节码只有基本类型和引用类型两种,这两种类型可以表示Java语言的全部类型,除了对象和数组属于引用对象以外,其它的Java类型都是基本类型 

  • J、D这种64位的类型需要使用相邻的两个寄存器储存
  • L可以代表Java类型的任何类,这些类在java代码中以package.name.ObjectName的方式引用,对应的汇编形式为Lpackage/name/ObjectName;最后有一个分号。例如Ljava/lang/String;对应于java.lang.String
  • [表示所有基本类型的数组,[后面紧跟类型描述符,例如[I代表java中的int[],n个[表示n维数组,与L组合就可以表示对象数组,[Ljava/lang/String就表示字符串数组

(2)方法

方法的格式为Lpackage/name/ObjectName;->MethodName(III)Z   III表示该方法有三个int型参数,Z表示返回值为boolean型,转换为java方法应该为Boolean MethodName(int,int, int)

(3)字段

格式为Lpackage/name/ObjectName;->FildName:Ljava/lang/String;

5.Dalvik指令集

(1)特点

参数顺序先是目的操作数,后是源操作数

名称后缀:64位字节码添加-wide后缀,特殊类型字节码根据具体类型添加后缀,例如-boolean -byte -class -void。

字节码后缀:根据布局和选项的不同,添加后缀用“/”分隔开例如/from16表示源为16位的寄存器变量

(2)空操作指令

助记符为nop,被用来对齐代码

(3)数据操作指令

move vA, vB 将vB的值赋给vA ;  move-wide vA, vB 赋值为64位

寄存器默认为4位,/16表示源寄存器和目的寄存器都为16位,/from16表示源为16位  -object表示为对象赋值,

move-result vA表示将上一个invoke类型操作的单字非对象结果赋值给vA寄存器,这里只有destination

move-exception vA 保存一个异常到vA寄存器

(4)返回指令

return-void 从一个void方法返回

return-vAA 表示返回一个32位非对象类型的值,返回值寄存器为8位的寄存器

return-wide vAA 表示函数返回64位非对象类型的值,返回值寄存器为8位的寄存器

return-object vAA 表示函数返回对象类型的值,返回值寄存器为8位的寄存器

(5)数据定义指令

const-wide/16 vAA, #+BBBB   将该常量值符号拓展至64位后赋值给vAA

......

(6)锁指令

monitor-enter vAA 为指定的对象获取锁

monitor-exit vAA 释放指定对象的锁

(7)实例操作指令

包括实例的类型转换、检查以及新建等

check-cast vAA,type@BBBB 将vAA寄存器中的对象引用转换为指定类型,失败会抛出异常

instance-of vA , vB ,type@CCCC  判断vB寄存器中的对象引用是否可以转换为指定类型,可以则给vA赋值为1,否则为0

new-instance vAA,type@BBBB 构造一个制定类型对象的新实例,并将对象引用赋值给vAA寄存器,type不能是数组类型

这三种指令加上/jumbo之后功能一样,但是寄存器值与指令索引取值范围更大

(8)数组操作指令

array-length vA, vB 获取vB寄存器数组的长度并将值赋给vA寄存器,数组长度指的是数组条目个数

new-array vA, vB, type@CCCC 构造指定类型的与大小的数组,将索引赋给vA,大小由vB决定

filled-new-array {vC,vD,vE,vF,vG} , type@BBBB 构造指定类型与大小的数组并填充数组内容,大小由vA隐含提供,并将值赋给vA

fill-array-data vAA,+BBBBBBBB 用指定的数据填充数组,vAA寄存器为数组引用,引用必须为基础类型的数组

(9)异常指令

throw vAA 抛出vAA寄存器中制定的异常

(10)跳转指令

分为无条件跳转goto、分支跳转switch与条件跳转if

goto +AA 跳转AA的偏移量

packed-switch vAA, +BBBBBBBB分支跳转指令,vAA寄存器为switch分支需要判断的值。+BBBBBBB指向一个packed-switch-payload格式的偏移表

sparse-switch vAA, +BBBBBBBB分支跳转指令,vAA寄存器为switch分支需要判断的值。+BBBBBBB指向一个sparse-switch-payload格式的偏移表

if-xx  vA,vB, +CCCC 比较vA和vB,满足xx条件跳转到CCCC的偏移处,条件包括eq(等于)、ne(不等于)、lt(小于)、ge(大于等于)等等

if-xxx  vA, +CCCC 把vA和0比较,满足xxx条件跳转到CCCC的偏移处,条件包括eqz(等于)、nez(不等于)、ltz(小于)、gez(大于等于)等等

(11)比较指令

cmpl-xxx vAA,vBB,vCC  如果vBB小于vCC,则结果为1,相等为0,否则-1,xxx指的是float、double

cmpg-xxx vAA,vBB,vCC  如果vBB大于vCC,则结果为1,相等为0,否则-1,xxx指的是float、double

cmp-long vAA,vBB,vCC  如果vBB大于vCC,则结果为1,相等为0,否则-1

(12)字段操作指令

这些指令用来对对象实例的字段进行读写操作,按照普通字段和静态字段分为两类:

iop vA,vB, field@CCCC 和 sop vAA, field@BBBB

iop代表iget iget-wide iget-object iget-boolean iget-byte iput iput-wide......

sop代表sget sget-wide sget-object sget-boolean sget-byte sput sput-wide......

其中get表示读操作,put表示写操作

(13)方法调用指令

invoke-kind {vC,vD,vE,vF,vG},meth@BBBB和 invoke-kind/range {vCCCC..vNNN},meth@BBBB ,二者相似,只是后者使用range指定寄存器范围。按照调用方法的kind具体分为以下几种:

invoke-virtual 或 invoke-virtual/range调用实例的虚方法

invoke-super 或 invoke-super/range调用实例的父类方法

invoke-direct 或 invoke-direct/range调用实例的直接方法

invoke-static 或 invoke-static/range调用实例的静态方法invoke-interface 或 invoke-interface/ragne调用实例的接口方法

(14)数据转换指令

op vA,vB  表示将VB寄存器的数据进行转换然后储存到vA寄存器.op分为以下几种

neg-int/long/float/double 求补

not-int/long/float/double 求补

int-to-long int转换为long

float-to-int

.......

(15)数据运算指令

数据运算指令包括算术运算指令(加减乘除移位等)和逻辑运算指令(与或非异或得等)

指令格式为以下几种:

op vAA,vBB,vCC  将vBB,vCC 进行运算,保存到vAA

op/2addr vA,vB    将 vA,vB进行运算,保存到vA

op/lit16 vA,vB,#+CCCC 将vB与常量CCCC运算,保存到vA

op/lit8 vAA,vBB,#+CC   将vBB与常量CC运算,保存到vAA

op包含add-type sub-type mul-type div-type rem-type and-type or-type xor-type shl-type shr-type ushr-type

6.smali代码实例

.class public LHelloWorld; 	#定义类名
.super Ljava/lang/Object; 	#定义父类
.method public static main([Ljava/lang/String;)V
        .registers 4		#程序中使用4个寄存器,v0,v1,v2和一个参数寄存器
        .parameter		#一个参数,有n个参数则有n行
        .prologue		#代码起始的指令
        #空指令
        nop
        nop
        nop
        nop
        #数据定义指令
        const/16 v0, 0x8
    	const/4 v1, 0x5
	const/4 v2, 0x3
	#数据操作指令
	move v1, v2
	#数组操作指令
	new-array v0, v0, [I
	array-length v1, v0
	#实例操作指令
	new-instance v1, Ljava/lang/StringBuilder;
	#方法调用指令
	invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
	#跳转指令
	if-nez v0, :cond_0
	goto :goto_0
	:cond_0
	#数据转换指令
	int-to-float v2, v2
	#数据运算指令
	add-float v2, v2, v2
	#比较指令
	cmpl-float v0, v2, v2
	#字段操作指令
	sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
	const-string v1, "Hello World" #构造字符串
	#方法调用指令
	invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
	#返回指令
	:goto_0
        return-void
.end method

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android虚拟机Dalvik完整源码,宝贵资源,欢迎下载! This directory contains the Dalvik virtual machine and core class library, as well as related tools, libraries, and tests. A note about the licenses and header comments --------------------------------------------- Much of the code under this directory originally came from the Apache Harmony project, and as such contains the standard Apache header comment. Some of the code was written originally for the Android project, and as such contains the standard Android header comment. Some files contain code from both projects. In these cases, the header comment is a combination of the other two, and the portions of the code from Harmony are identified as indicated in the comment. Here is the combined header comment: /* * Copyright (C) The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ---------- * * Portions of the code surrounded by "// BEGIN Harmony code" and * "// END Harmony code" are copyrighted and licensed separately, as * follows: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Native SH call bridge --------------------- Native SH call bridge is written by Shin-ichiro KAWASAKI and Contributed to Android by Hitachi, Ltd. and Renesas Solutions Corp.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值