├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── assets
│ │ │ └── xposed_init
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.webp
│ │ │ │ └── ic_launcher_round.webp
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ ├── themes.xml
│ │ │ │ └── arrays.xml
│ │ │ ├── values-zh-rCN
│ │ │ │ └── strings.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ ├── layout
│ │ │ │ └── settings_activity.xml
│ │ │ ├── xml
│ │ │ │ ├── backup_rules.xml
│ │ │ │ ├── data_extraction_rules.xml
│ │ │ │ └── pref_luckyhooker.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── wuxianlin
│ │ │ │ └── luckyhooker
│ │ │ │ ├── Hook.java
│ │ │ │ ├── BootCompletedReceiver.java
│ │ │ │ ├── LSPosedUtils.java
│ │ │ │ ├── hooks
│ │ │ │ ├── SuperSU.java
│ │ │ │ ├── NetworkCapture.java
│ │ │ │ ├── QiYi.java
│ │ │ │ ├── HaiXing.java
│ │ │ │ ├── PerfectPlayer.java
│ │ │ │ ├── NowCasting.java
│ │ │ │ ├── PacketCapture.java
│ │ │ │ ├── MxPlayer.java
│ │ │ │ ├── ShowJava.java
│ │ │ │ ├── CoolApk.java
│ │ │ │ ├── KSWEB.java
│ │ │ │ └── HttpCanary.java
│ │ │ │ ├── HookUtils.java
│ │ │ │ ├── HookMain.java
│ │ │ │ ├── SettingsManager.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── WorldReadablePrefs.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── wuxianlin
│ │ │ └── luckyhooker
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── wuxianlin
│ │ └── luckyhooker
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── .idea
├── .gitignore
├── compiler.xml
├── vcs.xml
├── AndroidProjectSystem.xml
├── migrations.xml
├── deploymentTargetSelector.xml
├── misc.xml
├── gradle.xml
└── runConfigurations.xml
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── libs.versions.toml
├── .gitignore
├── settings.gradle
├── gradle.properties
├── .github
└── workflows
│ └── build.yml
├── gradlew.bat
├── gradlew
└── LICENSE
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | com.wuxianlin.luckyhooker.HookMain
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuxianlin/LuckyHooker/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF000000
4 | #FFFFFFFF
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/AndroidProjectSystem.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LuckyHooker
3 | About
4 | Source
5 | Apps
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LuckyHooker
3 | 关于
4 | 源码
5 | 应用
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Feb 25 15:09:19 CST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetSelector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/settings_activity.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/test/java/com/wuxianlin/luckyhooker/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/Hook.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
4 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
5 |
6 | /**
7 | * Created by wuxianlin on 2016/1/2.
8 | */
9 | public interface Hook {
10 |
11 | boolean canHook(String packageName);
12 |
13 | void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable;
14 |
15 | void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google {
4 | content {
5 | includeGroupByRegex("com\\.android.*")
6 | includeGroupByRegex("com\\.google.*")
7 | includeGroupByRegex("androidx.*")
8 | }
9 | }
10 | mavenCentral()
11 | gradlePluginPortal()
12 | }
13 | }
14 | dependencyResolutionManagement {
15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
16 | repositories {
17 | google()
18 | mavenCentral()
19 | maven { url "https://api.xposed.info/" }
20 | }
21 | }
22 |
23 | rootProject.name = "LuckyHooker"
24 | include ':app'
25 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/BootCompletedReceiver.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Build;
7 |
8 | /**
9 | * Created by wuxianlin on 2017/8/10.
10 | */
11 |
12 | public class BootCompletedReceiver extends BroadcastReceiver {
13 |
14 | @Override
15 | public void onReceive(Context context, Intent intent) {
16 | if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
17 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
18 | !LSPosedUtils.checkLSPosed(context.createDeviceProtectedStorageContext())) {
19 | SettingsManager.getInstance(context).fixFolderPermissionsAsync();
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | - com.zhangyangjing.starfish
4 | - com.guoshi.httpcanary
5 | - com.guoshi.httpcanary.premium
6 | - ru.kslabs.ksweb
7 | - com.mxtech.videoplayer.pro
8 | - com.minhui.networkcapture
9 | - com.nowcasting.huawei
10 | - com.nowcasting.activity
11 | - app.greyshirts.sslcapture
12 | - com.niklabs.pp
13 | - com.qiyi.video
14 | - com.qiyi.video.pad
15 | - tv.pps.mobile
16 | - com.njlabs.showjava
17 | - eu.chainfire.supersu
18 | - com.coolapk.market
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/pref_luckyhooker.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
12 |
15 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/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
22 | -keep class com.wuxianlin.luckyhooker.HookMain
23 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/wuxianlin/luckyhooker/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.wuxianlin.luckyhooker", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | agp = "8.13.1"
3 | junit = "4.13.2"
4 | junitVersion = "1.3.0"
5 | espressoCore = "3.7.0"
6 | appcompat = "1.7.0"
7 | material = "1.12.0"
8 | preference = "1.2.1"
9 | xposed = "82"
10 |
11 | [libraries]
12 | junit = { group = "junit", name = "junit", version.ref = "junit" }
13 | ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
14 | espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
15 | appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
16 | material = { group = "com.google.android.material", name = "material", version.ref = "material" }
17 | preference = { group = "androidx.preference", name = "preference", version.ref = "preference" }
18 | xposed = { group = "de.robv.android.xposed", name = "api", version.ref = "xposed" }
19 |
20 | [plugins]
21 | android-application = { id = "com.android.application", version.ref = "agp" }
22 |
23 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.android.application)
3 | }
4 |
5 | android {
6 | namespace 'com.wuxianlin.luckyhooker'
7 | compileSdk 36
8 |
9 | defaultConfig {
10 | applicationId "com.wuxianlin.luckyhooker"
11 | minSdk 21
12 | targetSdk 36
13 | versionCode 3
14 | versionName "2.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled true
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | buildFeatures {
26 | buildConfig true
27 | }
28 | compileOptions {
29 | sourceCompatibility JavaVersion.VERSION_11
30 | targetCompatibility JavaVersion.VERSION_11
31 | }
32 | }
33 |
34 | dependencies {
35 |
36 | implementation libs.appcompat
37 | implementation libs.material
38 | implementation libs.preference
39 | compileOnly libs.xposed
40 | testImplementation libs.junit
41 | androidTestImplementation libs.ext.junit
42 | androidTestImplementation libs.espresso.core
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/LSPosedUtils.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.widget.Toast;
6 |
7 | import java.io.File;
8 | import java.lang.reflect.InvocationTargetException;
9 | import java.lang.reflect.Method;
10 |
11 | /**
12 | * https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences
13 | */
14 | public class LSPosedUtils {
15 |
16 | private static boolean checkResult = false;
17 | private static boolean checked = false;
18 |
19 | @SuppressLint("WorldReadableFiles")
20 | public static boolean checkLSPosed(Context context) {
21 | if (checked)
22 | return checkResult;
23 | try {
24 | context.getSharedPreferences(context.getPackageName() + "_preferences",
25 | Context.MODE_WORLD_READABLE);
26 | checkResult = true;
27 | checked = true;
28 | } catch (SecurityException exception) {
29 | Toast.makeText(context, "LuckyHooker Settings may not work", Toast.LENGTH_LONG).show();
30 | checkResult = false;
31 | checked = true;
32 | }
33 | return checkResult;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/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. For more details, visit
12 | # https://developer.android.com/r/tools/gradle-multi-project-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
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/SuperSU.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import com.wuxianlin.luckyhooker.Hook;
4 |
5 | import de.robv.android.xposed.XC_MethodHook;
6 | import de.robv.android.xposed.XposedBridge;
7 | import de.robv.android.xposed.XposedHelpers;
8 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
9 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
10 |
11 | /**
12 | * Created by wuxianlin on 2016/5/2.
13 | */
14 |
15 | public class SuperSU implements Hook {
16 |
17 | public static final String hookPackageName = "eu.chainfire.supersu";
18 |
19 | @Override
20 | public boolean canHook(String packageName) {
21 | return hookPackageName.equals(packageName);
22 | }
23 |
24 | @Override
25 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
26 | XposedBridge.log("start Hook SuperSU");
27 | XposedHelpers.findAndHookMethod("android.app.ApplicationPackageManager", lpparam.classLoader, "getApplicationInfo", String.class, int.class, new XC_MethodHook() {
28 | @Override
29 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
30 | if (param.args[0].equals("eu.chainfire.supersu.pro"))
31 | param.args[0] = "eu.chainfire.supersu";
32 | }
33 | });
34 | }
35 |
36 | @Override
37 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/NetworkCapture.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import android.content.Context;
4 |
5 | import com.wuxianlin.luckyhooker.Hook;
6 |
7 | import de.robv.android.xposed.XC_MethodReplacement;
8 | import de.robv.android.xposed.XposedBridge;
9 | import de.robv.android.xposed.XposedHelpers;
10 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
11 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
12 |
13 | /**
14 | * Created by wuxianlin on 2023/2/26.
15 | */
16 |
17 | public class NetworkCapture implements Hook {
18 |
19 | public static final String hookPackageName = "com.minhui.networkcapture";
20 |
21 | @Override
22 | public boolean canHook(String packageName) {
23 | return hookPackageName.equals(packageName);
24 | }
25 |
26 | @Override
27 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
28 | XposedBridge.log("start Hook Network Capture");
29 | XposedHelpers.findAndHookMethod("com.minhui.networkcapture.utils.ContextUtil", lpparam.classLoader, "isProVersion", Context.class, XC_MethodReplacement.returnConstant(true));
30 | XposedHelpers.findAndHookMethod("com.minhui.networkcapture.utils.ContextUtil", lpparam.classLoader, "hasRegister", Context.class, XC_MethodReplacement.returnConstant(true));
31 | XposedHelpers.findAndHookMethod("com.minhui.networkcapture.utils.ContextUtil", lpparam.classLoader, "isNoGooglePlayNoAds", Context.class, XC_MethodReplacement.returnConstant(true));
32 |
33 | }
34 |
35 | @Override
36 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/QiYi.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import com.wuxianlin.luckyhooker.Hook;
4 |
5 | import java.util.Arrays;
6 | import java.util.Properties;
7 |
8 | import de.robv.android.xposed.XC_MethodHook;
9 | import de.robv.android.xposed.XposedBridge;
10 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
11 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
12 |
13 | /**
14 | * Created by wuxianlin on 2018/1/3.
15 | */
16 |
17 | public class QiYi implements Hook {
18 |
19 | public static final String[] hookPackageNames = new String[]{"com.qiyi.video", "com.qiyi.video.pad", "tv.pps.mobile"};
20 |
21 | @Override
22 | public boolean canHook(String packageName) {
23 | return Arrays.asList(hookPackageNames).contains(packageName);
24 | }
25 |
26 | @Override
27 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
28 | XposedBridge.log("start Hook IQiYi");
29 | XposedBridge.hookAllMethods(Properties.class, "getProperty", new XC_MethodHook() {
30 | @Override
31 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
32 | if ("qiyi.export.key".equals(param.args[0])) {
33 | param.setResult("59e36a5e70e4c4efc6fcbc4db7ea59c1");
34 | //param.setResult("20485102b09bfb5842bf370463bed900");
35 | //param.setResult("200852026c791ac910651df45b27da50");
36 | }
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/HaiXing.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import com.wuxianlin.luckyhooker.Hook;
4 |
5 | import java.io.File;
6 |
7 | import de.robv.android.xposed.XC_MethodHook;
8 | import de.robv.android.xposed.XposedBridge;
9 | import de.robv.android.xposed.XposedHelpers;
10 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
11 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
12 |
13 | /**
14 | * Created by guhb on 2018/1/18.
15 | */
16 |
17 | public class HaiXing implements Hook {
18 |
19 | public static final String hookPackageName = "com.zhangyangjing.starfish";
20 |
21 | @Override
22 | public boolean canHook(String packageName) {
23 | return hookPackageName.equals(packageName);
24 | }
25 |
26 | @Override
27 | public void startHook(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
28 | XposedBridge.log("start Hook HaiXing:" + lpparam.packageName);
29 | XposedHelpers.findAndHookMethod("android.app.SharedPreferencesImpl", lpparam.classLoader, "getString", String.class, String.class, new XC_MethodHook() {
30 | @Override
31 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
32 | File mFile = (File) XposedHelpers.getObjectField(param.thisObject, "mFile");
33 | if (!mFile.getName().equals("app_settings.xml")) return;
34 | String key = (String) param.args[0];
35 | if (key.equals("account_type"))
36 | param.setResult("VIP1");
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/PerfectPlayer.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import com.wuxianlin.luckyhooker.Hook;
4 |
5 | import java.io.File;
6 |
7 | import de.robv.android.xposed.XC_MethodHook;
8 | import de.robv.android.xposed.XposedBridge;
9 | import de.robv.android.xposed.XposedHelpers;
10 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
11 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
12 |
13 | /**
14 | * Created by wuxianlin on 2017/9/25.
15 | */
16 |
17 | public class PerfectPlayer implements Hook {
18 |
19 | public static final String hookPackageName = "com.niklabs.pp";
20 |
21 | @Override
22 | public boolean canHook(String packageName) {
23 | return hookPackageName.equals(packageName);
24 | }
25 |
26 | @Override
27 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
28 | XposedBridge.log("start Hook PerfectPlayer");
29 | XposedHelpers.findAndHookMethod("android.app.SharedPreferencesImpl", lpparam.classLoader, "getBoolean", String.class, boolean.class, new XC_MethodHook() {
30 | @Override
31 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
32 | File mFile = (File) XposedHelpers.getObjectField(param.thisObject, "mFile");
33 | if (!mFile.getName().equals(hookPackageName + "_preferences.xml")) return;
34 | String key = (String) param.args[0];
35 | if (key.equals("pref_key_unlocked_full_version"))
36 | param.setResult(true);
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/NowCasting.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import com.wuxianlin.luckyhooker.Hook;
4 | import com.wuxianlin.luckyhooker.HookUtils;
5 |
6 | import org.json.JSONObject;
7 |
8 | import java.lang.reflect.Method;
9 | import java.util.Arrays;
10 |
11 | import de.robv.android.xposed.XC_MethodHook;
12 | import de.robv.android.xposed.XC_MethodReplacement;
13 | import de.robv.android.xposed.XposedBridge;
14 | import de.robv.android.xposed.XposedHelpers;
15 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
16 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
17 |
18 | /**
19 | * Created by wuxianlin on 2023/2/26.
20 | */
21 |
22 | public class NowCasting implements Hook {
23 |
24 | public static final String[] hookPackageNames = new String[]{"com.nowcasting.huawei",
25 | "com.nowcasting.activity"};
26 |
27 | @Override
28 | public boolean canHook(String packageName) {
29 | return Arrays.asList(hookPackageNames).contains(packageName);
30 | }
31 |
32 | @Override
33 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
34 | XposedBridge.log("start hook NowCasting");
35 | if (hookPackageNames[0].equals(lpparam.packageName)) {
36 | XposedBridge.hookAllMethods(XposedHelpers.findClass("com.huawei.android.sdk.drm.Drm", lpparam.classLoader), "check", XC_MethodReplacement.returnConstant(null));
37 | }
38 | XposedBridge.hookAllMethods(XposedHelpers.findClass("com.nowcasting.entity.UserInfo", lpparam.classLoader),"isVIP", XC_MethodReplacement.returnConstant(true));
39 | }
40 |
41 | @Override
42 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/PacketCapture.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import android.view.View;
4 | import android.widget.RelativeLayout;
5 |
6 | import com.wuxianlin.luckyhooker.Hook;
7 |
8 | import de.robv.android.xposed.XC_MethodReplacement;
9 | import de.robv.android.xposed.XposedBridge;
10 | import de.robv.android.xposed.XposedHelpers;
11 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
12 | import de.robv.android.xposed.callbacks.XC_LayoutInflated;
13 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
14 |
15 | /**
16 | * Created by wuxianlin on 2016/1/2.
17 | */
18 |
19 | public class PacketCapture implements Hook {
20 |
21 | public static final String hookPackageName = "app.greyshirts.sslcapture";
22 |
23 | @Override
24 | public boolean canHook(String packageName) {
25 | return hookPackageName.equals(packageName);
26 | }
27 |
28 | @Override
29 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
30 | XposedBridge.log("start Hook PacketCapture");
31 | XposedHelpers.findAndHookMethod("ui.PacketActivity", lpparam.classLoader, "getMInterstitialAd", XC_MethodReplacement.returnConstant(null));
32 | }
33 |
34 | @Override
35 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
36 | XposedBridge.log("start Hook PacketCapture");
37 | resparam.res.hookLayout(hookPackageName, "layout", "frag_ad", new XC_LayoutInflated() {
38 | @Override
39 | public void handleLayoutInflated(LayoutInflatedParam liparam) throws Throwable {
40 | RelativeLayout frag = (RelativeLayout) liparam.view;
41 | View adFragment = frag.findViewById(liparam.res.getIdentifier("adView", "id", hookPackageName));
42 | frag.removeView(adFragment);
43 | }
44 | });
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Apk Build
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches: [ master ]
7 |
8 | jobs:
9 | build:
10 | name: Build Apk
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Check out
15 | uses: actions/checkout@v4
16 |
17 | - name: Set up JDK 17
18 | uses: actions/setup-java@v4
19 | with:
20 | distribution: 'zulu'
21 | java-version: 17
22 |
23 | - name: download testkey
24 | run: |
25 | curl -s https://android.googlesource.com/platform/build/+/refs/heads/main/target/product/security/testkey.x509.pem?format=TEXT | base64 -d > testkey.x509.pem
26 | curl -s https://android.googlesource.com/platform/build/+/refs/heads/main/target/product/security/testkey.pk8?format=TEXT | base64 -d > testkey.pk8
27 | openssl pkcs8 -in testkey.pk8 -inform DER -outform PEM -out testkey.priv.pem -nocrypt
28 | openssl pkcs12 -export -in testkey.x509.pem -inkey testkey.priv.pem -out testkey.pk12 -password pass:android -name androiddebugkey
29 | keytool -importkeystore -srckeystore testkey.pk12 -srcstoretype PKCS12 -srcstorepass android -alias androiddebugkey -deststoretype JKS -destkeystore testkey.jks -deststorepass android
30 |
31 | - name: Build release APK
32 | run: bash gradlew assembleRelease
33 | shell: bash
34 |
35 | - name: Sign release APK
36 | run: |
37 | apksigner="$(find $ANDROID_SDK_ROOT/build-tools -name apksigner | sort -r | head -n 1)"
38 | "$apksigner" sign --ks testkey.jks --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android --in ./app/build/outputs/apk/release/app-release-unsigned.apk --out ./app/build/outputs/apk/release/app-release.apk
39 | shell: bash
40 |
41 | - name: Upload build artifact
42 | uses: actions/upload-artifact@v4
43 | with:
44 | name: app-release
45 | path: app/build/outputs/apk/release/app-release.apk
46 | if-no-files-found: error
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/MxPlayer.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import android.content.ContextWrapper;
4 | import android.os.Build;
5 |
6 | import com.wuxianlin.luckyhooker.Hook;
7 |
8 | import de.robv.android.xposed.XC_MethodHook;
9 | import de.robv.android.xposed.XposedBridge;
10 | import de.robv.android.xposed.XposedHelpers;
11 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
12 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
13 |
14 | /**
15 | * Created by wuxianlin on 2016/1/2.
16 | */
17 |
18 | public class MxPlayer implements Hook {
19 |
20 | public static final String hookPackageName = "com.mxtech.videoplayer.pro";
21 |
22 | @Override
23 | public boolean canHook(String packageName) {
24 | return hookPackageName.equals(packageName);
25 | }
26 |
27 | @Override
28 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
29 | XposedBridge.log("start Hook MxPlayer Pro");
30 | XposedHelpers.findAndHookMethod("com.mxtech.app.Apps", lpparam.classLoader, Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? "c" : "get", int.class, new XC_MethodHook() {
31 | @Override
32 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
33 | int input = (int) param.args[0];
34 | if (input == 1 || input == 2)
35 | param.setResult(1L);
36 | }
37 | });
38 | XposedHelpers.findAndHookMethod(ContextWrapper.class, "checkPermission", String.class, int.class, int.class, new XC_MethodHook() {
39 | @Override
40 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
41 | String perm = (String) param.args[0];
42 | if (perm.equals("com.android.vending.CHECK_LICENSE")
43 | || perm.equals("android.permission.GET_ACCOUNTS"))
44 | param.setResult(0);
45 | }
46 | });
47 | }
48 |
49 | @Override
50 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
8 |
9 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
37 |
38 |
39 |
40 |
41 |
44 |
47 |
50 |
53 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/ShowJava.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import com.wuxianlin.luckyhooker.Hook;
4 | import com.wuxianlin.luckyhooker.HookUtils;
5 |
6 | import de.robv.android.xposed.XC_MethodHook;
7 | import de.robv.android.xposed.XC_MethodReplacement;
8 | import de.robv.android.xposed.XposedBridge;
9 | import de.robv.android.xposed.XposedHelpers;
10 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
11 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
12 |
13 | /**
14 | * Created by wuxianlin on 2016/10/13.
15 | */
16 |
17 | public class ShowJava implements Hook {
18 |
19 | public static final String hookPackageName = "com.njlabs.showjava";
20 |
21 | @Override
22 | public boolean canHook(String packageName) {
23 | return hookPackageName.equals(packageName);
24 | }
25 |
26 | @Override
27 | public void startHook(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
28 | XposedBridge.log("start Hook ShowJava");
29 | int versionCode = HookUtils.getPackageVersionCode(hookPackageName);
30 | if (versionCode <= 21002) {
31 | XposedHelpers.findAndHookMethod("com.njlabs.showjava.ui.BaseActivity", lpparam.classLoader, "get", XC_MethodReplacement.returnConstant(true));
32 | XposedHelpers.findAndHookMethod("com.njlabs.showjava.ui.BaseActivity", lpparam.classLoader, "put", boolean.class, new XC_MethodHook() {
33 | @Override
34 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
35 | param.args[0] = true;
36 | }
37 | });
38 | } else {
39 | //30406//30502//30604--com.njlabs.showjava.activities.a.u()Z->com.njlabs.showjava.utils.d.b.d()Z
40 | //30300//30200//30107--com.njlabs.showjava.activities.a.s()Z->com.njlabs.showjava.utils.c.b.d()Z
41 | /*XposedHelpers.findAndHookMethod("com.njlabs.showjava.activities.a",
42 | lpparam.classLoader, versionCode>30502?"u":"s",
43 | XC_MethodReplacement.returnConstant(true));*/
44 | XposedHelpers.findAndHookMethod(versionCode >= 30406 ?
45 | "com.njlabs.showjava.utils.d.b" :
46 | "com.njlabs.showjava.utils.c.b",
47 | lpparam.classLoader, "d", XC_MethodReplacement.returnConstant(true));
48 |
49 | }
50 | }
51 |
52 | @Override
53 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/HookUtils.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.pm.PackageManager;
6 | import android.os.UserHandle;
7 | import android.text.TextUtils;
8 |
9 | import androidx.annotation.Nullable;
10 |
11 | import java.lang.reflect.InvocationTargetException;
12 | import java.lang.reflect.Method;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | import de.robv.android.xposed.XposedHelpers;
17 |
18 | /**
19 | * Created by wuxianlin on 2016/1/2.
20 | */
21 |
22 | public class HookUtils {
23 |
24 | public static Context getContext() {
25 | Object thread = XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentActivityThread");
26 | if (thread == null) {
27 | return null;
28 | }
29 | Context context = (Context) XposedHelpers.callMethod(thread, "getSystemContext");
30 | if (context == null) {
31 | return null;
32 | }
33 | return context;
34 | }
35 |
36 | public static int getPackageVersionCode(String packageName) {
37 | Context context = getContext();
38 | if (context == null)
39 | return 0;
40 | PackageManager packageManager = context.getPackageManager();
41 | if (packageManager == null)
42 | return 0;
43 | try {
44 | return packageManager.getPackageInfo(packageName, 0).versionCode;
45 | } catch (PackageManager.NameNotFoundException e) {
46 | e.printStackTrace();
47 | }
48 | return 0;
49 | }
50 |
51 | public static List findMethodWithName(String className, ClassLoader classLoader, String methodName) {
52 | List methods = new ArrayList<>();
53 | if (TextUtils.isEmpty(className) || TextUtils.isEmpty(methodName))
54 | return methods;
55 | Class hookClass = XposedHelpers.findClassIfExists(className, classLoader);
56 | if (hookClass == null)
57 | return methods;
58 | for (Method method : hookClass.getDeclaredMethods()) {
59 | if (methodName.equals(method.getName())) {
60 | methods.add(method);
61 | }
62 | }
63 | return methods;
64 | }
65 |
66 | public static int getMyUserId() {
67 | try {
68 | int uid = android.os.Process.myUid();
69 | Integer userId = (Integer) getGetUserIdMethod().invoke(null, uid);
70 | return userId;
71 | } catch (NoSuchMethodException ignored) {
72 | } catch (IllegalAccessException ignored) {
73 | } catch (InvocationTargetException ignored) {
74 | }
75 | return 0;
76 | }
77 |
78 | @Nullable
79 | private static Method sGetUserIdMethod;
80 |
81 | @SuppressLint("DiscouragedPrivateApi")
82 | private static Method getGetUserIdMethod() throws NoSuchMethodException {
83 | if (sGetUserIdMethod == null) {
84 | sGetUserIdMethod = UserHandle.class.getDeclaredMethod("getUserId", int.class);
85 | sGetUserIdMethod.setAccessible(true);
86 | }
87 | return sGetUserIdMethod;
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/HookMain.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import android.os.Build;
4 |
5 | import com.wuxianlin.luckyhooker.hooks.*;
6 |
7 | import java.io.File;
8 | import java.util.HashSet;
9 | import java.util.Set;
10 |
11 | import de.robv.android.xposed.IXposedHookInitPackageResources;
12 | import de.robv.android.xposed.IXposedHookLoadPackage;
13 | import de.robv.android.xposed.IXposedHookZygoteInit;
14 | import de.robv.android.xposed.XSharedPreferences;
15 | import de.robv.android.xposed.XposedBridge;
16 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
17 | import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
18 |
19 | /**
20 | * Created by wuxianlin on 2016/1/2.
21 | */
22 |
23 | public class HookMain implements IXposedHookZygoteInit, IXposedHookLoadPackage,
24 | IXposedHookInitPackageResources {
25 |
26 | private Set hooks = new HashSet();
27 |
28 | public static XSharedPreferences prefs;
29 | public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
30 | public static String MODULE_PATH = null;
31 | private static File prefsFileProt = new File("/data/user_de/" +
32 | HookUtils.getMyUserId() +
33 | "/" + PACKAGE_NAME + "/shared_prefs/" + PACKAGE_NAME + "_preferences.xml");
34 |
35 | public HookMain() {
36 | hooks.add(new CoolApk());
37 | hooks.add(new HaiXing());
38 | hooks.add(new HttpCanary());
39 | hooks.add(new KSWEB());
40 | hooks.add(new MxPlayer());
41 | hooks.add(new NetworkCapture());
42 | hooks.add(new NowCasting());
43 | hooks.add(new PacketCapture());
44 | hooks.add(new PerfectPlayer());
45 | hooks.add(new QiYi());
46 | hooks.add(new ShowJava());
47 | hooks.add(new SuperSU());
48 | }
49 |
50 | @Override
51 | public void initZygote(IXposedHookZygoteInit.StartupParam startupParam) throws Throwable {
52 | MODULE_PATH = startupParam.modulePath;
53 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && prefsFileProt.canRead()) {
54 | prefs = new XSharedPreferences(prefsFileProt);
55 | } else {
56 | prefs = new XSharedPreferences(PACKAGE_NAME);
57 | }
58 | }
59 |
60 | @Override
61 | public void handleInitPackageResources(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
62 | prefs.reload();
63 | for (Hook hook : hooks) {
64 | try {
65 | String packageName = resparam.packageName;
66 | if (hook.canHook(packageName) &&
67 | prefs.getBoolean(packageName, true))
68 | hook.startHook(resparam);
69 | } catch (Throwable t) {
70 | XposedBridge.log(t.toString());
71 | }
72 | }
73 | }
74 |
75 | @Override
76 | public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
77 | prefs.reload();
78 | for (Hook hook : hooks) {
79 | try {
80 | String packageName = lpparam.packageName;
81 | if (hook.canHook(packageName) &&
82 | prefs.getBoolean(packageName, true))
83 | hook.startHook(lpparam);
84 | } catch (Throwable t) {
85 | XposedBridge.log(t.toString());
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/hooks/CoolApk.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker.hooks;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | import com.wuxianlin.luckyhooker.Hook;
7 |
8 | import java.io.File;
9 |
10 | import de.robv.android.xposed.XC_MethodHook;
11 | import de.robv.android.xposed.XC_MethodReplacement;
12 | import de.robv.android.xposed.XposedBridge;
13 | import de.robv.android.xposed.XposedHelpers;
14 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
15 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
16 |
17 | public class CoolApk implements Hook {
18 |
19 | public static final String hookPackageName = "com.coolapk.market";
20 |
21 | @Override
22 | public boolean canHook(String packageName) {
23 | return hookPackageName.equals(packageName);
24 | }
25 |
26 | @Override
27 | public void startHook(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
28 | XposedBridge.log("start Hook CoolApk:" + lpparam.packageName);
29 | XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
30 | @Override
31 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
32 | ClassLoader classLoader = ((Context) param.args[0]).getClassLoader();
33 | try {
34 | XposedHelpers.findAndHookMethod("com.qq.e.comm.managers.GDTAdSdk", classLoader, "initWithoutStart", Context.class, String.class, XC_MethodReplacement.returnConstant(null));
35 | } catch (Throwable t) {
36 | XposedBridge.log(t.toString());
37 | }
38 | try {
39 | XposedHelpers.findAndHookMethod("com.bytedance.sdk.openadsdk.TTAdSdk", classLoader, "init", Context.class, "com.bytedance.sdk.openadsdk.TTAdConfig", XC_MethodReplacement.returnConstant(false));
40 | } catch (Throwable t) {
41 | XposedBridge.log(t.toString());
42 | }
43 | try {
44 | XposedHelpers.findAndHookMethod("com.bytedance.sdk.openadsdk.TTAdSdk", classLoader, "getAdManager", XC_MethodReplacement.returnConstant(null));
45 | } catch (Throwable t) {
46 | XposedBridge.log(t.toString());
47 | }
48 | try {
49 | XposedHelpers.findAndHookMethod("com.bytedance.sdk.open.douyin.a", classLoader, "init", "com.bytedance.sdk.open.douyin.DouYinOpenConfig", XC_MethodReplacement.returnConstant(false));
50 | } catch (Throwable t) {
51 | XposedBridge.log(t.toString());
52 | }
53 | try {
54 | XposedHelpers.findAndHookMethod("com.kwad.sdk.api.KsAdSDK", classLoader, "init", Context.class, "com.kwad.sdk.api.SdkConfig", XC_MethodReplacement.returnConstant(false));
55 | } catch (Throwable t) {
56 | XposedBridge.log(t.toString());
57 | }
58 | try {
59 | XposedHelpers.findAndHookMethod("com.umeng.commonsdk.UMConfigure", classLoader, "init", Context.class, String.class, String.class, int.class, String.class, XC_MethodReplacement.returnConstant(null));
60 | } catch (Throwable t) {
61 | XposedBridge.log(t.toString());
62 | }
63 | }
64 | });
65 | }
66 |
67 | @Override
68 | public void startHook(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/SettingsManager.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.os.AsyncTask;
6 | import android.os.Build;
7 | import android.os.FileObserver;
8 | import android.util.Log;
9 |
10 | import androidx.annotation.RequiresApi;
11 |
12 | import java.io.File;
13 | import java.lang.reflect.Field;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | /**
18 | * https://github.com/GravityBox/GravityBox/blob/r/GravityBox/src/main/java/com/ceco/r/gravitybox/SettingsManager.java
19 | */
20 | @RequiresApi(api = Build.VERSION_CODES.N)
21 | public class SettingsManager {
22 |
23 | public interface FileObserverListener {
24 | void onFileUpdated(String path);
25 |
26 | void onFileAttributesChanged(String path);
27 | }
28 |
29 | private static Context mContext;
30 | private static SettingsManager mInstance;
31 | private WorldReadablePrefs mPrefsMain;
32 | private FileObserver mFileObserver;
33 | private List mFileObserverListeners;
34 | private String mPreferenceDir;
35 |
36 | private SettingsManager(Context context) {
37 | mContext = !context.isDeviceProtectedStorage() ?
38 | context.createDeviceProtectedStorageContext() : context;
39 | mFileObserverListeners = new ArrayList<>();
40 | mPrefsMain = new WorldReadablePrefs(mContext, getPreferenceDir(), mContext.getPackageName() + "_preferences");
41 | mFileObserverListeners.add(mPrefsMain);
42 |
43 | registerFileObserver();
44 | }
45 |
46 | public String getPreferenceDir() {
47 | if (mPreferenceDir == null) {
48 | try {
49 | SharedPreferences prefs = mContext.getSharedPreferences("dummy", Context.MODE_PRIVATE);
50 | prefs.edit().putBoolean("dummy", false).commit();
51 | Field f = prefs.getClass().getDeclaredField("mFile");
52 | f.setAccessible(true);
53 | mPreferenceDir = new File(((File) f.get(prefs)).getParent()).getAbsolutePath();
54 | Log.d("GravityBox", "Preference folder: " + mPreferenceDir);
55 | } catch (NoSuchFieldException | IllegalAccessException e) {
56 | Log.e("GravityBox", "Could not determine preference folder path. Returning default.");
57 | e.printStackTrace();
58 | mPreferenceDir = mContext.getDataDir() + "/shared_prefs";
59 | }
60 | }
61 | return mPreferenceDir;
62 | }
63 |
64 | public static synchronized SettingsManager getInstance(Context context) {
65 | if (context == null && mInstance == null)
66 | throw new IllegalArgumentException("Context cannot be null");
67 |
68 | if (mInstance == null) {
69 | mInstance = new SettingsManager(context.getApplicationContext() != null ?
70 | context.getApplicationContext() : context);
71 | }
72 | return mInstance;
73 | }
74 |
75 | public void fixFolderPermissionsAsync() {
76 | AsyncTask.execute(() -> {
77 | // main dir
78 | File pkgFolder = mContext.getDataDir();
79 | if (pkgFolder.exists()) {
80 | pkgFolder.setExecutable(true, false);
81 | pkgFolder.setReadable(true, false);
82 | }
83 | });
84 | }
85 |
86 | public WorldReadablePrefs getMainPrefs() {
87 | return mPrefsMain;
88 | }
89 |
90 | private void registerFileObserver() {
91 | mFileObserver = new FileObserver(getPreferenceDir(),
92 | FileObserver.ATTRIB | FileObserver.CLOSE_WRITE) {
93 | @Override
94 | public void onEvent(int event, String path) {
95 | for (FileObserverListener l : mFileObserverListeners) {
96 | if ((event & FileObserver.ATTRIB) != 0)
97 | l.onFileAttributesChanged(path);
98 | if ((event & FileObserver.CLOSE_WRITE) != 0)
99 | l.onFileUpdated(path);
100 | }
101 | }
102 | };
103 | mFileObserver.startWatching();
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuxianlin/luckyhooker/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wuxianlin.luckyhooker;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.pm.ApplicationInfo;
6 | import android.content.pm.PackageInfo;
7 | import android.content.pm.PackageManager;
8 | import android.graphics.drawable.Drawable;
9 | import android.os.Build;
10 | import android.os.Bundle;
11 | import android.widget.Toast;
12 |
13 | import androidx.activity.EdgeToEdge;
14 | import androidx.appcompat.app.ActionBar;
15 | import androidx.appcompat.app.AppCompatActivity;
16 | import androidx.core.graphics.Insets;
17 | import androidx.core.view.ViewCompat;
18 | import androidx.core.view.WindowInsetsCompat;
19 | import androidx.preference.PreferenceCategory;
20 | import androidx.preference.PreferenceFragmentCompat;
21 | import androidx.preference.SwitchPreference;
22 |
23 | import com.wuxianlin.luckyhooker.hooks.*;
24 |
25 | import java.util.ArrayList;
26 | import java.util.Arrays;
27 | import java.util.HashMap;
28 | import java.util.List;
29 | import java.util.Map;
30 |
31 | public class MainActivity extends AppCompatActivity {
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | EdgeToEdge.enable(this);
37 | setContentView(R.layout.settings_activity);
38 | ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.settings), (v, insets) -> {
39 | Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
40 | v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
41 | return insets;
42 | });
43 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !LSPosedUtils.checkLSPosed(this)) {
44 | SettingsManager.getInstance(this).fixFolderPermissionsAsync();
45 | }
46 | if (savedInstanceState == null) {
47 | getSupportFragmentManager()
48 | .beginTransaction()
49 | .replace(R.id.settings, new PrefsFragment())
50 | .commit();
51 | }
52 | ActionBar actionBar = getSupportActionBar();
53 | if (actionBar != null) {
54 | actionBar.setDisplayHomeAsUpEnabled(true);
55 | }
56 | }
57 |
58 | public static class PrefsFragment extends PreferenceFragmentCompat {
59 |
60 | private static final String KEY_APPS = "apps_settings";
61 | private static final String[] switchPackageNames = new String[]{
62 | CoolApk.hookPackageName,
63 | HaiXing.hookPackageName,
64 | HttpCanary.hookPackageNames[0],
65 | HttpCanary.hookPackageNames[1],
66 | KSWEB.hookPackageName,
67 | MxPlayer.hookPackageName,
68 | NetworkCapture.hookPackageName,
69 | NowCasting.hookPackageNames[0],
70 | NowCasting.hookPackageNames[1],
71 | PacketCapture.hookPackageName,
72 | PerfectPlayer.hookPackageName,
73 | QiYi.hookPackageNames[0],
74 | QiYi.hookPackageNames[1],
75 | QiYi.hookPackageNames[2],
76 | ShowJava.hookPackageName,
77 | SuperSU.hookPackageName,
78 | };
79 |
80 | @Override
81 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
82 | setPreferencesFromResource(R.xml.pref_luckyhooker, rootKey);
83 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
84 | getPreferenceManager().setSharedPreferencesMode(Context.MODE_WORLD_READABLE);
85 | } else if (!LSPosedUtils.checkLSPosed(getContext())) {
86 | getPreferenceManager().setStorageDeviceProtected();
87 | }
88 | PreferenceCategory Apps = (PreferenceCategory) findPreference(KEY_APPS);
89 | List