即时运行app的逆向分析以及原理浅析以及谈谈xposed免重启更新是否能够兼容即时运行的可行性...

本文主要是介绍即时运行app的逆向分析以及原理浅析以及谈谈xposed免重启更新是否能够兼容即时运行的可行性...,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先即时运行app的即时更新是通过内容提供者的启动而更新的,通过分析源码发现并没有修改的是application节点,也就是说合application multidex的方式不同。

<provider android:name="com.android.tools.ir.server.InstantRunContentProvider" android:multiprocess="true" android:authorities="cn.qssq666.radiogroupdemo.com.android.tools.ir.server.InstantRunContentProvider" />
image.png
public final class InstantRunContentProvider extends ContentProvider {public boolean onCreate() {if (isMainProcess()) {Log.i("InstantRun", "starting instant run server: is main process");Server.create(getContext());} else {Log.i("InstantRun", "not starting instant run server: not main process");}return true;}private boolean isMainProcess() {boolean foundPackage = false;boolean isMainProcess = false;if (AppInfo.applicationId == null) {return isMainProcess;}int pid = Process.myPid();for (RunningAppProcessInfo processInfo : ((ActivityManager) getContext().getSystemService("activity")).getRunningAppProcesses()) {if (AppInfo.applicationId.equals(processInfo.processName)) {foundPackage = true;if (processInfo.pid == pid) {isMainProcess = true;break;}}}if (isMainProcess || foundPackage) {return isMainProcess;}isMainProcess = true;Log.w("InstantRun", "considering this process main process:no process with this package found?!");return isMainProcess;}

Server源码

public class Server {private static final boolean POST_ALIVE_STATUS = false;private static final boolean RESTART_LOCALLY = false;private static int wrongTokenCount;private final Context context;private LocalServerSocket serverSocket;private Server(java.lang.String r1, android.content.Context r2) {/* JADX: method processing error */
/*
Error: jadx.core.utils.exceptions.DecodeException: Load method exception in method: com.android.tools.ir.server.Server.<init>(java.lang.String, android.content.Context):voidat jadx.core.dex.nodes.MethodNode.load(MethodNode.java:116)at jadx.core.dex.nodes.ClassNode.load(ClassNode.java:249)at jadx.core.ProcessClass.process(ProcessClass.java:34)at jadx.api.JadxDecompiler.processClass(JadxDecompiler.java:306)at jadx.api.JavaClass.decompile(JavaClass.java:62)
Caused by: java.lang.NullPointerExceptionat jadx.core.dex.nodes.MethodNode.addJump(MethodNode.java:370)at jadx.core.dex.nodes.MethodNode.initJumps(MethodNode.java:356)at jadx.core.dex.nodes.MethodNode.load(MethodNode.java:106)... 4 more
*//*r0 = this;r4.<init>();r4.context = r6;r0 = new android.net.LocalServerSocket;  Catch:{ IOException -> 0x005c }r0.<init>(r5);   Catch:{ IOException -> 0x005c }r4.serverSocket = r0;    Catch:{ IOException -> 0x005c }r0 = "InstantRun";   Catch:{ IOException -> 0x005c }r1 = 2;  Catch:{ IOException -> 0x005c }r0 = android.util.Log.isLoggable(r0, r1);    Catch:{ IOException -> 0x005c }if (r0 == 0) goto L_0x0039;  Catch:{ IOException -> 0x005c }L_0x0015:r0 = "InstantRun";   Catch:{ IOException -> 0x005c }r2 = new java.lang.StringBuilder;    Catch:{ IOException -> 0x005c }r2.<init>();     Catch:{ IOException -> 0x005c }r3 = "Starting server socket listening for package ";    Catch:{ IOException -> 0x005c }r2.append(r3);   Catch:{ IOException -> 0x005c }r2.append(r5);   Catch:{ IOException -> 0x005c }r3 = " on ";     Catch:{ IOException -> 0x005c }r2.append(r3);   Catch:{ IOException -> 0x005c }r3 = r4.serverSocket;    Catch:{ IOException -> 0x005c }r3 = r3.getLocalSocketAddress();     Catch:{ IOException -> 0x005c }r2.append(r3);   Catch:{ IOException -> 0x005c }r2 = r2.toString();  Catch:{ IOException -> 0x005c }android.util.Log.v(r0, r2);  Catch:{ IOException -> 0x005c }r4.startServer();r0 = "InstantRun";r0 = android.util.Log.isLoggable(r0, r1);if (r0 == 0) goto L_0x005b;r0 = "InstantRun";r1 = new java.lang.StringBuilder;r1.<init>();r2 = "Started server for package ";r1.append(r2);r1.append(r5);r1 = r1.toString();android.util.Log.v(r0, r1);return;L_0x005c:r0 = move-exception;r1 = "InstantRun";r2 = new java.lang.StringBuilder;r2.<init>();r3 = "IO Error creating local socket at ";r2.append(r3);r2.append(r5);r2 = r2.toString();android.util.Log.e(r1, r2, r0);return;*/throw new UnsupportedOperationException("Method not decompiled: com.android.tools.ir.server.Server.<init>(java.lang.String, android.content.Context):void");}static /* synthetic */ int access$208() {int i = wrongTokenCount;wrongTokenCount = i + 1;return i;}public static Server create(Context context) {return new Server(context.getPackageName(), context);}private void startServer() {try {new Thread(new SocketServerThread(this, null)).start();} catch (Throwable e) {if (Log.isLoggable("InstantRun", 6)) {Log.e("InstantRun", "Fatal error starting Instant Run server", e);}}}public void shutdown() {if (this.serverSocket != null) {try {this.serverSocket.close();} catch (IOException e) {}this.serverSocket = null;}}private static boolean isResourcePath(String path) {if (!path.equals("resources.ap_")) {if (!path.startsWith("res/")) {return false;}}return true;}private static boolean hasResources(List<ApplicationPatch> changes) {for (ApplicationPatch change : changes) {if (isResourcePath(change.getPath())) {return true;}}return false;}private int handlePatches(List<ApplicationPatch> changes, boolean hasResources, int updateMode) {if (hasResources) {FileManager.startUpdate();}for (ApplicationPatch change : changes) {String path = change.getPath();if (path.equals("classes.dex.3")) {updateMode = handleHotSwapPatch(updateMode, change);} else if (isResourcePath(path)) {updateMode = handleResourcePatch(updateMode, change, path);}}if (hasResources) {FileManager.finishUpdate(true);}return updateMode;}private static int handleResourcePatch(int updateMode, ApplicationPatch patch, String path) {if (Log.isLoggable("InstantRun", 2)) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("Received resource changes (");stringBuilder.append(path);stringBuilder.append(")");Log.v("InstantRun", stringBuilder.toString());}FileManager.writeAaptResources(path, patch.getBytes());return Math.max(updateMode, 2);}private int handleHotSwapPatch(int updateMode, ApplicationPatch patch) {if (Log.isLoggable("InstantRun", 2)) {Log.v("InstantRun", "Received incremental code patch");}try {String dexFile = FileManager.writeTempDexFile(patch.getBytes());if (dexFile == null) {Log.e("InstantRun", "No file to write the code to");return updateMode;}if (Log.isLoggable("InstantRun", 2)) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("Reading live code from ");stringBuilder.append(dexFile);Log.v("InstantRun", stringBuilder.toString());}Class<?> aClass = Class.forName("com.android.tools.ir.runtime.AppPatchesLoaderImpl", true, new DexClassLoader(dexFile, this.context.getCacheDir().getPath(), FileManager.getNativeLibraryFolder().getPath(), getClass().getClassLoader()));if (Log.isLoggable("InstantRun", 2)) {StringBuilder stringBuilder2 = new StringBuilder();stringBuilder2.append("Got the patcher class ");stringBuilder2.append(aClass);Log.v("InstantRun", stringBuilder2.toString());}PatchesLoader loader = (PatchesLoader) aClass.newInstance();if (Log.isLoggable("InstantRun", 2)) {StringBuilder stringBuilder3 = new StringBuilder();stringBuilder3.append("Got the patcher instance ");stringBuilder3.append(loader);Log.v("InstantRun", stringBuilder3.toString());}int i = 0;String[] getPatchedClasses = (String[]) aClass.getDeclaredMethod("getPatchedClasses", new Class[0]).invoke(loader, new Object[0]);if (Log.isLoggable("InstantRun", 2)) {Log.v("InstantRun", "Got the list of classes ");int length = getPatchedClasses.length;while (i < length) {String getPatchedClass = getPatchedClasses[i];StringBuilder stringBuilder4 = new StringBuilder();stringBuilder4.append("class ");stringBuilder4.append(getPatchedClass);Log.v("InstantRun", stringBuilder4.toString());i++;}}if (!loader.load()) {updateMode = 3;}return updateMode;} catch (Exception e) {Log.e("InstantRun", "Couldn't apply code changes", e);e.printStackTrace();updateMode = 3;} catch (Throwable e2) {Log.e("InstantRun", "Couldn't apply code changes", e2);updateMode = 3;}}private void restart(int updateMode, boolean incrementalResources, boolean toast) {if (Log.isLoggable("InstantRun", 2)) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("Finished loading changes; update mode =");stringBuilder.append(updateMode);Log.v("InstantRun", stringBuilder.toString());}if (updateMode != 0) {if (updateMode != 1) {StringBuilder stringBuilder2;List<Activity> activities = Restarter.getActivities(this.context, false);if (incrementalResources && updateMode == 2) {File file = FileManager.getExternalResourceFile();if (Log.isLoggable("InstantRun", 2)) {stringBuilder2 = new StringBuilder();stringBuilder2.append("About to update resource file=");stringBuilder2.append(file);stringBuilder2.append(", activities=");stringBuilder2.append(activities);Log.v("InstantRun", stringBuilder2.toString());}if (file != null) {MonkeyPatcher.monkeyPatchExistingResources(this.context, file.getPath(), activities);} else {Log.e("InstantRun", "No resource file found to apply");updateMode = 3;}}Activity activity = Restarter.getForegroundActivity(this.context);if (updateMode == 2) {if (activity != null) {if (Log.isLoggable("InstantRun", 2)) {Log.v("InstantRun", "Restarting activity only!");}boolean handledRestart = false;try {Object result = activity.getClass().getMethod("onHandleCodeChange", new Class[]{Long.TYPE}).invoke(activity, new Object[]{Long.valueOf(0)});if (Log.isLoggable("InstantRun", 2)) {stringBuilder2 = new StringBuilder();stringBuilder2.append("Activity ");stringBuilder2.append(activity);stringBuilder2.append(" provided manual restart method; return ");stringBuilder2.append(result);Log.v("InstantRun", stringBuilder2.toString());}if (Boolean.TRUE.equals(result)) {handledRestart = true;if (toast) {Restarter.showToast(activity, "Applied changes");}}} catch (Throwable th) {}if (!handledRestart) {if (toast) {Restarter.showToast(activity, "Applied changes, restarted activity");}Restarter.restartActivityOnUiThread(activity);}return;}if (Log.isLoggable("InstantRun", 2)) {Log.v("InstantRun", "No activity found, falling through to do a full app restart");}updateMode = 3;}if (updateMode != 3) {if (Log.isLoggable("InstantRun", 6)) {StringBuilder stringBuilder3 = new StringBuilder();stringBuilder3.append("Unexpected update mode: ");stringBuilder3.append(updateMode);Log.e("InstantRun", stringBuilder3.toString());}return;}if (Log.isLoggable("InstantRun", 2)) {Log.v("InstantRun", "Waiting for app to be killed and restarted by the IDE...");}return;}}if (Log.isLoggable("InstantRun", 2)) {Log.v("InstantRun", "Applying incremental code without restart");}if (toast) {Activity foreground = Restarter.getForegroundActivity(this.context);if (foreground != null) {Restarter.showToast(foreground, "Applied code changes without activity restart");} else if (Log.isLoggable("InstantRun", 2)) {Log.v("InstantRun", "Couldn't show toast: no activity found");}}}
}

重点代码

private void startServer() {try {new Thread(new SocketServerThread(this, null)).start();} catch (Throwable e) {if (Log.isLoggable("InstantRun", 6)) {Log.e("InstantRun", "Fatal error starting Instant Run server", e);}}}

base.apk

image.png

base.apk就有很多个apk。那么到底是如何实现多dex加载的呢?不通过multidex技术,仅仅是通过内容提供者.

而上面的几个dex并不是主程序的,也就是说真正的代码被分割在data/app/包名/下,
包含了如下:split_lib_dependencies_apk.apk以及 split_lib_slice_[0_9]_.apk的10个apk中。

ok,下面的分析交给大家了,我只是遇到了一个问题,就是一个插件apk里面多个dex 在解压后加载然后融合出现了问题,融合貌似成功了,但是还是找不到,我特么快疯了。 各位大佬懂得求支个招。哈哈

另外懂了大概即时运行原理,那么也自然可以让xposed免重启技术兼容即时运行,但是无奈老夫功力欠缺,暂时先放一放,等功力提升的时候再研究研究。 另外对于官方的即时运行apk我都没玩过,也许我这分析半天还没有一个官方的demo详细,逆向只是野路子,哈哈。

另外我还发愁的一个问题就是开发工具不能自动识别设备、或针对部分项目不开启即时运行,对不同设备自动切换非即时运行,搞的我搞逆向插件研究的时候总是要把即时运行给关了。不然死活都激活不了。

这篇关于即时运行app的逆向分析以及原理浅析以及谈谈xposed免重启更新是否能够兼容即时运行的可行性...的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/959142

相关文章

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

22.手绘Spring DI运行时序图

1.依赖注入发生的时间 当Spring loC容器完成了 Bean定义资源的定位、载入和解析注册以后,loC容器中已经管理类Bean 定义的相关数据,但是此时loC容器还没有对所管理的Bean进行依赖注入,依赖注入在以下两种情况 发生: 、用户第一次调用getBean()方法时,loC容器触发依赖注入。 、当用户在配置文件中将<bean>元素配置了 lazy-init二false属性,即让

21.手绘Spring IOC运行时序图

1.再谈IOC与 DI IOC(lnversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创 建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让 容器知道需要创建的对象与对象的关系。这个描述最具体表现就是我们所看到的配置文件。 DI(Dependency Injection)依赖注入:就是指对象是被动接受依赖类

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

JavaScript全屏,监听页面是否全屏

在JavaScript中,直接监听浏览器是否进入全屏模式并不直接支持,因为全屏API主要是关于请求和退出全屏模式的,而没有直接的监听器可以告知页面何时进入或退出全屏模式。但是,你可以通过在你的代码中跟踪全屏状态的改变来模拟这个功能。 以下是一个基本的示例,展示了如何使用全屏API来请求全屏模式,并在请求成功或失败时更新一个状态变量: javascriptlet isInFullscreen =

java中查看函数运行时间和cpu运行时间

android开发调查性能问题中有一个现象,函数的运行时间远低于cpu执行时间,因为函数运行期间线程可能包含等待操作。native层可以查看实际的cpu执行时间和函数执行时间。在java中如何实现? 借助AI得到了答案 import java.lang.management.ManagementFactory;import java.lang.management.Threa

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

数据库原理与安全复习笔记(未完待续)

1 概念 产生与发展:人工管理阶段 → \to → 文件系统阶段 → \to → 数据库系统阶段。 数据库系统特点:数据的管理者(DBMS);数据结构化;数据共享性高,冗余度低,易于扩充;数据独立性高。DBMS 对数据的控制功能:数据的安全性保护;数据的完整性检查;并发控制;数据库恢复。 数据库技术研究领域:数据库管理系统软件的研发;数据库设计;数据库理论。数据模型要素 数据结构:描述数据库