本次加密的代码如下:
let info = "yashu"; toastLog(info);
环境
雷电模拟器安卓版本: 7.1.2
autojs版本: 8.8.20
jadx-gui: 1.2.0
frida版本: frida-server-15.1.1-android-x86
脚本加密方式: 单文件打包, 离线Dex加密
hook记录
01: hook代码
Java.perform(function () { function printObj(obj) { var arr = []; for (var k in obj) { // let objType = Object.prototype.toString.call(obj.k); arr.push(k + " = " + obj[k]); } arr.sort(); console.log("printObj====================开始"); console.log(arr.join("\n")); console.log("printObj====================结束"); } function trace() { var throwable = Java.use("java.lang.Throwable"); send( "Backtrace:===" + throwable .$new() .getStackTrace() .map((traceElement) => traceElement.toString()) .join("===") ); } // 获得Toast组件 var Toast = Java.use("android.widget.Toast"); var makeText = Toast.makeText; var String = Java.use("java.lang.String"); makeText.overload("android.content.Context", "java.lang.CharSequence", "int").implementation = function ( context, content, time ) { console.log("修改toast内容"); var content = "牙叔教程 超级棒棒\n".repeat(10); var hookContent = String.$new(content); trace(); return this.makeText(context, hookContent, time); }; });
02: hook Toast, 堆栈如下
小技巧: win10自带便利贴功能, 把堆栈放到便利贴, 并且使用DeskPins置顶, 随时查看
android.widget.Toast.makeText(Native Method) d.b.b.h.f.J0(:1) com.stardust.autojs.core.util.UiHandler.a(:1) d.g.c.m.n.a.run() android.os.Handler.handleCallback(Handler.java:751) android.os.Handler.dispatchMessage(Handler.java:95) android.os.Looper.loop(Looper.java:154) android.app.ActivityThread.main(ActivityThread.java:6161) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
03: 分析
makeText是我们hook的方法, 这是androidToast类的基本方法,
上一个方法是d.b.b.h.f.J0
这是jadx分析出的代码, m2029J0就是J0, 方法上面有注释rename
/* renamed from: J0 */ public static Toast m2029J0(Context context, CharSequence charSequence, int i) { Context applicationContext = context.getApplicationContext(); int i2 = C3007b.f4998a; Toast makeText = Toast.makeText(applicationContext, charSequence, i); C3007b.m3952a(makeText.getView(), new C3003a(applicationContext, makeText)); return new C3007b(applicationContext, makeText); }
这是一个静态方法, 三个参数,
context 上下文,
charSequence 应该是toast的内容
int 时间
返回值是new C3007b(applicationContext, makeText)
04: C3007b
/* renamed from: i.a.a.a.b */ public final class C3007b extends Toast { public C3007b(Context context, @NonNull Toast toast) { super(context); this.f4999b = toast; } }
没找到什么有用的信息
那么我们从toast的内容入手,
脚本要用toast, 就必然要修改toast的参数, 我们先hook一下toast的内容
hook 代码
Java.perform(function () { var Toast = Java.use("android.widget.Toast"); Toast.makeText.overload("android.content.Context", "java.lang.CharSequence", "int").implementation = function ( context, content, time ) { console.log(content); // yashu console.log(time); // 0 return this.makeText(context, content, time); }; });
time=0, 在Toast类中
public static final int LENGTH_SHORT = 0;
content=yashu
我们hook一下d.b.b.h.f.J0看他的参数是不是yashu
Java.perform(function () { var f = Java.use("d.b.b.h.f"); f.J0.overload("android.content.Context", "java.lang.CharSequence", "int").implementation = function ( context, charSequence, i ) { console.log(context); // com.stardust.autojs.inrt.App@b5993e console.log(charSequence); // yashu console.log(i); // 0 return this.J0(context, charSequence, i); }; });
果然是yashu
接下来分析一下yashu是在哪里设置的
顺藤摸瓜, 看看是谁给J0传入的参数
这是上面的堆栈, 怕大家忘了, 再贴一次
android.widget.Toast.makeText(Native Method) d.b.b.h.f.J0(:1) com.stardust.autojs.core.util.UiHandler.a(:1) d.g.c.m.n.a.run() android.os.Handler.handleCallback(Handler.java:751) android.os.Handler.dispatchMessage(Handler.java:95) android.os.Looper.loop(Looper.java:154) android.app.ActivityThread.main(ActivityThread.java:6161) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:892) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
我们先看看a方法
com.stardust.autojs.core.util.UiHandler.a
package com.stardust.autojs.core.util; import android.content.Context; import android.os.Handler; import android.os.Looper; import p015d.p019b.p022b.p046h.C1542f; import p204i.p205a.p206a.p207a.C3007b; public class UiHandler extends Handler { private Context mContext; public UiHandler(Context context) { super(Looper.getMainLooper()); this.mContext = context; } /* renamed from: a */ public void mo15354a(String str) { Context context = this.mContext; if (str == null) { str = ""; } ((C3007b) C1542f.m2029J0(context, str, 0)).f4999b.show(); } }
a方法, 即mo15354a, 他只有一个参数str, 必然就是yashu
继续顺腾摸瓜, d.g.c.m.n.a.run()
package p015d.p101g.p103c.p104m.p126n; import com.stardust.autojs.core.util.UiHandler; /* renamed from: d.g.c.m.n.a */ public final /* synthetic */ class RunnableC2471a implements Runnable { /* renamed from: d */ public final /* synthetic */ UiHandler f4062d; /* renamed from: e */ public final /* synthetic */ String f4063e; public /* synthetic */ RunnableC2471a(UiHandler uiHandler, String str) { this.f4062d = uiHandler; this.f4063e = str; } public final void run() { this.f4062d.mo15354a(this.f4063e); } }
这里就找到设置str为yashu的地方了
就是
public /* synthetic */ RunnableC2471a(UiHandler uiHandler, String str) { this.f4062d = uiHandler; this.f4063e = str; }
现在来hook一下d.g.c.m.n.a的实例, 也就是jadx里面的
大家记住, 类名要用frida打印的类名
jadx的类名和堆栈的类名不一样, 但是有备注
hook代码
Java.perform(function () { function trace() { var throwable = Java.use("java.lang.Throwable"); send( "Backtrace:\n\t" + throwable .$new() .getStackTrace() .map((traceElement) => traceElement.toString()) .join("===") ); } var f = Java.use("d.g.c.m.n.a"); f.$init.implementation = function (uiHandler, str) { console.log(uiHandler); // Handler (com.stardust.autojs.core.util.UiHandler) {9e57f60} console.log(str); // yashu trace(); return this.$init(uiHandler, str); }; });
堆栈
d.g.c.m.n.a.<init>(Native Method) com.stardust.autojs.core.util.UiHandler.toast() com.stardust.autojs.runtime.ScriptRuntime.toast() java.lang.reflect.Method.invoke(Native Method) org.mozilla.javascript.MemberBox.invoke() org.mozilla.javascript.NativeJavaMethod.call() org.mozilla.javascript.Interpreter.interpretLoop() org.mozilla.javascript.Interpreter.interpret() org.mozilla.javascript.InterpretedFunction.call() org.mozilla.javascript.optimizer.OptRuntime.callName() org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e._c_script_0(:2) org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.call() org.mozilla.javascript.ContextFactory.doTopCall() org.mozilla.javascript.ScriptRuntime.doTopCall() org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.call() org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.exec() d.g.c.o.g.a.doExecution(:2) com.stardust.autojs.engine.JavaScriptEngine.execute() com.stardust.autojs.engine.LoopBasedJavaScriptEngine.access$001() d.g.c.n.c.run(:2) android.os.Handler.handleCallback(Handler.java:751) android.os.Handler.dispatchMessage(Handler.java:95) android.os.Looper.loop(Looper.java:154) com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute() com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute() com.stardust.autojs.execution.LoopedBasedJavaScriptExecution.doExecution() com.stardust.autojs.execution.RunnableScriptExecution.execute() com.stardust.autojs.execution.RunnableScriptExecution.execute() com.stardust.autojs.execution.RunnableScriptExecution.run() java.lang.Thread.run(Thread.java:761)
接下来还是继续顺藤摸瓜, 一顿分析, 也可以说是随便逛逛
package com.stardust.autojs.core.util; public class UiHandler extends Handler { public void toast(String str) { post(new RunnableC2471a(this, str)); } }
接下来逛到这里了
com.stardust.autojs.runtime.ScriptRuntime
这里定义了autojs的全局方法, 比如
public void toast(String str) { this.uiHandler.toast(str); } public void unloadAll(boolean z) { C2496a androidClassLoader = getAndroidClassLoader(); synchronized (androidClassLoader) { androidClassLoader.f4107c.clear(); if (z) { PFiles.deleteRecursively(androidClassLoader.f4108d, false); } } } public void setClip(String str) { if (C1542f.m2005B0()) { C1542f.m2109l1(this.uiHandler.getContext(), str); return; } VolatileDispose volatileDispose = new VolatileDispose(); this.uiHandler.post(new RunnableC2514g(this, str, volatileDispose)); volatileDispose.blockedGet(); } public String getClip() { if (C1542f.m2005B0()) { return C1542f.m2046P(this.uiHandler.getContext()).toString(); } VolatileDispose volatileDispose = new VolatileDispose(); this.uiHandler.post(new RunnableC2515h(this, volatileDispose)); return (String) volatileDispose.blockedGetOrThrow(ScriptInterruptedException.class); } public UiSelector selector() { return new UiSelector(this.accessibilityBridge); } public AccessibilityBridge getAccessibilityBridge() { return this.accessibilityBridge; } public C2496a getAndroidClassLoader() { return (C2496a) ContextFactory.getGlobal().getApplicationClassLoader(); }
不要忘了我们的目标, 查看toast内容的传递链
继续顺腾摸瓜, 不要忘了堆栈, 再贴一次
d.g.c.m.n.a.<init>(Native Method) com.stardust.autojs.core.util.UiHandler.toast() com.stardust.autojs.runtime.ScriptRuntime.toast() // 这里定义了autojs全局属性 java.lang.reflect.Method.invoke(Native Method) org.mozilla.javascript.MemberBox.invoke() org.mozilla.javascript.NativeJavaMethod.call() org.mozilla.javascript.Interpreter.interpretLoop() org.mozilla.javascript.Interpreter.interpret() org.mozilla.javascript.InterpretedFunction.call() org.mozilla.javascript.optimizer.OptRuntime.callName() org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e._c_script_0(:2) org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.call() org.mozilla.javascript.ContextFactory.doTopCall() org.mozilla.javascript.ScriptRuntime.doTopCall() org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.call() org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.exec() d.g.c.o.g.a.doExecution(:2) com.stardust.autojs.engine.JavaScriptEngine.execute() com.stardust.autojs.engine.LoopBasedJavaScriptEngine.access$001() d.g.c.n.c.run(:2) android.os.Handler.handleCallback(Handler.java:751) android.os.Handler.dispatchMessage(Handler.java:95) android.os.Looper.loop(Looper.java:154) com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute() com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute() com.stardust.autojs.execution.LoopedBasedJavaScriptExecution.doExecution() com.stardust.autojs.execution.RunnableScriptExecution.execute() com.stardust.autojs.execution.RunnableScriptExecution.execute() com.stardust.autojs.execution.RunnableScriptExecution.run() java.lang.Thread.run(Thread.java:761)
org.mozilla.javascript.MemberBox.invoke()
/** * @description: * @param {Object} obj 调用基础方法的对象; * @param {Object[]} objArr method方法调用中使用的参数; * @return {*} */ public Object invoke(Object obj, Object[] objArr) { Method method = method(); return method.invoke(obj, objArr); }
org.mozilla.javascript.NativeJavaMethod.call()
mozilla官方文档
https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/NativeJavaMethod.html
public java.lang.Object call(Context cx, Scriptable scope, Scriptable thisObj, java.lang.Object[] args)
Description copied from class: BaseFunction
Should be overridden.
Specified by:
Specified by:
Overrides:
call in class BaseFunction
Parameters:
cx- the current Context for this thread
scope- the scope to execute the function relative to. This is set to the value returned by getParentScope() except when the function is called from a closure.
thisObj- the JavaScriptthisobject
args- the array of arguments
Returns:
the result of the call
org.mozilla.javascript.Interpreter.interpretLoop()
private static java.lang.Object interpretLoop(org.mozilla.javascript.Context r51, org.mozilla.javascript.Interpreter.CallFrame r52, java.lang.Object r53) { /* // Method dump skipped, instructions count: 6722 */ throw new UnsupportedOperationException("Method not decompiled: org.mozilla.javascript.Interpreter.interpretLoop(org.mozilla.javascript.Context, org.mozilla.javascript.Interpreter$CallFrame, java.lang.Object):java.lang.Object"); }
org.mozilla.javascript.Interpreter.interpret()
public static Object interpret(InterpretedFunction interpretedFunction, Context context, Scriptable scriptable, Scriptable scriptable2, Object[] objArr) { if (!ScriptRuntime.hasTopCall(context)) { Kit.codeBug(); } Object obj = context.interpreterSecurityDomain; Object obj2 = interpretedFunction.securityDomain; if (obj != obj2) { context.interpreterSecurityDomain = obj2; try { return interpretedFunction.securityController.callWithDomain(obj2, context, interpretedFunction, scriptable, scriptable2, objArr); } finally { context.interpreterSecurityDomain = obj; } } else { CallFrame callFrame = new CallFrame(); initFrame(context, scriptable, scriptable2, objArr, null, 0, objArr.length, interpretedFunction, null, callFrame); callFrame.isContinuationsTopFrame = context.isContinuationsTopCall; context.isContinuationsTopCall = false; return interpretLoop(context, callFrame, null); } }
org.mozilla.javascript.InterpretedFunction.call()
package org.mozilla.javascript; public final class InterpretedFunction extends NativeFunction implements Script { @Override // org.mozilla.javascript.Callable, org.mozilla.javascript.BaseFunction, org.mozilla.javascript.Function public Object call(Context context, Scriptable scriptable, Scriptable scriptable2, Object[] objArr) { return !ScriptRuntime.hasTopCall(context) ? ScriptRuntime.doTopCall(this, context, scriptable, scriptable2, objArr, this.idata.isStrict) : Interpreter.interpret(this, context, scriptable, scriptable2, objArr); } }
org.mozilla.javascript.optimizer.OptRuntime.callName()
package org.mozilla.javascript.optimizer; public final class OptRuntime extends ScriptRuntime { public static Object callName(Object[] objArr, String str, Context context, Scriptable scriptable) { return ScriptRuntime.getNameFunctionAndThis(str, context, scriptable).call(context, scriptable, ScriptRuntime.lastStoredScriptable(context), objArr); } }
org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e._c_script_0(:2)
package org.autojs.autojspro.gen; public class _7a9076d6d94e62c13d641aa71f19ae8e extends NativeFunction implements Script { private static Object _c_script_0(_7a9076d6d94e62c13d641aa71f19ae8e _7a9076d6d94e62c13d641aa71f19ae8e, Context context, Scriptable scriptable, Scriptable scriptable2, Object[] objArr) { ScriptRuntime.initScript(_7a9076d6d94e62c13d641aa71f19ae8e, scriptable2, context, scriptable, false); Object obj = Undefined.instance; ScriptRuntime.addInstructionCount(context, 1); ScriptRuntime.addInstructionCount(context, 1); ScriptRuntime.setName(ScriptRuntime.bind(context, scriptable, "info"), "yashu", context, scriptable, "info"); Object callName = OptRuntime.callName(new Object[]{ScriptRuntime.name(context, scriptable, "info")}, "toastLog", context, scriptable); ScriptRuntime.addInstructionCount(context, 63); return callName; } }
这个方法里面可以看到源码里的大部分单词
我们的源码, 你还记得吗
let info = "yashu"; toastLog(info);
info, yashu, toastLog这里都有
继续顺藤摸瓜往上看看
org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.call()
和上面的方法属于同一个类
@Override // org.mozilla.javascript.Callable, org.mozilla.javascript.BaseFunction, org.mozilla.javascript.Function public final Object call(Context context, Scriptable scriptable, Scriptable scriptable2, Object[] objArr) { return !ScriptRuntime.hasTopCall(context) ? ScriptRuntime.doTopCall(this, context, scriptable, scriptable2, objArr, false) : _c_script_0(this, context, scriptable, scriptable2, objArr); }
org.mozilla.javascript.ContextFactory.doTopCall()
package org.mozilla.javascript; public class ContextFactory { public Object doTopCall(Callable callable, Context context, Scriptable scriptable, Scriptable scriptable2, Object[] objArr) { Object call = callable.call(context, scriptable, scriptable2, objArr); return call instanceof ConsString ? call.toString() : call; } }
org.mozilla.javascript.ScriptRuntime.doTopCall()
package org.mozilla.javascript; public class ScriptRuntime { public static Object doTopCall(Callable callable, Context context, Scriptable scriptable, Scriptable scriptable2, Object[] objArr) { return doTopCall(callable, context, scriptable, scriptable2, objArr, context.isTopLevelStrict); } public static Object doTopCall(Callable callable, Context context, Scriptable scriptable, Scriptable scriptable2, Object[] objArr, boolean z) { if (scriptable == null) { throw new IllegalArgumentException(); } else if (context.topCallScope == null) { context.topCallScope = ScriptableObject.getTopLevelScope(scriptable); context.useDynamicScope = context.hasFeature(7); boolean z2 = context.isTopLevelStrict; context.isTopLevelStrict = z; try { Object doTopCall = context.getFactory().doTopCall(callable, context, scriptable, scriptable2, objArr); context.topCallScope = null; context.cachedXMLLib = null; context.isTopLevelStrict = z2; if (context.currentActivationCall == null) { return doTopCall; } throw new IllegalStateException(); } catch (Throwable th) { context.topCallScope = null; context.cachedXMLLib = null; context.isTopLevelStrict = z2; if (context.currentActivationCall != null) { throw new IllegalStateException(); } throw th; } } else { throw new IllegalStateException(); } } }
org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.call() // 上面已经贴过一次了
org.autojs.autojspro.gen._7a9076d6d94e62c13d641aa71f19ae8e.exec()
package org.autojs.autojspro.gen; public class _7a9076d6d94e62c13d641aa71f19ae8e extends NativeFunction implements Script { @Override // org.mozilla.javascript.Script public final Object exec(Context context, Scriptable scriptable) { return call(context, scriptable, scriptable, null); } }
d.g.c.o.g.a.doExecution(:2)
package p015d.p101g.p103c.p129o.p130g; import android.content.Context; import com.stardust.autojs.engine.LoopBasedJavaScriptEngine; import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.script.JavaScriptFileSource; import com.stardust.autojs.script.JavaScriptSource; import java.io.File; import java.util.Map; import java.util.Objects; import org.mozilla.javascript.CompileContext; import org.mozilla.javascript.Script; import p186h.p195q.p197c.C2943j; /* renamed from: d.g.c.o.g.a */ public final class C2484a extends LoopBasedJavaScriptEngine { /* renamed from: a */ public final File f4084a; /* JADX INFO: super call moved to the top of the method (can break code semantics) */ public C2484a(Context context, File file, Map<String, ? extends Object> map) { super(context, map); C2943j.m3908e(context, "context"); C2943j.m3908e(file, "projectDir"); C2943j.m3908e(map, "engineArgs"); C2943j.m3908e(context, "context"); C2943j.m3908e(map, "engineArgs"); this.f4084a = file; } /* JADX WARNING: Code restructure failed: missing block: B:35:0x0099, code lost: r1 = move-exception; */ /* JADX WARNING: Code restructure failed: missing block: B:36:0x009a, code lost: p015d.p019b.p022b.p046h.C1542f.m2134u(r11, r0); */ /* JADX WARNING: Code restructure failed: missing block: B:37:0x009d, code lost: throw r1; */ /* JADX WARNING: Removed duplicated region for block: B:17:0x0050 */ /* JADX WARNING: Removed duplicated region for block: B:19:0x0055 A[SYNTHETIC, Splitter:B:19:0x0055] */ /* renamed from: b */ /* Code decompiled incorrectly, please refer to instructions dump. */ private java.lang.Object m3402b(com.stardust.autojs.script.JavaScriptSource r11) { /* // Method dump skipped, instructions count: 206 */ throw new UnsupportedOperationException("Method not decompiled: p015d.p101g.p103c.p129o.p130g.C2484a.m3402b(com.stardust.autojs.script.JavaScriptSource):java.lang.Object"); } @Override // com.stardust.autojs.engine.RhinoJavaScriptEngine, com.stardust.autojs.engine.JavaScriptEngine public Object doExecution(JavaScriptSource javaScriptSource) { C2943j.m3908e(javaScriptSource, ScriptEngine.TAG_SOURCE); if (!(javaScriptSource instanceof JavaScriptFileSource)) { return m3402b(javaScriptSource); } try { Class<?> cls = Class.forName(CompileContext.Companion.generateClassName(this.f4084a, ((JavaScriptFileSource) javaScriptSource).f459g)); C2943j.m3907d(cls, "Class.forName(className)"); Object newInstance = cls.newInstance(); Objects.requireNonNull(newInstance, "null cannot be cast to non-null type org.mozilla.javascript.Script"); return ((Script) newInstance).exec(getContext(), getScriptable()); } catch (Exception unused) { return m3402b(javaScriptSource); } } }
com.stardust.autojs.engine.LoopBasedJavaScriptEngine.access$001()
jadx里面找不到access$001这个方法, 我们来hook一下
hook代码
Java.perform(function () { function trace() { var throwable = Java.use("java.lang.Throwable"); send( "Backtrace:\n\t" + throwable .$new() .getStackTrace() .map((traceElement) => traceElement.toString()) .join("===") ); } var LoopBasedJavaScriptEngine = Java.use("com.stardust.autojs.engine.LoopBasedJavaScriptEngine"); LoopBasedJavaScriptEngine.access$001.overload( "com.stardust.autojs.engine.LoopBasedJavaScriptEngine", "com.stardust.autojs.script.JavaScriptSource" ).implementation = function (a, b) { console.log(a); // ScriptEngine@f384d53{id=5,source='main.js',cwd='/data/user/0/com.example.script1631687221234/files/project'} console.log(b); // main.js trace(); return this.access$001(a, b); }; });
堆栈和上面的堆栈一模一样, 为啥jadx里面就找不到呢
com.stardust.autojs.engine.LoopBasedJavaScriptEngine.access$001(Native Method) d.g.c.n.c.run(:2) android.os.Handler.handleCallback(Handler.java:751) android.os.Handler.dispatchMessage(Handler.java:95) android.os.Looper.loop(Looper.java:154) com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute() com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute() com.stardust.autojs.execution.LoopedBasedJavaScriptExecution.doExecution() com.stardust.autojs.execution.RunnableScriptExecution.execute() com.stardust.autojs.execution.RunnableScriptExecution.execute() com.stardust.autojs.execution.RunnableScriptExecution.run() java.lang.Thread.run(Thread.java:761)
jadx找不到, 就用mt查看classes.dex吧
mt管理器找到的access$001信息如下
// // Decompiled by Jadx - 955ms // package com.stardust.autojs.engine; import android.app.Activity; import android.content.Context; import android.os.Handler; import android.os.Looper; import com.stardust.autojs.core.looper.LooperHelper; import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.ScriptSource; import d.g.c.n.c; import java.util.Map; public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine { private Handler mHandler; private boolean mLooping = false; public LoopBasedJavaScriptEngine(Context context, Map<String, Object> map) { super(context, map); } public static /* synthetic */ Object access$001(LoopBasedJavaScriptEngine loopBasedJavaScriptEngine, JavaScriptSource javaScriptSource) { return LoopBasedJavaScriptEngine.super.execute(javaScriptSource); } public synchronized void destroy() { LooperHelper.quitForThread(getThread()); LoopBasedJavaScriptEngine.super.destroy(); } public Object execute(JavaScriptSource javaScriptSource) { execute(javaScriptSource, (ExecuteCallback) null); return null; } public /* bridge */ /* synthetic */ Object execute(ScriptSource scriptSource) { return execute((JavaScriptSource) scriptSource); } /* JADX WARNING: Can't wrap try/catch for region: R(4:5|6|10|13) */ /* JADX WARNING: Code restructure failed: missing block: B:7:0x001f, code lost: r2 = move-exception; */ /* JADX WARNING: Code restructure failed: missing block: B:8:0x0020, code lost: r1.mLooping = false; */ /* JADX WARNING: Code restructure failed: missing block: B:9:0x0023, code lost: throw r2; */ /* JADX WARNING: Missing exception handler attribute for start block: B:5:0x001b */ /* JADX WARNING: Removed duplicated region for block: B:5:0x001b A[LOOP:0: B:5:0x001b->B:6:?, LOOP_START, SYNTHETIC, Splitter:B:5:0x001b] */ public void execute(ScriptSource scriptSource, ExecuteCallback executeCallback) { this.mHandler.post(new c(this, scriptSource, executeCallback)); if (!this.mLooping && Looper.myLooper() != Looper.getMainLooper()) { this.mLooping = true; while (true) { Looper.loop(); return; } } } public void forceStop() { LooperHelper.quitForThread(getThread()); Activity activity = (Activity) getTag("activity"); if (activity != null) { activity.finish(); } if (Looper.getMainLooper().getThread() != getThread()) { LoopBasedJavaScriptEngine.super.forceStop(); } } public void init() { LooperHelper.prepare(); this.mHandler = new Handler(); LoopBasedJavaScriptEngine.super.init(); } }
d.g.c.n.c.run(:2) jadx也没有搞出来, 还是用mt管理器查看
// // Decompiled by Jadx - 916ms // package d.g.c.n; import com.stardust.autojs.engine.LoopBasedJavaScriptEngine; import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.ScriptSource; import java.util.Objects; import org.mozilla.javascript.ContinuationPending; public final /* synthetic */ class c implements Runnable { public final /* synthetic */ LoopBasedJavaScriptEngine d; public final /* synthetic */ ScriptSource e; public final /* synthetic */ LoopBasedJavaScriptEngine.ExecuteCallback f; public /* synthetic */ c(LoopBasedJavaScriptEngine loopBasedJavaScriptEngine, ScriptSource scriptSource, LoopBasedJavaScriptEngine.ExecuteCallback executeCallback) { this.d = loopBasedJavaScriptEngine; this.e = scriptSource; this.f = executeCallback; } public final void run() { LoopBasedJavaScriptEngine loopBasedJavaScriptEngine = this.d; JavaScriptSource javaScriptSource = this.e; LoopBasedJavaScriptEngine.ExecuteCallback executeCallback = this.f; Objects.requireNonNull(loopBasedJavaScriptEngine); try { Object access$001 = LoopBasedJavaScriptEngine.access$001(loopBasedJavaScriptEngine, javaScriptSource); if (executeCallback != null) { executeCallback.onResult(access$001); } } catch (ContinuationPending unused) { } catch (Throwable th) { if (executeCallback != null) { executeCallback.onException(th); return; } throw th; } } }
android.os.Handler.handleCallback(Handler.java:751)
android.os.Handler.dispatchMessage(Handler.java:95)
android.os.Looper.loop(Looper.java:154)
jadx和mt管理器都没有, 直接github搜代码吧, 我认为这个不重要, 自己搜一下
Android -- Looper.prepare()和Looper.loop() —深入版
com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute()
jadx里面是这样的
package com.stardust.autojs.engine; public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine { @Override // com.stardust.autojs.engine.JavaScriptEngine public Object execute(JavaScriptSource javaScriptSource) { execute(javaScriptSource, null); return null; } /* JADX WARNING: Can't wrap try/catch for region: R(4:5|6|10|13) */ /* JADX WARNING: Code restructure failed: missing block: B:7:0x001f, code lost: r2 = move-exception; */ /* JADX WARNING: Code restructure failed: missing block: B:8:0x0020, code lost: r1.mLooping = false; */ /* JADX WARNING: Code restructure failed: missing block: B:9:0x0023, code lost: throw r2; */ /* JADX WARNING: Missing exception handler attribute for start block: B:5:0x001b */ /* JADX WARNING: Removed duplicated region for block: B:5:0x001b A[LOOP:0: B:5:0x001b->B:6:?, LOOP_START, SYNTHETIC, Splitter:B:5:0x001b] */ /* Code decompiled incorrectly, please refer to instructions dump. */ public void execute(com.stardust.autojs.script.ScriptSource r2, com.stardust.autojs.engine.LoopBasedJavaScriptEngine.ExecuteCallback r3) { /* r1 = this; d.g.c.n.c r0 = new d.g.c.n.c r0.<init>(r1, r2, r3) android.os.Handler r2 = r1.mHandler r2.post(r0) boolean r2 = r1.mLooping if (r2 != 0) goto L_0x0024 android.os.Looper r2 = android.os.Looper.myLooper() android.os.Looper r3 = android.os.Looper.getMainLooper() if (r2 == r3) goto L_0x0024 r2 = 1 r1.mLooping = r2 L_0x001b: android.os.Looper.loop() // Catch:{ ContinuationPending -> 0x001b, all -> 0x001f } goto L_0x0024 L_0x001f: r2 = move-exception r3 = 0 r1.mLooping = r3 throw r2 L_0x0024: return */ throw new UnsupportedOperationException("Method not decompiled: com.stardust.autojs.engine.LoopBasedJavaScriptEngine.execute(com.stardust.autojs.script.ScriptSource, com.stardust.autojs.engine.LoopBasedJavaScriptEngine$ExecuteCallback):void"); } }
mt管理器里面是这样的
// // Decompiled by Jadx - 955ms // package com.stardust.autojs.engine; import android.app.Activity; import android.content.Context; import android.os.Handler; import android.os.Looper; import com.stardust.autojs.core.looper.LooperHelper; import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.ScriptSource; import d.g.c.n.c; import java.util.Map; public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine { private Handler mHandler; private boolean mLooping = false; public LoopBasedJavaScriptEngine(Context context, Map<String, Object> map) { super(context, map); } public static /* synthetic */ Object access$001(LoopBasedJavaScriptEngine loopBasedJavaScriptEngine, JavaScriptSource javaScriptSource) { return LoopBasedJavaScriptEngine.super.execute(javaScriptSource); } public Object execute(JavaScriptSource javaScriptSource) { execute(javaScriptSource, (ExecuteCallback) null); return null; } public /* bridge */ /* synthetic */ Object execute(ScriptSource scriptSource) { return execute((JavaScriptSource) scriptSource); } /* JADX WARNING: Can't wrap try/catch for region: R(4:5|6|10|13) */ /* JADX WARNING: Code restructure failed: missing block: B:7:0x001f, code lost: r2 = move-exception; */ /* JADX WARNING: Code restructure failed: missing block: B:8:0x0020, code lost: r1.mLooping = false; */ /* JADX WARNING: Code restructure failed: missing block: B:9:0x0023, code lost: throw r2; */ /* JADX WARNING: Missing exception handler attribute for start block: B:5:0x001b */ /* JADX WARNING: Removed duplicated region for block: B:5:0x001b A[LOOP:0: B:5:0x001b->B:6:?, LOOP_START, SYNTHETIC, Splitter:B:5:0x001b] */ public void execute(ScriptSource scriptSource, ExecuteCallback executeCallback) { this.mHandler.post(new c(this, scriptSource, executeCallback)); if (!this.mLooping && Looper.myLooper() != Looper.getMainLooper()) { this.mLooping = true; while (true) { Looper.loop(); return; } } } }
com.stardust.autojs.execution.LoopedBasedJavaScriptExecution.doExecution()
package com.stardust.autojs.execution; import com.stardust.autojs.core.looper.Loopers; import com.stardust.autojs.engine.LoopBasedJavaScriptEngine; import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngineManager; import com.stardust.autojs.script.JavaScriptSource; public class LoopedBasedJavaScriptExecution extends RunnableScriptExecution { public LoopedBasedJavaScriptExecution(ScriptEngineManager scriptEngineManager, ScriptExecutionTask scriptExecutionTask) { super(scriptEngineManager, scriptExecutionTask); } @Override // com.stardust.autojs.execution.RunnableScriptExecution public Object doExecution(ScriptEngine scriptEngine) { scriptEngine.setTag(ScriptEngine.TAG_SOURCE, getSource()); getListener().onStart(this); sleep(getConfig().getDelay()); final LoopBasedJavaScriptEngine loopBasedJavaScriptEngine = (LoopBasedJavaScriptEngine) scriptEngine; final long interval = getConfig().getInterval(); loopBasedJavaScriptEngine.getRuntime().loopers.setMainLooperQuitHandler(new Loopers.LooperQuitHandler() { /* class com.stardust.autojs.execution.LoopedBasedJavaScriptExecution.C10521 */ public long times; { this.times = LoopedBasedJavaScriptExecution.this.getConfig().getLoopTimes() == 0 ? 2147483647L : (long) LoopedBasedJavaScriptExecution.this.getConfig().getLoopTimes(); } @Override // com.stardust.autojs.core.looper.Loopers.LooperQuitHandler public boolean shouldQuit() { long j = this.times - 1; this.times = j; if (j > 0) { LoopedBasedJavaScriptExecution.this.sleep(interval); loopBasedJavaScriptEngine.execute(LoopedBasedJavaScriptExecution.this.getSource()); return false; } loopBasedJavaScriptEngine.getRuntime().loopers.setMainLooperQuitHandler(null); return true; } }); loopBasedJavaScriptEngine.execute(getSource()); return null; } @Override // com.stardust.autojs.execution.ScriptExecution.AbstractScriptExecution, com.stardust.autojs.execution.ScriptExecution public JavaScriptSource getSource() { return (JavaScriptSource) super.getSource(); } }
com.stardust.autojs.execution.RunnableScriptExecution.execute()
com.stardust.autojs.execution.RunnableScriptExecution.run()
这两个方法在一个类RunnableScriptExecution
package com.stardust.autojs.execution; import android.util.Log; import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngineManager; import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.script.ScriptSource; import p015d.p019b.p047c.p048a.C1556a; public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecution implements Runnable { private static final String TAG = "RunnableJSExecution"; private ScriptEngine mScriptEngine; private ScriptEngineManager mScriptEngineManager; public RunnableScriptExecution(ScriptEngineManager scriptEngineManager, ScriptExecutionTask scriptExecutionTask) { super(scriptExecutionTask); this.mScriptEngineManager = scriptEngineManager; } private Object execute(ScriptEngine scriptEngine) { try { prepare(scriptEngine); Object doExecution = doExecution(scriptEngine); Throwable uncaughtException = scriptEngine.getUncaughtException(); if (uncaughtException != null) { onException(scriptEngine, uncaughtException); return null; } getListener().onSuccess(this, doExecution); scriptEngine.destroy(); return doExecution; } catch (Throwable th) { onException(scriptEngine, th); return null; } finally { scriptEngine.destroy(); } } private void prepare(ScriptEngine scriptEngine) { scriptEngine.setTag(ScriptEngine.TAG_WORKING_DIRECTORY, getConfig().getWorkingDirectory()); scriptEngine.setTag(ScriptEngine.TAG_ENV_PATH, getConfig().getPath()); scriptEngine.init(); } public Object doExecution(ScriptEngine scriptEngine) { scriptEngine.setTag(ScriptEngine.TAG_SOURCE, getSource()); getListener().onStart(this); long delay = getConfig().getDelay(); int loopTimes = getConfig().getLoopTimes(); if (loopTimes == 0) { loopTimes = Integer.MAX_VALUE; } long interval = getConfig().getInterval(); sleep(delay); ScriptSource source = getSource(); Object obj = null; for (int i = 0; i < loopTimes; i++) { obj = execute(scriptEngine, source); sleep(interval); } return obj; } public Object execute() { ScriptEngine createEngineOfSourceOrThrow = this.mScriptEngineManager.createEngineOfSourceOrThrow(getSource(), getId()); this.mScriptEngine = createEngineOfSourceOrThrow; createEngineOfSourceOrThrow.setTag(ExecutionConfig.TAG, getConfig()); return execute(this.mScriptEngine); } public Object execute(ScriptEngine scriptEngine, ScriptSource scriptSource) { return scriptEngine.execute(scriptSource); } @Override // com.stardust.autojs.execution.ScriptExecution.AbstractScriptExecution, com.stardust.autojs.execution.ScriptExecution public ScriptEngine getEngine() { return this.mScriptEngine; } public void onException(ScriptEngine scriptEngine, Throwable th) { Log.w(TAG, "onException: engine = " + scriptEngine, th); getListener().onException(this, th); } public void run() { Thread currentThread = Thread.currentThread(); StringBuilder i = C1556a.m2188i("Script-"); i.append(getId()); i.append(" Main ["); i.append(getSource()); i.append("]"); currentThread.setName(i.toString()); execute(); } public void sleep(long j) { if (j > 0) { try { Thread.sleep(j); } catch (InterruptedException unused) { throw new ScriptInterruptedException(); } } } }
java.lang.Thread.run(Thread.java:761)
package java.lang; public class Thread implements Runnable { public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } Thread(Runnable target, AccessControlContext acc) { init(null, target, "Thread-" + nextThreadNum(), 0, acc); } public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0); } public Thread(String name) { init(null, null, name, 0); } public Thread(ThreadGroup group, String name) { init(group, null, name, 0); } Thread(ThreadGroup group, String name, int priority, boolean daemon) { this.group = group; this.group.addUnstarted(); // Must be tolerant of threads without a name. if (name == null) { name = "Thread-" + nextThreadNum(); } // NOTE: Resist the temptation to call setName() here. This constructor is only called // by the runtime to construct peers for threads that have attached via JNI and it's // undesirable to clobber their natively set name. this.name = name; this.priority = priority; this.daemon = daemon; init2(currentThread()); tid = nextThreadID(); } // Android-added: Helper method for previous constructor and init(...) method. private void init2(Thread parent) { this.contextClassLoader = parent.getContextClassLoader(); this.inheritedAccessControlContext = AccessController.getContext(); if (parent.inheritableThreadLocals != null) { this.inheritableThreadLocals = ThreadLocal.createInheritedMap( parent.inheritableThreadLocals); } } // END Android-added: Private constructor - used by the runtime. public Thread(Runnable target, String name) { init(null, target, name, 0); } public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0); } public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize); } @Override public void run() { if (target != null) { target.run(); } } }
堆栈就分析到这里, 下一篇继续分析