没啥好说的,先扫一下盲
asset文件夹:
资源目录1:asset和res都是资源目录但有所区别,见下面说明
lib文件夹: so库存放位置,一般由NDK编译得到,常见于使用游戏引擎或JNI native调用的工程中
res文件夹 :资源目录2:asset和res都是资源目录但有所区别,见下面说明
classes.dex :Java代码编译得到的Dalvik VM能直接执行的文件,下面有介绍
res目录下的资源文件在编译时会自动生成索引文件(R.java),在Java代码中用R.xxx.yyy来引用;
而asset目录下的资源文件不需要生成索引,在Java代码中需要用AssetManager来访问;
一般来说,除了音频和视频资源(需要放在raw或asset下),使用Java开发的Android工程使用到的资源文件都会放在res下;使用C++游戏引擎(或使用Lua Unity3D等)的资源文件均需要放在asset下。
Dalvik字节码是什么?
Dalvik字节码是学习破解的基础,对它我们需要了解一下
Dalvik是google专门为Android操作系统设计的一个虚拟机,经过深度的优化。虽然Android上的程序是使用java来开发的,但是Dalvik和标准的java虚拟机JVM还是两回事。Dalvik VM是基于寄存器的,而JVM是基于栈的;Dalvik有专属的文件执行格式dex(dalvik executable),而JVM则执行的是java字节码。Dalvik VM比JVM速度更快,占用空间更少。
通过Dalvik的字节码我们不能直接看到原来的逻辑代码,这时需要借助如Apktool或dex2jar+jd-gui工具来帮助查看。但是,注意的是最终我们修改APK需要操作的文件是.smali文件,而不是导出来的Java文件重新编译。
什么是Smali?
Smali,Baksmali分别是指安卓系统里的Java虚拟机(Dalvik)所使用的一种。dex格式文件的汇编器,反汇编器。其语法是一种宽松式的Jasmin/dedexer语法,而且它实现了.dex格式所有功能(注解,调试信息,线路信息等)
当我们对APK文件进行反编译后,便会生成此类的文件,小编在此对smali文件进行简要的介绍。其中在Davlik字节码中,寄存器都是32位的,能够支持任何类型,64位类型(Long/Double)用2个寄存器表示;Dalvik字节码有两种类型:原始类型;引用类型(包括对象和数组)
原始类型
B—byte
C—char
D—double
F—float
I—int
J—long
S—short
V—void
Z—boolean
[XXX—array
Lxxx/yyy—object
这里解析下最后两项,数组的表示方式是:在基本类型前加上前中括号“[”,例如int数组和float数组分别表示为:[I、[F;对象的表示则以L作为开头,格式是LpackageName/objectName;(注意必须有个分号跟在最后),例如String对象在smali中为:Ljava/lang/String;,其中java/lang对应java.lang包,String就是定义在该包中的一个对象。
或许有人问,既然类是用LpackageName/objectName;来表示,那类里面的内部类又如何在smali中引用呢?答案是:LpackageName/objectName$$subObjectName;。也就是在内部类前加“$”符号,关于“$”符号更多的规则将在后面谈到。
方法的定义一般为: Func-Name (Para-Type1Para-Type2Para-Type3…)Return-Type 注意参数与参数之间没有任何分隔符,同样举几个例子就容易明白了: 1. hello ()V 没错,这就是void hello()。 2. hello (III)Z 这个则是boolean hello(int, int, int)。 3. hello (Z[I[ILjava/lang/String;J)Ljava/lang/String; 看出来这是String hello (boolean, int[], int[], String, long) 了吗?
Smali基本语法
.field private isFlag:z 定义变量
.method 方法
.parameter 方法参数
.prologue 方法开始
.line 123 此方法位于第123行
invoke-super 调用父函数
const/high16 v0, 0x7fo3 把0x7fo3赋值给v0
invoke-direct 调用函数
return-void 函数返回void
.end method 函数结束
new-instance 创建实例
iput-object 对象赋值
iget-object 调用对象
invoke-static 调用静态函数
条件跳转分支:
“if-eq vA, vB, :cond_xx” 如果vA等于vB则跳转到:cond_xx
“if-ne vA, vB, :cond_xx” 如果vA不等于vB则跳转到:cond_xx
“if-lt vA, vB, :cond_xx” 如果vA小于vB则跳转到:cond_xx
“if-ge vA, vB, :cond_xx” 如果vA大于等于vB则跳转到:cond_xx
“if-gt vA, vB, :cond_xx” 如果vA大于vB则跳转到:cond_xx
“if-le vA, vB, :cond_xx” 如果vA小于等于vB则跳转到:cond_xx
“if-eqz vA, :cond_xx” 如果vA等于0则跳转到:cond_xx
“if-nez vA, :cond_xx” 如果vA不等于0则跳转到:cond_xx
“if-ltz vA, :cond_xx” 如果vA小于0则跳转到:cond_xx
“if-gez vA, :cond_xx” 如果vA大于等于0则跳转到:cond_xx
“if-gtz vA, :cond_xx” 如果vA大于0则跳转到:cond_xx
“if-lez vA, :cond_xx” 如果vA小于等于0则跳转到:cond_xx