├── README.md ├── app ├── CMakeLists.txt ├── app.iml ├── build.gradle ├── build │ └── outputs │ │ └── logs │ │ └── manifest-merger-debug-report.txt ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── com │ │ └── jni │ │ └── dexshell │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ └── native-lib.cpp │ ├── java │ │ └── cn │ │ │ └── com │ │ │ └── jni │ │ │ └── dexshell │ │ │ ├── MainActivity.java │ │ │ ├── MyApplication.java │ │ │ ├── TestJNI.java │ │ │ └── utils │ │ │ ├── AppDeviceUtils.java │ │ │ └── MacUtils.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.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 │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── com │ └── jni │ └── dexshell │ └── ExampleUnitTest.java ├── build.gradle ├── dexShell.iml ├── dexShellMem.iml ├── gradle.properties ├── gradlew ├── gradlew.bat ├── local.properties ├── proxy_core ├── CMakeLists.txt ├── build.gradle ├── proguard-rules.pro ├── proxy_core.iml └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── com │ │ └── jni │ │ └── proxy_core │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── aes.cpp │ │ ├── aes.h │ │ ├── native-lib.cpp │ │ ├── rc4.cpp │ │ └── rc4.h │ ├── java │ │ └── cn │ │ │ └── com │ │ │ └── jni │ │ │ └── proxy_core │ │ │ ├── AES.java │ │ │ ├── ProxyApplication.java │ │ │ ├── RefInvoke.java │ │ │ ├── Utils.java │ │ │ └── Zip.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── cn │ └── com │ └── jni │ └── proxy_core │ └── ExampleUnitTest.java ├── proxy_tools ├── build.gradle ├── proxy1.jks ├── proxy_tools.iml └── src │ └── main │ └── java │ └── cn │ └── com │ └── jni │ └── proxy_tools │ ├── AES.java │ ├── Main.java │ ├── RC4.java │ ├── Utils.java │ └── Zip.java └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | # AndroidShell 2 | Android Apk 加固之Dex文件 完善篇 InMemoryDexClassLoader 之内存加载dex DexShell 3 | 4 | https://blog.csdn.net/q610098308/article/details/105199419 5 | 6 | 7 | https://blog.csdn.net/q610098308/article/details/105246355 8 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | native-lib 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | src/main/cpp/native-lib.cpp) 21 | 22 | # Searches for a specified prebuilt library and stores the path as a 23 | # variable. Because CMake includes system libraries in the search path by 24 | # default, you only need to specify the name of the public NDK library 25 | # you want to add. CMake verifies that the library exists before 26 | # completing its build. 27 | 28 | find_library( # Sets the name of the path variable. 29 | log-lib 30 | 31 | # Specifies the name of the NDK library that 32 | # you want CMake to locate. 33 | log) 34 | 35 | # Specifies libraries CMake should link to your target library. You 36 | # can link multiple libraries, such as libraries you define in this 37 | # build script, prebuilt third-party libraries, or system libraries. 38 | 39 | target_link_libraries( # Specifies the target library. 40 | native-lib 41 | 42 | # Links the target library to the log library 43 | # included in the NDK. 44 | ${log-lib}) -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "cn.com.jni.dexshell" 7 | minSdkVersion 27 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | externalNativeBuild { 13 | cmake { 14 | cppFlags "-std=c++11 -frtti" 15 | 16 | } 17 | } 18 | 19 | ndk { 20 | // 设置支持的 SO 库构架 21 | abiFilters 'armeabi-v7a' ,'arm64-v8a'//, 'x86', 'x86_64' 22 | ldLibs "log" 23 | } 24 | } 25 | buildTypes { 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | externalNativeBuild { 32 | cmake { 33 | path "CMakeLists.txt" 34 | } 35 | } 36 | sourceSets { 37 | main { 38 | jniLibs.srcDirs = ['libs'] 39 | } 40 | } 41 | } 42 | 43 | dependencies { 44 | implementation fileTree(include: ['*.jar'], dir: 'libs') 45 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 46 | testImplementation 'junit:junit:4.12' 47 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 48 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 49 | implementation project(':proxy_core') 50 | } 51 | -------------------------------------------------------------------------------- /app/build/outputs/logs/manifest-merger-debug-report.txt: -------------------------------------------------------------------------------- 1 | -- Merging decision tree log --- 2 | manifest 3 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 4 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 5 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 6 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 7 | MERGED from [com.android.support.constraint:constraint-layout:1.1.3] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\constraint-layout-1.1.3.aar\cf11269f0b605bd753f5f07e24b923b7\AndroidManifest.xml:2:1-11:12 8 | MERGED from [:proxy_core] E:\testcode\dexShellMem\proxy_core\build\intermediates\merged_manifests\debug\processDebugManifest\merged\AndroidManifest.xml:2:1-11:12 9 | MERGED from [com.android.support:appcompat-v7:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\appcompat-v7-28.0.0.aar\8b616d9be810f2d417a9e3d31efc31a6\AndroidManifest.xml:17:1-22:12 10 | MERGED from [com.android.support:support-fragment:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-fragment-28.0.0.aar\ac9e426cc8feb311ad9b008d34722840\AndroidManifest.xml:17:1-22:12 11 | MERGED from [com.android.support:animated-vector-drawable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\animated-vector-drawable-28.0.0.aar\69c00903647f198d01b8f16825c71544\AndroidManifest.xml:17:1-22:12 12 | MERGED from [com.android.support:support-core-ui:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-core-ui-28.0.0.aar\f864a19e79ea1474294c8b22013f53cb\AndroidManifest.xml:17:1-22:12 13 | MERGED from [com.android.support:support-core-utils:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-core-utils-28.0.0.aar\72c79784fbb915899730059b4bd2bdf0\AndroidManifest.xml:17:1-22:12 14 | MERGED from [com.android.support:support-vector-drawable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-vector-drawable-28.0.0.aar\967f23b6d60350051189c041630b4c4b\AndroidManifest.xml:17:1-22:12 15 | MERGED from [com.android.support:loader:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\loader-28.0.0.aar\14d4d3b9044c5dcf0a85110e739622c0\AndroidManifest.xml:17:1-22:12 16 | MERGED from [com.android.support:viewpager:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\viewpager-28.0.0.aar\4313913547ac1d9bde1916ca8f05807b\AndroidManifest.xml:17:1-22:12 17 | MERGED from [com.android.support:coordinatorlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\coordinatorlayout-28.0.0.aar\e59989980f8a291ad617e6547073f174\AndroidManifest.xml:17:1-22:12 18 | MERGED from [com.android.support:drawerlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\drawerlayout-28.0.0.aar\9fc92d5d79a88eb7e68d531005e659ce\AndroidManifest.xml:17:1-22:12 19 | MERGED from [com.android.support:slidingpanelayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\slidingpanelayout-28.0.0.aar\ea443f69b20c0a27e51a8462216c978c\AndroidManifest.xml:17:1-22:12 20 | MERGED from [com.android.support:customview:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\customview-28.0.0.aar\9ca3fa46e5ab4e98863be38b69183ad0\AndroidManifest.xml:17:1-22:12 21 | MERGED from [com.android.support:swiperefreshlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\swiperefreshlayout-28.0.0.aar\8e57c725ecfc50f2e0cf66f3c2374dea\AndroidManifest.xml:17:1-22:12 22 | MERGED from [com.android.support:asynclayoutinflater:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\asynclayoutinflater-28.0.0.aar\1a09752d4ec8b008ecf5f2e5998d4f67\AndroidManifest.xml:17:1-22:12 23 | MERGED from [com.android.support:support-compat:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-compat-28.0.0.aar\d4518021e01981166dfeee185361d03e\AndroidManifest.xml:17:1-24:12 24 | MERGED from [com.android.support:versionedparcelable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\versionedparcelable-28.0.0.aar\87532126cafd977d0ad46325b40ed676\AndroidManifest.xml:17:1-25:12 25 | MERGED from [com.android.support:cursoradapter:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\cursoradapter-28.0.0.aar\42518eaa436ca38047d1e776d5369cdc\AndroidManifest.xml:17:1-22:12 26 | MERGED from [android.arch.lifecycle:runtime:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\runtime-1.1.1.aar\64656c66c3f1ec55bdbfb2b8dd6c12fb\AndroidManifest.xml:17:1-22:12 27 | MERGED from [com.android.support:documentfile:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\documentfile-28.0.0.aar\bca6643c4767eb0bdd29de222f84560d\AndroidManifest.xml:17:1-22:12 28 | MERGED from [com.android.support:localbroadcastmanager:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\localbroadcastmanager-28.0.0.aar\50e5fceffb5c0042f18de92f0dcfd655\AndroidManifest.xml:17:1-22:12 29 | MERGED from [com.android.support:print:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\print-28.0.0.aar\a0896bb202fcbf28a0b817db15f26047\AndroidManifest.xml:17:1-22:12 30 | MERGED from [android.arch.lifecycle:viewmodel:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\viewmodel-1.1.1.aar\646819d298df038bf7e7a17ac574c1ed\AndroidManifest.xml:17:1-22:12 31 | MERGED from [android.arch.lifecycle:livedata:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\livedata-1.1.1.aar\5ad275a095204970322330fdc7f6f1c9\AndroidManifest.xml:17:1-22:12 32 | MERGED from [android.arch.lifecycle:livedata-core:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\livedata-core-1.1.1.aar\e1eb4d555131fcfb0c75f1db815499ca\AndroidManifest.xml:17:1-22:12 33 | MERGED from [android.arch.core:runtime:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\runtime-1.1.1.aar\11fa49863fb8aa4efd4bb0e513932a92\AndroidManifest.xml:17:1-22:12 34 | MERGED from [com.android.support:interpolator:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\interpolator-28.0.0.aar\df1e4bc292b789ff3c1498533e740e60\AndroidManifest.xml:17:1-22:12 35 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 36 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 37 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 38 | package 39 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:3:5-34 40 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 41 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 42 | android:versionName 43 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 44 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 45 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 46 | android:versionCode 47 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 48 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:1-34:12 49 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 50 | xmlns:android 51 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:2:11-69 52 | uses-permission#android.permission.INTERNET 53 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:4:5-67 54 | android:name 55 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:4:22-64 56 | uses-permission#android.permission.ACCESS_WIFI_STATE 57 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:5:5-76 58 | android:name 59 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:5:22-73 60 | uses-permission#android.permission.CHANGE_WIFI_STATE 61 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:6:5-76 62 | android:name 63 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:6:22-73 64 | uses-permission#android.permission.WAKE_LOCK 65 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:7:5-68 66 | android:name 67 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:7:22-65 68 | uses-permission#android.permission.READ_PHONE_STATE 69 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:8:5-74 70 | android:name 71 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:8:22-72 72 | uses-permission#android.permission.WRITE_EXTERNAL_STORAGE 73 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:9:5-80 74 | android:name 75 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:9:22-78 76 | application 77 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:10:5-32:19 78 | MERGED from [com.android.support.constraint:constraint-layout:1.1.3] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\constraint-layout-1.1.3.aar\cf11269f0b605bd753f5f07e24b923b7\AndroidManifest.xml:9:5-20 79 | MERGED from [com.android.support.constraint:constraint-layout:1.1.3] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\constraint-layout-1.1.3.aar\cf11269f0b605bd753f5f07e24b923b7\AndroidManifest.xml:9:5-20 80 | MERGED from [com.android.support:support-compat:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-compat-28.0.0.aar\d4518021e01981166dfeee185361d03e\AndroidManifest.xml:22:5-94 81 | MERGED from [com.android.support:support-compat:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-compat-28.0.0.aar\d4518021e01981166dfeee185361d03e\AndroidManifest.xml:22:5-94 82 | MERGED from [com.android.support:versionedparcelable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\versionedparcelable-28.0.0.aar\87532126cafd977d0ad46325b40ed676\AndroidManifest.xml:22:5-23:19 83 | MERGED from [com.android.support:versionedparcelable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\versionedparcelable-28.0.0.aar\87532126cafd977d0ad46325b40ed676\AndroidManifest.xml:22:5-23:19 84 | android:appComponentFactory 85 | ADDED from [com.android.support:support-compat:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-compat-28.0.0.aar\d4518021e01981166dfeee185361d03e\AndroidManifest.xml:22:18-91 86 | android:supportsRtl 87 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:16:9-35 88 | android:label 89 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:14:9-41 90 | android:roundIcon 91 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:15:9-54 92 | android:icon 93 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:13:9-43 94 | android:allowBackup 95 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:11:9-35 96 | android:theme 97 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:17:9-40 98 | android:name 99 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:12:9-62 100 | activity#cn.com.jni.dexshell.MainActivity 101 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:18:9-24:20 102 | android:name 103 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:18:19-47 104 | intent-filter#action:name:android.intent.action.MAIN+category:name:android.intent.category.LAUNCHER 105 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:19:13-23:29 106 | action#android.intent.action.MAIN 107 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:20:17-69 108 | android:name 109 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:20:25-66 110 | category#android.intent.category.LAUNCHER 111 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:22:17-77 112 | android:name 113 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:22:27-74 114 | meta-data#app_name 115 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:25:9-28:15 116 | android:value 117 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:27:13-62 118 | android:name 119 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:26:13-36 120 | meta-data#app_version 121 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:29:9-31:43 122 | android:value 123 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:31:13-40 124 | android:name 125 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml:30:13-39 126 | uses-sdk 127 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml reason: use-sdk injection requested 128 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 129 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 130 | MERGED from [com.android.support.constraint:constraint-layout:1.1.3] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\constraint-layout-1.1.3.aar\cf11269f0b605bd753f5f07e24b923b7\AndroidManifest.xml:5:5-7:41 131 | MERGED from [com.android.support.constraint:constraint-layout:1.1.3] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\constraint-layout-1.1.3.aar\cf11269f0b605bd753f5f07e24b923b7\AndroidManifest.xml:5:5-7:41 132 | MERGED from [:proxy_core] E:\testcode\dexShellMem\proxy_core\build\intermediates\merged_manifests\debug\processDebugManifest\merged\AndroidManifest.xml:7:5-9:41 133 | MERGED from [:proxy_core] E:\testcode\dexShellMem\proxy_core\build\intermediates\merged_manifests\debug\processDebugManifest\merged\AndroidManifest.xml:7:5-9:41 134 | MERGED from [com.android.support:appcompat-v7:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\appcompat-v7-28.0.0.aar\8b616d9be810f2d417a9e3d31efc31a6\AndroidManifest.xml:20:5-44 135 | MERGED from [com.android.support:appcompat-v7:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\appcompat-v7-28.0.0.aar\8b616d9be810f2d417a9e3d31efc31a6\AndroidManifest.xml:20:5-44 136 | MERGED from [com.android.support:support-fragment:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-fragment-28.0.0.aar\ac9e426cc8feb311ad9b008d34722840\AndroidManifest.xml:20:5-44 137 | MERGED from [com.android.support:support-fragment:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-fragment-28.0.0.aar\ac9e426cc8feb311ad9b008d34722840\AndroidManifest.xml:20:5-44 138 | MERGED from [com.android.support:animated-vector-drawable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\animated-vector-drawable-28.0.0.aar\69c00903647f198d01b8f16825c71544\AndroidManifest.xml:20:5-44 139 | MERGED from [com.android.support:animated-vector-drawable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\animated-vector-drawable-28.0.0.aar\69c00903647f198d01b8f16825c71544\AndroidManifest.xml:20:5-44 140 | MERGED from [com.android.support:support-core-ui:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-core-ui-28.0.0.aar\f864a19e79ea1474294c8b22013f53cb\AndroidManifest.xml:20:5-44 141 | MERGED from [com.android.support:support-core-ui:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-core-ui-28.0.0.aar\f864a19e79ea1474294c8b22013f53cb\AndroidManifest.xml:20:5-44 142 | MERGED from [com.android.support:support-core-utils:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-core-utils-28.0.0.aar\72c79784fbb915899730059b4bd2bdf0\AndroidManifest.xml:20:5-44 143 | MERGED from [com.android.support:support-core-utils:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-core-utils-28.0.0.aar\72c79784fbb915899730059b4bd2bdf0\AndroidManifest.xml:20:5-44 144 | MERGED from [com.android.support:support-vector-drawable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-vector-drawable-28.0.0.aar\967f23b6d60350051189c041630b4c4b\AndroidManifest.xml:20:5-44 145 | MERGED from [com.android.support:support-vector-drawable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-vector-drawable-28.0.0.aar\967f23b6d60350051189c041630b4c4b\AndroidManifest.xml:20:5-44 146 | MERGED from [com.android.support:loader:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\loader-28.0.0.aar\14d4d3b9044c5dcf0a85110e739622c0\AndroidManifest.xml:20:5-44 147 | MERGED from [com.android.support:loader:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\loader-28.0.0.aar\14d4d3b9044c5dcf0a85110e739622c0\AndroidManifest.xml:20:5-44 148 | MERGED from [com.android.support:viewpager:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\viewpager-28.0.0.aar\4313913547ac1d9bde1916ca8f05807b\AndroidManifest.xml:20:5-44 149 | MERGED from [com.android.support:viewpager:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\viewpager-28.0.0.aar\4313913547ac1d9bde1916ca8f05807b\AndroidManifest.xml:20:5-44 150 | MERGED from [com.android.support:coordinatorlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\coordinatorlayout-28.0.0.aar\e59989980f8a291ad617e6547073f174\AndroidManifest.xml:20:5-44 151 | MERGED from [com.android.support:coordinatorlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\coordinatorlayout-28.0.0.aar\e59989980f8a291ad617e6547073f174\AndroidManifest.xml:20:5-44 152 | MERGED from [com.android.support:drawerlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\drawerlayout-28.0.0.aar\9fc92d5d79a88eb7e68d531005e659ce\AndroidManifest.xml:20:5-44 153 | MERGED from [com.android.support:drawerlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\drawerlayout-28.0.0.aar\9fc92d5d79a88eb7e68d531005e659ce\AndroidManifest.xml:20:5-44 154 | MERGED from [com.android.support:slidingpanelayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\slidingpanelayout-28.0.0.aar\ea443f69b20c0a27e51a8462216c978c\AndroidManifest.xml:20:5-44 155 | MERGED from [com.android.support:slidingpanelayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\slidingpanelayout-28.0.0.aar\ea443f69b20c0a27e51a8462216c978c\AndroidManifest.xml:20:5-44 156 | MERGED from [com.android.support:customview:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\customview-28.0.0.aar\9ca3fa46e5ab4e98863be38b69183ad0\AndroidManifest.xml:20:5-44 157 | MERGED from [com.android.support:customview:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\customview-28.0.0.aar\9ca3fa46e5ab4e98863be38b69183ad0\AndroidManifest.xml:20:5-44 158 | MERGED from [com.android.support:swiperefreshlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\swiperefreshlayout-28.0.0.aar\8e57c725ecfc50f2e0cf66f3c2374dea\AndroidManifest.xml:20:5-44 159 | MERGED from [com.android.support:swiperefreshlayout:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\swiperefreshlayout-28.0.0.aar\8e57c725ecfc50f2e0cf66f3c2374dea\AndroidManifest.xml:20:5-44 160 | MERGED from [com.android.support:asynclayoutinflater:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\asynclayoutinflater-28.0.0.aar\1a09752d4ec8b008ecf5f2e5998d4f67\AndroidManifest.xml:20:5-44 161 | MERGED from [com.android.support:asynclayoutinflater:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\asynclayoutinflater-28.0.0.aar\1a09752d4ec8b008ecf5f2e5998d4f67\AndroidManifest.xml:20:5-44 162 | MERGED from [com.android.support:support-compat:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-compat-28.0.0.aar\d4518021e01981166dfeee185361d03e\AndroidManifest.xml:20:5-44 163 | MERGED from [com.android.support:support-compat:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\support-compat-28.0.0.aar\d4518021e01981166dfeee185361d03e\AndroidManifest.xml:20:5-44 164 | MERGED from [com.android.support:versionedparcelable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\versionedparcelable-28.0.0.aar\87532126cafd977d0ad46325b40ed676\AndroidManifest.xml:20:5-44 165 | MERGED from [com.android.support:versionedparcelable:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\versionedparcelable-28.0.0.aar\87532126cafd977d0ad46325b40ed676\AndroidManifest.xml:20:5-44 166 | MERGED from [com.android.support:cursoradapter:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\cursoradapter-28.0.0.aar\42518eaa436ca38047d1e776d5369cdc\AndroidManifest.xml:20:5-44 167 | MERGED from [com.android.support:cursoradapter:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\cursoradapter-28.0.0.aar\42518eaa436ca38047d1e776d5369cdc\AndroidManifest.xml:20:5-44 168 | MERGED from [android.arch.lifecycle:runtime:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\runtime-1.1.1.aar\64656c66c3f1ec55bdbfb2b8dd6c12fb\AndroidManifest.xml:20:5-44 169 | MERGED from [android.arch.lifecycle:runtime:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\runtime-1.1.1.aar\64656c66c3f1ec55bdbfb2b8dd6c12fb\AndroidManifest.xml:20:5-44 170 | MERGED from [com.android.support:documentfile:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\documentfile-28.0.0.aar\bca6643c4767eb0bdd29de222f84560d\AndroidManifest.xml:20:5-44 171 | MERGED from [com.android.support:documentfile:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\documentfile-28.0.0.aar\bca6643c4767eb0bdd29de222f84560d\AndroidManifest.xml:20:5-44 172 | MERGED from [com.android.support:localbroadcastmanager:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\localbroadcastmanager-28.0.0.aar\50e5fceffb5c0042f18de92f0dcfd655\AndroidManifest.xml:20:5-44 173 | MERGED from [com.android.support:localbroadcastmanager:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\localbroadcastmanager-28.0.0.aar\50e5fceffb5c0042f18de92f0dcfd655\AndroidManifest.xml:20:5-44 174 | MERGED from [com.android.support:print:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\print-28.0.0.aar\a0896bb202fcbf28a0b817db15f26047\AndroidManifest.xml:20:5-44 175 | MERGED from [com.android.support:print:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\print-28.0.0.aar\a0896bb202fcbf28a0b817db15f26047\AndroidManifest.xml:20:5-44 176 | MERGED from [android.arch.lifecycle:viewmodel:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\viewmodel-1.1.1.aar\646819d298df038bf7e7a17ac574c1ed\AndroidManifest.xml:20:5-44 177 | MERGED from [android.arch.lifecycle:viewmodel:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\viewmodel-1.1.1.aar\646819d298df038bf7e7a17ac574c1ed\AndroidManifest.xml:20:5-44 178 | MERGED from [android.arch.lifecycle:livedata:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\livedata-1.1.1.aar\5ad275a095204970322330fdc7f6f1c9\AndroidManifest.xml:20:5-44 179 | MERGED from [android.arch.lifecycle:livedata:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\livedata-1.1.1.aar\5ad275a095204970322330fdc7f6f1c9\AndroidManifest.xml:20:5-44 180 | MERGED from [android.arch.lifecycle:livedata-core:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\livedata-core-1.1.1.aar\e1eb4d555131fcfb0c75f1db815499ca\AndroidManifest.xml:20:5-44 181 | MERGED from [android.arch.lifecycle:livedata-core:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\livedata-core-1.1.1.aar\e1eb4d555131fcfb0c75f1db815499ca\AndroidManifest.xml:20:5-44 182 | MERGED from [android.arch.core:runtime:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\runtime-1.1.1.aar\11fa49863fb8aa4efd4bb0e513932a92\AndroidManifest.xml:20:5-44 183 | MERGED from [android.arch.core:runtime:1.1.1] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\runtime-1.1.1.aar\11fa49863fb8aa4efd4bb0e513932a92\AndroidManifest.xml:20:5-44 184 | MERGED from [com.android.support:interpolator:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\interpolator-28.0.0.aar\df1e4bc292b789ff3c1498533e740e60\AndroidManifest.xml:20:5-44 185 | MERGED from [com.android.support:interpolator:28.0.0] C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\caches\transforms-1\files-1.1\interpolator-28.0.0.aar\df1e4bc292b789ff3c1498533e740e60\AndroidManifest.xml:20:5-44 186 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 187 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 188 | android:targetSdkVersion 189 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 190 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 191 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 192 | android:minSdkVersion 193 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 194 | ADDED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 195 | INJECTED from E:\testcode\dexShellMem\app\src\main\AndroidManifest.xml 196 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/com/jni/dexshell/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.dexshell; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("cn.com.jni.dexshell", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define LOG_TAG "my-jni" 9 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__) 10 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__) 11 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__) 12 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__) 13 | #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG, __VA_ARGS__) 14 | #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) 15 | 16 | 17 | 18 | 19 | extern "C" JNIEXPORT jstring JNICALL 20 | Java_cn_com_jni_dexshell_MainActivity_stringFromJNI( 21 | JNIEnv *env, 22 | jobject jobj/* this */, jstring id) { 23 | 24 | std::string hello = "Hello from C++ ok"; 25 | return env->NewStringUTF(hello.c_str()); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/jni/dexshell/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.dexshell; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.widget.TextView; 6 | 7 | import cn.com.jni.dexshell.utils.AppDeviceUtils; 8 | 9 | public class MainActivity extends Activity { 10 | 11 | // Used to load the 'native-lib' library on application startup. 12 | static { 13 | System.loadLibrary("native-lib"); 14 | } 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | 21 | // Example of a call to a native method 22 | TextView tv = (TextView) findViewById(R.id.sample_text); 23 | tv.setText(stringFromJNI( "")); 24 | } 25 | 26 | /** 27 | * A native method that is implemented by the 'native-lib' native library, 28 | * which is packaged with this application. 29 | */ 30 | public native String stringFromJNI(String id); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/jni/dexshell/MyApplication.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.dexshell; 2 | 3 | import android.app.Application; 4 | 5 | public class MyApplication extends Application { 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/jni/dexshell/TestJNI.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.dexshell; 2 | 3 | public class TestJNI { 4 | public static native String native_rc4_de(String name,String address); 5 | 6 | 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/jni/dexshell/utils/AppDeviceUtils.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.dexshell.utils; 2 | 3 | import android.Manifest; 4 | import android.bluetooth.BluetoothAdapter; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.database.Cursor; 8 | import android.net.Uri; 9 | 10 | import android.os.Build; 11 | import android.provider.Settings; 12 | 13 | import android.telephony.TelephonyManager; 14 | 15 | 16 | import java.io.IOException; 17 | import java.io.InputStreamReader; 18 | import java.io.LineNumberReader; 19 | import java.security.MessageDigest; 20 | import java.security.NoSuchAlgorithmException; 21 | 22 | import static android.content.Context.TELEPHONY_SERVICE; 23 | 24 | 25 | public class AppDeviceUtils { 26 | /** 27 | * The IMEI: 仅仅只对Android手机有效 28 | * 采用此种方法,需要在AndroidManifest.xml中加入一个许可:android.permission.READ_PHONE_STATE,并且用 29 | * 户应当允许安装此应用。作为手机来讲,IMEI是唯一的,它应该类似于 359881030314356(除非你有一个没有量产的手 30 | * 机(水货)它可能有无效的IMEI,如:0000000000000)。 31 | * 32 | * @return imei 33 | */ 34 | public static String getIMEI(Context context) { 35 | TelephonyManager TelephonyMgr = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE); 36 | 37 | String szImei = TelephonyMgr.getDeviceId(); 38 | return szImei; 39 | } 40 | 41 | /** 42 | * Pseudo-Unique ID, 这个在任何Android手机中都有效 43 | * 有一些特殊的情况,一些如平板电脑的设置没有通话功能,或者你不愿加入READ_PHONE_STATE许可。而你仍然想获得唯 44 | * 一序列号之类的东西。这时你可以通过取出ROM版本、制造商、CPU型号、以及其他硬件信息来实现这一点。这样计算出 45 | * 来的ID不是唯一的(因为如果两个手机应用了同样的硬件以及Rom 镜像)。但应当明白的是,出现类似情况的可能性基 46 | * 本可以忽略。大多数的Build成员都是字符串形式的,我们只取他们的长度信息。我们取到13个数字,并在前面加上“35 47 | * ”。这样这个ID看起来就和15位IMEI一样了。 48 | * 49 | * @return PesudoUniqueID 50 | */ 51 | public static String getPesudoUniqueID() { 52 | String m_szDevIDShort = "35" + //we make this look like a valid IMEI 53 | Build.BOARD.length() % 10 + 54 | Build.BRAND.length() % 10 + 55 | 1 % 10 + 56 | Build.DEVICE.length() % 10 + 57 | Build.DISPLAY.length() % 10 + 58 | Build.HOST.length() % 10 + 59 | Build.ID.length() % 10 + 60 | Build.MANUFACTURER.length() % 10 + 61 | Build.MODEL.length() % 10 + 62 | Build.PRODUCT.length() % 10 + 63 | Build.TAGS.length() % 10 + 64 | Build.TYPE.length() % 10 + 65 | Build.USER.length() % 10; //13 digits 66 | return m_szDevIDShort; 67 | } 68 | 69 | /** 70 | * The Android ID 71 | * 通常被认为不可信,因为它有时为null。开发文档中说明了:这个ID会改变如果进行了出厂设置。并且,如果某个 72 | * Andorid手机被Root过的话,这个ID也可以被任意改变。无需任何许可。 73 | * 74 | * @return AndroidID 75 | */ 76 | public static String getAndroidID(Context context) { 77 | String m_szAndroidID = Settings.Secure.getString(context.getContentResolver(), 78 | Settings.Secure.ANDROID_ID); 79 | return m_szAndroidID; 80 | } 81 | 82 | /** 83 | * The WLAN MAC Address string 84 | * 是另一个唯一ID。但是你需要为你的工程加入android.permission.ACCESS_WIFI_STATE 权限,否则这个地址会为 85 | * null。Returns: 00:11:22:33:44:55 (这不是一个真实的地址。而且这个地址能轻易地被伪造。).WLan不必打开, 86 | * 就可读取些值。 87 | * 88 | * @return m_szWLANMAC 89 | */ 90 | 91 | public static String getWLANMACAddress(Context context) { 92 | 93 | String szWLANMAC = MacUtils.getMobileMAC(context); 94 | 95 | 96 | // Log.e("getIMEI",""+getIMEI(context)); 97 | // Log.e("getAndroidID",getAndroidID(context)); 98 | // Log.e("szWLANMAC",szWLANMAC); 99 | // Log.e("getCPUSerial()",""+getCPUSerial()); 100 | 101 | // String SerialNumber = android.os.Build.SERIAL; 102 | // 103 | // Log.e("SerialNumber()",""+SerialNumber); 104 | // 105 | //// String info = getIMEI(context) +"\n " +getAndroidID(context) +"\n " 106 | //// +szWLANMAC +"\n " +getCPUSerial() 107 | //// +"\n"+SerialNumber; 108 | // String info = "getIMEI " +getIMEI(context) +"\n " 109 | // +"getAndroidID " +getAndroidID(context) +"\n " 110 | // +"szWLANMAC " +szWLANMAC +"\n " 111 | // +"getCPUSerial " +getCPUSerial() 112 | // +"\n"+ 113 | // "SerialNumber "+SerialNumber; 114 | 115 | return szWLANMAC; 116 | } 117 | 118 | /** 119 | * 只在有蓝牙的设备上运行。并且要加入android.permission.BLUETOOTH 权限.Returns: 43:25:78:50:93:38 . 120 | * 蓝牙没有必要打开,也能读取。 121 | * 122 | * @return m_szBTMAC 123 | */ 124 | public String getBTMACAddress() { 125 | String m_szBTMAC=""; 126 | BluetoothAdapter m_BluetoothAdapter = null; // Local Bluetooth adapter 127 | m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 128 | if(null!= m_BluetoothAdapter) 129 | m_szBTMAC = m_BluetoothAdapter.getAddress(); 130 | 131 | return m_szBTMAC; 132 | } 133 | 134 | /** 135 | * Combined Device ID 136 | * 综上所述,我们一共有五种方式取得设备的唯一标识。它们中的一些可能会返回null,或者由于硬件缺失、权限问题等 137 | * 获取失败。但你总能获得至少一个能用。所以,最好的方法就是通过拼接,或者拼接后的计算出的MD5值来产生一个结果。 138 | * 通过算法,可产生32位的16进制数据:9DDDF85AFF0A87974CE4541BD94D5F55 139 | * 140 | * @return 141 | */ 142 | 143 | public static String getUniqueID(Context context) { 144 | // String m_szLongID = getIMEI() + getPesudoUniqueID() 145 | // + getAndroidID() + getWLANMACAddress() + getBTMACAddress(); 146 | try 147 | { 148 | 149 | String m_szLongID = getPesudoUniqueID() + getWLANMACAddress(context) +Build.SERIAL 150 | +getIMEI(context)+getAndroidID(context)+getCPUSerial() ; 151 | // compute md5 152 | MessageDigest m = null; 153 | try { 154 | m = MessageDigest.getInstance("MD5"); 155 | } catch (NoSuchAlgorithmException e) { 156 | e.printStackTrace(); 157 | } 158 | m.update(m_szLongID.getBytes(), 0, m_szLongID.length()); 159 | // get md5 bytes 160 | byte p_md5Data[] = m.digest(); 161 | // create a hex string 162 | String m_szUniqueID = new String(); 163 | for (int i = 0; i < p_md5Data.length; i++) { 164 | int b = (0xFF & p_md5Data[i]); 165 | // if it is a single digit, make sure it have 0 in front (proper padding) 166 | if (b <= 0xF) 167 | m_szUniqueID += "0"; 168 | // add number to string 169 | m_szUniqueID += Integer.toHexString(b); 170 | } // hex string to uppercase 171 | m_szUniqueID = m_szUniqueID.toUpperCase(); 172 | return m_szUniqueID; 173 | }catch (Exception e) 174 | { 175 | e.printStackTrace(); 176 | } 177 | return ""; 178 | } 179 | 180 | public static String getCPUSerial() { 181 | String str = "", strCPU = "", cpuAddress = ""; 182 | try { 183 | // 读取CPU信息 184 | Process pp = Runtime. getRuntime().exec("cat /proc/cpuinfo"); 185 | InputStreamReader ir = new InputStreamReader(pp.getInputStream()); 186 | LineNumberReader input = new LineNumberReader(ir); 187 | // 查找CPU序列号 188 | for ( int i = 1; i < 100; i++) { 189 | str = input.readLine(); 190 | if (str != null) { 191 | // 查找到序列号所在行 192 | if (str.indexOf( "Serial") > -1) { 193 | // 提取序列号 194 | strCPU = str.substring(str.indexOf(":" ) + 1, str.length()); 195 | // 去空格 196 | cpuAddress = strCPU.trim(); 197 | break; 198 | } 199 | } else { 200 | // 文件结尾 201 | break; 202 | } 203 | } 204 | } catch (IOException ex) { 205 | // 赋予默认值 206 | ex.printStackTrace(); 207 | } 208 | return cpuAddress; 209 | } 210 | 211 | private static String getGsfAndroidId(Context context) 212 | { 213 | Uri URI = Uri.parse("content://com.google.android.gsf.gservices"); 214 | String ID_KEY = "android_id"; 215 | String params[] = {ID_KEY}; 216 | Cursor c = context.getContentResolver().query(URI, null, null, params, null); 217 | if (null==c|| !c.moveToFirst() || c.getColumnCount() < 2) 218 | return null; 219 | try 220 | { 221 | return Long.toHexString(Long.parseLong(c.getString(1))); 222 | } 223 | catch (NumberFormatException e) 224 | { 225 | return null; 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/jni/dexshell/utils/MacUtils.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.dexshell.utils; 2 | 3 | 4 | import android.content.Context; 5 | import android.net.wifi.WifiInfo; 6 | import android.net.wifi.WifiManager; 7 | import android.os.Build; 8 | 9 | import android.text.TextUtils; 10 | import android.util.Log; 11 | 12 | import java.io.FileReader; 13 | import java.io.InputStreamReader; 14 | import java.io.LineNumberReader; 15 | import java.io.Reader; 16 | import java.net.NetworkInterface; 17 | import java.util.Collections; 18 | import java.util.List; 19 | 20 | /** 21 | * author : HLQ 22 | * e-mail : 925954424@qq.com 23 | * time : 2018/01/17 24 | * desc : 获取mac 兼容6.0获取 以及4g环境下获取失败 25 | * version: 1.0 26 | */ 27 | public class MacUtils { 28 | 29 | /** 30 | * 获取失败默认返回值 31 | */ 32 | public static final String ERROR_MAC_STR = "02:00:00:00:00:00"; 33 | 34 | // Wifi 管理器 35 | private static WifiManager mWifiManager; 36 | 37 | /** 38 | * 实例化WifiManager对象 39 | * 40 | * @param context 当前上下文对象 41 | * @return 42 | */ 43 | private static WifiManager getInstant(Context context) { 44 | if (mWifiManager == null) { 45 | mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 46 | } 47 | return mWifiManager; 48 | } 49 | 50 | /** 51 | * 开启wifi 52 | */ 53 | public static void getStartWifiEnabled() { 54 | // 判断当前wifi状态是否为开启状态 55 | if (!mWifiManager.isWifiEnabled()) { 56 | // 打开wifi 有些设备需要授权 57 | mWifiManager.setWifiEnabled(true); 58 | } 59 | } 60 | 61 | /** 62 | * 获取手机设备MAC地址 63 | * MAC地址:物理地址、硬件地址,用来定义网络设备的位置 64 | * modify by heliquan at 2018年1月17日 65 | * 66 | * @param context 67 | * @return 68 | */ 69 | public static String getMobileMAC(Context context) { 70 | mWifiManager = getInstant(context); 71 | // 如果当前设备系统大于等于6.0 使用下面的方法 72 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 73 | return getAndroidHighVersionMac(); 74 | } else { // 当前设备在6.0以下 75 | return getAndroidLowVersionMac(mWifiManager); 76 | } 77 | } 78 | 79 | /** 80 | * Android 6.0 设备兼容获取mac 81 | * 兼容原因:从Android 6.0之后,Android 移除了通过WiFi和蓝牙API来在应用程序中可编程的访问本地硬件标示符。 82 | * 现在WifiInfo.getMacAddress()和BluetoothAdapter.getAddress()方法都将返回:02:00:00:00:00:00 83 | * 84 | * @return 85 | */ 86 | public static String getAndroidHighVersionMac() { 87 | String str = ""; 88 | String macSerial = ""; 89 | try { 90 | // 由于Android底层基于Linux系统 可以根据shell获取 91 | Process pp = Runtime.getRuntime().exec( 92 | "cat /sys/class/net/wlan0/address "); 93 | InputStreamReader ir = new InputStreamReader(pp.getInputStream()); 94 | LineNumberReader input = new LineNumberReader(ir); 95 | for (; null != str; ) { 96 | str = input.readLine(); 97 | if (str != null) { 98 | macSerial = str.trim();// 去空格 99 | break; 100 | } 101 | } 102 | } catch (Exception ex) { 103 | ex.printStackTrace(); 104 | } 105 | if (macSerial == null || "".equals(macSerial)) { 106 | try { 107 | return loadFileAsString("/sys/class/net/eth0/address") 108 | .toUpperCase().substring(0, 17); 109 | } catch (Exception e) { 110 | e.printStackTrace(); 111 | macSerial = getAndroidVersion7MAC(); 112 | } 113 | } 114 | return macSerial; 115 | } 116 | 117 | /** 118 | * Android 6.0 以下设备获取mac地址 获取失败默认返回:02:00:00:00:00:00 119 | * 120 | * @param wifiManager 121 | * @return 122 | */ 123 | 124 | private static String getAndroidLowVersionMac(WifiManager wifiManager) { 125 | try { 126 | WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 127 | String mac = wifiInfo.getMacAddress(); 128 | if (TextUtils.isEmpty(mac)) { 129 | return ERROR_MAC_STR; 130 | } else { 131 | return mac; 132 | } 133 | } catch (Exception e) { 134 | e.printStackTrace(); 135 | Log.e("mac", "get android low version mac error:" + e.getMessage()); 136 | return ERROR_MAC_STR; 137 | } 138 | } 139 | 140 | /** 141 | * 兼容7.0获取不到的问题 142 | * 143 | * @return 144 | */ 145 | public static String getAndroidVersion7MAC() { 146 | try { 147 | List all = Collections.list(NetworkInterface.getNetworkInterfaces()); 148 | for (NetworkInterface nif : all) { 149 | if (!nif.getName().equalsIgnoreCase("wlan0")) continue; 150 | byte[] macBytes = nif.getHardwareAddress(); 151 | if (macBytes == null) { 152 | return ""; 153 | } 154 | StringBuilder res1 = new StringBuilder(); 155 | for (byte b : macBytes) { 156 | res1.append(String.format("%02X:", b)); 157 | } 158 | if (res1.length() > 0) { 159 | res1.deleteCharAt(res1.length() - 1); 160 | } 161 | return res1.toString(); 162 | } 163 | } catch (Exception e) { 164 | Log.e("mac", "get android version 7.0 mac error:" + e.getMessage()); 165 | } 166 | return ERROR_MAC_STR; 167 | } 168 | 169 | public static String loadFileAsString(String fileName) throws Exception { 170 | FileReader reader = new FileReader(fileName); 171 | String text = loadReaderAsString(reader); 172 | reader.close(); 173 | return text; 174 | } 175 | 176 | public static String loadReaderAsString(Reader reader) throws Exception { 177 | StringBuilder builder = new StringBuilder(); 178 | char[] buffer = new char[4096]; 179 | int readLength = reader.read(buffer); 180 | while (readLength >= 0) { 181 | builder.append(buffer, 0, readLength); 182 | readLength = reader.read(buffer); 183 | } 184 | return builder.toString(); 185 | } 186 | 187 | } 188 | 189 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | DexShell 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/test/java/cn/com/jni/dexshell/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.dexshell; 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 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.2.0' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /dexShell.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /dexShellMem.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /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=-Xmx1536m 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 | 15 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Thu Mar 26 16:02:32 CST 2020 8 | ndk.dir=D\:\\AndroidSDK\\ndk-bundle 9 | sdk.dir=D\:\\AndroidSDK 10 | -------------------------------------------------------------------------------- /proxy_core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | proxy_core-lib 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | src/main/cpp/rc4.cpp 21 | src/main/cpp/native-lib.cpp) 22 | 23 | # Searches for a specified prebuilt library and stores the path as a 24 | # variable. Because CMake includes system libraries in the search path by 25 | # default, you only need to specify the name of the public NDK library 26 | # you want to add. CMake verifies that the library exists before 27 | # completing its build. 28 | 29 | find_library( # Sets the name of the path variable. 30 | log-lib 31 | 32 | # Specifies the name of the NDK library that 33 | # you want CMake to locate. 34 | log) 35 | 36 | # Specifies libraries CMake should link to your target library. You 37 | # can link multiple libraries, such as libraries you define in this 38 | # build script, prebuilt third-party libraries, or system libraries. 39 | 40 | target_link_libraries( # Specifies the target library. 41 | proxy_core-lib 42 | 43 | # Links the target library to the log library 44 | # included in the NDK. 45 | ${log-lib}) -------------------------------------------------------------------------------- /proxy_core/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 28 5 | 6 | 7 | 8 | defaultConfig { 9 | minSdkVersion 27 10 | targetSdkVersion 28 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | externalNativeBuild { 16 | cmake { 17 | cppFlags "-std=c++11 -frtti" 18 | 19 | } 20 | } 21 | 22 | 23 | ndk { 24 | // 设置支持的 SO 库构架 25 | abiFilters 'armeabi-v7a' ,'arm64-v8a'//, 'x86', 'x86_64' 26 | ldLibs "log" 27 | } 28 | } 29 | 30 | buildTypes { 31 | release { 32 | minifyEnabled false 33 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 34 | } 35 | } 36 | externalNativeBuild { 37 | cmake { 38 | path "CMakeLists.txt" 39 | } 40 | } 41 | } 42 | 43 | dependencies { 44 | implementation fileTree(dir: 'libs', include: ['*.jar']) 45 | 46 | implementation 'com.android.support:appcompat-v7:28.0.0' 47 | testImplementation 'junit:junit:4.12' 48 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 49 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 50 | } 51 | -------------------------------------------------------------------------------- /proxy_core/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 | -------------------------------------------------------------------------------- /proxy_core/proxy_core.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /proxy_core/src/androidTest/java/cn/com/jni/proxy_core/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_core; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("cn.com.jni.proxy_core.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /proxy_core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /proxy_core/src/main/cpp/aes.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Administrator on 2020/3/27. 3 | // 4 | 5 | /************************************************************************/ 6 | /*AES: AES-128,AES-192,AES-256 7 | /*Author: chenweiliang 8 | /*Version: 1.0 9 | /*Note: The input data must be 128-bit. 10 | /************************************************************************/ 11 | #include "aes.h" 12 | 13 | byte AES::sBox[] = 14 | { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 15 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, /*0*/ 16 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, /*1*/ 17 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, /*2*/ 18 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, /*3*/ 19 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, /*4*/ 20 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, /*5*/ 21 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, /*6*/ 22 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, /*7*/ 23 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, /*8*/ 24 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, /*9*/ 25 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, /*a*/ 26 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, /*b*/ 27 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, /*c*/ 28 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, /*d*/ 29 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, /*e*/ 30 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 /*f*/ 31 | }; 32 | byte AES::invSBox[] = 33 | { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 34 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, /*0*/ 35 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, /*1*/ 36 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, /*2*/ 37 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, /*3*/ 38 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, /*4*/ 39 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, /*5*/ 40 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, /*6*/ 41 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, /*7*/ 42 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, /*8*/ 43 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, /*9*/ 44 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, /*a*/ 45 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, /*b*/ 46 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, /*c*/ 47 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, /*d*/ 48 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, /*e*/ 49 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d /*f*/ 50 | }; 51 | 52 | byte AES::rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; 53 | 54 | AES::AES() 55 | { 56 | //If no key is input,use the default key 57 | int keyBits = 128; 58 | byte key[16] = { 59 | 0x0f, 0x15, 0x71, 0xc9, 60 | 0x47, 0xd9, 0xe8, 0x59, 61 | 0x0c, 0xb7, 0xad, 0xd6, 62 | 0xaf, 0x7f, 0x67, 0x98 63 | }; 64 | setKey(key, keyBits); 65 | keyExpansion(); 66 | } 67 | 68 | AES::AES(const byte key[],enum KEYLENGTH keyBytes){ 69 | int keyBits; 70 | if (keyBytes == KEYLENGTH::KEY_LENGTH_16BYTES){ 71 | keyBits = 128; 72 | } 73 | else if (keyBytes==KEYLENGTH::KEY_LENGTH_24BYTES){ 74 | keyBits == 192; 75 | } 76 | else if (keyBytes==KEYLENGTH::KEY_LENGTH_32BYTES){ 77 | keyBits == 256; 78 | } 79 | setKey(key,keyBits); 80 | keyExpansion(); 81 | } 82 | 83 | void AES::setKey(const byte key[], const int keyBits){ 84 | mNb = 4; 85 | if (keyBits == 128){ 86 | mNk = 4; 87 | mNr = 10; 88 | } 89 | else if (keyBits == 192){ 90 | mNk = 6; 91 | mNr = 12; 92 | } 93 | else if (keyBits == 256){ 94 | mNk = 8; 95 | mNr = 14; 96 | } 97 | memcpy(mKey,key,mNk*4); 98 | } 99 | 100 | void AES::keyExpansion(){ 101 | //the first mNk words will be filled in mW derictly 102 | for (int i = 0; i < mNk; i++){ 103 | for (int j = 0; j < 4; j++){ 104 | //arranged vertically 105 | mW[i][j] = mKey[j+i*4]; 106 | } 107 | } 108 | 109 | //generate the secret key words 110 | for (int i = mNk; i < mNb*(mNr + 1); i++){ 111 | //last secret key word 112 | byte pre_w[4]; 113 | 114 | for (int k = 0; k < 4; k++){ 115 | pre_w[k] = mW[i-1][k]; 116 | } 117 | 118 | if(i%mNk == 0){ 119 | rotWord(pre_w); 120 | subWord(pre_w); 121 | pre_w[0] = pre_w[0] ^= rcon[i / mNk - 1]; 122 | } 123 | else if ((mNk>6)&&(i%mNk==4)){ 124 | subWord(pre_w); 125 | } 126 | 127 | for (int k = 0; k < 4; k++){ 128 | mW[i][k] = pre_w[k] ^ mW[i-mNk][k]; 129 | } 130 | } 131 | 132 | } 133 | 134 | void AES::subBytes(byte state[][4]) 135 | { 136 | for (int i = 0; i < 4; i++){ 137 | for (int j = 0; j < 4; j++){ 138 | state[i][j] = sBox[state[i][j]]; 139 | } 140 | } 141 | } 142 | 143 | void AES::shiftRows(byte state[][4]) 144 | { 145 | byte t[4]; 146 | for (int i = 1; i < 4; i++){ 147 | for (int j = 0; j < 4; j++){ 148 | t[j] = state[i][(i + j) % 4]; 149 | } 150 | for (int j = 0; j < 4; j++){ 151 | state[i][j] = t[j]; 152 | } 153 | } 154 | } 155 | 156 | void AES::mixColumns(byte state[][4]) 157 | { 158 | byte t[4]; 159 | for (int j = 0; j < 4; j++){ 160 | for (int i = 0; i < 4; i++){ 161 | t[i] = state[i][j]; 162 | } 163 | for (int i = 0; i < 4; i++){ 164 | state[i][j] = GF28Multi(t[i], 0x02) 165 | ^ GF28Multi(t[(i + 1) % 4], 0x03) 166 | ^ GF28Multi(t[(i + 2) % 4], 0x01) 167 | ^ GF28Multi(t[(i + 3) % 4], 0x01); 168 | } 169 | } 170 | } 171 | 172 | void AES::addRoundKey(byte state[][4], byte w[][4]) 173 | { 174 | for (int i = 0; i < 4; i++){ 175 | for (int j = 0; j < 4; j++){ 176 | state[i][j] ^= w[i][j]; 177 | } 178 | } 179 | } 180 | 181 | void AES::invSubBytes(byte state[][4]) 182 | { 183 | for (int i = 0; i < 4; i++){ 184 | for (int j = 0; j < 4; j++){ 185 | state[i][j] = invSBox[state[i][j]]; 186 | } 187 | } 188 | } 189 | 190 | void AES::invShiftRows(byte state[][4]) 191 | { 192 | byte t[4]; 193 | for (int i = 0; i < 4; i++){ 194 | for (int j = 0; j < 4; j++){ 195 | t[j] = state[i][(j-i + 4) % 4]; 196 | } 197 | for (int j = 0; j < 4; j++){ 198 | state[i][j] = t[j]; 199 | } 200 | } 201 | } 202 | 203 | void AES::invMixColumns(byte state[][4]) 204 | { 205 | byte t[4]; 206 | //calculate columns by columns 207 | for (int j = 0; j < 4; j++){ 208 | for (int i = 0; i < 4; i++){ 209 | t[i] = state[i][j]; 210 | } 211 | for (int i = 0; i < 4; i++){ 212 | state[i][j] = GF28Multi(t[i], 0x0e) 213 | ^ GF28Multi(t[(i+1)%4],0x0b) 214 | ^ GF28Multi(t[(i+2)%4],0x0d) 215 | ^ GF28Multi(t[(i+3)%4],0x09); 216 | } 217 | } 218 | } 219 | 220 | 221 | 222 | void AES::rotWord(byte w[]) 223 | { 224 | byte t; 225 | t = w[0]; 226 | w[0] = w[1]; 227 | w[1] = w[2]; 228 | w[2] = w[3]; 229 | w[3] = t; 230 | } 231 | 232 | void AES::subWord(byte w[]) 233 | { 234 | for (int i = 0; i < 4; i++){ 235 | w[i] = sBox[w[i]]; 236 | } 237 | } 238 | 239 | //calculate the least significant byte only for we only need 240 | //the least significant byte 241 | byte AES::GF28Multi(byte s,byte a){ 242 | byte t[4]; 243 | byte result = 0; 244 | t[0] = s; 245 | 246 | //calculate s*{02},s*{03},s*{04} 247 | for (int i = 1; i < 4; i++){ 248 | t[i] = t[i - 1] << 1; 249 | if (t[i - 1] & 0x80){ 250 | t[i] ^= 0x1b; 251 | } 252 | } 253 | //multiply a and s bit by bit and sum together 254 | for (int i = 0; i < 4; i++){ 255 | if ((a >> i) & 0x01){ 256 | result ^= t[i]; 257 | } 258 | } 259 | 260 | return result; 261 | } 262 | 263 | void AES::encrypt(const byte data[16], byte out[16]) 264 | { 265 | byte state[4][4]; 266 | byte key[4][4]; 267 | for (int i = 0; i < 4; i++){ 268 | for (int j = 0; j < 4; j++){ 269 | state[i][j] = data[i+j*4]; 270 | } 271 | } 272 | #ifdef DEBUG 273 | printf("plaintext:\n"); 274 | print128(state); 275 | printf("--------------------------Round 0 begin:--------------------------\n"); 276 | #endif // DEBUG 277 | getKeyAt(key, 0); 278 | 279 | addRoundKey(state, key); 280 | #ifdef DEBUG 281 | printf("addRoundKey:\n"); 282 | print128(state); 283 | #endif // DEBUG 284 | for (int i = 1; i <= mNr; i++){ 285 | #ifdef DEBUG 286 | printf("--------------------------Round %d begin:--------------------------\n",i); 287 | #endif // DEBUG 288 | subBytes(state); 289 | #ifdef DEBUG 290 | printf("subBytes:\n"); 291 | print128(state); 292 | #endif // DEBUG 293 | shiftRows(state); 294 | #ifdef DEBUG 295 | printf("shiftRows:\n"); 296 | print128(state); 297 | #endif // DEBUG 298 | 299 | if (i != mNr){ 300 | mixColumns(state); 301 | #ifdef DEBUG 302 | printf("mixColumns:\n"); 303 | print128(state); 304 | #endif // DEBUG 305 | } 306 | getKeyAt(key, i); 307 | addRoundKey(state, key); 308 | #ifdef DEBUG 309 | printf("addRoundKey:\n"); 310 | print128(state); 311 | #endif // DEBUG 312 | } 313 | 314 | for (int i = 0; i < 4; i++){ 315 | for (int j = 0; j < 4; j++){ 316 | out[i+j*4] = state[i][j]; 317 | } 318 | } 319 | } 320 | 321 | void AES::decrypt(const byte data[16], byte out[16]) 322 | { 323 | byte state[4][4]; 324 | byte key[4][4]; 325 | for (int i = 0; i < 4; i++){ 326 | for (int j = 0; j < 4; j++){ 327 | state[i][j] = data[i+j*4]; 328 | } 329 | } 330 | 331 | getKeyAt(key, mNr); 332 | addRoundKey(state,key); 333 | 334 | for (int i = (mNr - 1); i >= 0; i--){ 335 | invShiftRows(state); 336 | invSubBytes(state); 337 | getKeyAt(key, i); 338 | addRoundKey(state,key); 339 | if (i){ 340 | invMixColumns(state); 341 | } 342 | } 343 | 344 | for (int i = 0; i < 4; i++){ 345 | for (int j = 0; j < 4; j++){ 346 | out[i + j * 4] = state[i][j]; 347 | } 348 | } 349 | } 350 | 351 | #ifdef DEBUG 352 | void AES::print128(unsigned char state[16]){ 353 | for (int i = 0; i < 16; i++){ 354 | printf("%02hhx ", state[i]); 355 | } 356 | } 357 | 358 | void AES::print128(unsigned char state[4][4]){ 359 | for (int i = 0; i < 4; i++){ 360 | for (int j = 0; j < 4; j++){ 361 | printf("%02hhx ", state[i][j]); 362 | } 363 | printf("\n"); 364 | } 365 | } 366 | #endif // DEBUG 367 | 368 | 369 | //get the secret key for round "index",which will 370 | //be arranged vetically 371 | void AES::getKeyAt(byte key[][4], int index){ 372 | for (int i = index*4; i < index*4+4; i++){ 373 | for (int j = 0; j < 4; j++){ 374 | key[j][i-index*4] = mW[i][j]; 375 | } 376 | } 377 | #ifdef DEBUG 378 | printf("secret key for round %d\n", index); 379 | print128(key); 380 | #endif // DEBUG 381 | 382 | } 383 | 384 | AES::~AES() 385 | { 386 | } 387 | -------------------------------------------------------------------------------- /proxy_core/src/main/cpp/aes.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Administrator on 2020/3/27. 3 | // 4 | 5 | #ifndef DEXSHELL_AES_H 6 | #define DEXSHELL_AES_H 7 | 8 | #endif //DEXSHELL_AES_H 9 | /************************************************************************/ 10 | /*AES: AES-128,AES-192,AES-256 11 | /*Author: chenweiliang 12 | /*Version: 1.0 13 | /*Note: The input data must be 128-bit. 14 | /* To see all information output,please uncommet the macro 15 | /* definition "#define DEBUG" 16 | /************************************************************************/ 17 | 18 | #include 19 | #include 20 | 21 | #ifndef DEBUG 22 | //#define DEBUG 23 | #endif // !DEBUG 24 | 25 | typedef unsigned char byte; 26 | 27 | //length of secret key 28 | enum KEYLENGTH 29 | { 30 | KEY_LENGTH_16BYTES, KEY_LENGTH_24BYTES, KEY_LENGTH_32BYTES 31 | }; 32 | 33 | class AES 34 | { 35 | public: 36 | AES(); 37 | AES(const byte key[],enum KEYLENGTH keyBytes); 38 | virtual ~AES(); 39 | void encrypt(const byte data[16], byte out[16]); 40 | void decrypt(const byte data[16], byte out[16]); 41 | private: 42 | // 43 | int mNb; 44 | 45 | //word length of the secret key used in one turn 46 | int mNk; 47 | 48 | //number of turns 49 | int mNr; 50 | 51 | //the secret key,which can be 16bytes,24bytes or 32bytes 52 | byte mKey[32]; 53 | 54 | //the extended key,which can be 176bytes,208bytes,240bytes 55 | byte mW[60][4]; 56 | 57 | static byte sBox[]; 58 | static byte invSBox[]; 59 | //constant 60 | static byte rcon[]; 61 | void setKey(const byte key[], const int keyBits); 62 | 63 | void subBytes(byte state[][4]); 64 | void shiftRows(byte state[][4]); 65 | void mixColumns(byte state[][4]); 66 | void addRoundKey(byte state[][4], byte w[][4]); 67 | 68 | void invSubBytes(byte state[][4]); 69 | void invShiftRows(byte state[][4]); 70 | void invMixColumns(byte state[][4]); 71 | 72 | void keyExpansion(); 73 | 74 | // 75 | byte GF28Multi(byte s, byte a); 76 | 77 | void rotWord(byte w[]); 78 | void subWord(byte w[]); 79 | 80 | //get the secret key 81 | void getKeyAt(byte key[][4],int i); 82 | 83 | #ifdef DEBUG 84 | void print128(byte state[16]); 85 | void print128(byte state[4][4]); 86 | #endif // DEBUG 87 | }; 88 | -------------------------------------------------------------------------------- /proxy_core/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "rc4.h" 8 | #define LOG_TAG "native-jni" 9 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__) 10 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__) 11 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__) 12 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__) 13 | #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG, __VA_ARGS__) 14 | #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) 15 | 16 | unsigned char* readFile(const char* file, int *len) 17 | { 18 | FILE *fp; 19 | fp = fopen(file, "rb"); 20 | if (fp != NULL) { 21 | fseek(fp, 0L, SEEK_END); 22 | unsigned long filesize = ftell(fp); 23 | *len = filesize; 24 | if (filesize > 0) { 25 | unsigned char* fileBuffer = new unsigned char[filesize + 1]; 26 | // unsigned char *fileBuffer = new unsigned char[filesize + 1]; 27 | rewind(fp);//rewind函数作用等同于 (void)fseek(stream, 0L, SEEK_SET); 28 | fileBuffer[filesize] = '\0'; 29 | int ret = fread(fileBuffer, sizeof(char), filesize, fp); 30 | 31 | fclose(fp); 32 | fp = NULL; 33 | if (ret <= 0) { 34 | return NULL; 35 | } 36 | return fileBuffer; 37 | } 38 | 39 | fclose(fp); 40 | fp = NULL; 41 | } 42 | 43 | return NULL; 44 | } 45 | std::string jstring2str(JNIEnv *env, jstring jstr) { 46 | char *rtn = NULL; 47 | jclass clsstring = env->FindClass("java/lang/String"); 48 | jstring strencode = env->NewStringUTF("GB2312"); 49 | jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); 50 | jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode); 51 | jsize alen = env->GetArrayLength(barr); 52 | jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE); 53 | if (alen > 0) { 54 | rtn = (char *) malloc(alen + 1); 55 | memcpy(rtn, ba, alen); 56 | rtn[alen] = 0; 57 | } 58 | env->ReleaseByteArrayElements(barr, ba, 0); 59 | std::string stemp(rtn); 60 | free(rtn); 61 | return stemp; 62 | } 63 | 64 | bool writeFileDex(const char * path, const unsigned char * data,long size) 65 | { 66 | FILE *fp; 67 | if ((fp = fopen(path, "wb")) == NULL) 68 | { 69 | // LOGE("file cannot open %s", path); 70 | return false; 71 | } 72 | else 73 | { 74 | fwrite(data, 1, size, fp); 75 | } 76 | fclose(fp); 77 | 78 | return true; 79 | } 80 | //extern "C" JNIEXPORT jstring JNICALL 81 | //Java_cn_com_jni_dexshell_MainActivity_stringFromJNI( 82 | // JNIEnv *env, 83 | // jobject jobj/* this */, jstring id) { 84 | // std::string nid = jstring2str(env, id); 85 | // std::string hello = "Hello from C++"; 86 | // return env->NewStringUTF(nid.c_str()); 87 | //} 88 | 89 | using namespace std; 90 | //cn.com.jni.proxy_core.Utils.native_rc4_de( 91 | static const char *const kClassJniTest = 92 | "cn/com/jni/proxy_core/Utils"; 93 | 94 | 95 | 96 | void rc4Encrypt(unsigned char * data, int len) 97 | { 98 | unsigned char s[256] = { 0 } ;//S-box 99 | char key[256] = "8rrh1086omGe8qF0"; 100 | 101 | rc4::rc4_init(s, (unsigned char*)key, strlen(key));//已经完成了初始化 102 | rc4::rc4_run((unsigned char*)s, (unsigned char*)data, len);//解密 103 | } 104 | jbyteArray JNI_native_rc4(JNIEnv *env, jobject thizz,jstring filename,jstring outname) { 105 | LOGI(" native_1init"); 106 | 107 | string fname = jstring2str (env,filename); 108 | string oname = jstring2str (env,outname); 109 | 110 | int flen = 0; 111 | unsigned char* data = readFile(fname.c_str(),&flen); 112 | 113 | if(nullptr!= data) 114 | { 115 | rc4Encrypt(data,flen); 116 | jbyte *by = (jbyte*)data; 117 | jbyteArray jarray = env->NewByteArray(flen); 118 | 119 | //4. 赋值 120 | env->SetByteArrayRegion(jarray, 0, flen, by); 121 | delete []data; 122 | 123 | return jarray; 124 | } 125 | 126 | // if(! writeFileDex(oname.c_str(),data,flen)) 127 | // { 128 | // LOGE("open file :%s failed",oname.c_str()); 129 | // } 130 | return nullptr; 131 | } 132 | 133 | static const JNINativeMethod gMethods[] = { 134 | { 135 | "native_rc4_de", 136 | "(Ljava/lang/String;Ljava/lang/String;)[B", 137 | (void*) JNI_native_rc4 138 | } 139 | }; 140 | 141 | static int registerNativeMethods(JNIEnv *env, const char *className, const JNINativeMethod *gMethod, 142 | int numMethods) { 143 | jclass clazz; 144 | clazz = env->FindClass(className); 145 | if (clazz == NULL) { 146 | LOGI(" JNI reg faild:%s",className); 147 | return JNI_FALSE; 148 | } 149 | if (env->RegisterNatives(clazz, gMethod, numMethods) < 0) { 150 | LOGI(" JNI reg method failed:%s",gMethod->name); 151 | return JNI_FALSE; 152 | } 153 | 154 | return JNI_TRUE; 155 | } 156 | 157 | static int register_along_jni(JNIEnv *env) { 158 | 159 | return registerNativeMethods(env, kClassJniTest, gMethods, 160 | NELEM(gMethods)); 161 | } 162 | 163 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /* reserved */) { 164 | 165 | JNIEnv *env = NULL; 166 | jint result = -1; 167 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { 168 | LOGE("ERROR: JNI version error"); 169 | 170 | return JNI_ERR; 171 | } 172 | if (register_along_jni(env) == -1) { 173 | LOGE("ERROR: JNI_OnLoad failed"); 174 | return JNI_ERR; 175 | } 176 | result = JNI_VERSION_1_6; 177 | return result; 178 | } -------------------------------------------------------------------------------- /proxy_core/src/main/cpp/rc4.cpp: -------------------------------------------------------------------------------- 1 | #include "rc4.h" 2 | 3 | //加密或解密 4 | void rc4::rc4_init(unsigned char*s, unsigned char*key, unsigned long Len) 5 | { 6 | int i = 0, j = 0; 7 | char k[256] = { 0 }; 8 | unsigned char tmp = 0; 9 | for (i = 0; i<256; i++) 10 | { 11 | s[i] = i; 12 | k[i] = key[i%Len]; 13 | } 14 | for (i = 0; i<256; i++) 15 | { 16 | j = (j + s[i] + k[i]) % 256; 17 | tmp = s[i]; 18 | s[i] = s[j];//交换s[i]和s[j] 19 | s[j] = tmp; 20 | } 21 | } 22 | void rc4::rc4_run(unsigned char*s, unsigned char*Data, unsigned long Len) 23 | { 24 | int i = 0, j = 0, t = 0; 25 | unsigned long k = 0; 26 | unsigned char tmp; 27 | for (k = 0; k dexFiles = new ArrayList<>(); 58 | List ByteBufferList = new ArrayList<>(); 59 | //进行解密 (最好做md5文件校验) 60 | if (!dexDir.exists() || dexDir.list().length == 0){ 61 | //把apk解压到appDir 62 | if (!appDir.exists()) 63 | { 64 | Zip.unZip(apkFile,appDir); 65 | Log.e("filename","unZip---"+appDir.getAbsolutePath()); 66 | } 67 | 68 | //获取目录下所有的文件 69 | File[] files = appDir.listFiles(); 70 | for (File file:files){ 71 | String name = file.getName(); 72 | 73 | if (name.endsWith(".dex") && !TextUtils.equals(name,"classes.dex")){ 74 | try{ 75 | Log.e("filename","---"+file.getAbsolutePath()); 76 | byte[] bytes = Utils.native_rc4_de(file.getAbsolutePath(),file.getAbsolutePath()); 77 | dexFiles.add(file); 78 | if(null != bytes) 79 | { 80 | ByteBuffer buffer = ByteBuffer.wrap(bytes); 81 | ByteBufferList.add(buffer); 82 | } 83 | 84 | Log.e("filename","---"+file.getAbsolutePath()); 85 | }catch (Exception e){ 86 | e.printStackTrace(); 87 | } 88 | } 89 | } 90 | }else { 91 | for (File file:dexDir.listFiles()){ 92 | dexFiles.add(file); 93 | } 94 | } 95 | try { 96 | loadDexByMem(base,ByteBufferList); 97 | } catch (Exception e) { 98 | e.printStackTrace(); 99 | } 100 | } 101 | 102 | private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { 103 | // return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList"); 104 | return RefInvoke.getFieldOjbect("dalvik.system.BaseDexClassLoader",obj,"pathList"); 105 | } 106 | private void loadDexByMem(Context base, List ByteBufferList) throws Exception{ 107 | try { 108 | 109 | ByteBuffer[] byteBuffers = new ByteBuffer[ByteBufferList.size()]; 110 | int i =0; 111 | for(ByteBuffer buffer:ByteBufferList) 112 | { 113 | byteBuffers[i]=buffer; 114 | i++; 115 | } 116 | 117 | // 配置动态加载环境 118 | //反射获取主线程对象,并从中获取所有已加载的package信息,并中找到当前的LoadApk对象的弱引用 119 | 120 | //创建一个新的inMemoryDexClassLoader用于加载源Apk, 121 | // 父节点的inMemoryDexClassLoader使其遵循双亲委托模型 122 | 123 | //getClassLoader()等同于 (ClassLoader) RefInvoke.getFieldOjbect() 124 | //但是为了替换掉父节点我们需要通过反射来获取并修改其值 125 | Object currentActivityThread = RefInvoke.invokeStaticMethod( 126 | "android.app.ActivityThread", "currentActivityThread", 127 | new Class[] {}, new Object[] {}); 128 | String packageName = base.getPackageName(); 129 | Log.e("filename","packageName:"+packageName); 130 | ArrayMap mPackages = (ArrayMap) RefInvoke.getFieldOjbect( 131 | "android.app.ActivityThread", currentActivityThread, 132 | "mPackages"); 133 | 134 | WeakReference wr = (WeakReference) mPackages.get(packageName); 135 | 136 | 137 | Log.e("filename","android.app.LoadedApk"); 138 | InMemoryDexClassLoader inMemoryDexClassLoader = new InMemoryDexClassLoader(byteBuffers, 139 | (ClassLoader) RefInvoke.getFieldOjbect( 140 | "android.app.LoadedApk", wr.get(), "mClassLoader")); 141 | 142 | ClassLoader gclassloader = (ClassLoader) RefInvoke.getFieldOjbect( 143 | "android.app.LoadedApk", wr.get(), "mClassLoader"); 144 | 145 | Log.e(TAG,"父classloader:"+gclassloader); 146 | 147 | //将父节点DexClassLoader替换 148 | RefInvoke.setFieldOjbect("android.app.LoadedApk", "mClassLoader", 149 | wr.get(), inMemoryDexClassLoader); 150 | 151 | Log.i(TAG,"gclassloader classloader:"+inMemoryDexClassLoader); 152 | 153 | Log.e("filename","11 app_name: "+app_name); 154 | //创建用户真实的application (MyApplication) 155 | Class delegateClass = null; 156 | delegateClass =inMemoryDexClassLoader.loadClass(app_name); 157 | 158 | delegate = (Application) delegateClass.newInstance(); 159 | }catch (Exception e){ 160 | e.printStackTrace(); 161 | } 162 | } 163 | 164 | 165 | private void getMetaData(){ 166 | try { 167 | ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo( 168 | getPackageName(), PackageManager.GET_META_DATA); 169 | Bundle metaData = applicationInfo.metaData; 170 | if (null != metaData){ 171 | if (metaData.containsKey("app_name")){ 172 | app_name = metaData.getString("app_name"); 173 | } 174 | if (metaData.containsKey("app_version")){ 175 | app_version = metaData.getString("app_version"); 176 | } 177 | } 178 | }catch (Exception e){ 179 | e.printStackTrace(); 180 | } 181 | } 182 | 183 | /** 184 | * 开始替换application 185 | */ 186 | @Override 187 | public void onCreate() { 188 | super.onCreate(); 189 | try { 190 | bindRealApplication(); 191 | }catch (Exception e){ 192 | e.printStackTrace(); 193 | } 194 | } 195 | 196 | /** 197 | * 让代码走入if的第三段中 198 | * @return 199 | */ 200 | @Override 201 | public String getPackageName() { 202 | if (!TextUtils.isEmpty(app_name)){ 203 | return ""; 204 | } 205 | return super.getPackageName(); 206 | } 207 | 208 | @Override 209 | public Context createPackageContext(String packageName, int flags) throws PackageManager.NameNotFoundException { 210 | Log.e("filename","createPackageContext:packageName"+packageName); 211 | if (TextUtils.isEmpty(app_name)){ 212 | return super.createPackageContext(packageName, flags); 213 | } 214 | try { 215 | bindRealApplication(); 216 | } catch (Exception e) { 217 | e.printStackTrace(); 218 | } 219 | return delegate; 220 | 221 | } 222 | 223 | boolean isBindReal; 224 | Application delegate; 225 | //下面主要是通过反射系统源码的内容,然后进行处理,把我们的内容加进去处理 226 | private void bindRealApplication() throws Exception{ 227 | if (isBindReal){ 228 | return; 229 | } 230 | if (TextUtils.isEmpty(app_name)){ 231 | return; 232 | } 233 | 234 | Log.e("filename","bindRealApplication: "); 235 | //得到attchBaseContext(context) 传入的上下文 ContextImpl 236 | Context baseContext = getBaseContext(); 237 | 238 | //得到attch()方法 239 | Method attach = Application.class.getDeclaredMethod("attach",Context.class); 240 | attach.setAccessible(true); 241 | attach.invoke(delegate,baseContext); 242 | 243 | 244 | //获取ContextImpl ----> ,mOuterContext(app); 通过Application的attachBaseContext回调参数获取 245 | Class contextImplClass = Class.forName("android.app.ContextImpl"); 246 | //获取mOuterContext属性 247 | Field mOuterContextField = contextImplClass.getDeclaredField("mOuterContext"); 248 | mOuterContextField.setAccessible(true); 249 | mOuterContextField.set(baseContext,delegate); 250 | 251 | //ActivityThread ----> mAllApplication(ArrayList) ContextImpl的mMainThread属性 252 | Field mMainThreadField = contextImplClass.getDeclaredField("mMainThread"); 253 | mMainThreadField.setAccessible(true); 254 | Object mMainThread = mMainThreadField.get(baseContext); 255 | 256 | //ActivityThread -----> mInitialApplication ContextImpl的mMainThread属性 257 | Class activityThreadClass = Class.forName("android.app.ActivityThread"); 258 | Field mInitialApplicationField = activityThreadClass.getDeclaredField("mInitialApplication"); 259 | mInitialApplicationField.setAccessible(true); 260 | mInitialApplicationField.set(mMainThread,delegate); 261 | 262 | //ActivityThread ------> mAllApplications(ArrayList) ContextImpl的mMainThread属性 263 | Field mAllApplicationsField = activityThreadClass.getDeclaredField("mAllApplications"); 264 | mAllApplicationsField.setAccessible(true); 265 | ArrayList mApplications = (ArrayList) mAllApplicationsField.get(mMainThread); 266 | mApplications.remove(this); 267 | mApplications.add(delegate); 268 | 269 | //LoadedApk -----> mApplicaion ContextImpl的mPackageInfo属性 270 | Field mPackageInfoField = contextImplClass.getDeclaredField("mPackageInfo"); 271 | mPackageInfoField.setAccessible(true); 272 | Object mPackageInfo = mPackageInfoField.get(baseContext); 273 | 274 | 275 | Class loadedApkClass = Class.forName("android.app.LoadedApk"); 276 | Field mApplicationField = loadedApkClass.getDeclaredField("mApplication"); 277 | mApplicationField.setAccessible(true); 278 | mApplicationField.set(mPackageInfo,delegate); 279 | 280 | //修改ApplicationInfo className LoadedApk 281 | Field mApplicationInfoField = loadedApkClass.getDeclaredField("mApplicationInfo"); 282 | mApplicationInfoField.setAccessible(true); 283 | ApplicationInfo mApplicationInfo = (ApplicationInfo) mApplicationInfoField.get(mPackageInfo); 284 | mApplicationInfo.className = app_name; 285 | insertNativeLibraryPathElements(new File(so_path),delegate.getApplicationContext()); 286 | 287 | delegate.onCreate(); 288 | isBindReal = true; 289 | } 290 | 291 | public static void insertNativeLibraryPathElements(File soDirFile, Context context){ 292 | ClassLoader pathClassLoader = context.getClassLoader(); 293 | Object pathList = null; 294 | try { 295 | pathList = getPathList(pathClassLoader); 296 | } catch (ClassNotFoundException e) { 297 | e.printStackTrace(); 298 | } catch (NoSuchFieldException e) { 299 | e.printStackTrace(); 300 | } catch (IllegalAccessException e) { 301 | e.printStackTrace(); 302 | } 303 | if(pathList != null) { 304 | Field nativeLibraryPathElementsField = null; 305 | try { 306 | 307 | Method makePathElements; 308 | Object invokeMakePathElements; 309 | boolean isNewVersion = Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1; 310 | //调用makePathElements 311 | makePathElements = isNewVersion?pathList.getClass().getDeclaredMethod("makePathElements", List.class):pathList.getClass().getDeclaredMethod("makePathElements", List.class,List.class,ClassLoader.class); 312 | makePathElements.setAccessible(true); 313 | ArrayList suppressedExceptions = new ArrayList<>(); 314 | List nativeLibraryDirectories = new ArrayList<>(); 315 | nativeLibraryDirectories.add(soDirFile); 316 | List allNativeLibraryDirectories = new ArrayList<>(nativeLibraryDirectories); 317 | //获取systemNativeLibraryDirectories 318 | Field systemNativeLibraryDirectoriesField = pathList.getClass().getDeclaredField("systemNativeLibraryDirectories"); 319 | systemNativeLibraryDirectoriesField.setAccessible(true); 320 | List systemNativeLibraryDirectories = (List) systemNativeLibraryDirectoriesField.get(pathList); 321 | Log.i("insertNativeLibrary","systemNativeLibraryDirectories "+systemNativeLibraryDirectories); 322 | allNativeLibraryDirectories.addAll(systemNativeLibraryDirectories); 323 | invokeMakePathElements = isNewVersion?makePathElements.invoke(pathClassLoader, allNativeLibraryDirectories):makePathElements.invoke(pathClassLoader, allNativeLibraryDirectories,suppressedExceptions,pathClassLoader); 324 | Log.i("insertNativeLibrary","makePathElements "+invokeMakePathElements); 325 | 326 | nativeLibraryPathElementsField = pathList.getClass().getDeclaredField("nativeLibraryPathElements"); 327 | nativeLibraryPathElementsField.setAccessible(true); 328 | Object list = nativeLibraryPathElementsField.get(pathList); 329 | Log.i("insertNativeLibrary","nativeLibraryPathElements "+list); 330 | Object dexElementsValue = combineArray(list, invokeMakePathElements); 331 | //把组合后的nativeLibraryPathElements设置到系统中 332 | nativeLibraryPathElementsField.set(pathList,dexElementsValue); 333 | } catch (NoSuchFieldException e) { 334 | e.printStackTrace(); 335 | } catch (IllegalAccessException e) { 336 | e.printStackTrace(); 337 | } catch (NoSuchMethodException e) { 338 | e.printStackTrace(); 339 | } catch (InvocationTargetException e) { 340 | e.printStackTrace(); 341 | } 342 | 343 | } 344 | } 345 | 346 | public static Object combineArray(Object hostDexElementValue, Object pluginDexElementValue) { 347 | //获取原数组类型 348 | Class localClass = hostDexElementValue.getClass().getComponentType(); 349 | Log.i("insertNativeLibrary","localClass "+localClass); 350 | //获取原数组长度 351 | int i = Array.getLength(hostDexElementValue); 352 | //插件数组加上原数组的长度 353 | int j = i + Array.getLength(pluginDexElementValue); 354 | //创建一个新的数组用来存储 355 | Object result = Array.newInstance(localClass, j); 356 | //一个个的将dex文件设置到新数组中 357 | for (int k = 0; k < j; ++k) { 358 | if (k < i) { 359 | Array.set(result, k, Array.get(hostDexElementValue, k)); 360 | } else { 361 | Array.set(result, k, Array.get(pluginDexElementValue, k - i)); 362 | } 363 | } 364 | return result; 365 | } 366 | } 367 | -------------------------------------------------------------------------------- /proxy_core/src/main/java/cn/com/jni/proxy_core/RefInvoke.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_core; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | 7 | public class RefInvoke { 8 | /** 9 | * 反射执行类的静态函数(public) 10 | * @param class_name 类名 11 | * @param method_name 函数名 12 | * @param pareTyple 函数的参数类型 13 | * @param pareVaules 调用函数时传入的参数 14 | * @return 15 | */ 16 | public static Object invokeStaticMethod(String class_name, String method_name, Class[] pareTyple, Object[] pareVaules){ 17 | 18 | try { 19 | Class obj_class = Class.forName(class_name); 20 | Method method = obj_class.getMethod(method_name,pareTyple); 21 | return method.invoke(null, pareVaules); 22 | } catch (SecurityException e) { 23 | e.printStackTrace(); 24 | } catch (IllegalArgumentException e) { 25 | e.printStackTrace(); 26 | } catch (IllegalAccessException e) { 27 | e.printStackTrace(); 28 | } catch (NoSuchMethodException e) { 29 | e.printStackTrace(); 30 | } catch (InvocationTargetException e) { 31 | e.printStackTrace(); 32 | } catch (ClassNotFoundException e) { 33 | e.printStackTrace(); 34 | } 35 | return null; 36 | 37 | } 38 | 39 | /** 40 | * 反射执行类的函数(public) 41 | * @param class_name 42 | * @param method_name 43 | * @param obj 44 | * @param pareTyple 45 | * @param pareVaules 46 | * @return 47 | */ 48 | public static Object invokeMethod(String class_name, String method_name, Object obj ,Class[] pareTyple, Object[] pareVaules){ 49 | 50 | try { 51 | Class obj_class = Class.forName(class_name); 52 | Method method = obj_class.getMethod(method_name,pareTyple); 53 | return method.invoke(obj, pareVaules); 54 | } catch (SecurityException e) { 55 | e.printStackTrace(); 56 | } catch (IllegalArgumentException e) { 57 | e.printStackTrace(); 58 | } catch (IllegalAccessException e) { 59 | e.printStackTrace(); 60 | } catch (NoSuchMethodException e) { 61 | e.printStackTrace(); 62 | } catch (InvocationTargetException e) { 63 | e.printStackTrace(); 64 | } catch (ClassNotFoundException e) { 65 | e.printStackTrace(); 66 | } 67 | return null; 68 | 69 | } 70 | 71 | /** 72 | * 反射得到类的属性(包括私有和保护) 73 | * @param class_name 74 | * @param obj 75 | * @param filedName 76 | * @return 77 | */ 78 | public static Object getFieldOjbect(String class_name,Object obj, String filedName){ 79 | try { 80 | Class obj_class = Class.forName(class_name); 81 | Field field = obj_class.getDeclaredField(filedName); 82 | field.setAccessible(true); 83 | return field.get(obj); 84 | } catch (SecurityException e) { 85 | e.printStackTrace(); 86 | } catch (NoSuchFieldException e) { 87 | e.printStackTrace(); 88 | } catch (IllegalArgumentException e) { 89 | e.printStackTrace(); 90 | } catch (IllegalAccessException e) { 91 | e.printStackTrace(); 92 | } catch (ClassNotFoundException e) { 93 | e.printStackTrace(); 94 | } 95 | return null; 96 | 97 | } 98 | 99 | /** 100 | * 反射得到类的静态属性(包括私有和保护) 101 | * @param class_name 102 | * @param filedName 103 | * @return 104 | */ 105 | public static Object getStaticFieldOjbect(String class_name, String filedName){ 106 | 107 | try { 108 | Class obj_class = Class.forName(class_name); 109 | Field field = obj_class.getDeclaredField(filedName); 110 | field.setAccessible(true); 111 | return field.get(null); 112 | } catch (SecurityException e) { 113 | e.printStackTrace(); 114 | } catch (NoSuchFieldException e) { 115 | e.printStackTrace(); 116 | } catch (IllegalArgumentException e) { 117 | e.printStackTrace(); 118 | } catch (IllegalAccessException e) { 119 | e.printStackTrace(); 120 | } catch (ClassNotFoundException e) { 121 | e.printStackTrace(); 122 | } 123 | return null; 124 | 125 | } 126 | 127 | /** 128 | * 设置类的属性(包括私有和保护) 129 | * @param classname 130 | * @param filedName 131 | * @param obj 132 | * @param filedVaule 133 | */ 134 | public static void setFieldOjbect(String classname, String filedName, Object obj, Object filedVaule){ 135 | try { 136 | Class obj_class = Class.forName(classname); 137 | Field field = obj_class.getDeclaredField(filedName); 138 | field.setAccessible(true); 139 | field.set(obj, filedVaule); 140 | } catch (SecurityException e) { 141 | e.printStackTrace(); 142 | } catch (NoSuchFieldException e) { 143 | e.printStackTrace(); 144 | } catch (IllegalArgumentException e) { 145 | e.printStackTrace(); 146 | } catch (IllegalAccessException e) { 147 | e.printStackTrace(); 148 | } catch (ClassNotFoundException e) { 149 | e.printStackTrace(); 150 | } 151 | } 152 | 153 | /** 154 | * 设置类的静态属性(包括私有和保护) 155 | * @param class_name 156 | * @param filedName 157 | * @param filedVaule 158 | */ 159 | public static void setStaticOjbect(String class_name, String filedName, Object filedVaule){ 160 | try { 161 | Class obj_class = Class.forName(class_name); 162 | Field field = obj_class.getDeclaredField(filedName); 163 | field.setAccessible(true); 164 | field.set(null, filedVaule); 165 | } catch (SecurityException e) { 166 | e.printStackTrace(); 167 | } catch (NoSuchFieldException e) { 168 | e.printStackTrace(); 169 | } catch (IllegalArgumentException e) { 170 | e.printStackTrace(); 171 | } catch (IllegalAccessException e) { 172 | e.printStackTrace(); 173 | } catch (ClassNotFoundException e) { 174 | e.printStackTrace(); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /proxy_core/src/main/java/cn/com/jni/proxy_core/Utils.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_core; 2 | 3 | import java.io.File; 4 | import java.io.RandomAccessFile; 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.Method; 7 | import java.util.Arrays; 8 | 9 | 10 | public class Utils { 11 | static { 12 | System.loadLibrary("proxy_core-lib"); 13 | } 14 | 15 | /** 16 | * 读取文件 17 | * @param file 18 | * @return 19 | * @throws Exception 20 | */ 21 | public static byte[] getBytes(File file) throws Exception { 22 | RandomAccessFile r = new RandomAccessFile(file, "r"); 23 | byte[] buffer = new byte[(int) r.length()]; 24 | r.readFully(buffer); 25 | r.close(); 26 | return buffer; 27 | } 28 | 29 | /** 30 | * 反射获得 指定对象(当前-》父类-》父类...)中的 成员属性 31 | * @param instance 32 | * @param name 33 | * @return 34 | * @throws NoSuchFieldException 35 | */ 36 | public static Field findField(Object instance, String name) throws NoSuchFieldException { 37 | Class clazz = instance.getClass(); 38 | //反射获得 39 | while (clazz != null) { 40 | try { 41 | Field field = clazz.getDeclaredField(name); 42 | //如果无法访问 设置为可访问 43 | if (!field.isAccessible()) { 44 | field.setAccessible(true); 45 | } 46 | return field; 47 | } catch (NoSuchFieldException e) { 48 | //如果找不到往父类找 49 | clazz = clazz.getSuperclass(); 50 | } 51 | } 52 | throw new NoSuchFieldException("Field " + name + " not found in " + instance.getClass()); 53 | } 54 | 55 | 56 | /** 57 | * 反射获得 指定对象(当前-》父类-》父类...)中的 函数 58 | * @param instance 59 | * @param name 60 | * @param parameterTypes 61 | * @return 62 | * @throws NoSuchMethodException 63 | */ 64 | public static Method findMethod(Object instance, String name, Class... parameterTypes) 65 | throws NoSuchMethodException { 66 | Class clazz = instance.getClass(); 67 | while (clazz != null) { 68 | try { 69 | Method method = clazz.getDeclaredMethod(name, parameterTypes); 70 | if (!method.isAccessible()) { 71 | method.setAccessible(true); 72 | } 73 | return method; 74 | } catch (NoSuchMethodException e) { 75 | //如果找不到往父类找 76 | clazz = clazz.getSuperclass(); 77 | } 78 | } 79 | throw new NoSuchMethodException("Method " + name + " with parameters " + Arrays.asList 80 | (parameterTypes) + " not found in " + instance.getClass()); 81 | } 82 | public static native byte[] native_rc4_de(String filename,String outname); 83 | } 84 | -------------------------------------------------------------------------------- /proxy_core/src/main/java/cn/com/jni/proxy_core/Zip.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_core; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.InputStream; 7 | import java.util.Enumeration; 8 | import java.util.zip.CRC32; 9 | import java.util.zip.CheckedOutputStream; 10 | import java.util.zip.ZipEntry; 11 | import java.util.zip.ZipFile; 12 | import java.util.zip.ZipOutputStream; 13 | 14 | 15 | public class Zip { 16 | 17 | private static void deleteFile(File file){ 18 | if (file.isDirectory()){ 19 | File[] files = file.listFiles(); 20 | for (File f: files) { 21 | deleteFile(f); 22 | } 23 | }else{ 24 | file.delete(); 25 | } 26 | } 27 | 28 | /** 29 | * 解压zip文件至dir目录 30 | * @param zip 31 | * @param dir 32 | */ 33 | public static void unZip(File zip, File dir) { 34 | try { 35 | deleteFile(dir); 36 | ZipFile zipFile = new ZipFile(zip); 37 | //zip文件中每一个条目 38 | Enumeration entries = zipFile.entries(); 39 | //遍历 40 | while (entries.hasMoreElements()) { 41 | ZipEntry zipEntry = entries.nextElement(); 42 | //zip中 文件/目录名 43 | String name = zipEntry.getName(); 44 | //原来的签名文件 不需要了 45 | if (name.equals("META-INF/CERT.RSA") || name.equals("META-INF/CERT.SF") || name 46 | .equals("META-INF/MANIFEST.MF")) { 47 | continue; 48 | } 49 | //空目录不管 50 | if (!zipEntry.isDirectory()) { 51 | File file = new File(dir, name); 52 | //创建目录 53 | if (!file.getParentFile().exists()) { 54 | file.getParentFile().mkdirs(); 55 | } 56 | //写文件 57 | FileOutputStream fos = new FileOutputStream(file); 58 | InputStream is = zipFile.getInputStream(zipEntry); 59 | byte[] buffer = new byte[2048]; 60 | int len; 61 | while ((len = is.read(buffer)) != -1) { 62 | fos.write(buffer, 0, len); 63 | } 64 | is.close(); 65 | fos.close(); 66 | } 67 | } 68 | zipFile.close(); 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | 74 | /** 75 | * 压缩目录为zip 76 | * @param dir 待压缩目录 77 | * @param zip 输出的zip文件 78 | * @throws Exception 79 | */ 80 | public static void zip(File dir, File zip) throws Exception { 81 | zip.delete(); 82 | // 对输出文件做CRC32校验 83 | CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream( 84 | zip), new CRC32()); 85 | ZipOutputStream zos = new ZipOutputStream(cos); 86 | //压缩 87 | compress(dir, zos, ""); 88 | zos.flush(); 89 | zos.close(); 90 | } 91 | 92 | /** 93 | * 添加目录/文件 至zip中 94 | * @param srcFile 需要添加的目录/文件 95 | * @param zos zip输出流 96 | * @param basePath 递归子目录时的完整目录 如 lib/x86 97 | * @throws Exception 98 | */ 99 | private static void compress(File srcFile, ZipOutputStream zos, 100 | String basePath) throws Exception { 101 | if (srcFile.isDirectory()) { 102 | File[] files = srcFile.listFiles(); 103 | for (File file : files) { 104 | // zip 递归添加目录中的文件 105 | compress(file, zos, basePath + srcFile.getName() + "/"); 106 | } 107 | } else { 108 | compressFile(srcFile, zos, basePath); 109 | } 110 | } 111 | 112 | private static void compressFile(File file, ZipOutputStream zos, String dir) 113 | throws Exception { 114 | // temp/lib/x86/libdn_ssl.so 115 | String fullName = dir + file.getName(); 116 | // 需要去掉temp 117 | String[] fileNames = fullName.split("/"); 118 | //正确的文件目录名 (去掉了temp) 119 | StringBuffer sb = new StringBuffer(); 120 | if (fileNames.length > 1){ 121 | for (int i = 1;i 2 | proxy_core 3 | 4 | -------------------------------------------------------------------------------- /proxy_core/src/test/java/cn/com/jni/proxy_core/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_core; 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 | } -------------------------------------------------------------------------------- /proxy_tools/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java-library' 2 | 3 | dependencies { 4 | implementation fileTree(dir: 'libs', include: ['*.jar']) 5 | } 6 | 7 | sourceCompatibility = "7" 8 | targetCompatibility = "7" 9 | -------------------------------------------------------------------------------- /proxy_tools/proxy1.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GreateLi/AndroidShell/d6b0296195198bd30e292841baa43cb52805ce03/proxy_tools/proxy1.jks -------------------------------------------------------------------------------- /proxy_tools/proxy_tools.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /proxy_tools/src/main/java/cn/com/jni/proxy_tools/AES.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_tools; 2 | 3 | 4 | import java.security.InvalidKeyException; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | import javax.crypto.BadPaddingException; 8 | import javax.crypto.Cipher; 9 | import javax.crypto.IllegalBlockSizeException; 10 | import javax.crypto.NoSuchPaddingException; 11 | import javax.crypto.spec.SecretKeySpec; 12 | 13 | 14 | public class AES { 15 | 16 | //16字节 17 | public static final String DEFAULT_PWD = "abcdefghijklmnop"; 18 | //填充方式 19 | private static final String algorithmStr = "AES/ECB/PKCS5Padding"; 20 | private static Cipher encryptCipher; 21 | private static Cipher decryptCipher; 22 | 23 | public static void init(String password) { 24 | try { 25 | // 生成一个实现指定转换的 Cipher 对象。 26 | encryptCipher = Cipher.getInstance(algorithmStr); 27 | decryptCipher = Cipher.getInstance(algorithmStr);// algorithmStr 28 | byte[] keyStr = password.getBytes(); 29 | SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); 30 | encryptCipher.init(Cipher.ENCRYPT_MODE, key); 31 | decryptCipher.init(Cipher.DECRYPT_MODE, key); 32 | } catch (NoSuchAlgorithmException e) { 33 | e.printStackTrace(); 34 | } catch (NoSuchPaddingException e) { 35 | e.printStackTrace(); 36 | } catch (InvalidKeyException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | public static byte[] encrypt(byte[] content) { 42 | try { 43 | byte[] result = encryptCipher.doFinal(content); 44 | return result; 45 | } catch (IllegalBlockSizeException e) { 46 | e.printStackTrace(); 47 | } catch (BadPaddingException e) { 48 | e.printStackTrace(); 49 | } 50 | return null; 51 | } 52 | 53 | public static byte[] decrypt(byte[] content) { 54 | try { 55 | byte[] result = decryptCipher.doFinal(content); 56 | return result; 57 | } catch (IllegalBlockSizeException e) { 58 | e.printStackTrace(); 59 | } catch (BadPaddingException e) { 60 | e.printStackTrace(); 61 | } 62 | return null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /proxy_tools/src/main/java/cn/com/jni/proxy_tools/Main.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_tools; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.FilenameFilter; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class Main { 9 | 10 | public static void main(String[] args) throws Exception{ 11 | 12 | /** 13 | * 1、制作只包含解密代码的dex文件 14 | */ 15 | File aarFile = new File("proxy_core/build/outputs/aar/proxy_core-debug.aar"); 16 | File aarTemp = new File("proxy_tools/temp"); 17 | Zip.unZip(aarFile,aarTemp); 18 | 19 | File classesDex = new File(aarTemp,"classes.dex"); 20 | File classesJar = new File(aarTemp,"classes.jar"); 21 | //dx --dex --output out.dex in.jar E:\AndroidSdk\Sdk\build-tools\23.0.3 22 | Process process = Runtime.getRuntime().exec("cmd /c dx --dex --output " + classesDex.getAbsolutePath() 23 | + " " + classesJar.getAbsolutePath()); 24 | process.waitFor(); 25 | if (process.exitValue() != 0){ 26 | throw new RuntimeException("dex error"); 27 | } 28 | process.destroy(); 29 | 30 | /** 31 | * 2、加密apk中所有的dex文件 32 | */ 33 | File apkFile = new File("app/build/outputs/apk/debug/app-debug.apk"); 34 | File apkTemp = new File("app/build/outputs/apk/debug/temp"); 35 | Zip.unZip(apkFile,apkTemp); 36 | //只要dex文件拿出来加密 37 | File[] dexFiles = apkTemp.listFiles(new FilenameFilter() { 38 | @Override 39 | public boolean accept(File file, String s) { 40 | return s.endsWith(".dex"); 41 | } 42 | }); 43 | //RC4Base 加密 44 | 45 | for (File dexFile:dexFiles) { 46 | byte[] bytes = Utils.getBytes(dexFile); 47 | // byte[] encrypt = AES.encrypt(bytes); 48 | byte[] encrypt =RC4.RC4Base(bytes,RC4.ACCESSKEY); 49 | FileOutputStream fos = new FileOutputStream(new File(apkTemp,"secret-" + dexFile.getName())); 50 | fos.write(encrypt); 51 | fos.flush(); 52 | fos.close(); 53 | dexFile.delete(); 54 | } 55 | /** 56 | * 3、把dex放入apk解压目录,重新压成apk文件 57 | */ 58 | classesDex.renameTo(new File(apkTemp,"classes.dex")); 59 | File unSignedApk = new File("app/build/outputs/apk/debug/app-unsigned.apk"); 60 | Zip.zip(apkTemp,unSignedApk); 61 | /** 62 | * 4、对其和签名,最后生成签名apk 63 | */ 64 | // zipalign -v -p 4 my-app-unsigned.apk my-app-unsigned-aligned.apk 65 | File alignedApk=new File("app/build/outputs/apk/debug/app-unsigned-aligned.apk"); 66 | Process processAlign = Runtime.getRuntime().exec("cmd /c zipalign -v -p 4 "+unSignedApk.getAbsolutePath() 67 | +" "+alignedApk.getAbsolutePath()); 68 | // System.out.println("signedApkprocess : 11111" + " :-----> " +unSignedApk.getAbsolutePath() + "\n" + alignedApk.getAbsolutePath()); 69 | 70 | processAlign.waitFor( 10,TimeUnit.SECONDS); 71 | // if(process.exitValue()!=0){ 72 | // throw new RuntimeException("dex error"); 73 | // } 74 | processAlign.destroy(); 75 | 76 | // apksigner sign --ks my-release-key.jks --out my-app-release.apk my-app-unsigned-aligned.apk 77 | // apksigner sign --ks jks文件地址 --ks-key-alias 别名 --ks-pass pass:jsk密码 --key-pass pass:别名密码 --out out.apk in.apk 78 | File signedApk=new File("app/build/outputs/apk/debug/app-signed-aligned.apk"); 79 | File jks=new File("proxy_tools/proxy1.jks"); 80 | Process processsign= Runtime.getRuntime().exec("cmd /c apksigner sign --ks "+jks.getAbsolutePath() 81 | +" --ks-key-alias wwy --ks-pass pass:123456 --key-pass pass:123456 --out " 82 | +signedApk.getAbsolutePath()+" "+alignedApk.getAbsolutePath()); 83 | processsign.waitFor(); 84 | if(processsign.exitValue()!=0){ 85 | throw new RuntimeException("dex error"); 86 | } 87 | processsign.destroy(); 88 | System.out.println("excute successful"); 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /proxy_tools/src/main/java/cn/com/jni/proxy_tools/RC4.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_tools; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | /** 6 | * 负责生成ACCESS_TOKEN||REFRESH_TOKEN令牌 7 | * 8 | * @author witts 9 | * @project core-utils 10 | * @package cc.zeelan.framework.dense 11 | * @version 1.0 12 | * @message 林花谢了春红,太匆匆。无奈朝来寒雨,晚来风 13 | */ 14 | public class RC4 { 15 | /** ACCESS_TOKEN的加密钥匙 **/ 16 | public static final String ACCESSKEY = "8rrh1086omGe8qF0"; 17 | /** REFRESH_TOKEN的加密钥匙 **/ 18 | public static final String REFRESHKEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxREFRESHKEY"; 19 | 20 | /** 加密 **/ 21 | public static String encrypt(String data, String key) { 22 | if (data == null || key == null) { 23 | return null; 24 | } 25 | return toHexString(asString(encrypt_byte(data, key))); 26 | } 27 | 28 | /** 解密 **/ 29 | public static String decrypt(String data, String key) { 30 | if (data == null || key == null) { 31 | return null; 32 | } 33 | return new String(RC4Base(HexString2Bytes(data), key)); 34 | } 35 | 36 | /** 加密字节码 **/ 37 | public static byte[] encrypt_byte(String data, String key) { 38 | if (data == null || key == null) { 39 | return null; 40 | } 41 | byte b_data[] = data.getBytes(); 42 | return RC4Base(b_data, key); 43 | } 44 | 45 | private static String asString(byte[] buf) { 46 | StringBuffer strbuf = new StringBuffer(buf.length); 47 | for (int i = 0; i < buf.length; i++) { 48 | strbuf.append((char) buf[i]); 49 | } 50 | return strbuf.toString(); 51 | } 52 | 53 | private static byte[] initKey(String aKey) { 54 | byte[] b_key = aKey.getBytes(); 55 | byte state[] = new byte[256]; 56 | 57 | for (int i = 0; i < 256; i++) { 58 | state[i] = (byte) i; 59 | } 60 | int index1 = 0; 61 | int index2 = 0; 62 | if (b_key == null || b_key.length == 0) { 63 | return null; 64 | } 65 | for (int i = 0; i < 256; i++) { 66 | index2 = ((b_key[index1] & 0xff) + (state[i] & 0xff) + index2) & 0xff; 67 | byte tmp = state[i]; 68 | state[i] = state[index2]; 69 | state[index2] = tmp; 70 | index1 = (index1 + 1) % b_key.length; 71 | } 72 | return state; 73 | } 74 | 75 | private static String toHexString(String s) { 76 | String str = ""; 77 | for (int i = 0; i < s.length(); i++) { 78 | int ch = (int) s.charAt(i); 79 | String s4 = Integer.toHexString(ch & 0xFF); 80 | if (s4.length() == 1) { 81 | s4 = '0' + s4; 82 | } 83 | str = str + s4; 84 | } 85 | return str;// 0x表示十六进制 86 | } 87 | 88 | private static byte[] HexString2Bytes(String src) { 89 | int size = src.length(); 90 | byte[] ret = new byte[size / 2]; 91 | byte[] tmp = src.getBytes(); 92 | for (int i = 0; i < size / 2; i++) { 93 | ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]); 94 | } 95 | return ret; 96 | } 97 | 98 | private static byte uniteBytes(byte src0, byte src1) { 99 | char _b0 = (char) Byte.decode("0x" + new String(new byte[] { src0 })).byteValue(); 100 | _b0 = (char) (_b0 << 4); 101 | char _b1 = (char) Byte.decode("0x" + new String(new byte[] { src1 })).byteValue(); 102 | byte ret = (byte) (_b0 ^ _b1); 103 | return ret; 104 | } 105 | 106 | public static byte[] RC4Base(byte[] input, String mKkey) { 107 | int x = 0; 108 | int y = 0; 109 | byte key[] = initKey(mKkey); 110 | int xorIndex; 111 | byte[] result = new byte[input.length]; 112 | 113 | for (int i = 0; i < input.length; i++) { 114 | x = (x + 1) & 0xff; 115 | y = ((key[x] & 0xff) + y) & 0xff; 116 | byte tmp = key[x]; 117 | key[x] = key[y]; 118 | key[y] = tmp; 119 | xorIndex = ((key[x] & 0xff) + (key[y] & 0xff)) & 0xff; 120 | result[i] = (byte) (input[i] ^ key[xorIndex]); 121 | } 122 | return result; 123 | } 124 | 125 | /** 126 | * 字符串转换成十六进制字符串 127 | */ 128 | public static String str2HexStr(String str) { 129 | char[] chars = "0123456789ABCDEF".toCharArray(); 130 | StringBuilder sb = new StringBuilder(""); 131 | byte[] bs = str.getBytes(); 132 | int bit; 133 | for (int i = 0; i < bs.length; i++) { 134 | bit = (bs[i] & 0x0f0) >> 4; 135 | sb.append(chars[bit]); 136 | bit = bs[i] & 0x0f; 137 | sb.append(chars[bit]); 138 | } 139 | return sb.toString(); 140 | } 141 | 142 | /** 143 | * 144 | * 十六进制转换字符串 145 | * 146 | * @throws UnsupportedEncodingException 147 | */ 148 | 149 | public static String hexStr2Str(String hexStr) { 150 | String str = "0123456789ABCDEF"; 151 | char[] hexs = hexStr.toCharArray(); 152 | byte[] bytes = new byte[hexStr.length() / 2]; 153 | int n; 154 | for (int i = 0; i < bytes.length; i++) { 155 | n = str.indexOf(hexs[2 * i]) * 16; 156 | n += str.indexOf(hexs[2 * i + 1]); 157 | bytes[i] = (byte) (n & 0xff); 158 | } 159 | return new String(bytes); 160 | } 161 | 162 | public static void main(String[] args) { 163 | String data="hello!myfirends"; 164 | System.out.println("加密结果 "+RC4.encrypt(data, ACCESSKEY)); 165 | System.out.println("解密结果 "+RC4.decrypt(RC4.encrypt(data, ACCESSKEY), ACCESSKEY)); 166 | } 167 | } -------------------------------------------------------------------------------- /proxy_tools/src/main/java/cn/com/jni/proxy_tools/Utils.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_tools; 2 | 3 | import java.io.File; 4 | import java.io.RandomAccessFile; 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.Method; 7 | import java.util.Arrays; 8 | 9 | 10 | public class Utils { 11 | 12 | /** 13 | * 读取文件 14 | * @param file 15 | * @return 16 | * @throws Exception 17 | */ 18 | public static byte[] getBytes(File file) throws Exception { 19 | RandomAccessFile r = new RandomAccessFile(file, "r"); 20 | byte[] buffer = new byte[(int) r.length()]; 21 | r.readFully(buffer); 22 | r.close(); 23 | return buffer; 24 | } 25 | 26 | /** 27 | * 反射获得 指定对象(当前-》父类-》父类...)中的 成员属性 28 | * @param instance 29 | * @param name 30 | * @return 31 | * @throws NoSuchFieldException 32 | */ 33 | public static Field findField(Object instance, String name) throws NoSuchFieldException { 34 | Class clazz = instance.getClass(); 35 | //反射获得 36 | while (clazz != null) { 37 | try { 38 | Field field = clazz.getDeclaredField(name); 39 | //如果无法访问 设置为可访问 40 | if (!field.isAccessible()) { 41 | field.setAccessible(true); 42 | } 43 | return field; 44 | } catch (NoSuchFieldException e) { 45 | //如果找不到往父类找 46 | clazz = clazz.getSuperclass(); 47 | } 48 | } 49 | throw new NoSuchFieldException("Field " + name + " not found in " + instance.getClass()); 50 | } 51 | 52 | 53 | /** 54 | * 反射获得 指定对象(当前-》父类-》父类...)中的 函数 55 | * @param instance 56 | * @param name 57 | * @param parameterTypes 58 | * @return 59 | * @throws NoSuchMethodException 60 | */ 61 | public static Method findMethod(Object instance, String name, Class... parameterTypes) 62 | throws NoSuchMethodException { 63 | Class clazz = instance.getClass(); 64 | while (clazz != null) { 65 | try { 66 | Method method = clazz.getDeclaredMethod(name, parameterTypes); 67 | if (!method.isAccessible()) { 68 | method.setAccessible(true); 69 | } 70 | return method; 71 | } catch (NoSuchMethodException e) { 72 | //如果找不到往父类找 73 | clazz = clazz.getSuperclass(); 74 | } 75 | } 76 | throw new NoSuchMethodException("Method " + name + " with parameters " + Arrays.asList 77 | (parameterTypes) + " not found in " + instance.getClass()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /proxy_tools/src/main/java/cn/com/jni/proxy_tools/Zip.java: -------------------------------------------------------------------------------- 1 | package cn.com.jni.proxy_tools; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.InputStream; 7 | import java.util.Enumeration; 8 | import java.util.zip.CRC32; 9 | import java.util.zip.CheckedOutputStream; 10 | import java.util.zip.ZipEntry; 11 | import java.util.zip.ZipFile; 12 | import java.util.zip.ZipOutputStream; 13 | 14 | 15 | public class Zip { 16 | 17 | private static void deleteFile(File file){ 18 | if (file.isDirectory()){ 19 | File[] files = file.listFiles(); 20 | for (File f: files) { 21 | deleteFile(f); 22 | } 23 | }else{ 24 | file.delete(); 25 | } 26 | } 27 | 28 | /** 29 | * 解压zip文件至dir目录 30 | * @param zip 31 | * @param dir 32 | */ 33 | public static void unZip(File zip, File dir) { 34 | try { 35 | deleteFile(dir); 36 | ZipFile zipFile = new ZipFile(zip); 37 | //zip文件中每一个条目 38 | Enumeration entries = zipFile.entries(); 39 | //遍历 40 | while (entries.hasMoreElements()) { 41 | ZipEntry zipEntry = entries.nextElement(); 42 | //zip中 文件/目录名 43 | String name = zipEntry.getName(); 44 | //原来的签名文件 不需要了 45 | if (name.equals("META-INF/CERT.RSA") || name.equals("META-INF/CERT.SF") || name 46 | .equals("META-INF/MANIFEST.MF")) { 47 | continue; 48 | } 49 | //空目录不管 50 | if (!zipEntry.isDirectory()) { 51 | File file = new File(dir, name); 52 | //创建目录 53 | if (!file.getParentFile().exists()) { 54 | file.getParentFile().mkdirs(); 55 | } 56 | //写文件 57 | FileOutputStream fos = new FileOutputStream(file); 58 | InputStream is = zipFile.getInputStream(zipEntry); 59 | byte[] buffer = new byte[2048]; 60 | int len; 61 | while ((len = is.read(buffer)) != -1) { 62 | fos.write(buffer, 0, len); 63 | } 64 | is.close(); 65 | fos.close(); 66 | } 67 | } 68 | zipFile.close(); 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | 74 | /** 75 | * 压缩目录为zip 76 | * @param dir 待压缩目录 77 | * @param zip 输出的zip文件 78 | * @throws Exception 79 | */ 80 | public static void zip(File dir, File zip) throws Exception { 81 | zip.delete(); 82 | // 对输出文件做CRC32校验 83 | CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream( 84 | zip), new CRC32()); 85 | ZipOutputStream zos = new ZipOutputStream(cos); 86 | //压缩 87 | compress(dir, zos, ""); 88 | zos.flush(); 89 | zos.close(); 90 | } 91 | 92 | /** 93 | * 添加目录/文件 至zip中 94 | * @param srcFile 需要添加的目录/文件 95 | * @param zos zip输出流 96 | * @param basePath 递归子目录时的完整目录 如 lib/x86 97 | * @throws Exception 98 | */ 99 | private static void compress(File srcFile, ZipOutputStream zos, 100 | String basePath) throws Exception { 101 | if (srcFile.isDirectory()) { 102 | File[] files = srcFile.listFiles(); 103 | for (File file : files) { 104 | // zip 递归添加目录中的文件 105 | compress(file, zos, basePath + srcFile.getName() + "/"); 106 | } 107 | } else { 108 | compressFile(srcFile, zos, basePath); 109 | } 110 | } 111 | 112 | private static void compressFile(File file, ZipOutputStream zos, String dir) 113 | throws Exception { 114 | // temp/lib/x86/libdn_ssl.so 115 | String fullName = dir + file.getName(); 116 | // 需要去掉temp 117 | String[] fileNames = fullName.split("/"); 118 | //正确的文件目录名 (去掉了temp) 119 | StringBuffer sb = new StringBuffer(); 120 | if (fileNames.length > 1){ 121 | for (int i = 1;i