Android逆向之smali语言

一、Android应用程序架构

安卓应用程序使用JAVA语言编写。安卓的SDK工具负责将你编写的代码,用到的数据和资源文件编译进APK文件中。apk文件包含了一个安卓应用程序的所有内容,并且被安卓设备用来安装应用程序。
apk实际上就是一个标准的zip格式,修改后缀名,进行解压就可以看到内部结构。

如上图所示,每个文件夹都有各自不同的作用。

assets文件夹

保存一些额外的资源文件,如游戏的声音文件,字体文件等等,在代码中可以用AssetManager获取assets文件夹的资源。

lib文件夹

存放用C/C++编写的,用NDK编译生成的so文件,供java端调用。

META-INF文件夹

存放apk签名信息,用来保证apk包的完整性和系统安全。
在IDE编译生成一个apk包时,会对里面所有的文件做一个校验计算,并把计算结果存放在META-INF文件夹内,apk在安装的时候,系统会按照同样的算法对apk包里面的文件做校验,如果结果与META-INF里面的值不一样,系统就不会安装这个apk,这就保证了apk包里的文件不能被随意替换。

res文件夹

存放资源文件,包括icon,xml文件。

AndroidManifest.xml文件

应用程序配置文件,每个应用都必须定义和包含的,它描述了应用的名字、版本、权限、引用的库文件等信息。

classes.dex文件

传统Class文件是由一个Java源码文件生成的.Class文件,而Android是把所有Class文件进行合并优化,然后生成一个最终的class.dex文件。它包含APK的可执行代码,是分析Android软件时最常见的目标。

resources.arsc文件

二进制资源文件,包括字符串等。

二、何为smali语言?

smali是将Android字节码用可阅读的字符串形式表现出来的一种语言,可以称之为Android字节码的反汇编语言。
利用apktool或者Android Killer工具,反编classes.dex文件,就可以得到以smali为后缀的文件。
通过对smali文件的解读可以获取源码的信息。

三、如何将Java文件转换成smali文件?

打开idea,依次点击菜单栏上的File->Settings->Plugins->Marketplace,下载java2smali插件。下载好后重启idea。
新建一个class文件,简单写一个demo类。
鼠标放到demo类中,依次点击菜单栏上的Build->Compile to Smali,则会自动生成一个.smali文件。

四、如何看懂smali代码?

用Java简单写了一个demo类,Demo.class文件

package com.crawler;

public class Demo {

public static void main(String[] args) {
    Demo demo = new Demo();
    Integer calc = demo.calc(1);
    System.out.println(calc);
}

private Integer calc(Integer i){
    ++i;
    return i;
}

}

自动转换生成的Demo.smali文件

.class public Lcom/crawler/Demo;
.super Ljava/lang/Object;
.source “Demo.java”

direct methods

.method public constructor ()V
.registers 1

.prologue
.line 3
invoke-direct {p0}, Ljava/lang/Object;->()V

return-void

.end method

.method private calc(Ljava/lang/Integer;)Ljava/lang/Integer;
.registers 3
.param p1, “i” # Ljava/lang/Integer;

.prologue
.line 12
invoke-virtual {p1}, Ljava/lang/Integer;->intValue()I

move-result v0

add-int/lit8 v0, v0, 0x1

invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

move-result-object p1

.line 13
return-object p1

.end method

.method public static main([Ljava/lang/String;)V
.registers 4
.param p0, “args” # [Ljava/lang/String;

.prologue
.line 6
new-instance v1, Lcom/crawler/Demo;

invoke-direct {v1}, Lcom/crawler/Demo;->()V

.line 7
.local v1, "demo":Lcom/crawler/Demo;
const/4 v2, 0x1

invoke-static {v2}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

move-result-object v2

invoke-direct {v1, v2}, Lcom/crawler/Demo;->calc(Ljava/lang/Integer;)Ljava/lang/Integer;

move-result-object v0

.line 8
.local v0, "calc":Ljava/lang/Integer;
sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;

invoke-virtual {v2, v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V

.line 9
return-void

.end method

smali语言基础语法

示例1: .class关键字
.class public Lcom/crawler/Demo;

这是一个公开类,在com.crawler包下的Demo类。
L 表示类

示例2: .super关键字
.super Ljava/lang/Object;

父类是Object,所有的类都继承Object类。

示例3: .source关键字
.source “Demo.java”

当前类的源文件名。

示例4: .method关键字和.end method关键字
# direct methods
.method public constructor ()V
.registers 1

    .prologue
    .line 3
    invoke-direct {p0}, Ljava/lang/Object;->()V

    return-void
.end method

这是一个构造方法。
每个类都会有一个构造方法,虽然在java中省略了。
public Demo(){
super();
}

.method开始,.end method结束。
V 表示void。
invoke-direct 表示调用方法。其后{}表示传入的参数。
p0 在构造方法中表示this,指一个对象。

示例5: .registers关键字
.registers 1

表示寄存器有1个

示例6: .registers关键字
.prologue

代表函数的开始位置,其上为类似.registers的关键字,其下为函数逻辑。

示例7: .line N关键字
.line 3

代表还原成java代码在源文件第3行

作者:爬虫入坑记
链接:https://juejin.cn/post/7117281589721038879
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(测试,安全,安全)