mirror of
https://github.com/DroidPluginTeam/DroidPlugin.git
synced 2026-10-17 04:30:34 +08:00
1.add doc and doc license
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
前言:为什么要了解系统Activity,Service,,BroadCastReceiver,ContentProvider的启动流程,这是一个对于即将理解插件中的四大组件动态注册,占坑的前提,如果不了解的话,那么很难了解插件hook哪此东西,又是如何骗过AMS来启动Activity,Service,BroadCastReceiver,ContentProvider?
|
||||
|
||||
本节主要记录系统Activity的启动流程:
|
||||
先看下时序图:
|
||||

|
||||
|
||||

|
||||
|
||||
//接上面两张图:
|
||||

|
||||
和插件相关主要在第三张图,
|
||||
先看H类:这是ActivityThread中的内部类,此类继承自Handler,重写handleMeaage方法, 将msg转换成一个ActivityClientRecord对象,调用ActivityThread类成员函数getPackageInfoNoCheck来获得一个LoadApk对象,并且保存在ActivityClientRecord对象r的成员变量packageInfo中。
|
||||
ActivityThread有一个该类型的成员变量mH。scheduleLaunchActivity()里会发送一个LAUNCH_ACTIVITY类型的消息,该消息被mH处理并调用handleLaunchActivity()。
|
||||
|
||||
handleLaunchActivity(r,main)来启动ActivityClientRecord对象t所描述的一个Activity组件。即MyActivity
|
||||
|
||||
```
|
||||
private class H extends Handler {
|
||||
public static final int LAUNCH_ACTIVITY = 100;
|
||||
public static final int PAUSE_ACTIVITY = 101;
|
||||
public static final int PAUSE_ACTIVITY_FINISHING= 102;
|
||||
public static final int STOP_ACTIVITY_SHOW = 103;
|
||||
public static final int STOP_ACTIVITY_HIDE = 104;
|
||||
public static final int SHOW_WINDOW = 105;
|
||||
public static final int HIDE_WINDOW = 106;
|
||||
public static final int RESUME_ACTIVITY = 107;
|
||||
public static final int SEND_RESULT = 108;
|
||||
public static final int DESTROY_ACTIVITY = 109;
|
||||
public static final int BIND_APPLICATION = 110;
|
||||
public static final int EXIT_APPLICATION = 111;
|
||||
public static final int NEW_INTENT = 112;
|
||||
public static final int RECEIVER = 113;
|
||||
public static final int CREATE_SERVICE = 114;
|
||||
public static final int SERVICE_ARGS = 115;
|
||||
public static final int STOP_SERVICE = 116;
|
||||
public static final int REQUEST_THUMBNAIL = 117;
|
||||
public static final int CONFIGURATION_CHANGED = 118;
|
||||
public static final int CLEAN_UP_CONTEXT = 119;
|
||||
public static final int GC_WHEN_IDLE = 120;
|
||||
public static final int BIND_SERVICE = 121;
|
||||
public static final int UNBIND_SERVICE = 122;
|
||||
public static final int DUMP_SERVICE = 123;
|
||||
public static final int LOW_MEMORY = 124;
|
||||
public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
|
||||
public static final int RELAUNCH_ACTIVITY = 126;
|
||||
public static final int PROFILER_CONTROL = 127;
|
||||
public static final int CREATE_BACKUP_AGENT = 128;
|
||||
public static final int DESTROY_BACKUP_AGENT = 129;
|
||||
public static final int SUICIDE = 130;
|
||||
public static final int REMOVE_PROVIDER = 131;
|
||||
public static final int ENABLE_JIT = 132;
|
||||
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
|
||||
public static final int SCHEDULE_CRASH = 134;
|
||||
public static final int DUMP_HEAP = 135;
|
||||
public static final int DUMP_ACTIVITY = 136;
|
||||
public static final int SLEEPING = 137;
|
||||
public static final int SET_CORE_SETTINGS = 138;
|
||||
public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
|
||||
public static final int TRIM_MEMORY = 140;
|
||||
public static final int DUMP_PROVIDER = 141;
|
||||
public static final int UNSTABLE_PROVIDER_DIED = 142;
|
||||
public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
|
||||
public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
|
||||
public static final int INSTALL_PROVIDER = 145;
|
||||
String codeToString(int code) {
|
||||
if (DEBUG_MESSAGES) {
|
||||
switch (code) {
|
||||
case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
|
||||
case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
|
||||
case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
|
||||
case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
|
||||
case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
|
||||
case SHOW_WINDOW: return "SHOW_WINDOW";
|
||||
case HIDE_WINDOW: return "HIDE_WINDOW";
|
||||
case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
|
||||
case SEND_RESULT: return "SEND_RESULT";
|
||||
case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
|
||||
case BIND_APPLICATION: return "BIND_APPLICATION";
|
||||
case EXIT_APPLICATION: return "EXIT_APPLICATION";
|
||||
case NEW_INTENT: return "NEW_INTENT";
|
||||
case RECEIVER: return "RECEIVER";
|
||||
case CREATE_SERVICE: return "CREATE_SERVICE";
|
||||
case SERVICE_ARGS: return "SERVICE_ARGS";
|
||||
case STOP_SERVICE: return "STOP_SERVICE";
|
||||
case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
|
||||
case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
|
||||
case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
|
||||
case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
|
||||
case BIND_SERVICE: return "BIND_SERVICE";
|
||||
case UNBIND_SERVICE: return "UNBIND_SERVICE";
|
||||
case DUMP_SERVICE: return "DUMP_SERVICE";
|
||||
case LOW_MEMORY: return "LOW_MEMORY";
|
||||
case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
|
||||
case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
|
||||
case PROFILER_CONTROL: return "PROFILER_CONTROL";
|
||||
case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
|
||||
case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
|
||||
case SUICIDE: return "SUICIDE";
|
||||
case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
|
||||
case ENABLE_JIT: return "ENABLE_JIT";
|
||||
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
|
||||
case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
|
||||
case DUMP_HEAP: return "DUMP_HEAP";
|
||||
case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
|
||||
case SLEEPING: return "SLEEPING";
|
||||
case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
|
||||
case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
|
||||
case TRIM_MEMORY: return "TRIM_MEMORY";
|
||||
case DUMP_PROVIDER: return "DUMP_PROVIDER";
|
||||
case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
|
||||
case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
|
||||
case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
|
||||
case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
|
||||
}
|
||||
}
|
||||
return Integer.toString(code);
|
||||
}
|
||||
public void handleMessage(Message msg) {
|
||||
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
|
||||
switch (msg.what) {
|
||||
case LAUNCH_ACTIVITY: {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
|
||||
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
|
||||
|
||||
r.packageInfo = getPackageInfoNoCheck(
|
||||
r.activityInfo.applicationInfo, r.compatInfo);
|
||||
handleLaunchActivity(r, null);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
} break;
|
||||
case RELAUNCH_ACTIVITY: {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
|
||||
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
|
||||
handleRelaunchActivity(r);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
} break;
|
||||
case PAUSE_ACTIVITY:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
|
||||
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
|
||||
maybeSnapshot();
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case PAUSE_ACTIVITY_FINISHING:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
|
||||
handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case STOP_ACTIVITY_SHOW:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
|
||||
handleStopActivity((IBinder)msg.obj, true, msg.arg2);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case STOP_ACTIVITY_HIDE:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
|
||||
handleStopActivity((IBinder)msg.obj, false, msg.arg2);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case SHOW_WINDOW:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
|
||||
handleWindowVisibility((IBinder)msg.obj, true);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case HIDE_WINDOW:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
|
||||
handleWindowVisibility((IBinder)msg.obj, false);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case RESUME_ACTIVITY:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
|
||||
handleResumeActivity((IBinder)msg.obj, true,
|
||||
msg.arg1 != 0, true);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case SEND_RESULT:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
|
||||
handleSendResult((ResultData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case DESTROY_ACTIVITY:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
|
||||
handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
|
||||
msg.arg2, false);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case BIND_APPLICATION:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
|
||||
AppBindData data = (AppBindData)msg.obj;
|
||||
handleBindApplication(data);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case EXIT_APPLICATION:
|
||||
if (mInitialApplication != null) {
|
||||
mInitialApplication.onTerminate();
|
||||
}
|
||||
Looper.myLooper().quit();
|
||||
break;
|
||||
case NEW_INTENT:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
|
||||
handleNewIntent((NewIntentData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case RECEIVER:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
|
||||
handleReceiver((ReceiverData)msg.obj);
|
||||
maybeSnapshot();
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case CREATE_SERVICE:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
|
||||
handleCreateService((CreateServiceData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case BIND_SERVICE:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
|
||||
handleBindService((BindServiceData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case UNBIND_SERVICE:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
|
||||
handleUnbindService((BindServiceData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case SERVICE_ARGS:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
|
||||
handleServiceArgs((ServiceArgsData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case STOP_SERVICE:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
|
||||
handleStopService((IBinder)msg.obj);
|
||||
maybeSnapshot();
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case REQUEST_THUMBNAIL:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail");
|
||||
handleRequestThumbnail((IBinder)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case CONFIGURATION_CHANGED:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
|
||||
mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
|
||||
handleConfigurationChanged((Configuration)msg.obj, null);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case CLEAN_UP_CONTEXT:
|
||||
ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
|
||||
cci.context.performFinalCleanup(cci.who, cci.what);
|
||||
break;
|
||||
case GC_WHEN_IDLE:
|
||||
scheduleGcIdler();
|
||||
break;
|
||||
case DUMP_SERVICE:
|
||||
handleDumpService((DumpComponentInfo)msg.obj);
|
||||
break;
|
||||
case LOW_MEMORY:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
|
||||
handleLowMemory();
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case ACTIVITY_CONFIGURATION_CHANGED:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
|
||||
handleActivityConfigurationChanged((IBinder)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case PROFILER_CONTROL:
|
||||
handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);
|
||||
break;
|
||||
case CREATE_BACKUP_AGENT:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
|
||||
handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case DESTROY_BACKUP_AGENT:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
|
||||
handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case SUICIDE:
|
||||
Process.killProcess(Process.myPid());
|
||||
break;
|
||||
case REMOVE_PROVIDER:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
|
||||
completeRemoveProvider((ProviderRefCount)msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case ENABLE_JIT:
|
||||
ensureJitEnabled();
|
||||
break;
|
||||
case DISPATCH_PACKAGE_BROADCAST:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
|
||||
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case SCHEDULE_CRASH:
|
||||
throw new RemoteServiceException((String)msg.obj);
|
||||
case DUMP_HEAP:
|
||||
handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
|
||||
break;
|
||||
case DUMP_ACTIVITY:
|
||||
handleDumpActivity((DumpComponentInfo)msg.obj);
|
||||
break;
|
||||
case DUMP_PROVIDER:
|
||||
handleDumpProvider((DumpComponentInfo)msg.obj);
|
||||
break;
|
||||
case SLEEPING:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
|
||||
handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case SET_CORE_SETTINGS:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
|
||||
handleSetCoreSettings((Bundle) msg.obj);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case UPDATE_PACKAGE_COMPATIBILITY_INFO:
|
||||
handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
|
||||
break;
|
||||
case TRIM_MEMORY:
|
||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
|
||||
handleTrimMemory(msg.arg1);
|
||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||
break;
|
||||
case UNSTABLE_PROVIDER_DIED:
|
||||
handleUnstableProviderDied((IBinder)msg.obj, false);
|
||||
break;
|
||||
case REQUEST_ASSIST_CONTEXT_EXTRAS:
|
||||
handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
|
||||
break;
|
||||
case TRANSLUCENT_CONVERSION_COMPLETE:
|
||||
handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
|
||||
break;
|
||||
case INSTALL_PROVIDER:
|
||||
handleInstallProvider((ProviderInfo) msg.obj);
|
||||
break;
|
||||
}
|
||||
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
|
||||
}
|
||||
```
|
||||
再看handlePeformLanchActivity方法, 发送一个已中止状态的进程间通信请求给ActivityThread.
|
||||

