apk反汇编之smali语法
类型
Dalvik的字节码中拥有两个主要的类型:基类和引用类型。引用类型
引用类型是对象和数组,其他的一切都是基类
基类被一个简单的字符描述。我没有提出这些缩写词———他们实际以字符串的形式存储于dex文件中
他们被定义与dex格式网页文档中(在AOSP库中的路径是dalvik/docs/dex-format.html)
V 空类型---仅仅可以用来作为返回类型
Z Boolean 布尔型
B Byte字节型
S Short短整型(16位)
C Char字符型
I Int 整形
J long (64 bits)长整型(64位)
F Float浮点型
D double (64 bits)双精度型(64位)
对象采用这样的形式Lpackage/name/ObjectName---开始的L表明这是一个对象类型,package/name/就是该对象,对象
名是是对象的名称,并且分号表明对象名的结束。这个等同于java语言中的package.name.ObjectName结构,举个更具体的例
子,“ Ljava/lang/String;”就等同于java语言的“java.lang.String”。数组采用[I的形式—这代表一个一维整形
数组就像java语言中的int[]。而多维数组,你简单的增加字符‘[’就行了,例如[[I=int[][](最大的维度是255).你也可以使用数组
对象,例如[Ljava/lang/String就是一个字符串数组。
方法
方法总是被定义为一个非常复杂的包括方法,方法名,参数类型和返回值的形式。
所有的这些信息被要求对于虚拟机而言可以找到正确的方法并且能够表现字节码上的静态分析(为了确认挥着选择最优化)。他们采用如下形式
Lpackage/name/ObjectName;->MethodName(III)Z
在这个例子中,你应该识别出“ Lpackage/name/ObjectName; 是一个类, MethodName明显是一个方法名,(III)Z是方法的签名,‘III’在这个例子中是三个整形参数,Z是表示返回一个布尔类型的返回值。
They take the form
Lpackage/name/ObjectName;->MethodName(III)Z
In this example, you should recognize Lpackage/name/ObjectName; as a type. MethodName is obviously the name of the method. (III)Z is the method's signature. III are the parameters (in this case, 3 ints), and Z is the return type (bool).
方法的参数一个接一个的列举在右边,中间没有分号。给出一个更复杂的例子:
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
在java语言中,他应该是这样的
String method(int, int[][], int, String, Object[])
域
域同样的被指定为一个冗长的包括域,域名,域类型的形式。此外,它也允许虚拟机找到正确的域来表现字节编码的静态分析。
它们采用如下形式:
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
这相当的不言自明---分别表示域名,域名和域类型
在dalvik字节码中,寄存器总是32位可以存放任何类型的值,2个寄存器可以用来存放64位类型(长整形和双精度型)
指定方法中的寄存器数字
这里有两种办法来指定一种方法中的多个寄存器。寄存器直接指定方法中的寄存器总数,或者区域变量直接指定方法中的非参数寄存器数。寄存器总数包括方法中参数所需的所有寄存器。
多少参数传入方法
当一个方法被调用,方法中的参数被放置到最近的几个寄存器。如果一个方法拥有两个参数和五个寄存器,这些参数会被存放到最后的两个寄存器V3和V4.
动态方法的第一个参数总是被调用的第一个对象,例如让你写一个动态方法 LMyObject;->callMe(II)V,这个方法有两个整形参数,但是还有一个隐含的参数‘LMyObject’在两个整形参数之前,所以总共有三个参数在这个方法中。
我们假设你在一个方法中制定了5个寄存器(v0-v4),既不是寄存器5管理也不是本地寄存器2管理(2个本地寄存器和3个参数寄存器)
当该方法被调用后,被调用的对象是V2,第一个整型参数是V3,第二个是V4。在静态方法中也是同样的,除非没有隐含的this指针参数。
寄存器名称
对于寄存器这里有两种命名方案—标准的V命名方案和对于参数寄存器的P命名方案。
以p命名的第一个寄存器就是方法中的第一个参数寄存器,所以让我们回到之前的总共拥有5个寄存器其中3个参数的例子。下表中显示了为每个寄存器的标准v命名,紧接着是为参数寄存器的p命名
v0 the first local register
第一个本地寄存器
v1 the second local register
第二个本地寄存器
v2 p0 the first parameter register
第一个参数寄存器
v3 p1 the second parameter register
第二个参数寄存器
v4 p2 the third parameter register
第三个参数寄存器
你可以通过每个名称类参照参数寄存器—这没有什么两样
p命名方案是作为一个实用的内容被引入的来解决编辑smali编码中的共同的难点。
假设你有一个已经存在的方法拥有一定数目的参数,你想增加一些代码到这个方法,你会发现你需要一个额外的寄存器。
你会想,没什么大不了的,我仅仅在寄存器管理中增加寄存器数目就可以了。但是不幸的是,这并不容易。请记住方法中的参数是寄存在最近的寄存器中的。如果你增加寄存器数—你会改变方法参数的在寄存器中的输入。所以你就不得不改变寄存器管理并且重编号参数寄存器
但是如果是你在方法中使用p命名模式来引用参数寄存器,你可以很容易的改变方法中的寄存器数而不必担心重编号任何存在的寄存器。
注意:默认baksmali对于参数寄存器使用p命名模式来命名。如果你因为某些原因不适用p命名而强制使用V命名模式,你可以使用-p/--no-parameter-registers来选择。
Long/Double values
长整型/双精度型值
鉴于以前提到过,长整型和双精度型(用J和D分别代表)的基本单元是64位,需要使用2个寄存器。
当你引用方法中的参数时必须牢牢记住。
例如,我们夹着你拥有一个非静态的方法LMyObject;->MyMethod(IJZ)V。方法的参数是“LMyObject;”,整形,长整
形和布尔型。所以在这个方法中会要求五个寄存器来存放所有的参数。并且,当你以后调用这个方法时,你为了调用该指令不得不在寄存器列表中指定两个寄存器来
存放任何64位的参数
Baksmali现在可以来反编译odex文件,并且选择性的deodex他们。
注意:本页说明仅仅应用于baksmali v0.96-v1.1。v1.2以上版本开始不再要求deodexrant.随心版本说明可以在http://code.google.com/p/smali/wiki/DeodexInstructions找到。
详细介绍
他要求deodexrant 的帮助,这是一个较小的可以在手机上运行并且连接到dalvik酷的二进制文件
他的目的在从正在运行的dalvik中获得类似寄存器表,域偏移量等信息提供给baksmali
Deodexrant的语法如下:
deodexerant <odex_file> <port>
接着baksmali拥有一个新的选项来告诉deodex文件,语法如下:
baksmali -x <host>:<port> <odex_file>
你也可以用-x :<port> 作为 –x localhots:<port>的快捷方式
主要的事情你必须记住的是当你将文件deodex化的时候,当odex文件被创建的时候你必须运行一些“bootclasspath”jar文件
最容易满足的这个的是当你尝试deodex的时候运行在硬件上。如果你需要从不同的硬件上deodex一些文件时也有可能改变根目录环境,但是我会将它作为一个练习留给读者
我们假设你正在运行一个基于美国移动商的官方版本的rom,并且苹果程序在/system/app目录下被deodex。一个deodex交互会像如下情形:
adb push deodexerant /data/local
adb shell chmod 755 /data/local/deodexerant
adb forward tcp:1234 tcp:1234
adb pull /system/app/Calculator.odex .
adb shell /data/local/deodexerant /system/app/Calculator.odex 1234 &
java -jar baksmali.jar -x :1234 Calculator.odex
你会活得一系列的smali文件在外层目录下,准备好用smali反编译这些dex文件。
注意我如何适应adb来通过usb来通信。如果你试着用wifi这个将会很慢。
鉴于baksmali向deodex制造了大量短小的同步请求,潜在上抑制了性能,所以usb连接比wifi用时更少
Troubleshooting
解决问题
When deodexing, there are several common issues you may run into.
当进行deodex的时候,可能会有几个问题你会遇上
The most common, which is almost guaranteed to happen if you're deodexing an entire build, is an error which is something like "Cannot find class Lfoo/bar; for common superclass lookup".
最常见保证很有可能发生的是如果你deodex一个完整的构造,会出现一个类似的错误“Cannot find class Lfoo/bar; for common superclass lookup”。
这是由于当odex文件拥有在标准的BOOTCLASSPATH一个额外的附属物超出了jars的范围
This is caused when the odex file has an additional dependency, beyond the jars in the normal BOOTCLASSPATH. To resolve the issue, you need to find which jar contains the class mentioned in the error message, and then add that to the BOOTCLASSPATH environment variable (on the phone/device/emulator) before running deodexerant.
为了解决这个问题,你需要找到那个包含错误信息提示的那个类的jar文件并且在运行deodexrant前将它添加到BOOTCLASSPATH环境变量中。
You can usually guess which jar it is from the class name, but if not, you can disassemble the jars and find which one has that class.
通常你可以根据类名来猜测是哪个jar,如果不行,你可以反编译jars然后找出包含该类的jar
Once you find the extra dependency, let's say /system/framework/com.google.android.maps.jar (which is one that is commonly needed), the deodexerant command would be
(on linux/mac)
一旦你找到了该额外的附属,我们就假设它是/system/framework/com.google.android.maps.jar
(这是普遍被需求的一个jar),那么deodexrant命令就如下(linux和mac平台)
adb shell BOOTCLASSPATH=\$BOOTCLASSPATH:/system/framework/com.google.android.maps.jar deodexerant blah.odex 1234 &
Windows平台
adb shell BOOTCLASSPATH=$BOOTCLASSPATH:/system/framework/com.google.android.maps.jar deodexerant blah.odex 1234 &
________________________________________
另外的一件你可能遇到的事实堆溢出。错误提示类似“java.lang.OutOfMemoryError: Java heap space”。解决他
的办法是你可以增加java参数-Xmx512m来增加堆到512Mb。当然如果需要你也可以增加到更大。如果你正在使用类似
“java -jar baksmali.jar”来运行baksmali,可以用如下指令来代替
java -Xmx512m -jar baksmali.jar -x :1234 blah.odex
如果你正在使用封装脚本
baksmali -JXmx512m -x :1234 blah.odex
________________________________________
另外一件事是发生在一些平台上(个人认为尤其是windows平台)的堆溢出。错误提示类似
“java.lang.StackOverflowError”。错误的堆栈轨迹很可能是包含了类
似"at org.jf.dexlib.Util.DeodexUtil$insn.propagateRegisters(DeodexUtil.java:1396)"
的说明。
为了修正这个错误,你可以用-Xss10m指令来增加堆空间
java -Xss10m -jar baksmali.jar -x :1234 blah.odex
or
baksmali -JXss10m -x :1234 blah.odex
apk反汇编之smali语法的更多相关文章
- Smali语法
看阿里巴巴的<深入探索Android热修复>,里面的代码看不懂,一查才知道是Smali语法,百度了语法,转载如下 转载自smali 语言语法 1.smali apk文件通过apktool反 ...
- Smali语法简单介绍
Smali语言其实就是Davlik的寄存器语言: Smali语言就是android的应用程序.apk通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件,文件的展示 ...
- Smali语法编程
Smali背景: Smali,Baksmali分别是指安卓系统里的Java虚拟机(Dalvik)所使用的一种.dex格式文件的汇编器,反汇编器.其语法是一种宽松式的Jasmin/dedexer语法,而 ...
- Android 反编译 -smali语法
前言 前面我们有说过android反编译的工具,如何进行反编译.反编译后可以得到jar或者得到smali文件.Android采用的是java语言 进行开发,但是Android系统有自己的虚拟机Dalv ...
- Android逆向之smali语法宝典
0x01.前言 Android采用的是java语言进行开发,但是Android系统有自己的虚拟机Dalvik,代码编译最终不是采用的java的class,而是使用的smali.我们反编译得到的代码,j ...
- Android APK程序的smali动态调试
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/71250622 一.Apktool的下载和安装 Apktool是Android逆向分 ...
- apk反编译(3)smali语法
from http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html Dalvik opcodes Author: Gabor Paller Vx ...
- Smali语法基础
Smali是什么 Smali是Android虚拟机的反汇编语言. 我们都知道,Android代码一般是用java编写的,执行java程序一般需要用到java虚拟机,在Android平台上也不例外,但是 ...
- smali语法详解
smali文件格式 每个smali文件都由若干条语句组成,所有的语句都遵循着一套语法规则.在smali 文件的头3 行描述了当前类的一些信息,格式如下: .class < 访问权限> [ ...
随机推荐
- VBS控制鼠标移动和点击(附源代码下载)
森思:想用vbs来控制鼠标的移动和点击,虽然按键精灵可以做到,但做这么简单的事情不想启动那么大一个程序,所以自己用VC写了一个小程序,可以让VBS来控制鼠标移动和点击. 用法: 移动鼠标到桌面坐标20 ...
- 如何获取网页验证码图片并保存到本地(Java实现) [问题点数:40分,结帖人lanxuezaipiao]
http://bbs.csdn.net/topics/390426978 public static String readCheckImage(HashMap<String, String&g ...
- java中list集合的内容,如何使用像数据库中group by形式那样排序
java中list集合的内容,如何使用像数据库中group by形式那样排序,比如:有一个 List<JavaBean> 他中包含了一些如下的内容JavaBean:name mone ...
- CSS3秘笈:第三章
1.标签选择器:控制整体. 使用标签选择器,只需要输入标签的名称即可. 2.类选择器:精确控制. 假如你要指定一些相同的元素拥有不同的样式,可以给元素添加不同的类名,然后用类选择器来应用对应的样式. ...
- shell脚本学习(二)
4.cat命令 1) cat -s 摆脱多余的空白行 2) cat -T 将制表符显示为^I 3) cat -n 显示行号 4) cat -b 跳过空白行,然后显示行号 ...
- 括号匹配(C++ Stack)
最近在学习C++,所以使用stack容器来实现括号匹配 /**********************************************************/ stack<Ty ...
- 客户端 HttpUtils.java
package com.http.post; import java.io.ByteArrayOutputStream; import java.io.IOException; import java ...
- 解决win7和ubuntu双系统ubuntu不能上网的问题
1.电脑基本配置如下. 我的电脑 戴尔 OptiPlex 9020 Mini Tower操作系统 Windows 7 专业版 64位 SP1 Ubuntu 14.04 2.装系统的过程不再赘述. 可以 ...
- Linux常用Shell脚本珍藏【转载】
我们在运维中,尤其是linux运维,都知道脚本的重要性,脚本会让我们的 运维事半功倍,所以学会写脚本是我们每个linux运维必须学会的一门功课,这里收藏linux运维常用的脚本.如何学好脚本,最关键的 ...
- window.open页面关闭后刷新父页面
如题 function openWin(url,text,winInfo){ var winObj = window.open(url,text,winInfo); var loop = setInt ...