├── XposedSensitiveInfoChecker
├── app
│ ├── .gitignore
│ ├── src
│ │ └── main
│ │ │ ├── assets
│ │ │ └── xposed_init
│ │ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── themes.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ └── checker
│ │ │ └── xposed_hook
│ │ │ ├── MainActivity.java
│ │ │ └── XposedHook.java
│ ├── proguard-rules.pro
│ └── build.gradle
├── .idea
│ ├── .name
│ ├── compiler.xml
│ ├── kotlinc.xml
│ ├── vcs.xml
│ ├── AndroidProjectSystem.xml
│ ├── migrations.xml
│ ├── deploymentTargetSelector.xml
│ ├── misc.xml
│ ├── gradle.xml
│ ├── runConfigurations.xml
│ └── jarRepositories.xml
├── settings.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── .gitignore
├── build.gradle
├── gradle.properties
├── gradlew.bat
└── gradlew
├── imgs
├── Hooked.png
├── clone_app.png
├── Not_Hooked.png
├── add_module.png
├── Check_Results.png
├── Start_Checking.png
├── VirtualXposed.png
├── actual_desktop.png
├── install_dialog.png
├── activate_module.png
├── restart_virtual.png
├── virtual_desktop.png
├── virtual_desktop_2.png
├── virtual_settings.png
├── xposed_installer_logs.png
└── xposed_installer_logs_2.png
├── apk
└── VirtualXposed_0.18.2.apk
├── Xposed虚拟环境VirtualXposed入门教程.md
├── LICENSE
└── README.md
/XposedSensitiveInfoChecker/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/.name:
--------------------------------------------------------------------------------
1 | Xposed-Hook
--------------------------------------------------------------------------------
/imgs/Hooked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/Hooked.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name = "Xposed-Hook"
--------------------------------------------------------------------------------
/imgs/clone_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/clone_app.png
--------------------------------------------------------------------------------
/imgs/Not_Hooked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/Not_Hooked.png
--------------------------------------------------------------------------------
/imgs/add_module.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/add_module.png
--------------------------------------------------------------------------------
/imgs/Check_Results.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/Check_Results.png
--------------------------------------------------------------------------------
/imgs/Start_Checking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/Start_Checking.png
--------------------------------------------------------------------------------
/imgs/VirtualXposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/VirtualXposed.png
--------------------------------------------------------------------------------
/imgs/actual_desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/actual_desktop.png
--------------------------------------------------------------------------------
/imgs/install_dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/install_dialog.png
--------------------------------------------------------------------------------
/imgs/activate_module.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/activate_module.png
--------------------------------------------------------------------------------
/imgs/restart_virtual.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/restart_virtual.png
--------------------------------------------------------------------------------
/imgs/virtual_desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/virtual_desktop.png
--------------------------------------------------------------------------------
/imgs/virtual_desktop_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/virtual_desktop_2.png
--------------------------------------------------------------------------------
/imgs/virtual_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/virtual_settings.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | com.checker.xposed_hook.XposedHook
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/apk/VirtualXposed_0.18.2.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/apk/VirtualXposed_0.18.2.apk
--------------------------------------------------------------------------------
/imgs/xposed_installer_logs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/xposed_installer_logs.png
--------------------------------------------------------------------------------
/imgs/xposed_installer_logs_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/imgs/xposed_installer_logs_2.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | XposedChecker
3 | 获取敏感信息检测
4 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaojingwen945/Xposed/HEAD/XposedSensitiveInfoChecker/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/AndroidProjectSystem.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jul 24 15:17:37 CST 2025
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.5-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.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 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/deploymentTargetSelector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/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 |
23 | -keep class com.checker.xposed_hook.XposedHook { *; }
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | ext.kotlin_version = "1.9.0"
4 | repositories {
5 | maven { url 'https://maven.aliyun.com/repository/google' }
6 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
7 | google()
8 | mavenCentral()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:8.2.0'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | maven { url 'https://maven.aliyun.com/repository/google' }
22 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
23 | google()
24 | mavenCentral()
25 | }
26 | }
27 |
28 | task clean(type: Delete) {
29 | delete rootProject.buildDir
30 | }
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/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 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 | android.injected.testOnly=false
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | }
5 |
6 | android {
7 | namespace 'com.checker.xposed_hook'
8 | compileSdk 34
9 | buildToolsVersion "34.0.0"
10 |
11 | defaultConfig {
12 | applicationId "com.checker.xposed_hook"
13 | minSdk 23
14 | targetSdk 34
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | compileOptions {
28 | sourceCompatibility JavaVersion.VERSION_1_8
29 | targetCompatibility JavaVersion.VERSION_1_8
30 | }
31 | kotlinOptions {
32 | jvmTarget = '1.8'
33 | }
34 | }
35 |
36 | dependencies {
37 |
38 | implementation 'androidx.core:core-ktx:1.12.0'
39 | implementation 'androidx.appcompat:appcompat:1.6.1'
40 | implementation 'com.google.android.material:material:1.10.0'
41 | compileOnly 'de.robv.android.xposed:api:82'
42 | compileOnly 'de.robv.android.xposed:api:82:sources'
43 |
44 |
45 | // implementation 'com.squareup.okhttp3:okhttp:3.12.1'
46 | }
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
15 |
16 |
17 |
20 |
21 |
24 |
25 |
28 |
29 |
30 |
33 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/java/com/checker/xposed_hook/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.checker.xposed_hook;
2 |
3 | import android.content.pm.ApplicationInfo;
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager;
6 | import android.content.pm.Signature;
7 | import android.content.pm.SigningInfo;
8 | import android.os.Build;
9 | import android.os.Bundle;
10 | import android.os.Environment;
11 | import android.provider.Settings;
12 | import android.view.View;
13 | import android.widget.Toast;
14 |
15 | import androidx.annotation.Nullable;
16 | import androidx.annotation.RequiresApi;
17 | import androidx.appcompat.app.AppCompatActivity;
18 |
19 | public class MainActivity extends AppCompatActivity {
20 | private static final String TAG = "MainActivity";
21 |
22 | @RequiresApi(api = Build.VERSION_CODES.P)
23 | @Override
24 | protected void onCreate(@Nullable Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | setContentView(R.layout.activity_main);
27 |
28 | findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
29 | @Override
30 | public void onClick(View v) {
31 | // testGetSigningInfo();
32 |
33 | // String result = testGetMetaData("AppSignature");
34 | String result = testGetAndroidID();
35 | Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
36 |
37 | result = testGetExternalStorageState();
38 | Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
39 | }
40 | });
41 |
42 | }
43 |
44 | @RequiresApi(api = Build.VERSION_CODES.P)
45 | private void testGetSigningInfo() {
46 | PackageManager pm = getPackageManager();
47 | String packageName = getPackageName();
48 | PackageInfo packageInfo = null;
49 | try {
50 | packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES);
51 | } catch (PackageManager.NameNotFoundException e) {
52 | e.printStackTrace();
53 | }
54 |
55 | SigningInfo signingInfo = packageInfo.signingInfo;
56 | // 在VirtualXposed中获取到的signingInfo为空
57 | // Signature[] signatures = signingInfo.getApkContentsSigners();
58 | }
59 |
60 | private String testGetMetaData(String name) {
61 | ApplicationInfo applicationInfo = null;
62 | try {
63 | applicationInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
64 | } catch (Exception e) {
65 | }
66 | if (applicationInfo == null) {
67 | return "";
68 | }
69 | if (applicationInfo.metaData == null) {
70 | return "";
71 | }
72 | Object value = applicationInfo.metaData.get(name);
73 | if (value == null) {
74 | return "";
75 | }
76 | return String.valueOf(value);
77 | }
78 |
79 | private String testGetAndroidID() {
80 | return Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
81 | }
82 |
83 | private String testGetExternalStorageState() {
84 | return Environment.getExternalStorageState();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Xposed虚拟环境VirtualXposed入门教程.md:
--------------------------------------------------------------------------------
1 | # Xposed:VirtualXposed入门教程
2 |
3 | > Xposed 是一个 Android 平台上的动态劫持框架,通过替换手机上的孵化器 zygote 进程为 Xposed 自带的 zygote,使其在启动过程中加载 XposedBridge.jar,模块开发者可以通过 jar 提供的 API 来实现对所有的 Function 的劫持,在原 Function 执行的前后加上自定义代码。
4 | >
5 | > 但是,这套框架需要设备解锁了[Bootloader](https://zh.wikipedia.org/wiki/Bootloader)方可安装使用[[1\]](https://zh.wikipedia.org/wiki/Xposed_(框架)#cite_note-1)([root](https://zh.wikipedia.org/wiki/Root_(Android))为解锁Bootloader的充分不必要条件,而xposed安装仅需通过[TWRP](https://zh.wikipedia.org/wiki/TWRP)等第三方[Recovery](https://zh.wikipedia.org/w/index.php?title=Android_System_Recovery&action=edit&redlink=1)[卡刷](https://zh.wikipedia.org/wiki/刷机)安装包而不需要设备拥有完整的root权限),需要承担手机变砖和系统安全方面的风险,上手难度较高。而VirtualXposed的出现,则使Xposed的使用变得非常的简单,无需root、不需要解锁Bootloader、不需要刷机。
6 |
7 |
8 |
9 | 下面来介绍下如何使用VirtualXposed。
10 |
11 | [TOC]
12 |
13 |
14 |
15 | ## 1、准备虚拟环境
16 |
17 | 安装VirtualXposed.apk([V0.18.2下载链接](https://github.com/android-hacker/VirtualXposed/releases/download/0.18.2/VirtualXposed_0.18.2.apk))(注:经测试,这个版本的VirtualXposed可以兼容安卓10系统(华为Mate30),安卓14系统上可能出现应用拷贝过去一直loading等启动不起来的情况,其他系统兼容情况暂不清楚。)
18 |
19 | 安装好后,打开VirtualXposed,会显示虚拟环境桌面:
20 |
21 |
22 |
23 | 往上滑可以查看已安装在虚拟环境中的XposedInstaller和其他app,在桌面空白处长按,可以进入添加应用或设置页面:
24 |
25 |
26 |
27 |
28 |
29 | 点击关于,可以查看VirtualXposed版本:
30 |
31 |
32 |
33 | ## 2、安装Xposed Hook模块
34 |
35 | 准备好Hook模块,我们自己开发的Xposed Hook模块一般是以app的形式包装,将这个app安装到VirtualXposed有两种方式:
36 |
37 | 1)先正常安装这个带Hook的app到真实环境,再在VirtualXposed中通过添加应用的方式,复制到虚拟环境;
38 |
39 | 2)直接在VirtualXposed中通过添加应用、从手机存储中选择apk文件,安装app到虚拟环境。
40 |
41 | 第1种方式更为直接,下面我们就介绍这种方式:
42 |
43 | 首先安装这个带Hook的app到真实环境:
44 |
45 |
46 |
47 | 打开VirtualXposed,克隆这个带Hook的app到虚拟环境:虚拟桌面-长按-添加应用-勾选应用-安装
48 |
49 |
50 |
51 | 弹框中选择VirtualXposed:
52 |
53 |
54 |
55 | 等待安装,首次安装完成后,可以先不用打开,选择“完成”即可(因为首次安装后,xposed模块尚未加载生效):
56 |
57 |
58 |
59 | ## 3、激活Xposed Hook模块
60 |
61 | 安装完成后,回到桌面,开始激活xposed模块:桌面-设置-模块管理 (或 在桌面-XposedInstaller-左上角菜单-模块):
62 |
63 |
64 |
65 | 勾选模块:
66 |
67 |
68 |
69 | 检查模块是否为勾选状态,若不是,勾选模块。勾选模块后,会提示要重启虚拟环境才能生效,回到设置页面重启(与真实设备一样,在虚拟环境中,通过返回或在多任务界面中切换的方式可以回到设置页面):
70 |
71 |
72 |
73 | 好,现在我们的Xposed模块就已经生效了,可以在XposedInstaller中观察xposed日志:
74 |
75 |
76 |
77 |
78 |
79 | 在日志页面点击右上角保存按钮,可以把日志输出到本地文件,e.g. /storage/emulated/0/Android/data/de.robv.android.xposed.installer/files/xposed_error_20210809_144435.log
80 |
81 |
82 |
83 |
84 |
85 | 参考文献:
86 |
87 | [1] [关于 Android 7.1 的 Xposed,你想知道的都在这](https://sspai.com/post/40121#!)
88 |
89 | [2] [Andriod Xposed和VirtualXposed](https://www.cnblogs.com/zhucq/p/12079879.html)
90 |
91 | [3] [不需要 Root,也能用上强大的 Xposed 框架:VirtualXposed](https://sspai.com/post/44447)
92 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/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 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [TOC]
2 |
3 | ## 一、背景
4 |
5 | 目前,大量的移动app在使用过程中,涉及个人隐私信息和敏感信息。在个人信息处理、共享、转让、公开披露过程中,管理流程和技术手段不规范造成个人信息泄露的安全事件层出不穷。
6 |
7 | 中央网信办、工信部、公安部、市场监管总局指导成立App违法违规收集使用个人信息专项治理工作组(App专项治理工作组),组织开展App收集使用个人信息评估工作。对于未按规定收集用户隐私信息和敏感信息的app,可能会被要求整改或下架。
8 |
9 | 在我们的app发布时,也曾几次遇到发布到各应用市场时,由于未遵守敏感信息规定被打回的情况,导致发布推迟,涉及到的用户敏感信息主要有:IP地址、MAC地址、IMEI、IMSI、应用安装列表 等。
10 |
11 | 为了达到合法合规使用个人信息的要求,我们的整改目标是:
12 |
13 | 1)尽量减少对用户隐私信息及敏感信息的使用和收集;
14 |
15 | 2)对于无法规避、需要获取的用户信息,需要在app隐私协议中对用户声明;
16 |
17 | 3)未经用户授权,禁止对所有敏感信息的获取。
18 |
19 | 对应的处理方案为:
20 |
21 | 1)排查app工程代码,停止收集非必要的用户信息;
22 |
23 | 2)排查必要的用户信息,并在隐私协议中一一声明;
24 |
25 | 3)排查必要用户信息的收集时机,在用户授权同意隐私协议之前,禁止调用。
26 |
27 | 以上1和2由各app自己的业务决定,我们主要关注第3项的实现。
28 |
29 | ## 二、方案
30 |
31 | 对于以上第3点,整理我们自己的app中的信息获取可能比较好执行。然而,在我们的app中,通常会集成多个甚至几十上百个其他的库,这些库将在什么时机获取哪些敏感信息,通常我们无法控制,也无法感知。大部分app发布时被告知未遵守敏感信息规定被打回的情况都是源自于此。
32 |
33 | 对于大型app,一个一个排查第三方库是否合规不太现实。不过我们关注的用户敏感信息是有限的,用来获取这些数据的系统Api也是确定的,那么最好是直接hook到获取敏感信息的对应的系统Api,一旦有任何代码在隐私协议前调用了该系统Api,我们就能知道是哪里违规了。
34 |
35 | 经过调研,要Hook到系统Api,AspectJ等方式都是无法实现的,而Xposed框架可以实现对所有系统Api调用的拦截,使我们可以实现在不修改我们的目标app的前提下,去检测它的系统Api调用情况。
36 |
37 | Xposed 是一个 Android 平台上的动态劫持框架,通过替换手机上的孵化器 zygote 进程为 Xposed 自带的 zygote,使其在启动过程中加载 XposedBridge.jar,模块开发者可以通过 jar 提供的 API 来实现对所有的 Function 的劫持,在原 Function 执行的前后加上自定义代码([Xposed原理](https://bbs.pediy.com/thread-223713.htm))。
38 |
39 | 现在通过使用Xposed技术来hook系统api调用的方式,检测获取隐私信息api的调用,目前已纳入检测范围的有以下Api:
40 |
41 | 1. 获取MAC地址:WifiInfo.getMacAddress()
42 | 2. 获取MAC地址:NetworkInterface.getHardwareAddress()
43 | 3. 获取IMEI/deviceId:TelephonyManager.getDeviceId()
44 | 4. 获取IMSI:TelephonyManager.getSubscriberId()
45 | 5. 获取IP地址:WiFi:WifiInfo.getIpAddress(),Mobile:NetworkInterface.getInetAddresses()
46 | 6. 获取安装列表:PackageManager.getInstalledPackages(int)
47 | 7. 获取Android ID:Secure.getString(context.getContentResolver(), Secure.ANDROID_ID)
48 | 8. 获取设备硬件序列号:Build.getSerial()
49 | 9. 获取SIM卡序列号:TelephonyManager.getSimSerialNumber()
50 | 10. 获取SD卡挂载状态:Environment.getExternalStorageState()
51 | 11. 获取正在运行的所有应用程序进程:ActivityManager.getRunningAppProcesses()
52 |
53 | ## 三、实现
54 |
55 | 我们的无侵入式、获取敏感信息检测Hook模块实现如下:
56 |
57 | 1、在新建的检测app工程build.gralde中引入Xposed库:
58 |
59 | ```
60 | compileOnly 'de.robv.android.xposed:api:82'
61 | compileOnly 'de.robv.android.xposed:api:82:sources'
62 | ```
63 |
64 | 2、实现Xposed自定义模块Hook类,添加检测代码:
65 |
66 | 1)可以修改HOOK_PACKAGE_NAME常量内容,及打开相关注释代码,来指定过滤的目标app包名,以免hook到其他app产生干扰。
67 |
68 | 2)rewriteMetaData()接口可以修改获取到的MetaData内容,若目标app中有签名校验逻辑,可能导致在VirtualXposed中由于签名校验不通过无法打开,那么我们的检测模块是否真的可以做到无侵入,就看目标app是否有签名校验逻辑、以及如果有 那我们是否可以屏蔽它的签名校验逻辑了。
69 |
70 | 如果是检测我们自己的app,由于我们能知道它是否有签名校验、以及校验实现逻辑,要做到这个还是比较简单的,比如:已知虚拟环境中获取到的签名信息为空,如果签名校验逻辑是判断从packageInfo.signingInfo中获取的签名信息与从MetaData中取出来的值是否一致,那么就要通过Hook来修改获取MetaData时返回的对应字段也为空,就可以“骗过”签名校验逻辑了。
71 |
72 | ```java
73 | public class XposedHook implements IXposedHookLoadPackage {
74 | // 待检测的包名
75 | private static final String HOOK_PACKAGE_NAME = "com.sina.weibo";
76 | // 是否打印调用堆栈
77 | private static final boolean PRINT_STACK_TRACE = true;
78 |
79 | @RequiresApi(api = Build.VERSION_CODES.P)
80 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
81 | XposedBridge.log("包名:-->> " + lpparam.packageName);
82 |
83 | /*过滤hook的包名*/
84 | // if (!HOOK_PACKAGE_NAME.equals(lpparam.packageName)) {
85 | // return;
86 | // }
87 |
88 | // 获取签名信息
89 | // getSigningInfo(lpparam);
90 |
91 | // 可用于屏蔽签名校验
92 | rewriteMetaData(lpparam, "AppSignature", "You Are Hooked");
93 |
94 | // 检查敏感信息获取
95 | checkPrivateInfoApis(lpparam);
96 | }
97 |
98 | /**
99 | * 获取签名
100 | *
101 | * @param lpparam
102 | */
103 | @RequiresApi(api = Build.VERSION_CODES.P)
104 | private void getSigningInfo(XC_LoadPackage.LoadPackageParam lpparam) {
105 | // 获取签名信息:抽象方法需要找到其实现类来hook
106 | XposedHelpers.findAndHookMethod(
107 | "android.app.ApplicationPackageManager",
108 | lpparam.classLoader,
109 | "getPackageInfo",
110 | String.class,
111 | int.class,
112 | new XC_MethodHook() {
113 | @Override
114 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
115 | XposedBridge.log("\n获取打包信息:-->> packageInfo = " + param.getResult());
116 | PackageInfo packageInfo = (PackageInfo) param.getResult();
117 | XposedBridge.log("\n获取签名信息:-->> packageInfo.signingInfo = " + packageInfo.signingInfo);
118 | super.afterHookedMethod(param);
119 | }
120 | });
121 | }
122 |
123 | /**
124 | * 重写Meta数据
125 | *
126 | * @param lpparam
127 | * @param key
128 | * @param value
129 | */
130 | private void rewriteMetaData(XC_LoadPackage.LoadPackageParam lpparam, String key, String value) {
131 | XposedHelpers.findAndHookMethod(
132 | "android.app.ApplicationPackageManager",
133 | lpparam.classLoader,
134 | "getApplicationInfo",
135 | String.class,
136 | int.class,
137 | new XC_MethodHook() {
138 | @Override
139 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
140 | ApplicationInfo applicationInfo = (ApplicationInfo) param.getResult();
141 | // XposedBridge.log("\n获取Meta数据:-->> metaData = " + applicationInfo.metaData);
142 | // XposedBridge.log("\n获取Meta数据:-->> " + key + " = " + applicationInfo.metaData.get(key));
143 | // 修改数据
144 | applicationInfo.metaData.putString(key, value);
145 | // XposedBridge.log("\n修改Meta数据:-->> " + key + " = " + value);
146 | }
147 | });
148 | }
149 |
150 | private void checkPrivateInfoApis(XC_LoadPackage.LoadPackageParam lpparam) {
151 | XposedBridge.log("开始检测:-->> ");
152 | // MAC地址
153 | XposedHelpers.findAndHookMethod(
154 | android.net.wifi.WifiInfo.class.getName(),
155 | lpparam.classLoader,
156 | "getMacAddress",
157 | new XC_MethodHook() {
158 | @Override
159 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
160 | super.beforeHookedMethod(param);
161 | XposedBridge.log("\n获取MAC地址:调用WifiInfo.getMacAddress()");
162 | if (PRINT_STACK_TRACE) {
163 | XposedBridge.log(getMethodStack());
164 | }
165 | }
166 | }
167 | );
168 |
169 | // MAC地址
170 | XposedHelpers.findAndHookMethod(
171 | java.net.NetworkInterface.class.getName(),
172 | lpparam.classLoader,
173 | "getHardwareAddress",
174 | new XC_MethodHook() {
175 | @Override
176 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
177 | super.beforeHookedMethod(param);
178 | XposedBridge.log("\n获取MAC地址:调用NetworkInterface.getHardwareAddress()");
179 | if (PRINT_STACK_TRACE) {
180 | XposedBridge.log(getMethodStack());
181 | }
182 | }
183 | }
184 | );
185 |
186 | // IP地址:WiFi
187 | XposedHelpers.findAndHookMethod(
188 | android.net.wifi.WifiInfo.class.getName(),
189 | lpparam.classLoader,
190 | "getIpAddress",
191 | new XC_MethodHook() {
192 | @Override
193 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
194 | super.beforeHookedMethod(param);
195 | XposedBridge.log("\n获取IP地址(WiFi):调用WifiInfo.getIpAddress()");
196 | if (PRINT_STACK_TRACE) {
197 | XposedBridge.log(getMethodStack());
198 | }
199 | }
200 | });
201 |
202 | // IP地址:Mobile
203 | XposedHelpers.findAndHookMethod(
204 | java.net.NetworkInterface.class.getName(),
205 | lpparam.classLoader,
206 | "getInetAddresses",
207 | new XC_MethodHook() {
208 | @Override
209 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
210 | super.beforeHookedMethod(param);
211 | XposedBridge.log("\n获取IP地址(Mobile):调用NetworkInterface.getInetAddresses()");
212 | if (PRINT_STACK_TRACE) {
213 | XposedBridge.log(getMethodStack());
214 | }
215 | }
216 | });
217 |
218 | // IMEI
219 | XposedHelpers.findAndHookMethod(
220 | android.telephony.TelephonyManager.class.getName(),
221 | lpparam.classLoader,
222 | "getDeviceId",
223 | new XC_MethodHook() {
224 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
225 | super.beforeHookedMethod(param);
226 | XposedBridge.log("\n获取IMEI:调用TelephonyManager.getDeviceId()");
227 | if (PRINT_STACK_TRACE) {
228 | XposedBridge.log(getMethodStack());
229 | }
230 | }
231 | });
232 |
233 | // IMSI
234 | XposedHelpers.findAndHookMethod(
235 | android.telephony.TelephonyManager.class.getName(),
236 | lpparam.classLoader,
237 | "getSubscriberId",
238 | new XC_MethodHook() {
239 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
240 | super.beforeHookedMethod(param);
241 | XposedBridge.log("\n获取IMSI:调用TelephonyManager.getSubscriberId()");
242 | if (PRINT_STACK_TRACE) {
243 | XposedBridge.log(getMethodStack());
244 | }
245 | }
246 | });
247 |
248 | // 获取安装列表:抽象方法需要找到其实现类来hook
249 | XposedHelpers.findAndHookMethod(
250 | "android.app.ApplicationPackageManager",
251 | lpparam.classLoader,
252 | "getInstalledPackages",
253 | int.class,
254 | new XC_MethodHook() {
255 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
256 | super.beforeHookedMethod(param);
257 | XposedBridge.log("\n获取安装列表:调用PackageManager.getInstalledPackages(int)");
258 | if (PRINT_STACK_TRACE) {
259 | XposedBridge.log(getMethodStack());
260 | }
261 | }
262 | });
263 | }
264 |
265 | private String getMethodStack() {
266 | StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
267 |
268 | StringBuilder stringBuilder = new StringBuilder();
269 |
270 | for (StackTraceElement temp : stackTraceElements) {
271 | stringBuilder.append(temp.toString() + "\n");
272 | }
273 |
274 | return stringBuilder.toString();
275 | }
276 | }
277 | ```
278 |
279 | 3)注册Xposed自定义模块:
280 |
281 | 在src/main/assets下新建`xposed_init`文件,在这个文件里添加Hook类路径:
282 |
283 | ```
284 | com.checker.xposed_hook.XposedHook
285 | ```
286 |
287 | 在`AndroidManifest.xml`中添加:
288 |
289 | ```xml
290 |
291 |
294 |
295 |
298 |
299 |
302 | ```
303 |
304 | ## 四、使用
305 |
306 | 1)编译项目,安装Xposed模块到VirtualXposed,并确认已勾选并生效(可查看[VirtualXposed入门教程](./Xposed虚拟环境VirtualXposed入门教程.md))。
307 |
308 | 2)将需要检测的目标app复制/安装到VirtualXposed,注意不要使用加固后的app,可能会无法打开。
309 |
310 | 3)运行目标app,并观察分析XposedInstaller中的日志:
311 |
312 | 检测开始:
313 |
314 |
315 |
316 | 检测到敏感信息Api调用:
317 |
318 |
319 |
320 | 4)若在同意隐私协议前,只有“开始检测”日志,而无敏感信息Api调用日志,就说明目标App已经合规了;若不合规,则需要查看其Api调用堆栈,将相关调用挪到隐私协议之后。保存下来的日志文件一般在“/sdcard/Android/data/de.robv.android.xposed.installer/files”目录下。
321 |
322 | ## 参考文档
323 |
324 | [Android获取敏感信息整改---基于Xposed的方法检测](https://blog.csdn.net/DeMonliuhui/article/details/116191106)
325 |
326 | [Android 违规获取用户隐私(获取MAC地址)整改](https://blog.csdn.net/EthanCo/article/details/111544333)
327 |
328 | [Xposed模块开发入门](https://www.52pojie.cn/thread-688466-1-1.html)
329 |
330 |
--------------------------------------------------------------------------------
/XposedSensitiveInfoChecker/app/src/main/java/com/checker/xposed_hook/XposedHook.java:
--------------------------------------------------------------------------------
1 | package com.checker.xposed_hook;
2 |
3 | import android.app.ActivityManager;
4 | import android.content.ClipboardManager;
5 | import android.content.ContentResolver;
6 | import android.content.pm.ApplicationInfo;
7 | import android.content.pm.PackageInfo;
8 | import android.os.Build;
9 | import android.os.Environment;
10 | import android.provider.Settings;
11 |
12 | import androidx.annotation.RequiresApi;
13 |
14 | import de.robv.android.xposed.IXposedHookLoadPackage;
15 | import de.robv.android.xposed.XC_MethodHook;
16 | import de.robv.android.xposed.XposedBridge;
17 | import de.robv.android.xposed.XposedHelpers;
18 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
19 |
20 | public class XposedHook implements IXposedHookLoadPackage {
21 | // 待检测的包名
22 | private static final String HOOK_PACKAGE_NAME = "com.sina.weibo";
23 | // 是否打印调用堆栈
24 | private static final boolean PRINT_STACK_TRACE = true;
25 |
26 | @RequiresApi(api = Build.VERSION_CODES.P)
27 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
28 | XposedBridge.log("包名:-->> " + lpparam.packageName);
29 |
30 | /*过滤hook的包名*/
31 | // if (!HOOK_PACKAGE_NAME.equals(lpparam.packageName)) {
32 | // return;
33 | // }
34 |
35 | // 获取签名信息
36 | // getSigningInfo(lpparam);
37 |
38 | // 可用于屏蔽签名校验
39 | // rewriteMetaData(lpparam, "AppSignature", "You Are Hooked");
40 |
41 | // 检查敏感信息获取
42 | checkPrivateInfoApis(lpparam);
43 | }
44 |
45 | /**
46 | * 获取签名
47 | *
48 | * @param lpparam
49 | */
50 | @RequiresApi(api = Build.VERSION_CODES.P)
51 | private void getSigningInfo(XC_LoadPackage.LoadPackageParam lpparam) {
52 | // 获取签名信息:抽象方法需要找到其实现类来hook
53 | XposedHelpers.findAndHookMethod(
54 | "android.app.ApplicationPackageManager",
55 | lpparam.classLoader,
56 | "getPackageInfo",
57 | String.class,
58 | int.class,
59 | new XC_MethodHook() {
60 | @Override
61 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
62 | XposedBridge.log("\n获取打包信息:-->> packageInfo = " + param.getResult());
63 | PackageInfo packageInfo = (PackageInfo) param.getResult();
64 | XposedBridge.log("\n获取签名信息:-->> packageInfo.signingInfo = " + packageInfo.signingInfo);
65 | super.afterHookedMethod(param);
66 | }
67 | });
68 | }
69 |
70 | /**
71 | * 重写Meta数据
72 | *
73 | * @param lpparam
74 | * @param key
75 | * @param value
76 | */
77 | private void rewriteMetaData(XC_LoadPackage.LoadPackageParam lpparam, String key, String value) {
78 | XposedHelpers.findAndHookMethod(
79 | "android.app.ApplicationPackageManager",
80 | lpparam.classLoader,
81 | "getApplicationInfo",
82 | String.class,
83 | int.class,
84 | new XC_MethodHook() {
85 | @Override
86 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
87 | ApplicationInfo applicationInfo = (ApplicationInfo) param.getResult();
88 | // XposedBridge.log("\n获取Meta数据:-->> metaData = " + applicationInfo.metaData);
89 | // XposedBridge.log("\n获取Meta数据:-->> " + key + " = " + applicationInfo.metaData.get(key));
90 | // 修改数据
91 | applicationInfo.metaData.putString(key, value);
92 | // XposedBridge.log("\n修改Meta数据:-->> " + key + " = " + value);
93 | }
94 | });
95 | }
96 |
97 | private void checkPrivateInfoApis(XC_LoadPackage.LoadPackageParam lpparam) {
98 | XposedBridge.log("开始检测:-->> ");
99 | // MAC地址
100 | XposedHelpers.findAndHookMethod(
101 | android.net.wifi.WifiInfo.class.getName(),
102 | lpparam.classLoader,
103 | "getMacAddress",
104 | new XC_MethodHook() {
105 | @Override
106 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
107 | super.beforeHookedMethod(param);
108 | XposedBridge.log("\n获取MAC地址:调用WifiInfo.getMacAddress()");
109 | if (PRINT_STACK_TRACE) {
110 | XposedBridge.log(getMethodStack());
111 | }
112 | }
113 | }
114 | );
115 |
116 | // MAC地址
117 | XposedHelpers.findAndHookMethod(
118 | java.net.NetworkInterface.class.getName(),
119 | lpparam.classLoader,
120 | "getHardwareAddress",
121 | new XC_MethodHook() {
122 | @Override
123 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
124 | super.beforeHookedMethod(param);
125 | XposedBridge.log("\n获取MAC地址:调用NetworkInterface.getHardwareAddress()");
126 | if (PRINT_STACK_TRACE) {
127 | XposedBridge.log(getMethodStack());
128 | }
129 | }
130 | }
131 | );
132 |
133 | // IP地址:WiFi
134 | XposedHelpers.findAndHookMethod(
135 | android.net.wifi.WifiInfo.class.getName(),
136 | lpparam.classLoader,
137 | "getIpAddress",
138 | new XC_MethodHook() {
139 | @Override
140 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
141 | super.beforeHookedMethod(param);
142 | XposedBridge.log("\n获取IP地址(WiFi):调用WifiInfo.getIpAddress()");
143 | if (PRINT_STACK_TRACE) {
144 | XposedBridge.log(getMethodStack());
145 | }
146 | }
147 | });
148 |
149 | // IP地址:Mobile
150 | XposedHelpers.findAndHookMethod(
151 | java.net.NetworkInterface.class.getName(),
152 | lpparam.classLoader,
153 | "getInetAddresses",
154 | new XC_MethodHook() {
155 | @Override
156 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
157 | super.beforeHookedMethod(param);
158 | XposedBridge.log("\n获取IP地址(Mobile):调用NetworkInterface.getInetAddresses()");
159 | if (PRINT_STACK_TRACE) {
160 | XposedBridge.log(getMethodStack());
161 | }
162 | }
163 | });
164 |
165 | // IMEI
166 | XposedHelpers.findAndHookMethod(
167 | android.telephony.TelephonyManager.class.getName(),
168 | lpparam.classLoader,
169 | "getDeviceId",
170 | new XC_MethodHook() {
171 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
172 | super.beforeHookedMethod(param);
173 | XposedBridge.log("\n获取IMEI:调用TelephonyManager.getDeviceId()");
174 | if (PRINT_STACK_TRACE) {
175 | XposedBridge.log(getMethodStack());
176 | }
177 | }
178 | });
179 |
180 | // IMSI
181 | XposedHelpers.findAndHookMethod(
182 | android.telephony.TelephonyManager.class.getName(),
183 | lpparam.classLoader,
184 | "getSubscriberId",
185 | new XC_MethodHook() {
186 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
187 | super.beforeHookedMethod(param);
188 | XposedBridge.log("\n获取IMSI:调用TelephonyManager.getSubscriberId()");
189 | if (PRINT_STACK_TRACE) {
190 | XposedBridge.log(getMethodStack());
191 | }
192 | }
193 | });
194 |
195 | // 获取安装列表:抽象方法需要找到其实现类来hook
196 | XposedHelpers.findAndHookMethod(
197 | "android.app.ApplicationPackageManager",
198 | lpparam.classLoader,
199 | "getInstalledPackages",
200 | int.class,
201 | new XC_MethodHook() {
202 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
203 | super.beforeHookedMethod(param);
204 | XposedBridge.log("\n获取安装列表:调用PackageManager.getInstalledPackages(int)");
205 | if (PRINT_STACK_TRACE) {
206 | XposedBridge.log(getMethodStack());
207 | }
208 | }
209 | });
210 |
211 | // 获取安装列表:抽象方法需要找到其实现类来hook
212 | XposedHelpers.findAndHookMethod(
213 | "android.app.ApplicationPackageManager",
214 | lpparam.classLoader,
215 | "getInstalledApplications",
216 | int.class,
217 | new XC_MethodHook() {
218 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
219 | super.beforeHookedMethod(param);
220 | XposedBridge.log("\n获取安装列表:调用PackageManager.getInstalledApplications(int)");
221 | if (PRINT_STACK_TRACE) {
222 | XposedBridge.log(getMethodStack());
223 | }
224 | }
225 | });
226 |
227 | // Android ID
228 | XposedHelpers.findAndHookMethod(
229 | "android.provider.Settings.Secure",
230 | lpparam.classLoader,
231 | "getString",
232 | ContentResolver.class,
233 | String.class,
234 | new XC_MethodHook() {
235 | @Override
236 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
237 | super.beforeHookedMethod(param);
238 | if (Settings.Secure.ANDROID_ID.equals(param.args[1])) {
239 | XposedBridge.log("\n获取Android ID:调用Secure.getString(ContentResolver, String) where String==Secure.ANDROID_ID");
240 | if (PRINT_STACK_TRACE) {
241 | XposedBridge.log(getMethodStack());
242 | }
243 | }
244 | }
245 | }
246 | );
247 |
248 | // 设备硬件序列号SN
249 | XposedHelpers.findAndHookMethod(
250 | Build.class.getName(),
251 | lpparam.classLoader,
252 | "getSerial",
253 | new XC_MethodHook() {
254 | @Override
255 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
256 | super.beforeHookedMethod(param);
257 | XposedBridge.log("\n获取设备硬件序列号SN:调用Build.getSerial()");
258 | if (PRINT_STACK_TRACE) {
259 | XposedBridge.log(getMethodStack());
260 | }
261 | }
262 | }
263 | );
264 |
265 | // SIM卡序列号
266 | XposedHelpers.findAndHookMethod(
267 | android.telephony.TelephonyManager.class.getName(),
268 | lpparam.classLoader,
269 | "getSimSerialNumber",
270 | new XC_MethodHook() {
271 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
272 | super.beforeHookedMethod(param);
273 | XposedBridge.log("\n获取SIM卡序列号:调用TelephonyManager.getSimSerialNumber()");
274 | if (PRINT_STACK_TRACE) {
275 | XposedBridge.log(getMethodStack());
276 | }
277 | }
278 | });
279 |
280 | // 获取SD卡挂载状态
281 | XposedHelpers.findAndHookMethod(
282 | Environment.class.getName(),
283 | lpparam.classLoader,
284 | "getExternalStorageState",
285 | new XC_MethodHook() {
286 | @Override
287 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
288 | super.beforeHookedMethod(param);
289 | XposedBridge.log("\n获取SD卡挂载状态:调用Environment.getExternalStorageState()");
290 | if (PRINT_STACK_TRACE) {
291 | XposedBridge.log(getMethodStack());
292 | }
293 | }
294 | }
295 | );
296 |
297 | // 获取正在运行的所有应用程序进程
298 | XposedHelpers.findAndHookMethod(
299 | ActivityManager.class.getName(),
300 | lpparam.classLoader,
301 | "getRunningAppProcesses",
302 | new XC_MethodHook() {
303 | @Override
304 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
305 | super.beforeHookedMethod(param);
306 | XposedBridge.log("\n获取正在运行的所有应用程序进程:调用ActivityManager.getRunningAppProcesses()");
307 | if (PRINT_STACK_TRACE) {
308 | XposedBridge.log(getMethodStack());
309 | }
310 | }
311 | }
312 | );
313 |
314 | // 获取剪贴板信息
315 | XposedHelpers.findAndHookMethod(
316 | ClipboardManager.class.getName(),
317 | lpparam.classLoader,
318 | "getPrimaryClip",
319 | new XC_MethodHook() {
320 | @Override
321 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
322 | super.beforeHookedMethod(param);
323 | XposedBridge.log("\n获取剪贴板信息:调用ClipboardManager.getPrimaryClip()");
324 | if (PRINT_STACK_TRACE) {
325 | XposedBridge.log(getMethodStack());
326 | }
327 | }
328 | }
329 | );
330 | }
331 |
332 | private String getMethodStack() {
333 | StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
334 |
335 | StringBuilder stringBuilder = new StringBuilder();
336 |
337 | for (StackTraceElement temp : stackTraceElements) {
338 | stringBuilder.append(temp.toString() + "\n");
339 | }
340 |
341 | return stringBuilder.toString();
342 | }
343 | }
344 |
--------------------------------------------------------------------------------