|
||||
|
||||
以MyActivity继承为例(假定是我们app的第一个Activity),MyActivity被启动,共要经历5个大的步骤:
|
||||
MyActivity组件是由Launcher组件来启动的,而Launcher组件又是Activity管理服务ActivityManagerService来启动的。
|
||||
|
||||
MyActivity组件、Launcher组件和ActivityManagerService组件分别运行在不同的进程中,MyActivity启动过程就涉及了
|
||||
三个进程,这三个进程通过Binder进程间通信来完成。
|
||||
|
||||
Launcher组件启动MyActivity的过程如下:
|
||||
|
||||
- **Lanuncher组件向ActivityManagerService发送一个启动MyActivity组件的进程间通信请求**
|
||||
- **ActivityManagerService首先将要启动的MyActivity组件的信息保存下来,然后再向Launcher组件发送一个中止状态的进程间通信请求**
|
||||
|
||||
- **Launcher组件进入到中止状态后,就会向ActivityManagerService发送一个已中止状态的进程间通信请求,以便ActivityManagerService可以继续执行MyActivity组件的操作**
|
||||
|
||||
- **ActivityManagerService发现用来运行MyActivity组件的应用程序不存在,因此,它就会启动一个新的应用程序进程**
|
||||
|
||||
- **新的应用程序进程启动完成后,就会向ActivityManagerService发送一个启动完成的进程间通信请求,以便ActivityManagerService可以继续执行启动MyActivity组件的操作。**
|
||||
|
||||
- **ActivityManagerService将第2步保存下来的MyActivity组件的信息发送给第4步创建的应用程序进程,以便它可以将yActivity组件启动起来。**
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
前言:为什么要了解系统Activity,Service,BroadCastReceiver,ContentProvider的启动流程,这是一个对于即将理解插件中的四大组件动态注册,占坑的前提,如果不了解的话,那么很难了解插件hook哪此东西,又是如何骗过AMS来启动Activity,Service,BroadCastReceiver,ContentProvider?
|
||||
|
||||
本节主要记录系统BroadCastReceiver的注册,发送流程:
|
||||
|
||||
在了解注册,发送之前,先想一个问题:为什么有广播?
|
||||
|
||||
- **1、广播是一种组件之间传递的方式,这些组件可以运行在同一进程中,也可以运行在不同的进程中。**
|
||||
- **2、广播的机制是建立在Binder进程间通信基础上的。在Binder进程间通信,Client组件在和Service组件进行通信之前,必须要先获取它的一个代理对象,即Client组件事先要知道Service组件的存在。然而,在广播机制中,广播发送者事先不需要知道广播接收者是存在的,这样就可以降低广播接收者和发送者之间的耦合度,得到模块分离。**
|
||||
- **3、广播机制是一种基于消息发布和订阅的事件驱动模型,广播发送者负责发布消息,而广播接收者需要先订阅消息,然后才能收到消息。**
|
||||
- **4、广播机制存在一个注册中心,它是由ActivityManagerService来担当的,广播接收者订阅消息的表现形式就是将自己注册到ActivieyManagerService中,并且指定要接收的广播的类型,当广播发送者向广播接收者发送一个广播时,这个广播首先发送到ActivityManagerService,然后ActivityManagerService可根据这个类型找到相应的广播接收者,最后将这个广播发送给它们处理。**
|
||||
- **5、广播接收者的注册分为静态注册和动态注册,广播的发送方式分为有序和无序两种**
|
||||
- **6、广播的生命周期,从对象调用它开始,到onReceiver方法执行完成之后结束。另外,每次广播被接收后会重新创建BroadcastReceiver对象,并在onReceiver方法中执行完就销毁,如果BroadcastReceiver的onReceiver方法中不能在10秒内执行完成,Android会出现ANR异常。所以不要在BroadcastReceiver的onReceiver方法中执行耗时的操作。**
|
||||
- **7、如果需要在BroadcastReceiver中执行耗时的操作,可以通过Intent启动Service来完成。但不能绑定Service。特别是,您可能无法从一个BroadcastReceiver中显示一个对话框,或绑定到服务。对于前者,则应该使用NotificationManager的API。对于后者,你可以使用Context.startService()来启动一个Service。**
|
||||
|
||||
##BroadCastReceiver注册流程
|
||||
先看一张时序图:
|
||||

|
||||
|
||||
首先得有一个广播类,以下叫MyBroadCastReceiver:
|
||||
|
||||

|
||||
|
||||
有一个TestBroadCastActivity的类:
|
||||
|
||||

|
||||
|
||||
通过动态注册的方式注册了一个MyBroadCastReceiver广播类,以上就是一个广播的注册过程。
|
||||
|
||||
##BroadCastReceiver发送流程
|
||||
先看下面两张时序图(ps:太长,只能分开截图):发送过程远比注册过程复杂的多
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
广播的发送过程:
|
||||
|
||||
- **1、广播发送者,即一个Activity组件或者一个service组件,将一个特定类型的广播发送给ActivityManagerService;**
|
||||
- 2 、ActivityManagerService接收到一个广播之后,首先找到与这个广播对应的广播接收者,然后将他们添加一个广播调度队列中,最后向
|
||||
ActivityManagerService发送一个类型为BROADCAST_INTENT_MSG的值,这时广播对发送者来说,一个广播发送过程就完成了;
|
||||
- **3、当发送到ActivityManagerService所运行的线程的消息队列中BROADCAST_INTENT_MSG消息被处理时,ActivityManagerService就会从广播调度队列中找到需要的广播的接收者,并且将对应的广播发送给它们所运行的应用程序进程。**
|
||||
- **4、广播接收者所运行在的应用程序进程接收到ActivityManagerService发送过来的广播之后,并不是直接将接受到的广播分发给广播接收者来处理,而是将接收到的广播封装成一个消息,并且发送到主线程的消息队列中,当这个消息被处理时,应用程序进程才会将它所描述的广播发送给相应的广播接收者处理。**
|
||||
- **5、ActivityManagerService向一个应用程序发送一个广播时,采用的是异步进程间通信,Binder驱动结构体中binder_node时提到,发送给一一个Binder实体对象的所有异步事务都是保存在一个异步事务队列中的,由于保存在一个异步事务队列中的异步事务在同一时刻只有一个会得到处理,即只有位于队列头部的异步事务才会得到处理,因为,ActivityManagerService就可以保证它发送给同一个应用程序的所有都可以按照发送顺序来串行地接收和处理。**
|
||||
|
||||
以上就是广播的注册发送过程,ContentProvider不再分析,下篇将正式进入插件占坑,四大组件动态化注册分析。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
前言:为什么要了解系统Activity,Service,BroadCastReceiver,ContentProvider的启动流程,这是一个对于即将理解插件中的四大组件动态注册,占坑的前提,如果不了解的话,那么很难了解插件hook哪此东西,又是如何骗过AMS来启动Activity,Service,BroadCastReceiver,ContentProvider?
|
||||
|
||||
本节主要记录系统Service的启动流程:
|
||||
先看时序图:
|
||||

