安卓恶意代码逆向基础知识
一 Android采用分层的架构,分为四层,从高层到底层分为
1. Linux核心层
linux内核(Linux Kernel)
Android平台的基础,直接和硬件打交道。硬件驱动、进程管理、内存管理、网络管理的功能在这里实现。
硬件抽象层(Hardware Abstraction Layer)
为上层的Java API Framework提供相关硬件的界面显示,Audio,Bluetooth等是组成硬件抽象层的库模块,实现每个硬件的界面显示功能。
2. 系统运行库和运行环境层
Android 运行环境(Android Runtime)
ART是Android操作系统的运行环境,通过运行虚拟机来执行dex文件。其中,dex文件是专为安卓设计的的字节码格式,好处多多,不再赘述。Android toolchain(一种编译工具)可以将Java代码编译为dex字节码格式,过程如下图,jack是一种编译工具链(tool chain)
原生C/C++ 库(Native c/c++ Libraries)
上面提到的ART就依赖于C/C++库。开发者可以通过调用Java API Framework来使用原生库的功能,也可以用Android NDK直接调用原生库。
3. 应用程序框架层
java API Framework
我们最常用的组件和服务都在这一层,也是每一个安卓开发者必须要熟悉的一层
4. Application层
系统应用(system apps)
可以理解为内置在Android系统的app,我们可以像调用Java API Framework层一样直接调用系统app。
二 Android四大组件
android四大组件分别是:Activity, service,content provider,broadcast receiver
1. Activity
前台界面, 直接面向User, 提供UI和操作.
android 中,Activity 相当于一个页面,可以在Activity中添加Button、CheckBox 等控件,一个android 程序有多个Activity组成。
activity有四种状态:
Runing :一个新 Activity 启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。
2. Service
后台任务.
一个Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。
比较好的一个例子就是一个正在从播放列表中播放歌曲的媒体播放器。在一个媒体播放器的应用中,应该会有多个activity,让使用者可以选择歌曲并播放歌曲。然而,音乐重放这个功能并没有对应的activity,因为使用者当然会认为在导航到其它屏幕时音乐应该还在播放的。在这个例子中,媒体播放器这个activity 会使用Context.startService()来启动一个service,从而可以在后台保持音乐的播放。同时,系统也将保持这个service 一直执行,直到这个service 运行结束。另外,我们还可以通过使用Context.bindService()方法,连接到一个service 上(如果这个service 还没有运行将启动它)。当连接到一个service 之后,我们还可以service 提供的接口与它进行通讯。拿媒体播放器这个例子来说,我们还可以进行暂停、重播等操作。
3. Content Provider 内容提供器
数据提供者.
4. Broadcast Receiver
广播接收者.
三 Android命名规范
1 包名
采用反域名命名规则,全部使用小写字母。一级包名为com,二级包名为xx(可以是公司或则个人的随便),三级包名根据应用进行命名,四级包名为模块名或层级名
例如:com.公司名称简写.项目名称简写.模块名
2 类名
采用大驼峰命名法,尽量避免缩写,除非该缩写是众所周知的
例如:LoginActivity
3 接口
命名规则与类一样采用大驼峰命名法,多以able或ible结尾
例如:interface Runna ble;interface Accessible。
4 方法
动词或动名词,采用小驼峰命名法
例如:onCreate(),run()
5 变量
采用小驼峰命名法。类中控件名称必须与xml布局id保持一致
用统一的量词通过在结尾处放置一个量词,就可创建更加统一的变量,它们更容易理解,也更容易搜索。例如,请使用strCustomerFirst和strCustomerLast,而不要使用strFirstCustomer和strLastCustomer。
6 常量
全部大写,采用下划线命名法
例如:MIN_WIDTH,MAX_HEIGHT
四 安卓方法
1 onCreate()
onCreate函数是在activity初始化时调用,在onCreate()中调用setContentView(int)函数填充屏幕的UI,一般通过findViewById(int)返回xml中定义的视图或组件的ID。子类在重写onCreate()方法的时候必须调用父类的onCreate()方法,即super.onCreate(),否则会抛出异常。
一个activity启动调用的第一个函数就是onCreate,它主要做这个activity启动时一些必要的初始化工作,这个函数调用完后,这个activity并不是说就已经启动了,或者是跳到前台了。而是还需要其他的大量工作,
我们知道:onCreate之后还有onRestart()和onStart()等,实际上onStart()调用完毕了这个activity还没有完全启动,也只是前台可见,直到 onResume() 调用后这个onCreate才算终于启动。
2 onStart()
3 onResume()
五 安卓启动流程
- bootloader启动内核和init进程.
- init进程分裂出更多名为”daemons(守护进程)”的底层的Linux进程, 诸如android debug deamon, USB deamon等. 这些守护进程处理底层硬件相关的接口.
-
init进程会启动一个非常有意思的进程—“Zygote”. 顾名思义, 这是一个Android平台的非常基础的进程. 这个进程初始化了第一个VM, 并且预加载了framework和众多App所需要的通用资源.
-
开启一个Socket接口来监听请求, 根据请求孵化出新的VM来管理新的App进程.
- 一旦收到新的请求, Zygote会基于自身预先加载的VM来孵化出一个新的VM创建一个新的进程.
-
启动Zygote之后, init进程会启动runtime进程.
-
Zygote会孵化出一个超级管理进程—System Server.
-
SystemServer会启动所有系统核心服务, 例如Activity Manager Service, 硬件相关的Service等.
-
到此, 系统准备好启动它的第一个App进程—Home进程了.
六 APP启动流程
用户点击Home上的一个App图标, 启动一个应用时:
Click事件会调用startActivity(Intent), 会通过Binder IPC机制, 最终调用到ActivityManagerService.
该Service会执行如下操作:
- 第一步通过PackageManager的resolveIntent()收集这个intent对象的指向信息.
- 指向信息被存储在一个intent对象中.
- 下面重要的一步是通过grantUriPermissionLocked()方法来验证用户是否有足够的权限去调用该intent对象指向的Activity.
- 如果有权限, ActivityManagerService会检查并在新的task中启动目标activity.
- 现在, 是时候检查这个进程的ProcessRecord是否存在了.
如果ProcessRecord是null, ActivityManagerService会创建新的进程来实例化目标activity.
6.1 创建进程
ActivityManagerService调用startProcessLocked()方法来创建新的进程, 该方法会通过前面讲到的socket通道传递参数给Zygote进程. Zygote孵化自身, 并调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid.
6.2 绑定Application
6.3 启动Activity
经过前两个步骤之后, 系统已经拥有了该application的进程. 后面的调用顺序就是普通的从一个已经存在的进程中启动一个新进程的activity了.
实际调用方法是realStartActivity(), 它会调用application线程对象中的sheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到消息队列中, 通过 handleLaunchActivity()来处理该消息.
假设点击的是一个视频浏览的App, 其流程如下: