Apktool反编译apk后程序中每一个类都会有一个smali文件。

一、当前类信息:smali文件的头三行描述了当前类的一些信息。

Eg:

.class <访问权限> [修饰关键字]<类名>

.super<父类名>

.source<源文件名>

根据DexClassDef结构解析获取三个字段的信息

说明:经过混淆的dex文件反编译出来的smali文件可能没有源文件,及 .source为空

二、Smali文件类的主体部分:一个类由字段和方法组成

1.字段

.field字段声明,字段分两类:

1. 静态字段,baksmali会在静态字段起始处添加“static fields”注释,以#开头。

静态字段格式:

#static fields

.field<访问权限>static[修饰关键字]<字段名>:<字段类型>

2. 实例字段,类似静态字段,没有“static”关键字

实例字段格式:

#instance fields

.field<访问权限>[修饰关键字]<字段名>:<字段类型>

Eg:

2.方法声明使用的是 .method有两种:

1. 直接方法

格式:

#direct methods

.method<访问权限>[修饰关键字]<方法原型>

<.locals>    局部变量个数

[.parameter]      指定一个参数,与参数个数一一对应

[.prologue]        指定代码的开始处,混淆过的代码可能没有

[.line]                指定该条指令在源码中的行号,混淆过的代码可能没有

<代码体>

.end method

2. 虚方法:与直接方法相同只是起始处有“virtual methods”注释

3.接口,如果类实现了接口,smali文件中会使用“.implements”

格式:

#interfaces

.implements<接口名>

接口名对应

4.注解“.annotation”,作用范围:类,方法或字段。

格式:

#annotations

.annotation[注解属性]<注解类名>

[注解字段 = 值]

.end annotation

作用范围是类,“annotation”直接定义在smali文件中,

如果是方法或字段,“annotation”定义在方法或字段中

三、Android中的类

1.内部类:Java允许类的内部定义另一个类

内部类分:成员内部类、静态嵌套类,方法内部类,匿名内部类。baksmali反编译时每个单独类都会有一个smali文件。

内部类的文件格式:

[外部类]$[内部类].smali

this$x 字段都被指定为synthetic属性,他们是被编编译器合成的、虚构的。

Eg:

对于一个非静态方法,会隐含使用p0寄存器当作类的this引用。

内部类的初始化步骤:

1. 保存外部类的引用到本类的一个所有难题hetic字段

2. 调用内部类的父类构造函数初始化父类

3. 对内部类自身初始化

Eg:

2.监听器:按钮响应事件,本质是接口

由于监听器只是临时使用,没有复用价值,所以大多采用内部类的方式实现。

分析smali文件时内部类:[外部类]$[内部类].smali文件开头的 .implements接口的实现,应该注意。另外注解器和监听器的构造函数都是编译器自动生成的,不必太关心。

3.注解类

注解包分两类:

1。dalvik.annotation:该注解不对外开放,仅供核心库与代码测试用

在libcore\dalvik\src\main\java\dalvik\annotation

2。android.annotation

在frameworks\base\core\java\android\annotation

4。自动生成的类:

R类:为资源设置ID

BuildConfig类:只有一个boolean类型的DEBUG字段标示发布的版本类型。默认true

修改为false的方法:

使用Eclipse导出项目既可

注解类:反编译后在smali\android\annotation目录下的smali文件

四、smali代码语句

1。循环语句:

常见循环语句,迭代器,for,while,do while

一般格式:

Iterator<对象><对象名>=<方法返回一个对象列表>;

for(<对象><对象名>:<对象列表>){

[处理单个对象的代码体]

}

Iterator<对象><迭代器>=<方法返回一个迭代器>;

while(<迭代器>.hasNext()){

<对象><对象名>=<迭代器>.next();

[处理单个对象的代码体]

}

迭代器特点:

1。调用hasNext()方法检测循环条件是否满足

2。调用next()方法获取单个对象

3。循环使用goto指令控制代码的流程

4。for形式的迭代器循环展开后即为while形式迭代循环

for循环代码特点:

1。循环前线初始化循环计数器变量,且值在循环体中更改

2。循环条件判断可以使条件跳转指令组成的合法语句

3。循环使用goto指令控制代码流程

switch语句,采用的是packed-switch指令

1。有规律的跳转:

packed-switch指令在Dalvik中格式:

packed-switch vAA,+BBBBBBBB

其中+BBBBBBBB被指明一个packed-switch-payload格式的偏移,它的格式:

struct packed-switch-payload{

ushort ident; // 值固定为0x100

ushort size; // case数目

int first_key; // 初始case的值

int[] target; // 每个case相对switch指令处的偏移

}

2。没有规律的跳转

packed-switch vAA,+BBBBBBBB

struct packed-switch-payload{

ushort ident; // 值固定为0x200

ushort size; // case数目

int first_key; // 初始case的值,顺序从低到高

int[] target; // 每个case相对switch指令处的偏移

}

2。try/catch语句

try语句块使用try_start_0 开头,以try_end_0 标号结束,后面跟数字,语句块后面的数值依次递增。在try_end_0下面使用 .catch指令处理异常类型与catch的标号格式:

.catch<异常类型>{<try 起始标号>...<try 结束标号>}<catch 标号>

在Dalvik指令集中,并没有Try/Catch相关指令,通过相关的数据结构来保存异常信息

try_item保存了try语句信息,DexTry声明

354struct DexTry {

355    u4  startAddr;          /* 起始地址 */

356    u2  insnCount;          /* 指令数量 */

357    u2  handlerOff;         /* handler的偏移 */

358};

使用Android SDK的dexdump工具获取dex文件的try/catch信息

命令行:dexdump [dex文件路径] > [文件名.txt]   打开生成的 文件名.txt 文件

Eg:

8 smali文件格式的更多相关文章

  1. smali语法详解

    smali文件格式 每个smali文件都由若干条语句组成,所有的语句都遵循着一套语法规则.在smali 文件的头3 行描述了当前类的一些信息,格式如下: .class < 访问权限> [  ...

  2. [Android Security] Smali和逆向分析

    copy : https://blog.csdn.net/u012573920/article/details/44034397 1.Smali简介 Smali是Dalvik的寄存器语言,它与Java ...

  3. Android 程序静态分析

    简介 静态分析是探索Android程序内幕的一种最常见的方法,它与动态调剂双剑合璧,帮助分析人员解决分析时遇到的各种“疑难”问题. 静态分析是指在不运行的情况下,采用词法分析.语法分析等各种技术手段对 ...

  4. Android 应用的逆向和审计

    Android 应用程序拆解 Android 应用程序是在开发应用程序时创建的数据和资源文件的归档文件. Android 应用程序的扩展名是.apk,意思是应用程序包,在大多数情况下包括以下文件和文件 ...

  5. 静态分析Android程序

    快速定位Android程序的关键代码 1.通过apktool反编译apk文件,得到AndroidManifest.xml文件,可以得到程序用到的组建.配置.以及主Activity 2.信息反馈法(特殊 ...

  6. Android逆向之旅---解析编译之后的Dex文件格式

    一.前言 新的一年又开始了,大家是否还记得去年年末的时候,我们还有一件事没有做,那就是解析Android中编译之后的classes.dex文件格式,我们在去年的时候已经介绍了: 如何解析编译之后的xm ...

  7. dex文件格式学习

    一.dex文件的生成 我们可以通过java文件来生成一个简单的dex文件 编译过程: 首先编写java代码如下: (1) 编译成 java class 文件 执行命令 : javac Hello.ja ...

  8. RIFF和WAVE音频文件格式

    RIFF file format RIFF全称为资源互换文件格式(Resources Interchange File Format),是Windows下大部分多媒体文件遵循的一种文件结构.RIFF文 ...

  9. JavaSe:Properties文件格式

    Properties文件格式说明 Properties继承自Hashtable,是由一组key-value的集合. 在Java中,常用properties文件作为配置文件.它的格式是什么样的呢? 下图 ...

随机推荐

  1. 每天一道Rust-LeetCode(2019-06-02)

    每天一道Rust-LeetCode(2019-06-02) Z 字形变换 坚持每天一道题,刷题学习Rust. LeetCode原题 Z 字形变换 题目描述 将一个给定字符串根据给定的行数,以从上往下. ...

  2. HDU2650 A math problem——高斯素数

    题意 给你一个数 $a+bj, \ j=\sqrt {-2}$,如果它只能被1.-1.本身和本身的相反数整除,则输出Yes,否则输出No. 分析 高斯整数 $a+bi$ 是素数当且仅当: (1)$a, ...

  3. 前端 / JavaScript 导出PDF的实践

    1.库:jspdf,自己定义一个高宽,如A4的210mm×297mm 2.让设计给背景图(包括:页眉页脚),水印图(背景透明,高宽和你的PDF单页一致)以及很多,能设计给的设计要给,因为在pdf上,排 ...

  4. Problem C. 欧皇 ————2019.10.12

    题目: 再次感激土蛋 #include <bits/stdc++.h> using namespace std; typedef long long ll; ; ll C[][]; voi ...

  5. getpeername、getsockname

    函数原型: #include<sys/socket.h> int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t ...

  6. pacemaker和keepalived的区别

    1.pacemaker Pacemaker 是一款开源的高可用资源管理软件,适合大集群或者小集群. Pacemaker 由Novell支持,SLES HAE就是用Pacemaker来管理集群,并且Pa ...

  7. V8 引擎如何进行垃圾内存的回收?

    JS 语言不像 C/C++, 让程序员自己去开辟或者释放内存,而是类似Java,采用自己的一套垃圾回收算法进行自动的内存管理.作为一名资深的前端工程师,对于JS内存回收的机制是需要非常清楚, 以便于在 ...

  8. Go:为何带来泛型

    中文版 English version 介绍 [这是在Gophercon 2019上发表的演讲版本.视频链接可供使用.] 这篇文章是关于向Go添加泛型的意义,以及为什么我认为我们应该这样做.我还将介绍 ...

  9. Java一个对象占用多少字节

    虚拟机:Java HotSpot(TM) 64-Bit Server VM (25.221-b11, mixed mode) 对象的内存以字节为单位,且必须是8的倍数,它的构成由3部分组成:对象头+实 ...

  10. rpc通讯

    dotnet core各rpc组件的性能测试 一般rpc通讯组件都具有高性特性,因为大部分rpc都是基于二进制和连接复用的特点,相对于HTTP(2.0以下的版本)来说有着很大的性能优势,非常适合服务间 ...