【前言】
Android手机开机后-->启动Zygoye进程-->创建SystemServer进程
1.Zygoye进程孵化器:Android中的所有进程,如 系统进程、应用进程、SystemServer进程,都是由Zygoye调用fork方法创建的
2.SysremServer进程:就是核心服务所在进程,核心服务如 WindowsManagerServer、PowerManagerService、ActivityManagerService等系统服务
3.ActivityManagerService服务:简称AMS,该服务由SystemServer启动,主要功能是控制四大组件启动和调度工作,控制应用程序的管理和调度工作
【应用程序启动】
Launcher应用(系统主界面)-->最终获得ActivityManagerService-->ActivityManagerService.start()方法-->判断要启动的应用是否存在-->存在则直接切换到前台-->不存在则调用Process类,通过Process类调用Zygoye的fork方法创建进程-->调用ActivityThread的main函数
handleLaunchActivity(r, null)-->performLaunchActivity(r, customIntent)--> mInstrumentation.callActivityOnCreate(activity, r.state)-->activity.performCreate(icicle)-->onCreate(icicle)
注意,此时调用到的onCreate方法就是我们平常写Android代码时候的Activity的onCreate方法
handleBindApplication(data)-->data.info.makeApplication(data.restrictedBackupMode, null)-->mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext)--> app.attach(context)-->attachBaseContext(context)
handleBindApplication(data)-->mInstrumentation.callApplicationOnCreate(app)--> app.onCreate()
可以分析到Application最终是分别调用了两个方法attachBaseContext和onCreate,此处的onCreate和Activity的onCreate是两码事
综上分析可以得出,在真正调用到Activity的onCreate方法之前,还会经过两个关键的函数,就是Application的attachBaseContext和onCreate方法
【可以做什么?】
可以在Application调用的函数中进行真正的dex代码的加载替换。达到加壳的目的,因为在调用Activity之前回调用Application的两个函数,所以在此期间将真正程序的代码给替换进来即可。
【前言】
了解Android的ClassLoader的继承关系
【文件目录】libcore
【类名】DexClassLoader
【构造方法】public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)
【父类构造】super(dexPath, new File(optimizedDirectory), libraryPath, parent);
继承自父类BaseDexClassLoader(pathClassLoader也是继承自此父类)
父类构造方法
【文件目录】libcore
【类名】BaseDexClassLoader
【构造方法】public BaseDexClassLoader(String dexPath, File optimizedDirectory, String libraryPath, ClassLoader parent)
【父类构造】super(parent);
【文件目录】libcore
【类名】ClassLoader
【构造方法】protected ClassLoader(ClassLoader parentLoader)
【初始化】ClassLoader(ClassLoader parentLoader, boolean nullAllowed){ parent = parentLoader;}
【构造方法初始化】this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
【类成员】private final DexPathList pathList;
【文件目录】libcore
【类名】DexPathList
【构造方法】public DexPathList(ClassLoader definingContext, String dexPath, String libraryPath, File optimizedDirectory)
【成员变量】private final Element[] dexElements;
5.1 对类加载器、dex文件路径、文件优化路径等参数基本判断
5.2 调用方法makeDexElements 对成员变量赋值dexElements
【方法原型】private static Element[] makeDexElements(ArrayList<File> files, File optimizedDirectory
6.1 判断文件名后缀
6.2 loadDexFile加载dex后缀的文件
6.3 根据加载进来的dex文件new Element对象,并且赋值到成员变量中
6.4 返回局部变量Element对象数组
【方法原型】private static DexFile loadDexFile(File file, File optimizedDirectory)
7.1 如果不存在优化后的dex文件,则直接创建DexFile类对象
7.2 如果存在优化后的dex文件,则调用DexFile类的loadDex方法加载dex文件
7.3 这里对于优化后的文件,以及dex如何被优化的,在稍后有专门描述该内容
【文件目录】libcore
【类名】DexFile
【构造方法】public DexFile(String fileName) throws IOException
【成员变量】private int mCookie;
8.1 调用方法openDexFile获取Cookie值
【参数说明】:参数1:dex路径名;参数2:优化文件路径名
【函数说明】:调用openDexFileNative方法进入c++代码,并且返回cookie值
【文件目录】dalvik
【文件名】dalvik_system_DexFile
【方法】static void Dalvik_dalvik_system_DexFile_openDexFileNative(const u4 args, JValue pResult)
10.1 java层进入native层,获得参数,并且转换为c的类型格式
10.2 dvmClassPathContains判断dex文件路径是否当前类加载器加载或者存在的
10.3 hasDexExtension如果以dex结尾返回true
10.4 dvmRawDexFileOpen打开没有被优化的dex文件
10.5 pDexorJar 管理dex文件内部结构
【如果类路径包含特定路径返回true】
【如果name以dex结尾,返回true】
【文件目录】vm/dalvik
【文件名】RawDexFile.cpp
【方法】int dvmRawDexFileOpen(const char fileName, const char odexOutputName, RawDexFile** ppRawDexFile, bool isBootstrap)
11.1 dvmOptimizeDexFile生成优化版的dex文件
【文件目录】vm/dalvik
【文件名】DexPrepare.cpp
【方法】bool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength, const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
13.1 包括Dex文件缓冲区和长度
14.1 加载Dex的过程中,加载一个dex文件并赋值DexPathList的字段Element[] dexElements
14.2 创建一次Dex对象,打开dex文件时回赋值mCookie值
14.3 进入native层会对dex文件进行优化
3.1 GenerateOatFileNoChecks
3.2 Dex2Oat
3.3 Exec
3.4 ExecAndReturnCode
4.1 Dex2oat()
4.2 Setup()
【OpenDexFilesFromOat函数中】
【脱壳点】OpenAndReadMagic、DexFile::OpenFile
6.1 DexFile::OpenFile
6.2 OpenCommon
【特点】:仅加载DEX文件,并不会对文件进行优化生成oat文件
【文件目录】libore
【父类】BaseDexClassLoader
【父类】ClassLoader
2.1父类构造函数,设置父类变量parent
2.2创建DexPathList对象
【构造函数】public DexPathList(ClassLoader definingContext, ByteBuffer[] dexFiles)
【3.1】makInMemoryDexElements
返回值:Element数组(dex文件信息数组)
dexFiles:dex缓冲区数组
创建DexFile文件对象并根据DexFile对象创建Element对象
【构造方法】:DexFile(ByteBuffer buf) throws IOException
【4.1】openInMemoryDexFile
调用native层方法进入c++
【文件目录】/art/runtime/native/dalvik_system_DexFile.cc
【5.1】DexFile_createCookieWithDirectBuffer
【5.2】DexFile_createCookieWithArray
【5.3】 CreateSingleDexFileCookie
创建DexFile实例对象和ConvertDexFilesToJavaArray
【5.4】CreateDexFile
DexFile::Open和dex_file.release()
【5.5】/art/runtime/dex_file.cc/DexFile::Open
【5.6】DexFile::OpenCommon
【5.7】DexFile构造函数
【5.8】InitializeSectionsFromMapList
判断比较Dex文件格式是否有误
ActivityThread类
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
Process.setArgV0(
"<pre-initialized>"
);
Looper.prepareMainLooper();
ActivityThread thread
=
new ActivityThread();
/
/
创建ActivityThread对象
thread.attach(false);
if
(sMainThreadHandler
=
=
null) {
sMainThreadHandler
=
thread.getHandler();
}
AsyncTask.init();
if
(false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG,
"ActivityThread"
));
}
Looper.loop();
/
/
启动Looper.loop无限循环处理消息
throw new RuntimeException(
"Main thread loop unexpectedly exited"
);
}
}
ActivityThread类
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
Process.setArgV0(
"<pre-initialized>"
);
Looper.prepareMainLooper();
ActivityThread thread
=
new ActivityThread();
/
/
创建ActivityThread对象
thread.attach(false);
if
(sMainThreadHandler
=
=
null) {
sMainThreadHandler
=
thread.getHandler();
}
AsyncTask.init();
if
(false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG,
"ActivityThread"
));
}
Looper.loop();
/
/
启动Looper.loop无限循环处理消息
throw new RuntimeException(
"Main thread loop unexpectedly exited"
);
}
}
Looper类
public static void loop() {
final Looper me
=
myLooper();
if
(me
=
=
null) {
throw new RuntimeException(
"No Looper; Looper.prepare() wasn't called on this thread."
);
}
final MessageQueue queue
=
me.mQueue;
Binder.clearCallingIdentity();
final
long
ident
=
Binder.clearCallingIdentity();
for
(;;) {
Message msg
=
queue.
next
();
/
/
might block
if
(msg
=
=
null) {
return
;
}
Printer logging
=
me.mLogging;
if
(logging !
=
null) {
logging.println(
">>>>> Dispatching to "
+
msg.target
+
" "
+
msg.callback
+
": "
+
msg.what);
}
msg.target.dispatchMessage(msg);
if
(logging !
=
null) {
logging.println(
"<<<<< Finished to "
+
msg.target
+
" "
+
msg.callback);
}
/
/
Make sure that during the course of dispatching the
/
/
identity of the thread wasn't corrupted.
final
long
newIdent
=
Binder.clearCallingIdentity();
if
(ident !
=
newIdent) {
Log.wtf(TAG,
"Thread identity changed from 0x"
+
Long
.toHexString(ident)
+
" to 0x"
+
Long
.toHexString(newIdent)
+
" while dispatching to "
+
msg.target.getClass().getName()
+
" "
+
msg.callback
+
" what="
+
msg.what);
}
msg.recycle();
}
}
Looper类
public static void loop() {
final Looper me
=
myLooper();
if
(me
=
=
null) {
throw new RuntimeException(
"No Looper; Looper.prepare() wasn't called on this thread."
);
}
final MessageQueue queue
=
me.mQueue;
Binder.clearCallingIdentity();
final
long
ident
=
Binder.clearCallingIdentity();
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)