Android软件安全与逆向分析-笔记(1)

1.破解android程序通常使用的方法是将apk文件利用ApkTool反编译,生成Smali格式的反汇编代码,在实际的分析过程中,还可以使用IDAhoPro直接分析apk文件,或者dex2jar与jd-gui配合来进行java源代码级的分析.

2.Smali,Baksmali分别是指安卓系统里是java虚拟机(Dalvik)所使用的一种.dex格式文件的汇编器,反汇编器。

3.使用Apktool反编译apk文件后,所有的索引值保存在string.xml文件同目录下的public.xml文件中。编译生成的apk没有签名,还不能安装测试,接下来还需要使用signapk.jar工具对apk文件进行签名。使用signapk.jar签名时需要提供签名文件,可以使用android源码中提供的签名文件testkey.pk8与testkey.x509.pem.

4.Dalvik虚拟机运行的是Dalvik字节码,所有的Dalvik字节码由java字节码转换而来,并打包到一个DEX(Dalvik Executable)可执行文件中,Dalvik虚拟机通过解释DEX文件来执行这些字节码。

5.Android SDK中有一个叫dx的工具负责将java字节码转换为Dalvik字节码。dx工具将Java类文件重新排列,消除在类文件中出现的所有冗余信息,避免虚拟机在初始化时出现重复的文件加载与解析过程。dx工具它将所有的java类文件中的常量池进行分解,消除其中的冗余信息,重新组合形成一个常量池。所有的类文件共享同一个常量池。

6.java虚拟机基于栈架构。程序在运行时虚拟机需要频繁的从栈上读取或写入数据。而Dalvik虚拟机基于寄存器架构。数据的访问通过寄存器间直接传递,这样的访问方式比基于栈的方式要快很多。使用Android SDK中的dexdump.exe查看Dalvik字节码。

7.iload_1可以分成两个部分:第一部分为下划线左边的iload,它属于JVM指令集中load系列的一条,i是指令前缀,表示操作类型为int类型,load表示将局部变量存入java栈。第二部分为下划线右边的数字,表示要操作具体哪个局部变量,索引值从0开始计数,iload_1表示将第二个int类型的局部变量进栈。

8.Dalvik虚拟机运行时同样为每一个线程维护一个PC计数器与调用栈,这个调用栈维护一份寄存器列表,寄存器的数量在方法结构体的

registers字段中给出,Dalvik虚拟机会根据这个值来创建一份虚拟的寄存器列表。基于寄存器架构的Dalvik虚拟机与基于栈架构的java虚拟机相比,生成的代码指令减少了,程序执行速度会更快一些。

9.Android系统的架构采用分层的思想,这样的好处是拥有减少各层之间的依赖性、便于独立分发、容易收敛问题和错误等优点。Android

系统由Linux内核、函数库、Android运行时、应用程序框架以及应用程序组成。Android系统启动加载完内核后,第一个执行的是init进

程,init进程首先要做的是设备的初始化工作,然后读取init.rc文件并启动系统中的重要外部程序Zygote。Zygote进程是Android所有进

程的孵化器进程,它启动后首先初始化Dalvik虚拟机,然后启动system_server并进入Zygote模式通过socket等候命令。当执行一个Android应用程序时,system_server进程通过socket方式发送命令给Zygote,Zygote收到命令后通过fork自身创建一个Dalvik虚拟机的实例来执行应用程序的入口程序,这样一个程序就启动完成了。

10.JIT(just-in-time Compilation,即时编译),又叫动态编译,是一种通过在运行时将字节码翻译为机器码的技术,使得程序的执行速度更快。

Dalvik虚拟机默认采用trace方式编译代码,同时也支持采用method方式来编译。

11.目前DEX可执行文件主流的反汇编工具有BakSmali与Dedexer。ARM架构,过去称作进阶精简指令集机器,是一个32位精简指令集(RISC)处理器架构,其广泛地使用在许多嵌入式系统中。fp为ARM栈帧寄存器,在虚拟机运行到某个函数时它指向函数的局部变量,其中就维护着一份寄存器值的列表。

12.Dalvik虚拟机参数传递方式为,参数使用最后的N个寄存器中,局部变量使用从v0开始的前M-N个寄存器。Dalvik字节码类型描述符有:V,Z(boole),B,S,C,I,J(long),F,D,L(java类类型),[(数组类型)。L与[可以同时使用来表示对象数组。

13.字段与方法很相似,只是字段没有方法签名域中的参数与返回值,取而代之的是字段的类型。nop指令被用来作对齐代码之用,无实际操作。move-result vAA:将上一个invoke类型指令操作的双字非对象结果赋给vAA寄存器。const/4 vA,#+B:将数值符号扩展为32位后赋值给寄存器vA."monitor-enter vAA":为指定的对象获取锁。"monitor-exit vAA":释放指定的对象锁。

14."check-cast VAA,type@BBBB":将VAA寄存器中的对象引用转换成指定的类型。"instance-of vA,VB,type@CCCC",判断vB寄存器中的对象引用是否可以转换成指定的类型,如果可以vA寄存器赋值为1,否则不0;

15."array-length vA,vB"获取给定vB寄存器中数组的长度并将值赋给vA寄存器。"filled-new-array{vC,vD,vE,vF,vG},type@BBBB"构造指定类型(type@BBBB)与大小(vA)的数组并填充数组内容。vA寄存器是隐含使用的。"packed-switch vAA,+BBBBBBBB"分支跳转指令。vAA寄存器为switch分支中需要判断的值,BBBBBBBB指向一个packed-switch-payload格式的偏移表,表中的值是有规律递增的。"if-test vA,vB,+CCCC"条件跳转指令。比较vA寄存器与vB寄存器的值,如果比较结果满足就跳转到CCCC指定的偏移处。

16."cmpkind vAA,vBB,vCC",比较指令用于对两个寄存器的值进行比较,比较结果放入vAA寄存器中。方法调用指令负责调用类实例的方法。它的基础指令为invoke."neg-int"对整型数求补。"ushr-type"vBB寄存器值(无符号数)右移vCC位(vBB>>vCC).

17.dex文件使用到的数据类型,u1等同于uint8_t,u8等同于uint64_t,sleb128 有符号LEB!28,可变长度1~5字节,uleb128pl无符号LEB128值加1,可变长度1~5字节。LEB128由1~5个字节组成,所有的字节组合在一起表示一个32位的数据。

你可能感兴趣的:(Android软件安全与逆向分析-笔记(1))