|
||||
|
||||
与Activity组件的启动方式很像,Service启动分为隐式和显式两种,对于隐式启动Service组件来说,我们只需要知道它的组件名称,而对于显示的Service组件来说,需要知道它的类名称。
|
||||
以一个后台播放音乐场景来说明:
|
||||
通过实现一个MyService来实现一个异步任务来播放后台音乐
|
||||
|
||||
MyActivity.java
|
||||

|
||||

|
||||
|
||||
MyService.java
|
||||

|
||||
|
||||
MyActivity组件绑定MyService的过程:
|
||||
|
||||
- **1.MyActivity向ActivityManagerService发送一个绑定CounterService组件的进程间通信请求。**
|
||||
- **2.ActivityManagerService发现用来运行MyService组件的应用程序进程即为MyActivity组件所运行的应用程序进程,因此,它就直接通知应用程序进程将MyService启动起来。**
|
||||
- **3.MyService组件启动起来后,ActivityManagerService就请求它返回一个Binder本地对象,以便MyActivity可以通过这个Binder本地对象来和MyService组件建立连接。**
|
||||
- **4.ActivityManagerService将前面从MyService组件中获得的一个Binder本地对象发送给MyActivity组件。**
|
||||
- **5.MyActivity组件获得了ActivityManagerService给它发送的Binder本地对象之后,就可以通过它来获得MyService组件的一个访问接口,MyActivity组件之后就可以通过这个访问接口来使用MyService组件所提供的服务,这就相当于将MyService绑定在了MyActivity中了。**
|
||||
|
||||
那service在系统中绑定是如何的呢?
|
||||
同样看下时序图:
|
||||

|
||||
|
||||

