1.APK文件
apk=android Application PacKage=APK
apk文件是什么:是安卓app的安装文件
本质:(apk文件其实就是个)zip压缩包
意味着
可以用解压缩工具把apk当做zip文件一样去解压
解压后,得到一堆安卓相关文件
可以在apktool等工具破解和修改了安卓文件后,再重新用压缩文件工具或apktool等工具,重新打包为apk文件
2.apk内容结构
3.什么是dex文件
简答:
dex = Dalvik EXecutable format=dex文件=dex格式
dex之于Android,类似于class之于Java
注:java的class文件内部是Java的字节码(Java bytecode)
dex=Dalvik EXecutable
相关:dex文件=dex字节码
dex反汇编后是:Smali代码
即:Android(虚拟机中的dex文件)反汇编(后的)代码:Smali
详解:
安卓系统中,用Dalvik/ART虚拟机(DVM=Dalvik Virtual Machine)去把java源码编译为dex可执行文件(Dalvik Executable)。
而dex文件中保存的就是:编译后了的安卓程序代码文件
4.安卓虚拟机
1.历史背景
Android
代码语言:Java
Java的虚拟机是:JVM
Android:出于性能考虑,没用JVM,用了自己的虚拟机VM
安卓虚拟机=Android虚拟机=Android VM
旧:Android < 5.0:Dalvik
Dalvik VM=DVM
概述
Dalvik是google专门为Android操作系统设计的一个虚拟机,经过深度的优化。虽然Android上的程序是使用java来
开发的,但是Dalvik和标准的java虚拟机JVM还是两回事
新:Android >= 5.0:ART
ART=Android RunTime
ART的特点:
预先编译AOT
垃圾回收方面的优化
开发和调试方面的优化
支持采样分析器
支持更多调试功能
优化了异常和崩溃报告中的诊断详细信息
5.smali 语法
Smali
1.是什么:⼀种 汇编语法 / 汇编⽂件
⼀种语法: Smali语法
来源:是 Dalvik 的 VM 的字节码,即 dex ⽂件中的 bytecode = ⼆进制数据 ,反汇编后得到的:Smali代码
语法:⼀种宽松式的Jasmin/dedexer语法
它实现了 .dex 格式所有功能(注解,调试信息,线路信息等)
对应⽂件叫: Smali⽂件
2.举例
java源码:int x = 42
Dalvik编译后的,dex中二进制数据=bytecode=字节码:13 00 2A 00二进制,人类很难读懂
用工具反汇编后的,smali代码:const/16 v0, 42 smali代码,人类基本可读
3.学习Smali的用途
分析Apk:静态分析
需要动态分析,涉及Smali
修改APK逻辑:修改smali 代码,重新编译打包APK
Android逆向基础:掌握Smail
能阅读 smali 代码对进行 android 逆向十分重要
4.Smali基本语法
5.1数据类型 Types
5.2寄存器
Java中变量都是存放在内存中的
Android为了提高性能,变量都是存放在寄存器中的
寄存器为32位,可以支持任何类型
寄存器
类型
本地寄存器
用v开头数字结尾的符号来表示:v0, v1, v2
参数寄存器
用p开头数字结尾的符号来表示:p0,p1,p2
注意
在非static方法中,p0代指this,p1为方法的第一个参数
在static方法中,p0为方法的第一个参数
说明
指定有多少寄存器是可用
.registers:指定了方法中寄存器的总数
.locals: 表明了方法中非参寄存器的总数,出现在方法中的第一行
5.3 Smali代码示例
const/4 v0, 0x1 //把值0x1存到v0本地寄存器
iput-boolean v0,p0,Lcom/aaa;->IsRegisterd:Z //把v0中的值赋给com.aaa.IsRegistered,p0代表this,相当于this.Isregistered=true
5.3.1
成员变量
格式
.field public/private [static][final] varName:<类型>
指令
获取指令
iget, sget, iget-boolean, sget-boolean, iget-object, sget-object
操作指令
iput, sput, iput-boolean, sput-boolean, iput-object, sput-object
array的操作是aget和aput
Smali代码示例
sget-object v0,Lcom/aaa;->ID:Ljava/lang/String;
获取ID这个String类型的成员变量并放到v0这个寄存器中
iget-object v0,p0,Lcom/aaa;->view:Lcom/aaa/view;
iget-object比sget-object多一个参数p0,这个参数代表变量所在类的实例。这里p0就是this
const/4 v3, 0x0
sput-object v3, Lcom/aaa;->timer:Lcom/aaa/timer;
相当于JAVA代码
this.timer = null;
.local v0, args:Landroid/os/Message;
const/4 v1, 0x12
iput v1,v0,Landroid/os/Message;->what:I
相当于java代码
args.what = 18;
其中args为Message的实例
方法/函数 Methods
函数定义格式
.method public/private [static][final] methodName()<类型>
.end method
函数类型
direct method= private方法
virtual method = 其余的方法
函数调用
格式
invoke-指令类型 {参数1, 参数2,...}, L类名;->方法名
包含
invoke-direct
invoke-virtual
invoke-static
invoke-super
invoke-interface
smali代码示例
.method private ifRegistered()Z
.locals 2 // 本地寄存器的个数
.prologue
const/4 v0, 0x1 //v0赋值为1
if-eqz v0, :cond_0 //判断v0是否等于0,等于0则跳到cond_0执行
const/4 v1, 0x1 //符合条件分支
:goto_0 //标签
return v1 //返回v1的值
:cond_0 //标签
const/4 v1, 0x0 //cond_0分支
goto :goto_0 //跳到goto_0执行
.end method
const-string v0, "NDKLIB"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
相当于java代码
System.loadLibrary("NDKLIB")
const-string v0, "Eric"
invoke-static {v0}, Lcmb/pbi;->t(Ljava/lang/String;)Ljava/lang/String;
move-result-object v2
表示将方法t返回的String对象保存到v2中
作业:解释下每行语句 可以百度查询
视频教程:点我跳转