T callOrigin(Object instance/*Nullable*/, Object... args) {
96 | return (T) nativeCallOrigin(instance, args);
97 | }
98 |
99 | /**
100 | * Note: Only the current thread is affected!
101 | *
102 | * If you want to disable hook-status in the current thread, pass true.
103 | * HookTransition(true);
104 | *
105 | * enable hook-status in the current thread, Pass false
106 | * HookTransition(false);
107 | *
108 | * @param originMode Represents whether the original function is executed when method enter
109 | * true: call originMethod
110 | * false: call proxyMethod
111 | */
112 | public static native void hookTransition(boolean originMode);
113 |
114 | private static native Object nativeCallOrigin(Object instance/*Nullable*/, Object[] args);
115 |
116 | /**
117 | * @param proxyMethods
118 | * @param mode {@link MODE}
119 | * @param interpretLogOn
120 | * @param filterRegex
121 | * @return If hook success, will return true
122 | */
123 | private static native boolean nativeStartHook(HashMap proxyMethods, @MODE int mode, boolean interpretLogOn, String filterRegex);
124 |
125 | private static native void reserve0();
126 |
127 | private static native void reserve1();
128 |
129 | @Retention(SOURCE)
130 | @Target({ANNOTATION_TYPE})
131 | @interface IntDef {
132 | int[] value() default {};
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/java/org/apolo/ArtHookInternal.java:
--------------------------------------------------------------------------------
1 | package org.apolo;
2 |
3 | import android.util.Log;
4 |
5 | import java.lang.annotation.Annotation;
6 | import java.lang.reflect.Constructor;
7 | import java.lang.reflect.Member;
8 | import java.lang.reflect.Method;
9 | import java.util.HashMap;
10 |
11 | class ArtHookInternal {
12 | final static HashMap methods = new HashMap<>();
13 |
14 | private static final String TAG = "ArtHookInternal";
15 |
16 | public static void addHooker(ClassLoader loader, Class> cls, boolean ignoreException) throws Throwable {
17 | if (loader == null) {
18 | loader = ArtHookInternal.class.getClassLoader();
19 | }
20 | Class> target = getHookTarget(loader, cls);
21 |
22 | Method[] methods = cls.getDeclaredMethods();
23 |
24 | for (Method method : methods) {
25 | try {
26 | Annotation[][] annotations = method.getParameterAnnotations();
27 | MethodEntity entity = new MethodEntity(target, method);
28 |
29 | HookName name = method.getAnnotation(HookName.class);
30 | if (name != null) {
31 | entity.name = name.value();
32 | entity._constructor = HookName.CONSTRUCTOR.contains(entity.name);
33 | } else {
34 | HookConstructor constructor = method.getAnnotation(HookConstructor.class);
35 | if (constructor != null) {
36 | entity.name = "";
37 | entity._constructor = true;
38 | }
39 | }
40 | if (entity.name == null) continue;
41 |
42 | if (annotations.length > 0) {
43 | for (int i = 0; i < annotations[0].length; i++) {
44 | if (annotations[0][i].annotationType() == ThisObject.class) {
45 | entity._static = true;
46 | break;
47 | }
48 |
49 | }
50 | }
51 | int paramIndex = 0;
52 | if (entity._static) {
53 | paramIndex++;
54 | }
55 | Class>[] types = method.getParameterTypes();
56 | entity.paramTypes = new Class>[types.length - paramIndex];
57 | for (int i = paramIndex; i < annotations.length; i++) {
58 | int index = i - paramIndex;
59 | for (int j = 0; j < annotations[i].length; j++) {
60 | if (annotations[i][j].annotationType() == HookName.class) {
61 | HookName hookName = (HookName) annotations[i][j];
62 | entity.paramTypes[index] = loadClass(loader, hookName.value());
63 | }
64 | }
65 | if (entity.paramTypes[index] == null) {
66 | entity.paramTypes[index] = types[i];
67 | }
68 | }
69 |
70 | if (entity._constructor) {
71 | Constructor> constructor = entity.declaredClass.getDeclaredConstructor(entity.paramTypes);
72 | constructor.setAccessible(true);
73 | entity.member = constructor;
74 | } else {
75 | Method m = entity.declaredClass.getDeclaredMethod(entity.name, entity.paramTypes);
76 | m.setAccessible(true);
77 | entity.member = m;
78 | }
79 | Log.d(TAG, String.format("addHooker: %s.%s", entity.declaredClass.getName(), entity.name));
80 | ArtHookInternal.methods.put(entity.member, method);
81 | } catch (Throwable e) {
82 | if (!ignoreException) {
83 | throw e;
84 | }
85 | Log.w(TAG, "addHooker: failed " + e);
86 | }
87 |
88 |
89 | }
90 | }
91 |
92 | private static Class> getHookTarget(ClassLoader loader, Class> cls) throws Throwable {
93 | HookClass targetAno = cls.getAnnotation(HookClass.class);
94 | Class> target = null;
95 |
96 | if (targetAno != null) {
97 | target = targetAno.value();
98 | } else {
99 | HookName name = cls.getAnnotation(HookName.class);
100 | if (name != null) {
101 | target = loadClass(loader, name.value());
102 | }
103 | }
104 | return target;
105 | }
106 |
107 | private static Class> loadClass(ClassLoader loader, String name) throws Throwable {
108 | return loader.loadClass(name);
109 | }
110 |
111 | public static void addHook(Member member, Method proxyMethod) {
112 | methods.put(member, proxyMethod);
113 | }
114 |
115 | public static boolean contains(Member member) {
116 | return methods.containsKey(member);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/java/org/apolo/HookClass.java:
--------------------------------------------------------------------------------
1 | package org.apolo;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
10 | public @interface HookClass {
11 | Class> value();
12 | }
13 |
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/java/org/apolo/HookConstructor.java:
--------------------------------------------------------------------------------
1 | package org.apolo;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Target({ElementType.CONSTRUCTOR})
10 | public @interface HookConstructor {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/java/org/apolo/HookName.java:
--------------------------------------------------------------------------------
1 | package org.apolo;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
10 | public @interface HookName {
11 | String CONSTRUCTOR = "";
12 |
13 | String value();
14 | }
15 |
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/java/org/apolo/MethodEntity.java:
--------------------------------------------------------------------------------
1 | package org.apolo;
2 |
3 | import java.lang.reflect.Member;
4 | import java.lang.reflect.Method;
5 |
6 | class MethodEntity {
7 | boolean _static;
8 | boolean _constructor;
9 | Class>[] paramTypes;
10 | String name;
11 | Class> declaredClass;
12 | Member member;
13 | Method proxyMethod;
14 |
15 | public MethodEntity(Class> target, Method method) {
16 | declaredClass = target;
17 | proxyMethod = method;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/java/org/apolo/ThisObject.java:
--------------------------------------------------------------------------------
1 | package org.apolo;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Target({ElementType.PARAMETER})
10 | public @interface ThisObject {
11 | }
12 |
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/jniLibs/arm64-v8a/libapolo.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/ApoloPlugin/src/main/jniLibs/arm64-v8a/libapolo.so
--------------------------------------------------------------------------------
/ApoloPlugin/src/main/jniLibs/armeabi-v7a/libapolo.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/ApoloPlugin/src/main/jniLibs/armeabi-v7a/libapolo.so
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 WaxMoon
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdk rootProject.ext.compileSdkVersion
7 | buildToolsVersion rootProject.ext.buildToolsVersion
8 | ndkVersion rootProject.ext.ndkVersion
9 |
10 | defaultConfig {
11 | applicationId "com.example.apolo"
12 | minSdk rootProject.ext.minSdkVersion
13 | targetSdk rootProject.ext.targetSdkVersion
14 | versionCode 1
15 | versionName "1.0"
16 | ndk {
17 | setAbiFilters(["armeabi-v7a", "arm64-v8a"])
18 | }
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | signingConfig signingConfigs.create("release")
26 | signingConfig.initWith(buildTypes.debug.signingConfig)
27 | }
28 | }
29 | compileOptions {
30 | sourceCompatibility rootProject.ext.javaVersion
31 | targetCompatibility rootProject.ext.javaVersion
32 | }
33 | }
34 |
35 | dependencies {
36 |
37 | implementation 'androidx.appcompat:appcompat:1.4.1'
38 | implementation 'com.google.android.material:material:1.5.0'
39 | implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
40 |
41 | if (rootProject.ext.useLocalLibrary) {
42 | implementation project(':ApoloPlugin')
43 | implementation project(':xposed')
44 | } else {
45 | implementation "io.github.waxmoon:ApoloPlugin:${POM_VERSION_NAME}"
46 | implementation "io.github.waxmoon:xposed:${POM_VERSION_NAME}"
47 | }
48 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/assets/jni.properties:
--------------------------------------------------------------------------------
1 | JniBridgeEntry=org.apolo.ArtEngine
2 | #only used when use repack.sh
3 | InjectEntry=com.example.apolo.HookInject
4 |
--------------------------------------------------------------------------------
/app/src/main/java/com/apolo/helper/FileLogUtils.java:
--------------------------------------------------------------------------------
1 | package com.apolo.helper;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import java.io.File;
7 | import java.io.FileNotFoundException;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.io.RandomAccessFile;
11 | import java.text.SimpleDateFormat;
12 | import java.util.Date;
13 |
14 | public class FileLogUtils {
15 | private static final String TAG = FileLogUtils.class.getSimpleName();
16 | private static FileLogUtils instance;
17 |
18 | private Context mAppContext;
19 | private File mSaveDir;
20 |
21 | private final String mLogFile = "log.txt";
22 |
23 | private FileLogUtils() {
24 |
25 | }
26 |
27 | public static FileLogUtils getInstance() {
28 | if (instance == null) {
29 | synchronized (FileLogUtils.class) {
30 | if (instance == null) {
31 | instance = new FileLogUtils();
32 | }
33 | }
34 | }
35 | return instance;
36 | }
37 |
38 | public void init(Context context) {
39 | mAppContext = context;
40 | mSaveDir = mAppContext.getExternalCacheDir();
41 | }
42 |
43 | private void initSaveDirIfNeed() {
44 | if (mSaveDir == null) {
45 | synchronized (this) {
46 | if (mSaveDir == null) {
47 | mSaveDir = ProcessUtils.getMainApplication().getExternalCacheDir();
48 | }
49 | }
50 | }
51 | }
52 |
53 |
54 | /**
55 | * 清空Log
56 | */
57 | public void clearLogs() {
58 | initSaveDirIfNeed();
59 | File file_log = new File(mSaveDir, mLogFile);
60 | if (!file_log.exists()) {
61 | return;
62 | }
63 | FileOutputStream fos = null;
64 | try {
65 | fos = new FileOutputStream(file_log);
66 | fos.write("".getBytes());
67 | } catch (FileNotFoundException e) {
68 | e.printStackTrace();
69 | } catch (IOException e) {
70 | e.printStackTrace();
71 | } finally {
72 | if (fos != null) {
73 | try {
74 | fos.close();
75 | } catch (IOException e) {
76 | e.printStackTrace();
77 | }
78 | }
79 | }
80 | }
81 |
82 |
83 | /**
84 | * 追加保存Log
85 | */
86 | public void saveLog(String content) {
87 | initSaveDirIfNeed();
88 | if (!mSaveDir.exists()) {
89 | Log.e(TAG, "saveLogs mkdir");
90 | mSaveDir.mkdir();
91 | }
92 |
93 | Log.e(TAG, "SaveDir=" + mSaveDir);
94 |
95 | RandomAccessFile randomAccessFile = null;
96 |
97 | try {
98 |
99 | StringBuffer stringBuffer = new StringBuffer();
100 | stringBuffer.setLength(0);
101 | //拼接一个日期
102 | stringBuffer.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date()));
103 | stringBuffer.append(" ");
104 | stringBuffer.append(content);
105 | stringBuffer.append("\n");
106 |
107 | File file_log = new File(mSaveDir, mLogFile);
108 | if (!file_log.exists()) {
109 | file_log.createNewFile();
110 | }
111 |
112 | randomAccessFile = new RandomAccessFile(file_log, "rw");
113 | randomAccessFile.seek(file_log.length());
114 | randomAccessFile.write(stringBuffer.toString().getBytes("UTF-8"));
115 |
116 | } catch (IOException e) {
117 | e.printStackTrace();
118 | } finally {
119 | if (randomAccessFile != null) {
120 | try {
121 | randomAccessFile.close();
122 | } catch (IOException e) {
123 | e.printStackTrace();
124 | }
125 | }
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/app/src/main/java/com/apolo/helper/ProcessUtils.java:
--------------------------------------------------------------------------------
1 | package com.apolo.helper;
2 |
3 | import android.app.ActivityManager;
4 | import android.app.Application;
5 | import android.content.Context;
6 | import android.os.Process;
7 | import android.text.TextUtils;
8 | import android.util.Log;
9 |
10 | import java.util.List;
11 |
12 |
13 | public class ProcessUtils {
14 | private static final String TAG = ProcessUtils.class.getSimpleName();
15 | private static String sCurProcessName;
16 | private static Application sMainApplication;
17 | public static String getCurProcessName(Context context) {
18 | String procName = sCurProcessName;
19 | if (!TextUtils.isEmpty(procName)) {
20 | return procName;
21 | }
22 | try {
23 | int selfPid = Process.myPid();
24 | ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
25 | for (ActivityManager.RunningAppProcessInfo info : mActivityManager.getRunningAppProcesses()) {
26 | if (info.pid == selfPid) {
27 | sCurProcessName = info.processName;
28 | return sCurProcessName;
29 | }
30 | }
31 | } catch (Exception e) {
32 | Log.e(TAG, "getCurProcessName failed", e);
33 | }
34 | return sCurProcessName;
35 | }
36 |
37 | public static Application getMainApplication() {
38 | if (sMainApplication != null) {
39 | return sMainApplication;
40 | }
41 | RefUtils.MethodRef methodRef_currentActivityThread = new RefUtils.MethodRef(
42 | "android.app.ActivityThread", true,
43 | "currentActivityThread", new Class[0]
44 | );
45 | RefUtils.FieldRef> fieldRef_mAllApplications = new RefUtils.FieldRef>(
46 | "android.app.ActivityThread", false, "mAllApplications"
47 | );
48 | Object activityThread = methodRef_currentActivityThread.invoke(null, new Object[0]);
49 | List allApplications = fieldRef_mAllApplications.get(activityThread);
50 |
51 | if (allApplications != null && allApplications.size() > 0) {
52 | for (int i = 0; i < allApplications.size(); i++) {
53 | Application tmp = allApplications.get(i);
54 | if (TextUtils.equals(tmp.getApplicationInfo().processName,
55 | ProcessUtils.getCurProcessName(tmp))) {
56 | sMainApplication = tmp;
57 | Log.d(TAG, "getMainApplication success");
58 | break;
59 | }
60 | }
61 | } else {
62 | Log.e(TAG, "getMainApplication fail");
63 | }
64 |
65 | return sMainApplication;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/apolo/helper/RefUtils.java:
--------------------------------------------------------------------------------
1 | package com.apolo.helper;
2 |
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.Method;
5 |
6 | public class RefUtils {
7 | public static Field getField(Class refClass, boolean isStatic, String filedName) {
8 | if (refClass == null || filedName == null) {
9 | return null;
10 | }
11 | try {
12 | return refClass.getDeclaredField(filedName);
13 | } catch (NoSuchFieldException e) {
14 |
15 | }
16 | return null;
17 | }
18 |
19 | public static Method getMethod(Class refClass, boolean isStatic, String funcName, Class[] paramTypes) {
20 | if (refClass == null || funcName == null) {
21 | return null;
22 | }
23 | try {
24 | return refClass.getDeclaredMethod(funcName, paramTypes);
25 | } catch (NoSuchMethodException e) {
26 |
27 | }
28 | return null;
29 | }
30 |
31 | public static class FieldRef {
32 | boolean mIsStatic;
33 | Field mField;
34 | public FieldRef(Class refClass, boolean isStatic, String name) {
35 | mIsStatic = isStatic;
36 | mField = getField(refClass, isStatic, name);
37 | if (mField != null) {
38 | mField.setAccessible(true);
39 | }
40 | }
41 | public FieldRef(String className, boolean isStatic, String name) {
42 | try {
43 | Class targetClass = Class.forName(className);
44 | mField = getField(targetClass, isStatic, name);
45 | } catch (ClassNotFoundException e) {
46 | }
47 | mIsStatic = isStatic;
48 | if (mField != null) {
49 | mField.setAccessible(true);
50 | }
51 | }
52 |
53 | public boolean isValid() {
54 | return mField != null;
55 | }
56 |
57 | public T get(Object instance) {
58 | try {
59 | return (T) mField.get(instance);
60 | } catch (Exception e) {
61 |
62 | }
63 | return null;
64 | }
65 | public void set(Object instance, T value) {
66 | try {
67 | mField.set(instance, value);
68 | } catch (Exception e) {
69 |
70 | }
71 | }
72 | }
73 |
74 | public static class MethodRef {
75 | Method mMethod;
76 | public MethodRef(String className, boolean isStatic, String funcName, Class[] paramsTypes) {
77 | try {
78 | Class targetClass = Class.forName(className);
79 | mMethod = getMethod(targetClass, isStatic, funcName, paramsTypes);
80 | } catch (Exception e) {
81 | }
82 | if (mMethod != null) {
83 | mMethod.setAccessible(true);
84 | }
85 | }
86 | public MethodRef(Class refClass, boolean isStatic, String funcName, Class[] paramsTypes) {
87 | mMethod = getMethod(refClass, isStatic, funcName, paramsTypes);
88 | if (mMethod != null) {
89 | mMethod.setAccessible(true);
90 | }
91 | }
92 |
93 | public boolean isValid() {
94 | return mMethod != null;
95 | }
96 |
97 | public T invoke(Object instance, Object[] args) {
98 | try {
99 | return (T) mMethod.invoke(instance, args);
100 | } catch (Exception e) {
101 | }
102 | return null;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/apolo/ButtonActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.apolo;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.Button;
9 | import android.widget.FrameLayout;
10 | import android.widget.LinearLayout;
11 | import android.widget.ScrollView;
12 |
13 | import androidx.appcompat.app.AppCompatActivity;
14 |
15 | import java.util.UUID;
16 |
17 | public class ButtonActivity extends AppCompatActivity {
18 | protected String TAG = "Button." + getClass().getSimpleName();
19 |
20 | private LinearLayout mContainer;
21 |
22 | public Intent withIntent(Class extends ButtonActivity> cls) {
23 | Intent intent = new Intent(this, cls);
24 | intent.putExtra("serial", UUID.randomUUID().toString());
25 | return intent;
26 | }
27 |
28 | public Intent withIntent(Class extends ButtonActivity> cls, int flags) {
29 | Intent intent = new Intent(this, cls);
30 | intent.putExtra("serial", UUID.randomUUID().toString());
31 | intent.addFlags(flags);
32 | return intent;
33 | }
34 |
35 | public Intent withIntent(Intent intent, int flags) {
36 | intent.putExtra("serial", UUID.randomUUID().toString());
37 | intent.addFlags(flags);
38 | return intent;
39 | }
40 |
41 | public String serial(Intent intent) {
42 | return intent.getStringExtra("serial");
43 | }
44 |
45 | @Override
46 | protected void onNewIntent(Intent intent) {
47 | super.onNewIntent(intent);
48 | Log.d(TAG, "onNewIntent: " + serial(intent) + " " + getTaskId());
49 | }
50 |
51 | @Override
52 | protected void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | Log.d(TAG, "onCreate: " + serial(getIntent()) + " " + getTaskId());
55 | mContainer = new LinearLayout(this);
56 | mContainer.setOrientation(LinearLayout.VERTICAL);
57 | ScrollView scrollView = new ScrollView(this);
58 | scrollView.addView(mContainer);
59 | setContentView(scrollView);
60 | addButton(getClass().getName() + " " + getTaskId(), null);
61 | }
62 |
63 | @Override
64 | protected void onStart() {
65 | super.onStart();
66 | Log.d(TAG, "onStart: ");
67 | }
68 |
69 | @Override
70 | protected void onRestart() {
71 | super.onRestart();
72 | Log.d(TAG, "onRestart: ");
73 | }
74 |
75 | @Override
76 | protected void onResume() {
77 | super.onResume();
78 | Log.d(TAG, "onResume: ");
79 | }
80 |
81 | @Override
82 | protected void onPause() {
83 | super.onPause();
84 | Log.d(TAG, "onPause: ");
85 | }
86 |
87 | @Override
88 | protected void onStop() {
89 | super.onStop();
90 | Log.d(TAG, "onStop: ");
91 | }
92 |
93 | @Override
94 | protected void onDestroy() {
95 | super.onDestroy();
96 | Log.d(TAG, "onDestroy: ");
97 | }
98 |
99 | protected Button addButton(final String text, final View.OnClickListener clickListener) {
100 | Button button = new Button(this);
101 | button.setText(text);
102 | button.setAllCaps(false);
103 | button.setOnClickListener(clickListener);
104 | mContainer.addView(button, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
105 | return button;
106 | }
107 |
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/apolo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.apolo;
2 |
3 | import android.app.Activity;
4 | import android.app.Application;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 |
8 | import com.apolo.helper.FileLogUtils;
9 | import com.apolo.helper.ProcessUtils;
10 |
11 | import org.apolo.ArtEngine;
12 |
13 | import de.robv.android.xposed.XC_MethodHook;
14 | import de.robv.android.xposed.XposedHelpers;
15 | import hook.Test;
16 | import hook.android.app.ActivityManagerProxy;
17 | import hook.android.app.ActivityTaskManagerProxy;
18 | import hook.android.app.ActivityThread;
19 | import hook.android.app.ApplicationPackageManager;
20 | import hook.android.app.ContextImpl;
21 | import hook.android.os.HandlerProxy;
22 | import hook.android.os.ProcessProxy;
23 | import hook.android.provider.Settings;
24 | import hook.douyin.EncryptorUtilProxy;
25 | import hook.douyin.TTEncryptUtilsProxy;
26 | import hook.java.io.FileProxy;
27 | import hook.java.lang.StringProxy;
28 | import hook.javax.net.ssl.HttpsURLConnection;
29 |
30 |
31 | public class DemoApplication extends Application {
32 |
33 | private static final String TAG = DemoApplication.class.getSimpleName();
34 |
35 | private static Application sApp;
36 |
37 | @Override
38 | public void onCreate() {
39 | super.onCreate();
40 | sApp = this;
41 | FileLogUtils.getInstance().init(this);
42 | FileLogUtils.getInstance().clearLogs();
43 | HookInject.main();
44 | }
45 |
46 | public static Application getMyApplication() {
47 | return sApp;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/apolo/HookInject.java:
--------------------------------------------------------------------------------
1 | package com.example.apolo;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 |
7 | import org.apolo.ArtEngine;
8 |
9 | import de.robv.android.xposed.XC_MethodHook;
10 | import de.robv.android.xposed.XposedHelpers;
11 | import hook.Test;
12 | import hook.android.app.ActivityManagerProxy;
13 | import hook.android.app.ActivityTaskManagerProxy;
14 | import hook.android.app.ActivityThread;
15 | import hook.android.app.ApplicationPackageManager;
16 | import hook.android.app.ContextImpl;
17 | import hook.android.os.HandlerProxy;
18 | import hook.android.os.ProcessProxy;
19 | import hook.android.provider.Settings;
20 | import hook.java.io.FileProxy;
21 | import hook.javax.net.ssl.HttpsURLConnection;
22 |
23 | public class HookInject {
24 | static {
25 | //init ArtHook
26 | ArtEngine.preLoad();
27 | }
28 |
29 | public static void main() {
30 | ArtEngine.addHookers(DemoApplication.class.getClassLoader(),
31 | // StringProxy.class,
32 | // StringBuilder.class,//尽量不hook StringBuilder
33 | FileProxy.class,
34 | ProcessProxy.class,
35 | HandlerProxy.class,
36 | ActivityThread.class,
37 | ApplicationPackageManager.class,
38 | ContextImpl.class,
39 | Settings.Global.class,
40 | Test.class);
41 |
42 | ArtEngine.addHooker(ActivityManagerProxy.class);
43 | ArtEngine.addHooker(ActivityTaskManagerProxy.class);
44 |
45 |
46 | //try inject douyin
47 | // try {
48 | // ArtEngine.addHookers(ProcessUtils.getMainApplication().getClassLoader(),
49 | // EncryptorUtilProxy.class,
50 | // TTEncryptUtilsProxy.class);
51 | // } catch (Exception e) {
52 | // e.printStackTrace();
53 | // }
54 |
55 | ArtEngine.addHooker(HttpsURLConnection.class);
56 |
57 | XposedHelpers.findAndHookMethod(Activity.class, "onResume", new XC_MethodHook() {
58 | @Override
59 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
60 | super.beforeHookedMethod(param);
61 | Log.e("XposedCompat", "beforeHookedMethod: " + param.method.getName());
62 | }
63 |
64 | @Override
65 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
66 | super.afterHookedMethod(param);
67 | Log.e("XposedCompat", "afterHookedMethod: " + param.method.getName());
68 | }
69 | });
70 |
71 | XposedHelpers.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() {
72 | @Override
73 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
74 | super.beforeHookedMethod(param);
75 | Log.e("XposedCompat", "beforeHookedMethod: " + param.method.getName());
76 | }
77 |
78 | @Override
79 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
80 | super.afterHookedMethod(param);
81 | Log.e("XposedCompat", "afterHookedMethod: " + param.method.getName());
82 | }
83 | });
84 | //split ','
85 | //ArtEngine.setInterpretFilterRegex("android.app.*,android.os.*");
86 | //ArtEngine.enableInterpretLog();
87 | ArtEngine.setHookMode(ArtEngine.MODE_INTERPRET);//如果已声明debuggable=true,此处不需要再调用
88 | ArtEngine.startHook();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/apolo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.apolo;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.util.Log;
6 | import android.view.View;
7 |
8 | import java.io.IOException;
9 | import java.util.List;
10 |
11 | import hook.Test;
12 |
13 |
14 | public class MainActivity extends ButtonActivity {
15 |
16 | final static String TAG = "MainActivity";
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | addButton("getPackageManager", new View.OnClickListener() {
22 | @Override
23 | public void onClick(View v) {
24 | Log.d(TAG, "getInstalledPackages called before+++++++");
25 | List xx = getPackageManager().getInstalledPackages(0);
26 | Log.d(TAG, "getInstalledPackages called end--------" + xx);
27 | }
28 | });
29 |
30 | addButton("test io exception", new View.OnClickListener() {
31 | @Override
32 | public void onClick(View v) {
33 | try {
34 | new Test().test();
35 | } catch (IOException e) {
36 | e.printStackTrace();
37 | }
38 | }
39 | });
40 |
41 | addButton("Handler enqueueMessage", new View.OnClickListener() {
42 | @Override
43 | public void onClick(View v) {
44 | Log.d(TAG, "Handler post begin++++");
45 | new Handler().post(new Runnable() {
46 | @Override
47 | public void run() {
48 | Log.d(TAG, "runnable execute...");
49 | }
50 | });
51 | Log.d(TAG, "Handler post end----");
52 | }
53 | });
54 |
55 | }
56 | }
--------------------------------------------------------------------------------
/app/src/main/java/hook/Test.java:
--------------------------------------------------------------------------------
1 | package hook;
2 |
3 | import java.io.IOException;
4 | import org.apolo.ArtEngine;
5 | import org.apolo.HookClass;
6 | import org.apolo.HookName;
7 | import org.apolo.ThisObject;
8 | import hook.utils.Slog;
9 |
10 | @HookClass(Test.class)
11 | public class Test {
12 | @HookName("test")
13 | public static void test(@ThisObject Object o) {
14 | Slog.d("test", "test: " + o);
15 | ArtEngine.callOrigin(o);
16 | }
17 |
18 | public void test() throws IOException {
19 | throw new IOException("test");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/app/ActivityManagerProxy.java:
--------------------------------------------------------------------------------
1 | package hook.android.app;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 |
7 | import org.apolo.ArtEngine;
8 | import org.apolo.HookName;
9 | import org.apolo.ThisObject;
10 |
11 | import hook.utils.Slog;
12 |
13 | @HookName("android.app.ActivityManager")
14 | public class ActivityManagerProxy {
15 | private static final String TAG = ActivityManagerProxy.class.getSimpleName();
16 |
17 | @HookName("startActivity")
18 | public void startActivity(@ThisObject Object thiz, Context context, Intent intent, Bundle options) {
19 |
20 | Slog.d(TAG, "startActivity " + intent, new Exception());
21 | ArtEngine.callOrigin(thiz, context, intent, options);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/app/ActivityTaskManagerProxy.java:
--------------------------------------------------------------------------------
1 | package hook.android.app;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.os.IBinder;
6 |
7 | import org.apolo.ArtEngine;
8 | import org.apolo.HookName;
9 | import org.apolo.ThisObject;
10 |
11 | import hook.utils.Slog;
12 |
13 | @HookName("android.app.IActivityTaskManager$Stub$Proxy")
14 | public class ActivityTaskManagerProxy {
15 |
16 | private static final String TAG = ActivityTaskManagerProxy.class.getSimpleName();
17 |
18 | //android11.0+
19 | @HookName("startActivity")
20 | public static int startActivity(@ThisObject Object thiz,
21 | @HookName("android.app.IApplicationThread") Object appThread,
22 | String callingPackage, String xx, Intent intent,
23 | String resolvedType, IBinder resultTo, String resultWho,
24 | int requestCode, int flags,
25 | @HookName("android.app.ProfilerInfo") Object profilerInfo,
26 | Bundle options) {
27 |
28 | Slog.d(TAG, "startActivity called " + intent, new Exception());
29 | return ArtEngine.callOrigin(thiz, appThread, callingPackage, xx, intent,
30 | resolvedType, resultTo, resultWho, requestCode, flags, profilerInfo, options);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/app/ActivityThread.java:
--------------------------------------------------------------------------------
1 | package hook.android.app;
2 |
3 | import org.apolo.ArtEngine;
4 | import org.apolo.HookName;
5 | import hook.utils.Slog;
6 |
7 | @HookName("android.app.ActivityThread")
8 | public class ActivityThread {
9 |
10 | private static final String TAG = ActivityThread.class.getSimpleName();
11 |
12 | @HookName("currentActivityThread")
13 | public static Object currentActivityThread() {
14 | Slog.d(TAG, "proxy_currentActivityThread called", new Exception());
15 | return ArtEngine.callOrigin(null);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/app/ApplicationPackageManager.java:
--------------------------------------------------------------------------------
1 | package hook.android.app;
2 |
3 | import android.content.pm.PackageInfo;
4 | import android.content.pm.PackageManager;
5 | import android.widget.Toast;
6 |
7 | import com.example.apolo.DemoApplication;
8 |
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 |
13 | import org.apolo.ArtEngine;
14 | import org.apolo.HookName;
15 | import org.apolo.ThisObject;
16 | import hook.utils.Slog;
17 |
18 | @HookName("android.app.ApplicationPackageManager")
19 | public class ApplicationPackageManager {
20 |
21 | private static final String TAG = ApplicationPackageManager.class.getSimpleName();
22 |
23 | @HookName("getInstalledPackages")
24 | public static List getInstalledPackages(@ThisObject PackageManager pm, int flags) {
25 | Slog.d(TAG, "proxy_getInstalledPackages called+++ ", new Throwable());
26 | List pkgInfos = ArtEngine.callOrigin(pm, flags);
27 | Slog.d(TAG, "proxy_getInstalledPackages origin list.size: " + pkgInfos.size());
28 |
29 | Toast.makeText(DemoApplication.getMyApplication(), "proxy_getInstalledPackages called", Toast.LENGTH_SHORT).show();
30 |
31 | Slog.d(TAG, "proxy_getInstalledPackages force return empty result");
32 | return Collections.emptyList();
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/app/ContextImpl.java:
--------------------------------------------------------------------------------
1 | package hook.android.app;
2 |
3 | import org.apolo.ArtEngine;
4 | import org.apolo.HookName;
5 | import org.apolo.ThisObject;
6 | import hook.utils.Slog;
7 |
8 | @HookName("android.app.ContextImpl")
9 | public class ContextImpl {
10 | private static final String TAG = ContextImpl.class.getSimpleName();
11 |
12 | @HookName("getSystemService")
13 | public static Object getSystemService(@ThisObject Object thiz, String serviceName) {
14 | Slog.d(TAG, "proxy_getSystemService for %s", new Exception(), serviceName);
15 | return ArtEngine.callOrigin(thiz, serviceName);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/os/HandlerProxy.java:
--------------------------------------------------------------------------------
1 | package hook.android.os;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import android.os.MessageQueue;
6 |
7 | import org.apolo.ArtEngine;
8 | import org.apolo.HookClass;
9 | import org.apolo.HookName;
10 | import org.apolo.ThisObject;
11 |
12 | import hook.utils.Slog;
13 |
14 | @HookClass(Handler.class)
15 | public class HandlerProxy {
16 | private static final String TAG = HandlerProxy.class.getSimpleName();
17 |
18 | @HookName("sendMessageAtTime")
19 | public static boolean sendMessageAtTime(@ThisObject Object obj, Message msg, long uptimeMillis) {
20 | Slog.d(TAG, "proxy_sendMessageAtTime called: " + msg);
21 | return ArtEngine.callOrigin(obj, msg, uptimeMillis);
22 | }
23 |
24 | @HookName("enqueueMessage")
25 | public static boolean enqueueMessage(@ThisObject Handler handler, MessageQueue msgQueue,
26 | Message msg, long uptimeMillis) {
27 | Slog.d(TAG, "proxy_enqueueMessage called");
28 | return ArtEngine.callOrigin(handler, msgQueue, msg, uptimeMillis);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/os/ProcessProxy.java:
--------------------------------------------------------------------------------
1 | package hook.android.os;
2 |
3 | import android.os.Process;
4 |
5 | import org.apolo.ArtEngine;
6 | import org.apolo.HookClass;
7 | import org.apolo.HookName;
8 |
9 | import hook.utils.Slog;
10 |
11 | @HookClass(Process.class)
12 | public class ProcessProxy {
13 |
14 | private static final String TAG = "ProcessProxy";
15 | @HookName("killProcess")
16 | public static final void killProcess(int pid) {
17 | Slog.d(TAG, "killProcess", new Exception());
18 | ArtEngine.callOrigin(null, pid);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/android/provider/Settings.java:
--------------------------------------------------------------------------------
1 | package hook.android.provider;
2 |
3 | import android.content.ContentResolver;
4 |
5 | import org.apolo.ArtEngine;
6 | import org.apolo.HookName;
7 | import hook.utils.Slog;
8 |
9 | public class Settings {
10 | @HookName("android.provider.Settings$Global")
11 | public static class Global {
12 | private static final String TAG = "Settings.Global";
13 |
14 | public static String getString(ContentResolver cr, String key) {
15 | String ret = ArtEngine.callOrigin(null, cr, key);
16 | Slog.d(TAG, "proxy_getString key: %s value: %s", key, ret);
17 | return ret;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/douyin/EncryptorUtilProxy.java:
--------------------------------------------------------------------------------
1 | package hook.douyin;
2 |
3 | import org.apolo.ArtEngine;
4 | import org.apolo.HookName;
5 |
6 | import hook.utils.Slog;
7 |
8 | @HookName("com.bytedance.frameworks.encryptor.EncryptorUtil")
9 | public class EncryptorUtilProxy {
10 |
11 | private static final String TAG = "EncryptorUtilProxy";
12 |
13 | @HookName("LIZ")
14 | public static byte[] LIZ(byte[] arg1, int arg2) {
15 | Slog.d(TAG, "LIZ called");
16 | return ArtEngine.callOrigin(null, arg1, arg2);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/douyin/TTEncryptUtilsProxy.java:
--------------------------------------------------------------------------------
1 | package hook.douyin;
2 |
3 | import org.apolo.ArtEngine;
4 | import org.apolo.HookName;
5 |
6 | import hook.utils.Slog;
7 |
8 | @HookName("com.bytedance.frameworks.core.encrypt.TTEncryptUtils")
9 | public class TTEncryptUtilsProxy {
10 | private static final String TAG = TTEncryptUtilsProxy.class.getSimpleName();
11 |
12 | @HookName("encrypt")
13 | public static byte[] encrypt(byte[] bytes, int arg) {
14 | Slog.d(TAG, "encrypt called");
15 | return ArtEngine.callOrigin(bytes, arg);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/java/io/FileProxy.java:
--------------------------------------------------------------------------------
1 | package hook.java.io;
2 |
3 | import org.apolo.ArtEngine;
4 | import org.apolo.HookClass;
5 | import org.apolo.HookName;
6 | import org.apolo.ThisObject;
7 |
8 | import java.io.File;
9 |
10 | import hook.utils.Slog;
11 |
12 | @HookClass(File.class)
13 | public class FileProxy {
14 |
15 | private static final String TAG = "FileProxy";
16 |
17 | @HookName("mkdir")
18 | public static boolean mkdir(@ThisObject File thiz) {
19 | Slog.d(TAG, "proxy_mkdir " + thiz.getPath(), new Exception());
20 | return ArtEngine.callOrigin(thiz);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/java/lang/StringBuilder.java:
--------------------------------------------------------------------------------
1 | package hook.java.lang;
2 |
3 | import org.apolo.ArtEngine;
4 | import org.apolo.HookName;
5 | import org.apolo.ThisObject;
6 | import hook.utils.Slog;
7 |
8 | @HookName("java.lang.StringBuilder")
9 | public class StringBuilder {
10 |
11 | private static final String TAG = StringBuilder.class.getSimpleName();
12 |
13 | @HookName("toString")
14 | public static String toString(@ThisObject Object sb) {
15 | String ret = ArtEngine.callOrigin(sb);
16 | ArtEngine.hookTransition(true);
17 | Slog.d(TAG, "proxy_toString :" + ret);
18 | ArtEngine.hookTransition(false);
19 | return ret;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/java/lang/StringProxy.java:
--------------------------------------------------------------------------------
1 | package hook.java.lang;
2 |
3 | import org.apolo.ArtEngine;
4 | import org.apolo.HookClass;
5 | import org.apolo.HookName;
6 | import org.apolo.ThisObject;
7 | import hook.utils.Slog;
8 |
9 | @HookClass(String.class)
10 | public class StringProxy {
11 |
12 | private static final String TAG = StringProxy.class.getSimpleName();
13 | @HookName("equals")
14 | public static boolean equals(@ThisObject String str1, Object str2) {
15 | Slog.d(TAG, "proxy_equals called %s vs %s", str1, str2);
16 | return ArtEngine.callOrigin(str1, str2);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/javax/net/ssl/HttpsURLConnection.java:
--------------------------------------------------------------------------------
1 | package hook.javax.net.ssl;
2 |
3 | import javax.net.ssl.HostnameVerifier;
4 | import javax.net.ssl.SSLSocketFactory;
5 |
6 | import org.apolo.ArtEngine;
7 | import org.apolo.HookName;
8 | import org.apolo.ThisObject;
9 | import hook.utils.Slog;
10 |
11 | @HookName("javax.net.ssl.HttpsURLConnection")
12 | public class HttpsURLConnection {
13 | private static final String TAG = HttpsURLConnection.class.getSimpleName();
14 |
15 | @HookName("getDefaultSSLSocketFactory")
16 | public static SSLSocketFactory getDefaultSSLSocketFactory() {
17 | Slog.d(TAG, "proxy_getDefaultSSLSocketFactory called", new Exception());
18 | return ArtEngine.callOrigin(null);
19 | }
20 |
21 | @HookName("setSSLSocketFactory")
22 | public static void setSSLSocketFactory(@ThisObject Object thiz, SSLSocketFactory sf) {
23 | Slog.d(TAG, "proxy_setSSLSocketFactory called", new Exception());
24 | ArtEngine.callOrigin(thiz, sf);
25 | }
26 |
27 | @HookName("setHostnameVerifier")
28 | public static void setHostnameVerifier(@ThisObject Object thiz, HostnameVerifier v) {
29 | Slog.d(TAG, "proxy_setHostnameVerifier called", new Exception());
30 | ArtEngine.callOrigin(thiz, v);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/hook/utils/Slog.java:
--------------------------------------------------------------------------------
1 | package hook.utils;
2 |
3 | import android.util.Log;
4 |
5 | import com.apolo.helper.FileLogUtils;
6 |
7 | import org.apolo.ArtEngine;
8 |
9 | public class Slog {
10 | private static final boolean LOG_TO_FILE = false;
11 | public static void d(String tag, String format, Object... args) {
12 | ArtEngine.hookTransition(true);
13 | if (LOG_TO_FILE) {
14 | FileLogUtils.getInstance().saveLog(tag + ": " + String.format(format, args));
15 | } else {
16 | Log.d(tag, String.format(format, args));
17 | }
18 | ArtEngine.hookTransition(false);
19 | }
20 |
21 | public static void d(String tag, String format, Throwable thr, Object... args) {
22 | ArtEngine.hookTransition(true);
23 | if (LOG_TO_FILE) {
24 | FileLogUtils.getInstance().saveLog(String.format(format, args));
25 | } else {
26 | Log.d(tag, String.format(format, args), thr);
27 | }
28 | ArtEngine.hookTransition(false);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ArtHook
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:7.0.3'
9 | classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | google()
19 | jcenter()
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
26 |
27 | ext {
28 | minSdkVersion = 21
29 | compileSdkVersion = 31
30 | targetSdkVersion = 31
31 | buildToolsVersion = "31.0.0"
32 | javaVersion = JavaVersion.VERSION_1_8
33 | ndkVersion = "21.0.6113669"
34 | cmakeVersion = "3.18.1"
35 | abiFilters = "armeabi-v7a,arm64-v8a"
36 |
37 | useLocalLibrary = true
38 |
39 | POM_GROUP_ID = "io.github.waxmoon"
40 | POM_VERSION_NAME = "0.0.7"
41 |
42 | POM_URL = "https://github.com/WaxMoon/ApoloPlugin"
43 | POM_INCEPTION_YEAR = "2022"
44 | POM_PACKAGING = "aar"
45 |
46 | POM_SCM_CONNECTION = "https://github.com/WaxMoon/ApoloPlugin.git"
47 | POM_ISSUE_SYSTEM = "github"
48 | POM_ISSUE_URL = "https://github.com/WaxMoon/ApoloPlugin/issues"
49 |
50 | POM_LICENCE_NAME = "The MIT License"
51 | POM_LICENCE_URL = "https://opensource.org/licenses/MIT"
52 | POM_LICENCE_DIST = "repo"
53 |
54 | POM_DEVELOPER_ID = "WaxMoon"
55 | POM_DEVELOPER_NAME = "WaxMoon"
56 | POM_DEVELOPER_EMAIL = "cocos_sh@sina.com"
57 | }
58 |
--------------------------------------------------------------------------------
/docs/Apolo插件优化-支持trace过滤.md:
--------------------------------------------------------------------------------
1 | ## 背景
2 |
3 | [Apolo插件](https://github.com/WaxMoon/ApoloPlugin)提供了一些轻量级art hook接口,并且已经发布到[maven central](https://search.maven.org/),接入非常方便。将来也会提供更多的周边功能,其目的是为了帮助大家逆向/安全分析,app合规检测等。
4 |
5 | 鉴于trace功能带来的严重卡顿,可能使某些应用黑屏时间过长、anr、闪退,所以急切需要过滤功能。如果您有此需求,可以使用0.0.5版本。
6 |
7 | ## 参考文档
8 |
9 | [项目主页](https://github.com/WaxMoon/ApoloPlugin/blob/main/README-zh-CN.md)
10 |
11 | ## trace过滤功能接入说明
12 |
13 | **前提**: 如果您不知道如何使用apolo开启trace功能,那么您可以先翻阅一下[Apolo插件实战-dex反优化后trace代码](docs/Apolo%E6%8F%92%E4%BB%B6%E5%AE%9E%E6%88%98-dex%E5%8F%8D%E4%BC%98%E5%8C%96%E5%90%8Etrace%E4%BB%A3%E7%A0%81.md)
14 |
15 | ### 使用正则表达式进行trace 过滤
16 |
17 | 非常简单, 您只需要在开启trace的前提下,调用ArtEngine.setInterpretFilterRegex接口即可
18 |
19 | ```Java
20 |
21 | //split ','
22 | ArtEngine.setInterpretFilterRegex("android.app.*,android.os.*");
23 |
24 | ...
25 | ...
26 | //trace
27 | ArtEngine.enableInterpretLog();
28 | ArtEngine.setHookMode(ArtEngine.MODE_INTERPRET);
29 | ArtEngine.startHook();
30 |
31 | ```
32 | 上述demo中传入了android.app.*以及android.os.*,多个正则表达式用逗号分割开来,最终log中只会打印与正则相匹配的method。
33 |
34 | log效果截图
35 | 
--------------------------------------------------------------------------------
/docs/Apolo插件实战-dex反优化后trace代码.md:
--------------------------------------------------------------------------------
1 | ## 背景
2 |
3 | [Apolo插件](https://github.com/WaxMoon/ApoloPlugin)提供了一些轻量级art hook接口,并且已经发布到[maven central](https://search.maven.org/),接入非常方便。将来也会提供更多的周边功能,其目的是为了帮助大家逆向/安全分析,app合规检测等。
4 |
5 | 今天,给大家带来ApoloPlugin模块新功能,dex反优化trace java层代码执行流程。
6 |
7 | ## 参考文档
8 |
9 | [项目主页](https://github.com/WaxMoon/ApoloPlugin/blob/main/README-zh-CN.md)
10 |
11 | [Apolo插件实战-ROM环境注入app分析其行为](https://github.com/WaxMoon/ApoloPlugin/blob/main/docs/Apolo%E6%8F%92%E4%BB%B6%E5%AE%9E%E6%88%98-ROM%E7%8E%AF%E5%A2%83%E6%B3%A8%E5%85%A5app%E5%88%86%E6%9E%90%E5%85%B6%E8%A1%8C%E4%B8%BA.md)
12 |
13 | ## dex反优化trace使用场景
14 |
15 | * app加固,脱壳困难? 通过trace分析程序流
16 | * 不清楚对一款app如何下手? 通过trace找切入点
17 | * app是否有不合规调用? 通过trace抓取log,分析log即可
18 | * 入门学习安卓framework,会有些许帮助
19 |
20 | ## 如何开启trace
21 |
22 | **注意**:trace功能在ApoloPlugin:0.0.4版本才引入
23 |
24 | ### 第一步:必须调用ArtEngine.setHookMode
25 |
26 | ```Java
27 | @IntDef({
28 | MODE_SIMPLE,
29 | MODE_TRAMPOLINE,
30 | MODE_INTERPRET
31 | })
32 | public @interface MODE {}
33 | public static final int MODE_SIMPLE = 0x1;
34 | public static final int MODE_TRAMPOLINE = 0x1 << 1;
35 | public static final int MODE_INTERPRET = 0x1 << 2;
36 |
37 | public static void setHookMode(@MODE int mode) {
38 | sInterpretMode = mode;
39 | }
40 | ```
41 |
42 |
43 | #### HookMode属性
44 | 您可以修改HookMode为simple、trampo、interpret三种模式,分别对应三种场景:
45 |
46 | 1) simple: 如果您只需要关注app是否调用了系统api,此模式已够用
47 | 2) trampo: 此模式暂时先不支持,还有些许问题,比如性能
48 | 3) interpret: 解释执行模式,逆向hook/trace等场景使用
49 |
50 | ### 第二步:调用ArtEngine.enableInterpretLog函数
51 | 可以设置为ON、OFF两种选择。当为ON时,adb log会有大量log。
52 |
53 | ### 第三步:调用ArtEngine.startHook
54 | 如果您不hook java,也需要调用此接口
55 |
56 | **友情提醒:** 会造成app卡顿比较严重
57 |
58 | ## 案例-trace某讯聊天软件
59 |
60 | 
61 |
62 |
63 |
--------------------------------------------------------------------------------
/docs/assets/Application_entry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/Application_entry.png
--------------------------------------------------------------------------------
/docs/assets/StringBuilder_toString.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/StringBuilder_toString.png
--------------------------------------------------------------------------------
/docs/assets/WaxMoon_wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/WaxMoon_wechat.png
--------------------------------------------------------------------------------
/docs/assets/log_Handler_sendMsg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/log_Handler_sendMsg.png
--------------------------------------------------------------------------------
/docs/assets/log_HttpsUrlConn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/log_HttpsUrlConn.png
--------------------------------------------------------------------------------
/docs/assets/log_StringBuilder_toString.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/log_StringBuilder_toString.png
--------------------------------------------------------------------------------
/docs/assets/log_StringProxy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/log_StringProxy.png
--------------------------------------------------------------------------------
/docs/assets/patch_appFilter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/patch_appFilter.png
--------------------------------------------------------------------------------
/docs/assets/patch_bindApp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/patch_bindApp.png
--------------------------------------------------------------------------------
/docs/assets/patch_bindApp_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/patch_bindApp_2.png
--------------------------------------------------------------------------------
/docs/assets/qq_scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/qq_scan.png
--------------------------------------------------------------------------------
/docs/assets/qq_trace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/qq_trace.png
--------------------------------------------------------------------------------
/docs/assets/trace_filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/docs/assets/trace_filter.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Enables namespacing of each library's R class so that its R class includes only the
19 | # resources declared in the library itself and none from the library's dependencies,
20 | # thereby reducing the size of the R class for that library
21 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven-publish'
2 | apply plugin: 'signing'
3 |
4 | ext["signing.keyId"] = ''
5 | ext["signing.password"] = ''
6 | ext["signing.secretKeyRingFile"] = ''
7 | ext["ossrhUsername"] = ''
8 | ext["ossrhPassword"] = ''
9 |
10 | File secretPropsFile = project.rootProject.file('local.properties')
11 | if (secretPropsFile.exists()) {
12 | Properties p = new Properties()
13 | p.load(new FileInputStream(secretPropsFile))
14 | p.each { name, value ->
15 | ext[name] = value
16 | }
17 | } else {
18 | ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID')
19 | ext["signing.password"] = System.getenv('SIGNING_PASSWORD')
20 | ext["signing.secretKeyRingFile"] = System.getenv('SIGNING_SECRET_KEY_RING_FILE')
21 | ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME')
22 | ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD')
23 | }
24 |
25 | tasks.withType(JavaCompile) {
26 | options.encoding = "utf-8"
27 | }
28 |
29 | tasks.withType(Javadoc) {
30 | options.encoding = "utf-8"
31 | }
32 |
33 | task sourcesJar(type: Jar) {
34 | archiveClassifier.set("sources")
35 | from android.sourceSets.main.java.srcDirs
36 | }
37 |
38 | task javadoc(type: Javadoc) {
39 | source = android.sourceSets.main.java.sourceFiles
40 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
41 | options.encoding = "utf-8"
42 | options.charSet = "utf-8"
43 | }
44 |
45 | task javadocJar(type: Jar, dependsOn: javadoc) {
46 | archiveClassifier.set("javadoc")
47 | from javadoc.destinationDir
48 | }
49 |
50 | artifacts {
51 | archives javadocJar
52 | archives sourcesJar
53 | }
54 |
55 | project.afterEvaluate {
56 | publishing {
57 | publications {
58 | release(MavenPublication) {
59 | from components.release
60 |
61 | artifactId POM_ARTIFACT_ID
62 | groupId POM_GROUP_ID
63 | version POM_VERSION_NAME
64 |
65 | pom {
66 | name = POM_NAME
67 | description = POM_DESCRIPTION
68 | url = POM_URL
69 | inceptionYear = POM_INCEPTION_YEAR
70 | packaging = POM_PACKAGING
71 | scm {
72 | connection = POM_SCM_CONNECTION
73 | url = POM_URL
74 | }
75 | issueManagement {
76 | system = POM_ISSUE_SYSTEM
77 | url = POM_ISSUE_URL
78 | }
79 | licenses {
80 | license {
81 | name = POM_LICENCE_NAME
82 | url = POM_LICENCE_URL
83 | distribution = POM_LICENCE_DIST
84 | }
85 | }
86 | developers {
87 | developer {
88 | id = POM_DEVELOPER_ID
89 | name = POM_DEVELOPER_NAME
90 | email = POM_DEVELOPER_EMAIL
91 | }
92 | }
93 | }
94 | }
95 | }
96 | repositories {
97 | maven {
98 | name = "sonatype"
99 |
100 | def releasesRepoUrl = "https://s01.oss.sonatype.org/content/repositories/releases/"
101 | def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
102 | url = POM_VERSION_NAME.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
103 |
104 | credentials {
105 | username ossrhUsername
106 | password ossrhPassword
107 | }
108 | }
109 | }
110 | }
111 | }
112 |
113 | signing {
114 | sign publishing.publications
115 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WaxMoon/ApoloPlugin/9d2e1cd99120202b08ee75c4ae101e37ffd5976e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed May 04 20:58:26 CST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = "ApoloPlugin"
2 | include ':app'
3 | include ':ApoloPlugin'
4 | include ':xposed'
5 |
--------------------------------------------------------------------------------
/xposed/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/xposed/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | ext {
4 | POM_ARTIFACT_ID = "xposed"
5 | POM_NAME = "ApoloXposed"
6 | POM_DESCRIPTION = "An extension library of ApoloPlugin module"
7 | }
8 |
9 | android {
10 | compileSdk rootProject.ext.compileSdkVersion
11 |
12 | defaultConfig {
13 | minSdk rootProject.ext.minSdkVersion
14 | targetSdk rootProject.ext.targetSdkVersion
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
19 |
20 | }
21 |
22 | buildTypes {
23 | debug {
24 | minifyEnabled false
25 | }
26 | release {
27 | minifyEnabled false
28 | // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 |
32 | packagingOptions {
33 | exclude '**/libapolo.so'
34 | }
35 | }
36 |
37 | dependencies {
38 | implementation fileTree(include: ['*.jar'], dir: 'libs')
39 | implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3'
40 | if (rootProject.ext.useLocalLibrary) {
41 | compileOnly project(':ApoloPlugin')
42 | } else {
43 | compileOnly "io.github.waxmoon:ApoloPlugin:${POM_VERSION_NAME}"
44 | }
45 | }
46 |
47 | apply from: rootProject.file('gradle/publish.gradle')
48 |
--------------------------------------------------------------------------------
/xposed/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/xposed/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/xposed/src/main/java/com/android/dx/BinaryOp.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.dx;
18 |
19 | import com.android.dx.rop.code.Rop;
20 | import com.android.dx.rop.code.Rops;
21 | import com.android.dx.rop.type.TypeList;
22 |
23 | /**
24 | * An operation on two values of the same type.
25 | *
26 | * Math operations ({@link #ADD}, {@link #SUBTRACT}, {@link #MULTIPLY},
27 | * {@link #DIVIDE}, and {@link #REMAINDER}) support ints, longs, floats and
28 | * doubles.
29 | *
30 | *
Bit operations ({@link #AND}, {@link #OR}, {@link #XOR}, {@link
31 | * #SHIFT_LEFT}, {@link #SHIFT_RIGHT}, {@link #UNSIGNED_SHIFT_RIGHT}) support
32 | * ints and longs.
33 | *
34 | *
Division by zero behaves differently depending on the operand type.
35 | * For int and long operands, {@link #DIVIDE} and {@link #REMAINDER} throw
36 | * {@link ArithmeticException} if {@code b == 0}. For float and double operands,
37 | * the operations return {@code NaN}.
38 | */
39 | public enum BinaryOp {
40 | /**
41 | * {@code a + b}
42 | */
43 | ADD() {
44 | @Override
45 | Rop rop(TypeList types) {
46 | return Rops.opAdd(types);
47 | }
48 | },
49 |
50 | /**
51 | * {@code a - b}
52 | */
53 | SUBTRACT() {
54 | @Override
55 | Rop rop(TypeList types) {
56 | return Rops.opSub(types);
57 | }
58 | },
59 |
60 | /**
61 | * {@code a * b}
62 | */
63 | MULTIPLY() {
64 | @Override
65 | Rop rop(TypeList types) {
66 | return Rops.opMul(types);
67 | }
68 | },
69 |
70 | /**
71 | * {@code a / b}
72 | */
73 | DIVIDE() {
74 | @Override
75 | Rop rop(TypeList types) {
76 | return Rops.opDiv(types);
77 | }
78 | },
79 |
80 | /**
81 | * {@code a % b}
82 | */
83 | REMAINDER() {
84 | @Override
85 | Rop rop(TypeList types) {
86 | return Rops.opRem(types);
87 | }
88 | },
89 |
90 | /**
91 | * {@code a & b}
92 | */
93 | AND() {
94 | @Override
95 | Rop rop(TypeList types) {
96 | return Rops.opAnd(types);
97 | }
98 | },
99 |
100 | /**
101 | * {@code a | b}
102 | */
103 | OR() {
104 | @Override
105 | Rop rop(TypeList types) {
106 | return Rops.opOr(types);
107 | }
108 | },
109 |
110 | /**
111 | * {@code a ^ b}
112 | */
113 | XOR() {
114 | @Override
115 | Rop rop(TypeList types) {
116 | return Rops.opXor(types);
117 | }
118 | },
119 |
120 | /**
121 | * {@code a << b}
122 | */
123 | SHIFT_LEFT() {
124 | @Override
125 | Rop rop(TypeList types) {
126 | return Rops.opShl(types);
127 | }
128 | },
129 |
130 | /**
131 | * {@code a >> b}
132 | */
133 | SHIFT_RIGHT() {
134 | @Override
135 | Rop rop(TypeList types) {
136 | return Rops.opShr(types);
137 | }
138 | },
139 |
140 | /**
141 | * {@code a >>> b}
142 | */
143 | UNSIGNED_SHIFT_RIGHT() {
144 | @Override
145 | Rop rop(TypeList types) {
146 | return Rops.opUshr(types);
147 | }
148 | };
149 |
150 | abstract Rop rop(TypeList types);
151 | }
152 |
--------------------------------------------------------------------------------
/xposed/src/main/java/com/android/dx/Comparison.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.dx;
18 |
19 | import com.android.dx.rop.code.Rop;
20 | import com.android.dx.rop.code.Rops;
21 | import com.android.dx.rop.type.TypeList;
22 |
23 | /**
24 | * A comparison between two values of the same type.
25 | */
26 | public enum Comparison {
27 |
28 | /**
29 | * {@code a < b}. Supports int only.
30 | */
31 | LT() {
32 | @Override
33 | Rop rop(TypeList types) {
34 | return Rops.opIfLt(types);
35 | }
36 | },
37 |
38 | /**
39 | * {@code a <= b}. Supports int only.
40 | */
41 | LE() {
42 | @Override
43 | Rop rop(TypeList types) {
44 | return Rops.opIfLe(types);
45 | }
46 | },
47 |
48 | /**
49 | * {@code a == b}. Supports int and reference types.
50 | */
51 | EQ() {
52 | @Override
53 | Rop rop(TypeList types) {
54 | return Rops.opIfEq(types);
55 | }
56 | },
57 |
58 | /**
59 | * {@code a >= b}. Supports int only.
60 | */
61 | GE() {
62 | @Override
63 | Rop rop(TypeList types) {
64 | return Rops.opIfGe(types);
65 | }
66 | },
67 |
68 | /**
69 | * {@code a > b}. Supports int only.
70 | */
71 | GT() {
72 | @Override
73 | Rop rop(TypeList types) {
74 | return Rops.opIfGt(types);
75 | }
76 | },
77 |
78 | /**
79 | * {@code a != b}. Supports int and reference types.
80 | */
81 | NE() {
82 | @Override
83 | Rop rop(TypeList types) {
84 | return Rops.opIfNe(types);
85 | }
86 | };
87 |
88 | abstract Rop rop(TypeList types);
89 | }
90 |
--------------------------------------------------------------------------------
/xposed/src/main/java/com/android/dx/Constants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.dx;
18 |
19 | import com.android.dx.rop.cst.CstBoolean;
20 | import com.android.dx.rop.cst.CstByte;
21 | import com.android.dx.rop.cst.CstChar;
22 | import com.android.dx.rop.cst.CstDouble;
23 | import com.android.dx.rop.cst.CstFloat;
24 | import com.android.dx.rop.cst.CstInteger;
25 | import com.android.dx.rop.cst.CstKnownNull;
26 | import com.android.dx.rop.cst.CstLong;
27 | import com.android.dx.rop.cst.CstShort;
28 | import com.android.dx.rop.cst.CstString;
29 | import com.android.dx.rop.cst.CstType;
30 | import com.android.dx.rop.cst.TypedConstant;
31 |
32 | /**
33 | * Factory for rop constants.
34 | */
35 | final class Constants {
36 | private Constants() {
37 | }
38 |
39 | /**
40 | * Returns a rop constant for the specified value.
41 | *
42 | * @param value null, a boxed primitive, String, Class, or TypeId.
43 | */
44 | static TypedConstant getConstant(Object value) {
45 | if (value == null) {
46 | return CstKnownNull.THE_ONE;
47 | } else if (value instanceof Boolean) {
48 | return CstBoolean.make((Boolean) value);
49 | } else if (value instanceof Byte) {
50 | return CstByte.make((Byte) value);
51 | } else if (value instanceof Character) {
52 | return CstChar.make((Character) value);
53 | } else if (value instanceof Double) {
54 | return CstDouble.make(Double.doubleToLongBits((Double) value));
55 | } else if (value instanceof Float) {
56 | return CstFloat.make(Float.floatToIntBits((Float) value));
57 | } else if (value instanceof Integer) {
58 | return CstInteger.make((Integer) value);
59 | } else if (value instanceof Long) {
60 | return CstLong.make((Long) value);
61 | } else if (value instanceof Short) {
62 | return CstShort.make((Short) value);
63 | } else if (value instanceof String) {
64 | return new CstString((String) value);
65 | } else if (value instanceof Class) {
66 | return new CstType(TypeId.get((Class>) value).ropType);
67 | } else if (value instanceof TypeId) {
68 | return new CstType(((TypeId) value).ropType);
69 | } else {
70 | throw new UnsupportedOperationException("Not a constant: " + value);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/xposed/src/main/java/com/android/dx/FieldId.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.dx;
18 |
19 | import com.android.dx.rop.cst.CstFieldRef;
20 | import com.android.dx.rop.cst.CstNat;
21 | import com.android.dx.rop.cst.CstString;
22 |
23 | /**
24 | * Identifies a field.
25 | *
26 | * @param the type declaring this field
27 | * @param the type of value this field holds
28 | */
29 | public final class FieldId {
30 | final TypeId declaringType;
31 | final TypeId type;
32 | final String name;
33 |
34 | /**
35 | * cached converted state
36 | */
37 | final CstNat nat;
38 | final CstFieldRef constant;
39 |
40 | FieldId(TypeId declaringType, TypeId type, String name) {
41 | if (declaringType == null || type == null || name == null) {
42 | throw new NullPointerException();
43 | }
44 | this.declaringType = declaringType;
45 | this.type = type;
46 | this.name = name;
47 | this.nat = new CstNat(new CstString(name), new CstString(type.name));
48 | this.constant = new CstFieldRef(declaringType.constant, nat);
49 | }
50 |
51 | public TypeId getDeclaringType() {
52 | return declaringType;
53 | }
54 |
55 | public TypeId getType() {
56 | return type;
57 | }
58 |
59 | public String getName() {
60 | return name;
61 | }
62 |
63 | @Override
64 | public boolean equals(Object o) {
65 | return o instanceof FieldId
66 | && ((FieldId, ?>) o).declaringType.equals(declaringType)
67 | && ((FieldId, ?>) o).name.equals(name);
68 | }
69 |
70 | @Override
71 | public int hashCode() {
72 | return declaringType.hashCode() + 37 * name.hashCode();
73 | }
74 |
75 | @Override
76 | public String toString() {
77 | return declaringType + "." + name;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/xposed/src/main/java/com/android/dx/Label.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.android.dx;
18 |
19 | import com.android.dx.rop.code.BasicBlock;
20 | import com.android.dx.rop.code.Insn;
21 | import com.android.dx.rop.code.InsnList;
22 | import com.android.dx.util.IntList;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Collections;
26 | import java.util.List;
27 |
28 | /**
29 | * A branch target in a list of instructions.
30 | */
31 | public final class Label {
32 |
33 | final List instructions = new ArrayList<>();
34 |
35 | Code code;
36 |
37 | boolean marked = false;
38 |
39 | /**
40 | * an immutable list of labels corresponding to the types in the catch list
41 | */
42 | List