|
||||
|
||||
客户端组件启动Server组件的过程:
|
||||
|
||||
- **1.Client组件启动ActivityManagerService发送一个启动Server组件的进程间通信请求。**
|
||||
- 2.ActivityManagerService发现用来运行Server组件的应用程序进程不存在,因此,它就会首先将Server组件的信息保存下来,接着再
|
||||
创建一个新的应用程序进程
|
||||
- **3.新的应用程序启动完成之后,就会向ActivityManagerService发送一个启动完成进程间通信请求,以便ActivityManagerServices可以继续执行启动Service组件的操作。**
|
||||
- **4.ActitivtyManagerService将2中保存下来的Service组件信息发送级第2步创建的应用程序进程,以便它可以将Server组件启动起来。**
|
||||
@@ -0,0 +1,74 @@
|
||||
插件开发之360 DroidPlugin源码分析(一)初识
|
||||
|
||||
###DroidPlugin的是什么?
|
||||
|
||||
一种新的插件机制,一种免安装的运行机制,是一个沙箱(但是不完全的沙箱。就是对于使用者来说,并不知道他会把apk怎么样), 是模块化的基础。
|
||||
|
||||
###DroidPlugin的缺点是什么?
|
||||
|
||||
- a.通知栏限制(无法在插件中发送具有自定义资源的Notification,例如: 1. 带自定义RemoteLayout的Notification 2. 图标通过R.drawable.XXX指定的通知(插件系统会自动将其转化为Bitmap)
|
||||
|
||||
- b.安全性担忧(可以修改,hook一些重要信息)
|
||||
|
||||
- c.机型适配(不是所有机器上都能行,因为大量用反射相关,如果rom厂商深度定制了framework层,反射的方法或者类不在,容易插件运用失败)
|
||||
|
||||
- d. 需要预先注册权限(在Library中申请了原生系统所有的权限)
|
||||
|
||||
- e. 无法在插件中注册一些具有特殊Intent Filter的Service、Activity、BroadcastReceiver、ContentProvider等组件以供Android系统、已经安装的其他APP调用。
|
||||
|
||||
- f. 缺乏对Native层的Hook,对某些带native代码的apk支持不好,可能无法运行。比如一部分游戏无法当作插件运行。
|
||||
|
||||
###DroidPlugin的特点是什么?
|
||||
|
||||
- a.免安装(就是如果只要从网上下载一个apk,不用安装apk,在插件机制下,就能运行)
|
||||
|
||||
- b.无需修改源码(因为大量反射,代理,Binder相关,这些足以骗过framework层)
|
||||
|
||||
- c.二进制级别隔离
|
||||
|
||||
- d.插件之间可以相互调用
|
||||
|
||||
- e.解除耦合
|
||||
|
||||
- f.静默安装,就是前面说的不用安装,就可在插件机制中运行apk
|
||||
|
||||
- g.崩溃隔离,插件崩溃,对主应用来说,不会有明显影响
|
||||
|
||||
- h.还原插件自己的多进程机制,适配性
|
||||
|
||||
- i.模块隔离,如可以把UI和控制逻辑进行隔离,控制逻辑可用插件化的方式
|
||||
|
||||
###官方说明:
|
||||
|
||||
- 支持Androd 2.3以上系统
|
||||
- 插件APK完全不需做任何修改,可以独立安装运行、也可以做插件运行。要以插件模式运行某个APK,你无需重新编译、无需知道其源码。
|
||||
- 插件的四大组件完全不需要在Host程序中注册,支持Service、Activity、BroadcastReceiver、ContentProvider四大组件
|
||||
- 插件之间、Host程序与插件之间会互相认为对方已经"安装"在系统上了。
|
||||
- API低侵入性:极少的API。HOST程序只是需要一行代码即可集成Droid Plugin
|
||||
- 超强隔离:插件之间、插件与Host之间完全的代码级别的隔离:不能互相调用对方的代码。通讯只能使用Android系统级别的通讯方法。
|
||||
- 支持所有系统API
|
||||
- 资源完全隔离:插件之间、与Host之间实现了资源完全隔离,不会出现资源窜用的情况。
|
||||
- 实现了进程管理,插件的空进程会被及时回收,占用内存低。
|
||||
- 插件的静态广播会被当作动态处理,如果插件没有运行(即没有插件进程运行),其静态广播也永远不会被触发。
|
||||
|
||||
###DroidPlugin的的基本原理是什么?
|
||||
|
||||
- a.共享进程:为android提供一个进程运行多个apk的机制,通过API欺骗机制瞒过系统
|
||||
|
||||
- b.占坑:通过预先占坑的方式实现不用在mainfest注册,通过一带多的方式实现服务管理
|
||||
|
||||
- c.Hook机制:动态代理实现函数hook,Binder代理绕过部分系统服务限制,IO重定向(先获取原始Object-->Read,然后动态代理Hook Object后-->Write回去,达到瞒天过海的目的)
|
||||
|
||||
插件Host的程序架构:
|
||||

|
||||
|
||||
|
||||
下一篇开始分析基本原理中的Hook机制
|
||||
|
||||
---
|
||||
|
||||
在此输入正文
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
- **Hook机制中Binder代理类关系图**
|
||||
- **Hook机制中Binder代理时序图**
|
||||
- **MyServiceManager**
|
||||
- **ServiceManagerCacheBinderHook**
|
||||
- **ServiceManagerBinderHook**
|
||||
- **BinderHook**
|
||||
|
||||
##Hook机制中Binder代理类关系图
|
||||

|
||||
|
||||
##Hook机制中Binder代理时序图
|
||||

|
||||

|
||||
|
||||
##MyServiceManager
|
||||

|
||||
|
||||
- **mOriginServiceCache:这里存储的是原始的service cache。每个ActivityThread在bindApplication()的时候,会从ServiceManager那边获得一个service cache(可以减少和Binder代理之间通信,系统Binder是一个专门的BinderProxy和把上层的service和Binder driver进行IPC),每次要和某个service通信时,会先检查这个cache里有没有代理对象,如果有的话就直接用,不需要再和ServiceManager进行一次binder交互了。**
|
||||
- **mProxiedServiceCache:这里存储的就是service cache的代理对象了,因为我们要hook这些binder和上层(serviceConnection时会转成IBinder接口)调用,所以必须把service cache也替换成我们的代理对象,每次调用都会走进ServiceManagerCacheBinderHook对象的invoke()方法。**
|
||||
- **mProxiedObjCache:这里存储的是所有的proxyservice Object,那原始的service对象放在哪里呢?其实是在BinderHook的mOldObj里。**
|
||||
##ServiceManagerCacheBinderHook
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
前面把service cache存起来,下次如果要真正和service进行通信,通过getOriginService()把原始的service cache拿出来用就行了。
|
||||
|
||||
##ServiceManagerBinderHook
|
||||

|
||||
这个类继承自ProxyHook,主要是用来hook住getService()和checkService()这两个API。如果这两个API被调用,并且在mProxiedObjCache发现有对应的代理对象,则直接返回这个代理对象。
|
||||
##BinderHook
|
||||

|
||||
|
||||

|
||||
先调用ServiceManagerCacheBinderHook的onInstall()方法更新一下service cache,然后生成一个新的代理对象放到mProxiedObjCache里。这样下次不管是从cache里取,还是直接通过binder调用,就都会返回我们的代理对象。
|
||||
|
||||
Binder代理其实在android 系统中也是一个十分重要的角色。
|
||||
|
||||
|
||||
这部分可以从网上搜下相关资料。360 plugin 的Binder代理就是借鉴了系统的Binder相关。
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
前言:新插件的开发,可以说是为插件开发者带来了福音,虽然还很多坑要填补,对于这款牛逼的插件机制,一直想找个时间分析和总结下它的code,话不多说,直接入正题,本文是分析../hook/handle及../hook/proxy下代码,../hook/binder单独分析
|
||||
|
||||
- **Hook机制的包结构关系**
|
||||
- **Hook机制的类图关系**
|
||||
- **Hook机制的时序图关系**
|
||||
- **Manifest权制申请**
|
||||
- **基类Hook做了什么?**
|
||||
- **HookedMethodHandler**
|
||||
- **基类BaseHookHandle和Hook有什么关系?**
|
||||
- **ProxyHook能干什么?**
|
||||
- **实例-如何hook IPackageManager**
|
||||
|
||||
##Hook机制的包结构关系
|
||||

|
||||
|
||||
##Hook机制类图关系
|
||||

|
||||
首先定义了一个基类Hook,抽象类,外部可以通过setEnable()方法来使能否hook。声明了onInstall和onUnInstall及相关的方法,子类可以覆盖这些方法完成相应的车间机床,这里相当于提供一个车间,机床上的具体操作什么由子类去自己实现。
|
||||
|
||||
##Hook机制的时序图关系
|
||||

|
||||
|
||||
##Manifest权限申请
|
||||
插件管理服务类声明:
|
||||

|
||||
|
||||
权限申请:
|
||||

|
||||
|
||||
##基类Hook做了什么?
|
||||

|
||||
|
||||
##ProxyHook
|
||||

|
||||
|
||||
ProxyHook继承自Hook,实现了InvocationHandler接口。它有一个setOldObj()方法,用来保存原始对象。新的代理对象可以看到在代码中是如何实现的(动态代理)
|
||||
|
||||
##BaseHookHandle
|
||||

|
||||
|
||||

|
||||
接上面ProxyHook中的invoke()方法,mHookHandles是一个BaseHookHandle对象,内部包含了一个Map,可以根据API名映射到对应对应的HookedMethodHandler对象。这个Map由其子类IXXXHookHandle在初始化的时候进行填充。
|
||||
紧接着调用HookedMethodHandler的doHookInner()方法:
|
||||
|
||||
##HookedMethodHandler
|
||||

|
||||
|
||||
##ReplaceCallingPackageHookedMethodHandler
|
||||

|
||||
|
||||
##IO重定向
|
||||

|
||||
|
||||
##递归遍历
|
||||

|
||||
|
||||
##以IPackageManager为例
|
||||
IPackageManagerHook:Hook所有IPackageManager的方法
|
||||
IActivityManagerHookHandle:安装所有被Hook的方法的处理对象,加入到Map中
|
||||
IPackageManagerHandle.checkSignatures:这是一个内部类,继承HookedMethodHandler, 专门校验签名的。以此,还有各种各样的PackageManger原生中的方法,在这都变成了一个内部类继承了HookedMethodHandler.上图:
|
||||
IPackageManagerHookHandle:
|
||||
|
||||

|
||||
@@ -0,0 +1,126 @@
|
||||
在了解系统的activity,service,broadcastReceiver的启动过程后,今天将分析下360 DroidPlugin是如何预注册占坑的?本篇文章主要分析Service预注册占坑,Service占了坑后又是什么时候开始瞒天过海欺骗AMS的?先看下Agenda:
|
||||
|
||||
- **AndroidMainfest.xml中概览**
|
||||
- **Service中关键方法被hook时机**
|
||||
- **startService被hook**
|
||||
- **瞒天过海流程图**
|
||||
- **认识ServiceManager**
|
||||
|
||||
##AndroidMainfest.xml中概览
|
||||
|
||||

|
||||
|
||||
android:process=":PluginP02" 表示自定义一个名为PluginP02的进程,该属性一旦设置, 那么App启动之后, Service肯定会以远程服务方式启动, ---- 可通过adb shell ps 就可以看到有一个独立的进程启动了.
|
||||
|
||||
项目 Package为 com.morgoo.droidplugin , 并设置 android:process=":PluginP02", 那么App运行时, 通过 adb shell ps | grep com.morgoo.droidplugin , 可以看到有两个进程:
|
||||
|
||||

|
||||
|
||||
##startService被hook
|
||||
|
||||
IActivityManagerHookHandle.startService方法
|
||||
|
||||

|
||||
|
||||
replaceFirstServiceIntentOfArgs()
|
||||
|
||||

|
||||
|
||||
接下来我们继续回到StartService类中,看下afterInvoke方法
|
||||
|
||||

|
||||
|
||||
stopService,bindService,unbindService,setServiceForeground都是类似逻辑,可从源码中证实。
|
||||
在前一篇[《插件开发之360 DroidPlugin源码分析(四)Activity预注册占坑》](http://blog.csdn.net/hejjunlin/article/details/52258434),我们曾了解到,8个进程中的service在预注册占坑,在AndroidManifest.xml中只有一个,那如果插件要启动多个service怎么办?这是第一个问题,而我们知道所有和服务相关的都要在系统的systemServer进程中进行注册,难道DroidPlugin要逆天的本事?这是第二个问题
|
||||
我们从代码中发现有一个ServceManager,这和android系统中大管家ServiceManager相差一个i,难道要改大管家的职责?又多了一个疑惑
|
||||
仔细看了下ServceManager中的代码:
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
以上代码可总结为:(以虚线分上下两部分)
|
||||
1.上部分主要是ServceManager单例及有一个handleXXX相关的方法,下部分主要是Service的一些生命周期方法。
|
||||
2.我们基本可以确定之前问题2和问题3的答案了,没有那么逆天的本事来操作ServiceManager,也不能修改大管家ServiceManager的职责
|
||||
3.那问题又来了,这个类到底是做啥的?还起一个叫ServceManager的名字,
|
||||
以hanldeOnTaskRemoveOne方法为例看看:
|
||||
|
||||

|
||||
|
||||
接着再看下ServceManager中的onBind方法:
|
||||
|
||||

|
||||
|
||||
然后调到handleOnBindOne方法中,我们前面分析了一个handleOnTaskRemovedOne方法,下面1-7步骤套路都是一样,主要在return时,直接调用service自身的onBind了,这和我们平时在Activity中new Intent,然后把这个intent传到onBind中.
|
||||
|
||||

|
||||
|
||||
那么问题来了,还要这么一个类倒腾来干啥呢?还记得上面有一处逻辑service为null时,就调用了handleCreateServiceOne,好戏在这里:
|
||||
|
||||

|
||||

|
||||
|
||||
看了上面的分析后,我们再去回想第一个问题,那如果插件要启动多个service怎么办?不知道不没有注意到mTokenServices,mNameService,mServiceTaskIds这些成员变量,它们都是Map,key不一样,value全是Service,如个有多个service在插件中启动了,mTokenServices,mNameService,mServiceTaskIds这些成员变量分别掌握了Service的Token,name,及任务id(通过token拿到的)。那岂不是已经在管理这些多个service了。至于附属于这个类起的名字,叫什么都无所谓。
|
||||
以上可用如下流程图表示:
|
||||

|
||||
|
||||
前面一直有个问题解释的不彻底,就是问题3,ServceManager是否担当了修改系统大管家ServiceManager的职责?接下来,我们就稍微了解下系统大管家ServiceManager是做什么的?(PS: ServiceManager和Binder机制一样,不是一天两个就能研究的清楚的)
|
||||
|
||||
##认识ServiceManager
|
||||
|
||||
Android系统Binder机制的总管是ServiceManager,所有的Server(System Server)都需要向它注册,应用程序需要向其查询相应的服务。平时,我们在studio上的DDMS中调试程序时,下图这个就是ServiceManager
|
||||
|
||||
这里以Java层加入ServiceManager及getService为数据流分析一下。
|
||||
|
||||
复习一下典型的Binder模式,有利于后面的理解:
|
||||
1、客户端通过某种方式得到服务器端的代理对象。从客户端角度看来代理对象和他的本地对象没有什么差别。它可以像其他本地对象一样调用其方法,访问其变量。
|
||||
2、客户端通过调用服务器代理对象的方法向服务器端发送请求。
|
||||
3、代理对象把用户请求通过Android内核(Linux内核)的Binder驱动发送到服务器进程。
|
||||
4、服务器进程处理用户请求,并通过Android内核(Linux内核)的Binder驱动返回处理结果给客户端的服务器代理对象。
|
||||
5、客户端收到服务器端的返回结果。
|
||||
|
||||
JAVA层代码分析:
|
||||
ServiceManager.java (frameworks\base\core\java\android\os)
|
||||
|
||||
对于xxxManager获取服务端service基本如此用法:
|
||||
举例:
|
||||
利用ContextImpl.java中的 public Object getSystemService(String name)
|
||||
|
||||

|
||||
|
||||
然后再调用:ServiceManager.getService(ServiceName);获取相应的服务端
|
||||
|
||||

|
||||
|
||||
知道了客户端获取一个Service的方法之后,我们回到ServiceManager的服务端:
|
||||
|
||||

|
||||
|
||||
BinderInternal.getContextObject() @ BinderInternal.java 是一个native 函数:
|
||||
|
||||
android_os_BinderInternal_getContextObject @ android_util_Binder.cpp
|
||||
返回一个 BinderProxy对象保存到类成员mRemote(ServiceManagerProxy类成员)
|
||||
|
||||
public abstract class ServiceManagerNative extends Binder implements IServiceManager
|
||||
ServiceManagerNative 继承自 Binder 并实现了 IServiceManager 接口,利用 asInterface()则提供一个 ServiceManagerProxy 代理对象使用
|
||||
|
||||
class ServiceManagerProxy implements IServiceManager
|
||||
定义了类ServiceManagerProxy(代理),ServiceManagerProxy继承自IServiceManager,并实现了其声明的操作函数,只会被ServiceManagerNative创建,它实现了IServiceManager的接口,IServiceManager提供了getService和addService两个成员函数来管理系统中的Service。
|
||||
|
||||

|
||||
|
||||
上面代码总结如下:Java层先利用Parcel对象将数据进行序列化,然后利用transact将数据传给binder驱动,就是上面mRemote.transact,mRemote在JNI层是一个叫BpBinder的对象:
|
||||
|
||||
JNI层代码分析:
|
||||
android_util_Binder.cpp
|
||||
|
||||

|
||||
|
||||
每当我们利用BpBinder的transact()函数发起一次跨进程事务时,其内部其实是调用IPCThreadState对象的transact()。BpBinder的transact()代码如下:
|
||||
|
||||

|
||||
|
||||
到此,不再向下深究,具体想了解可以看Binder机制及IPC相关内容。
|
||||
所以,到这把第2个问题彻底弄明白了,ServceManager和ServiceManager根本不是一回事。到次,Service的瞒天过海得以实现,接着,就是介绍时候说的那样无需修改源码,多进程,多service等功能。另外ContentProvider及BroadCast原理是类似,不再进行分析。
|
||||
下篇将开始分析包管理(宿主插件和插件包名有什么规则),APK解析(为什么可以免安装),进程管理(能确保隐藏起来,不会在process轻易被kill)
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
在了解系统的activity,service,broadcastReceiver的启动过程后,今天将分析下360 DroidPlugin是如何预注册占坑的?本篇文章主要分析Activity预注册占坑,Activity占了坑后又是什么时候开始瞒天过海欺骗AMS的?先看下Agenda:
|
||||
|
||||
- **AndroidMainfest.xml中概览**
|
||||
- **Activity中关键方法被hook时机**
|
||||
- **startActivity被hook**
|
||||
- **handelPerformActivity被hook**
|
||||
- **Activity预注册占坑整体流程图**
|
||||
- **瞒天过海,冒充真实身份,欺骗AMS**
|
||||
|
||||
##AndroidMainfest.xml中概览
|
||||
我们知道所有能用的四大组件都要在Manifest中注册声明,第一步,先看AndroidManifest.xml,虽然在说hook机制时,也有提及过,但是毕竟没细致分析,话不多说,看代码上图:
|
||||
|
||||

|
||||
|
||||
然后看下各个属性的意思
|
||||
|
||||

|
||||
|
||||
表示一个activity1原来属于task1,但是如果task2启动起来的话,activity1可能不再属于task1了,转而投奔task2去了。
|
||||
|
||||

|
||||
|
||||
|
||||
功能:启动硬件加速
|
||||
缺点:占用内存
|
||||
特点:可以在Application、Activity、Window、View四个级别进行硬件加速控制
|
||||
|
||||
从Android3.0(API Level 11)开始,Android 2D渲染管道能够更好的支持硬件加速。硬件加速执行的所有的绘图操作都是使用GPU在View对象的画布上来进行的。因为启用硬件加速会增加资源的需求,因此这样的应用会占用更多的内存。
|
||||
|
||||
启用硬件加速的最容易的方法是给整个应用程序都打开全局硬件加速功能。如果应用程序只使用标准的View和Drawable,那么打开全局硬件加速不会导致任何的不良的绘制效果。但是,因为硬件加速并不支持所有的2D图形绘制操作,所以对于那些使用定制的View和绘制调用的应用程序来说,打开全局硬件加速,可以会影响绘制效果。问题通常会出现在对那些不可见的元素进行了异常或错误的像素渲染。为了避免这种问题,Android提供以下级别,以便可选择性的启用或禁止硬件加速:
|
||||
|
||||
控制硬件加速,能够用以下级别来控制硬件加速:
|
||||
|
||||
1、Application级别
|
||||
|
||||
在应用的Android清单文件中,把下列属性添加到元素中,来开启整个应用程序的硬件加速。
|
||||
|
||||
2、Activity级别
|
||||
|
||||
如果应用程序不能够正确的使用被打开的全局硬件加速,那么也可以对Activity分别进行控制。在元素中使用android:hardwareAccelerated属性,能够启用或禁止Activity级别的硬件加速。以下示例启用全局的硬件加速,但却禁止了一个Activity的硬件加速。
|
||||
|
||||
3、Window级别
|
||||
|
||||
如果需要更细粒度的控制,就可以使用下列代码来针对给定的窗口来启用硬件加速:
|
||||
|
||||
注意:当前不能在Window级别禁止硬件加速。
|
||||
|
||||

|
||||
|
||||
4、View级别
|
||||
|
||||
能够使用下列代码在运行时针对一个独立的View对象来禁止硬件加速:
|
||||
|
||||

|
||||
|
||||
注意:当前不能在View级别开启硬件加速。View层除了禁止硬件加速以外,还有其他的功能,更多的相关信息请看本文的“View层”。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
以上就是声明属性的含义说明,作为背景了解即可。重点看下面的分析
|
||||
|
||||

|
||||
|
||||
Manifest中注册了8个进程,加上主进程共9个
|
||||
然后第每个进程下面又有26个Activity注册,一个service,一个contentprovider,那么问题来了,搞这么多注册在manifest做什么用?仔细分类:就两类一类是Activity,一类是Dialog,我们知道Dialog是建立在Activity之上的,如果Activity被finish或destory后,就会报出异常:android.view.WindowManager$BadTokenException: Unable to add window — token android.os.BinderProxy@438e7108 is not valid; is your activity running?
|
||||
|
||||
附[《插件占坑,四大组件动态注册前奏(一) 系统Activity的启动流程》](http://blog.csdn.net/hejjunlin/article/details/52190050)(也可点击链接过去看详细过程)的activity的启动时序列图:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
##Activity中关键方法被hook时机
|
||||
其中startActivity()和handleLanchActivity()是被DroidPlugin 要欺骗系统的两个主要方法:
|
||||
|
||||
第一个方法是最被经常使用的startActivity(),hook机制见[《插件开发之360 DroidPlugin源码分析(二)Hook机制》](http://blog.csdn.net/hejjunlin/article/details/52124397)中分析,主要是通过Java的反射机制替换掉IActivityManager全局对象,具体IActivityManagerHookHandle的onInstall()方法如下:
|
||||
|
||||

|
||||

|
||||
|
||||
第二个方法是handleLaunchActivity(),这个方法属于ActivityThread的一个叫做H的内部类,前面讲Activity启动时,已埋下伏笔,可以参考[《插件占坑,四大组件动态注册前奏(一) 系统Activity的启动流程》](http://blog.csdn.net/hejjunlin/article/details/52190050),如果学过中间人攻击协议的话,我们知道,现个通信双方发出消息后,进行消息验证,如果中间人拦截相关协议内容,通过一个代理进行转发出去,从而达到欺骗的目的,这里暂且理解handleLanchActivity被中间人攻击了,当启动handleLanchActivity时,被DroidPlugin hook后,那多人可能会想,你怎么hook住hanleLanchActivity呢?别忘了,我们可是在Manifest占了一堆坑的。要是不好理解,可以参看《插件前奏-android黑科技 hook介绍 :http://blog.csdn.net/hejjunlin/article/details/52091833》,可能更直观些,哪在DroidPlugin中,如何在代码中瞒天过海的呢?
|
||||
我们可以看下:PluginCallbackHook.java,其中有一个onInstall()方法:
|
||||
|
||||

|
||||
|
||||
如上代码也有注释,可总结为:
|
||||
1.DroidPlugin不是完全攻击mH这个内部类,而是把mH的mCallback成员变量攻击了,然后替换成了一个PluginCallback对象,进行消息分发,那么就可以在在PluginCallback的handleMessage()里任意拦截想要分发的消息,来欺骗AMS。经过中间人这么一闹腾,那就能达到控制这个区域的目的了。
|
||||
|
||||
最狠的看下面:
|
||||
上面代码中,有一个mH的mCallback,是被拦截攻击了吧,既然被拦截后又要冒充一个担当mH的mCallback职责相关,(这里暂且夸张的说)那肯定得扒了它身上的某些特性放到冒充的mCallback吧,如身份验证相关之类,所以那原来的mCallback丢了它的身份相关,不就是废了,暂且理解为mCallback为null,实际上有mCallback在未赋值之前,初始化时,本身也是null。然后看下PluginCallback的handleMessage()方法:(ps: PluginCallback简直就是仿照ActivityThread中的H内部类写的,几乎逻辑一样,具体可看系统源码证实)
|
||||
|
||||

|
||||
|
||||
这里只拦截了一个消息类型为LAUNCH_ACTIVITY(ActivityThread中的H内部类中会有很多消息类型,也包含LAUNCH_ACTIVITY)。mCallback不为null,就是发一些伪装的消息(因为我们刚拦截了mCallback),如果为null,返回false,这样就会会再通过mH调用回真正ActivityThread的handleLaunchActivity()。(ps:系统发的消息没什么卵用时,我们就不去拦截,暂且理解为这样)
|
||||
|
||||
以上就是两个方法怎么被hook相关分析,也可参考在Hook机制举例为IPackageManager的验证签名被hook的过程,接下来就是要看hook中做了什么事?附一张Activity预注册占坑整体流程图:
|
||||
|
||||

|
||||
|
||||
|
||||
前面我们都是在说DroidPlugin怎么用中间人攻击方式,拦截了startActivity()方法和hanleLanchActivity()方法,接下来要看下拦截了后,怎么把这种身份角色搞变化了(就是一个怎么扮演冒充的角色过程):
|
||||
1.首先得找一个和真实的人像的角色,这时启用的我们备用人员,也就是事先占的坑stub.ActivityStubxxx。
|
||||
2.真实的角色身上有某些特定的特性,如爱抽烟,头发乱糟糟的,像Activity中Intent作为一个extra传到另一个Activity时,还有一些自己的lanchmode(启动方式),theme(主题),这些都是Activity的一些特性,所以stub.ActivityStubxxx也得有这些,否则怎么能达到冒充呢,这些我们在代码中早就写好了,所有的那些注册的26个备用人员都是继承ActivityStub,而ActivityStub是直接继承Activity,那还说啥呢,不就是天然的冒充么?说这么多了,直接看代码IActivityManagerHookHandle$startActvity:
|
||||
这是一个静态内部类,继承ReplaceCallingPackageHookedMethodHandler,重写了beforeInvoke方法,暂且理解为在冒充之前的一些准备工作,如下:
|
||||
|
||||

|
||||
|
||||
接着再看beforeStartActivity方法:
|
||||
|
||||

|
||||
|
||||
就是判断了下Activity的启动模式,接着都调入doFinshIt(mRunningXXXActivityList),继续看此方法:
|
||||
|
||||

|
||||
|
||||
STUB_NO_ACTIVITY_MAX_NUM为4,上面方法总结为:runningActivityList(备用activity的list的总数)大于等于3时,就把最早进入activityRecord栈中的那个finish掉,因为坑就那么多,要是都占着不干活,那要它干嘛?
|
||||
|
||||
##瞒天过海,冒充真实身份,欺骗AMS
|
||||
前面这些,还是小打小闹,接下来看一个核心方法,就是beforeInvoke中的doReplaceIntentForStartActivityAPILow方法:
|
||||
|
||||

|
||||
|
||||
前面我们说了,欺骗了两个方法,上面说的都是startActivity(),接下来看另个一个方法handleLanchActivity(), 这个方法在哪呢?我们前面说过有一个仿照ActivityThread中H内部类的class叫PluginCallBack,对,handleLaunchActivity就是在接到handleMessage中消息类型为LANCH_ACTIVITY时调用的:
|
||||
|
||||

|
||||
|
||||
以上就是Activity预注册占坑,并欺骗AMS的过程,下篇分析Service预注册占坑。
|
||||
|
||||
|
||||
如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易
|
||||
Reference in New Issue
Block a user