hook逆向autojs离线Dex加密的ap

本文涉及的产品
文本翻译,文本翻译 100万字符
图片翻译,图片翻译 100张
文档翻译,文档翻译 1千页
简介: hook逆向autojs离线Dex加密的ap

本次加密的代码如下:

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:

call in interface Callable

Specified by:

call in interface Function

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();
        }
    }
}


堆栈就分析到这里, 下一篇继续分析











相关文章
|
JavaScript 数据安全/隐私保护 Python
Crack App | 某搜索 App 中关于 x 信文章检索功能的加密参数分析(Frida Hook 篇)
Crack App | 某搜索 App 中关于 x 信文章检索功能的加密参数分析(Frida Hook 篇)
112 0
|
存储 数据安全/隐私保护
离线存储加密货币的最佳方式是什么?
离线存储加密货币的最佳方式是什么?
|
JavaScript 数据安全/隐私保护
hook逆向autojs离线Dex加密的app(七)
hook逆向autojs离线Dex加密的app(七)
420 0
|
数据安全/隐私保护
hook逆向autojs离线Dex加密的app(六)
hook逆向autojs离线Dex加密的app(六)
285 0
|
6天前
|
SQL 安全 算法
揭秘网络安全:漏洞、加密与安全意识的三重奏
【10月更文挑战第39天】在数字时代的交响乐中,网络安全扮演着不可或缺的角色。本文旨在通过浅显易懂的语言,揭示网络安全的三大核心要素:网络漏洞、加密技术以及安全意识。我们将探索这些元素如何相互交织,共同维护我们的数字安全。从初学者到资深专家,每个人都能从中获得宝贵的知识和启示。
|
6天前
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【10月更文挑战第39天】在数字化时代,网络安全和信息安全成为了我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的内容,帮助读者更好地了解网络安全的重要性,并提供一些实用的技巧和方法来保护自己的信息安全。
19 2
|
8天前
|
安全 算法 网络安全
网络安全的盾牌与利剑:漏洞防御与加密技术的双刃舞
【10月更文挑战第37天】在数字世界的海洋里,网络安全是航船的锚,保护我们的数据不受风暴侵袭。本文将深入浅出地探讨网络安全的两大支柱——漏洞防御和加密技术。我们将从网络安全的基本概念出发,逐步深入到漏洞的类型、检测方法以及防御策略。同时,我们也将探索加密技术的原理和应用,如何通过这一技术保护信息的完整性和私密性。最后,我们将讨论提升个人及组织安全意识的重要性,以及如何构建一个安全的网络环境。这不仅是技术人员的战斗,每个人都是自己信息安全的第一道防线。让我们一起扬帆起航,探索网络安全的世界,学习如何成为自己数据的守护者。
|
8天前
|
SQL 安全 网络安全
网络安全的护城河:漏洞防御与加密技术的深度解析
【10月更文挑战第37天】在数字时代的浪潮中,网络安全成为守护个人隐私与企业资产的坚固堡垒。本文将深入探讨网络安全的两大核心要素——安全漏洞和加密技术,以及如何通过提升安全意识来强化这道防线。文章旨在揭示网络攻防战的复杂性,并引导读者构建更为稳固的安全体系。
18 1
|
7天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【10月更文挑战第38天】本文将探讨网络安全与信息安全的重要性,包括网络安全漏洞、加密技术和安全意识等方面。我们将通过代码示例和实际操作来展示如何保护网络和信息安全。无论你是个人用户还是企业,都需要了解这些知识以保护自己的网络安全和信息安全。
|
6天前
|
存储 安全 网络安全
网络安全与信息安全:漏洞、加密技术与安全意识的交织
【10月更文挑战第39天】在数字化时代,网络安全与信息安全成为保护个人隐私和组织资产的重要屏障。本文将探讨网络安全中的常见漏洞、加密技术的应用以及提升安全意识的重要性。通过具体案例分析,我们将深入了解网络攻击的手段和防御策略,同时提供实用建议,以增强读者对网络安全的认识和防护能力。