├── .gitattributes ├── .gitignore ├── README.md ├── bin ├── apksecure.jar ├── apktool.jar ├── classes.dex ├── config.xml ├── msgnow-release.apk ├── mysignature.jks ├── readme.txt └── secure-lib │ ├── arm64-v8a │ └── libsecret.so │ ├── armeabi-v7a │ └── libsecret.so │ ├── armeabi │ └── libsecret.so │ ├── x86 │ └── libsecret.so │ └── x86_64 │ └── libsecret.so ├── dex └── apksecure │ ├── .gitignore │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── secure-jni │ ├── .gitignore │ ├── CMakeLists.txt │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── dev │ │ │ └── mars │ │ │ └── secure │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── dev │ │ │ │ └── mars │ │ │ │ └── secure │ │ │ │ ├── LogUtils.java │ │ │ │ ├── ProxyApplication.java │ │ │ │ └── ZipUtils.java │ │ ├── jni │ │ │ ├── CMakeLists.txt │ │ │ ├── logutils.h │ │ │ └── secret.cpp │ │ └── res │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── dev │ │ └── mars │ │ └── secure │ │ └── ExampleUnitTest.java │ ├── settings.gradle │ └── testapplication │ ├── .gitignore │ ├── build.gradle │ ├── multidex-config.txt │ ├── mysignature.jks │ ├── proguard-rules.pro │ └── src │ ├── androidTest │ └── java │ │ └── dev │ │ └── mars │ │ └── testapplication │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── dev │ │ │ └── mars │ │ │ └── testapplication │ │ │ ├── LogUtils.java │ │ │ ├── MainActivity.java │ │ │ ├── Methods.java │ │ │ ├── Methods2.java │ │ │ ├── MyApplication.java │ │ │ ├── MyBroadCastReceiver.java │ │ │ ├── MyContentProvider.java │ │ │ └── MyService.java │ ├── jni │ │ ├── CMakeLists.txt │ │ └── reflect.cpp │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── dev │ └── mars │ └── testapplication │ └── ExampleUnitTest.java └── java_tool └── ApkSecure ├── .classpath ├── .project ├── .settings ├── org.eclipse.core.resources.prefs └── org.eclipse.core.runtime.prefs ├── libs ├── dom4j-2.0.0-RC1-sources.jar ├── dom4j-2.0.0-RC1.jar └── zip4j_1.3.2.jar └── src └── dev └── mars └── apksecure ├── DESUtils.java ├── FileUtil.java ├── Main.java ├── SystemCommand.java ├── Zip4JUtil.java └── ZipUtil.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | bin/output 49 | java_tool/ApkSecure/bin 50 | dex/apksecure/build 51 | dex/apksecure/secure-jni/build 52 | dex/apksecure/secure-jni/.externalNativeBuild 53 | dex/apksecure/.idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 自研利用动态加载技术实现APK加壳,壳程序用JNI实现增加源码破解难度。 2 | 尚未解决动态加载dex在ART虚拟机下初次加载优化OAT的问题。 3 | 4 | * dex文件夹下是壳程序的源码 5 | * java_tool文件夹是对apk的java加固工具源码,通过命令行使用 6 | * bin 文件夹是编译好的工具 7 | -------------------------------------------------------------------------------- /bin/apksecure.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/apksecure.jar -------------------------------------------------------------------------------- /bin/apktool.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/apktool.jar -------------------------------------------------------------------------------- /bin/classes.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/classes.dex -------------------------------------------------------------------------------- /bin/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | mysignature.jks 4 | abcdefg 5 | abcdefg 6 | abcdefg 7 | -------------------------------------------------------------------------------- /bin/msgnow-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/msgnow-release.apk -------------------------------------------------------------------------------- /bin/mysignature.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/mysignature.jks -------------------------------------------------------------------------------- /bin/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/readme.txt -------------------------------------------------------------------------------- /bin/secure-lib/arm64-v8a/libsecret.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/secure-lib/arm64-v8a/libsecret.so -------------------------------------------------------------------------------- /bin/secure-lib/armeabi-v7a/libsecret.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/secure-lib/armeabi-v7a/libsecret.so -------------------------------------------------------------------------------- /bin/secure-lib/armeabi/libsecret.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/secure-lib/armeabi/libsecret.so -------------------------------------------------------------------------------- /bin/secure-lib/x86/libsecret.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/secure-lib/x86/libsecret.so -------------------------------------------------------------------------------- /bin/secure-lib/x86_64/libsecret.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/bin/secure-lib/x86_64/libsecret.so -------------------------------------------------------------------------------- /dex/apksecure/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /dex/apksecure/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.2' 9 | classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.3.0' 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /dex/apksecure/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /dex/apksecure/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/dex/apksecure/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /dex/apksecure/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /dex/apksecure/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /dex/apksecure/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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Sets the minimum version of CMake required to build the native 2 | # library. You should either keep the default value or only pass a 3 | # value of 3.4.0 or lower. 4 | 5 | cmake_minimum_required(VERSION 3.4.1) 6 | 7 | # Creates and names a library, sets it as either STATIC 8 | # or SHARED, and provides the relative paths to its source code. 9 | # You can define multiple libraries, and CMake builds it for you. 10 | # Gradle automatically packages shared libraries with your APK. 11 | 12 | add_library( # Sets the name of the library. 13 | native-lib 14 | 15 | # Sets the library as a shared library. 16 | SHARED 17 | 18 | # Provides a relative path to your source file(s). 19 | # Associated headers in the same location as their source 20 | # file are automatically included. 21 | src/main/cpp/native-lib.cpp ) 22 | 23 | # Searches for a specified prebuilt library and stores the path as a 24 | # variable. Because system libraries are included 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 the 38 | # build script, prebuilt third-party libraries, or system libraries. 39 | 40 | target_link_libraries( # Specifies the target library. 41 | native-lib 42 | 43 | # Links the target library to the log library 44 | # included in the NDK. 45 | ${log-lib} ) 46 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.getkeepsafe.dexcount' 3 | 4 | android { 5 | compileSdkVersion 24 6 | buildToolsVersion "25.0.2" 7 | defaultConfig { 8 | applicationId "dev.mars.secure" 9 | minSdkVersion 19 10 | targetSdkVersion 24 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | externalNativeBuild { 15 | cmake { 16 | cppFlags "" 17 | } 18 | } 19 | ndk { 20 | // Specifies the ABI configurations of your native 21 | // libraries Gradle should build and package with your APK. 22 | abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 23 | 'arm64-v8a' 24 | } 25 | } 26 | buildTypes { 27 | release { 28 | minifyEnabled true 29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 30 | } 31 | debug { 32 | jniDebuggable true 33 | } 34 | } 35 | externalNativeBuild { 36 | cmake { 37 | path './src/main/jni/CMakeLists.txt' 38 | } 39 | } 40 | } 41 | 42 | dependencies { 43 | compile fileTree(include: ['*.jar'], dir: 'libs') 44 | //compile 'com.android.support:appcompat-v7:24.2.1' 45 | } 46 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | #将异常发生的类名重命名为 EXCEPTIONCLASS 2 | -renamesourcefileattribute EXCEPTIONCLASS 3 | #保留行号 4 | -keepattributes SourceFile,LineNumberTable 5 | 6 | -keepnames class * implements java.io.Serializable 7 | -keepclassmembers class * implements java.io.Serializable { 8 | static final long serialVersionUID; 9 | private static final java.io.ObjectStreamField[] serialPersistentFields; 10 | !static !transient ; 11 | private void writeObject(java.io.ObjectOutputStream); 12 | private void readObject(java.io.ObjectInputStream); 13 | java.lang.Object writeReplace(); 14 | java.lang.Object readResolve(); 15 | } 16 | 17 | -keep public class * extends android.app.Service 18 | -keep public class * extends android.app.Application 19 | -keep public class * extends android.content.BroadcastReceiver 20 | 21 | -dontwarn android.support.v4.** 22 | -keep class android.support.v4.** { *; } 23 | -keep interface android.support.v4.** { *; } 24 | 25 | -dontwarn android.support.v7.** 26 | -keep class android.support.v7.** { *; } 27 | -keep interface android.support.v7.** { *; } 28 | 29 | -keep class dev.mars.secure.ZipUtils{*;} -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/androidTest/java/dev/mars/secure/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package dev.mars.secure; 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 | * Instrumentation 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() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("dev.mars.secure", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/java/dev/mars/secure/LogUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.secure; 2 | 3 | import android.util.Log; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * Created by ma.xuanwei on 2017/4/27. 9 | */ 10 | 11 | public class LogUtils { 12 | private static final boolean DEBUG = BuildConfig.DEBUG; 13 | private static final String TAG = "dev_mars"; 14 | public static void d(String str){ 15 | if(DEBUG){ 16 | Log.d(TAG,str); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/java/dev/mars/secure/ProxyApplication.java: -------------------------------------------------------------------------------- 1 | package dev.mars.secure; 2 | 3 | import android.app.Application; 4 | import android.content.ContentProvider; 5 | import android.content.Context; 6 | import android.content.pm.ApplicationInfo; 7 | import android.os.Build; 8 | import android.util.ArrayMap; 9 | import android.util.Log; 10 | 11 | import java.lang.ref.WeakReference; 12 | import java.util.HashMap; 13 | import java.util.Iterator; 14 | 15 | 16 | public class ProxyApplication extends Application { 17 | 18 | long time; 19 | 20 | static { 21 | System.loadLibrary("secret"); 22 | } 23 | 24 | @Override 25 | protected void attachBaseContext(Context base) { 26 | super.attachBaseContext(base); 27 | time = System.currentTimeMillis(); 28 | try { 29 | onAttachBaseContext(Build.VERSION.SDK_INT); 30 | } catch (Exception e) { 31 | LogUtils.d(e.getMessage()); 32 | e.printStackTrace(); 33 | } 34 | } 35 | 36 | @Override 37 | public void onCreate() {//得到ActivityThread对象 38 | onShellCreate(Build.VERSION.SDK_INT); 39 | Log.e("dev_mars","apk secure spend time "+(System.currentTimeMillis()-time)+" ms"); 40 | } 41 | 42 | private native void onAttachBaseContext(int sdkInt) throws Exception; 43 | 44 | private native void onShellCreate(int sdkInt); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/java/dev/mars/secure/ZipUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.secure; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.util.ArrayList; 11 | import java.util.Enumeration; 12 | import java.util.List; 13 | import java.util.zip.ZipEntry; 14 | import java.util.zip.ZipFile; 15 | import java.util.zip.ZipOutputStream; 16 | 17 | public class ZipUtils { 18 | 19 | private static byte[] _byte = new byte[1024] ; 20 | /** 21 | * 压缩文件或路径 22 | * @param zip 压缩的目的地址 23 | * @param srcFiles 压缩的源文件 24 | */ 25 | public static void zipFile( String zip , List srcFiles ){ 26 | try { 27 | if( zip.endsWith(".zip") || zip.endsWith(".ZIP") ){ 28 | ZipOutputStream _zipOut = new ZipOutputStream(new FileOutputStream(new File(zip))) ; 29 | for( File _f : srcFiles ){ 30 | handlerFile(zip , _zipOut , _f , ""); 31 | } 32 | _zipOut.close(); 33 | }else{ 34 | System.out.println("target file[" + zip + "] is not .zip type file"); 35 | } 36 | } catch (FileNotFoundException e) { 37 | } catch (IOException e) { 38 | } 39 | } 40 | 41 | /** 42 | * 43 | * @param zip 压缩的目的地址 44 | * @param zipOut 45 | * @param srcFile 被压缩的文件信息 46 | * @param path 在zip中的相对路径 47 | * @throws IOException 48 | */ 49 | private static void handlerFile(String zip , ZipOutputStream zipOut , File srcFile , String path ) throws IOException{ 50 | System.out.println(" begin to compression file[" + srcFile.getName() + "]"); 51 | if( !"".equals(path) && ! path.endsWith(File.separator)){ 52 | path += File.separator ; 53 | } 54 | if( ! srcFile.getPath().equals(zip) ){ 55 | if( srcFile.isDirectory() ){ 56 | File[] _files = srcFile.listFiles() ; 57 | if( _files.length == 0 ){ 58 | zipOut.putNextEntry(new ZipEntry( path + srcFile.getName() + File.separator)); 59 | zipOut.closeEntry(); 60 | }else{ 61 | for( File _f : _files ){ 62 | handlerFile( zip ,zipOut , _f , path + srcFile.getName() ); 63 | } 64 | } 65 | }else{ 66 | InputStream _in = new FileInputStream(srcFile) ; 67 | zipOut.putNextEntry(new ZipEntry(path + srcFile.getName())); 68 | int len = 0 ; 69 | while( (len = _in.read(_byte)) > 0 ){ 70 | zipOut.write(_byte, 0, len); 71 | } 72 | _in.close(); 73 | zipOut.closeEntry(); 74 | } 75 | } 76 | } 77 | 78 | /** 79 | * 解压缩ZIP文件,将ZIP文件里的内容解压到targetDIR目录下 80 | * @param zipPath 待解压缩的ZIP文件名 81 | * @param descDir 目标目录 82 | */ 83 | public static List unzipFile(String zipPath, String descDir) { 84 | return unzipFile( new File(zipPath) , descDir ) ; 85 | } 86 | 87 | /** 88 | * 对.zip文件进行解压缩 89 | * @param zipFile 解压缩文件 90 | * @param descDir 压缩的目标地址,如:D:\\测试 或 /mnt/d/测试 91 | * @return 92 | */ 93 | @SuppressWarnings("rawtypes") 94 | public static List unzipFile(File zipFile, String descDir) { 95 | List _list = new ArrayList() ; 96 | try { 97 | ZipFile _zipFile = new ZipFile(zipFile) ; 98 | for( Enumeration entries = _zipFile.entries() ; entries.hasMoreElements() ; ){ 99 | ZipEntry entry = (ZipEntry)entries.nextElement() ; 100 | File _file = new File(descDir + File.separator + entry.getName()) ; 101 | if( entry.isDirectory() ){ 102 | _file.mkdirs() ; 103 | }else{ 104 | File _parent = _file.getParentFile() ; 105 | if( !_parent.exists() ){ 106 | _parent.mkdirs() ; 107 | } 108 | InputStream _in = _zipFile.getInputStream(entry); 109 | OutputStream _out = new FileOutputStream(_file) ; 110 | int len = 0 ; 111 | while( (len = _in.read(_byte)) > 0){ 112 | _out.write(_byte, 0, len); 113 | } 114 | _in.close(); 115 | _out.flush(); 116 | _out.close(); 117 | _list.add(_file) ; 118 | } 119 | } 120 | } catch (IOException e) { 121 | } 122 | return _list ; 123 | } 124 | 125 | /** 126 | * 对临时生成的文件夹和文件夹下的文件进行删除 127 | */ 128 | public static void deletefile(String delpath) { 129 | try { 130 | File file = new File(delpath); 131 | if (!file.isDirectory()) { 132 | file.delete(); 133 | } else if (file.isDirectory()) { 134 | String[] filelist = file.list(); 135 | for (int i = 0; i < filelist.length; i++) { 136 | File delfile = new File(delpath + File.separator + filelist[i]); 137 | if (!delfile.isDirectory()) { 138 | delfile.delete(); 139 | } else if (delfile.isDirectory()) { 140 | deletefile(delpath + File.separator + filelist[i]); 141 | } 142 | } 143 | file.delete(); 144 | } 145 | } catch (Exception e) { 146 | e.printStackTrace(); 147 | } 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Sets the minimum version of CMake required to build the native 2 | # library. You should either keep the default value or only pass a 3 | # value of 3.4.0 or lower. 4 | 5 | cmake_minimum_required(VERSION 3.4.1) 6 | 7 | # Creates and names a library, sets it as either STATIC 8 | # or SHARED, and provides the relative paths to its source code. 9 | # You can define multiple libraries, and CMake builds it for you. 10 | # Gradle automatically packages shared libraries with your APK. 11 | 12 | add_library( # Sets the name of the library. 13 | secret 14 | 15 | # Sets the library as a shared library. 16 | SHARED 17 | 18 | # Provides a relative path to your source file(s). 19 | # Associated headers in the same location as their source 20 | # file are automatically included. 21 | secret.cpp logutils.h) 22 | 23 | # Searches for a specified prebuilt library and stores the path as a 24 | # variable. Because system libraries are included 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 the 38 | # build script, prebuilt third-party libraries, or system libraries. 39 | 40 | target_link_libraries( # Specifies the target library. 41 | secret 42 | 43 | # Links the target library to the log library 44 | # included in the NDK. 45 | ${log-lib} ) 46 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/jni/logutils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by ma.xuanwei on 2017/5/5. 3 | // 4 | #include 5 | 6 | #define LOG_TAG "dev_mars_native" 7 | #define LOGOPEN 1 //日志开关,1为开,其它为关 8 | #if(LOGOPEN==1) 9 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) 10 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 11 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 12 | #else 13 | #define LOGD(...) NULL 14 | #define LOGE(...) NULL 15 | #define LOGI(...) NULL 16 | #endif 17 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/jni/secret.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "logutils.h" 5 | 6 | const jbyte pwd[100]="laChineestunlionendormi"; 7 | const char* encryptedFileName = "apksecurefile"; 8 | 9 | 10 | 11 | extern "C" { 12 | void replaceDefaultClassLoader(JNIEnv *env, jobject instance, jstring dexFilePath,jint build_version); 13 | 14 | jobject NewFile(JNIEnv *env,jclass FileClass,jstring path) { 15 | jmethodID FileMethodId = env->GetMethodID(FileClass, "", "(Ljava/lang/String;)V"); 16 | return env->NewObject(FileClass, FileMethodId, path); 17 | } 18 | 19 | /** 20 | * 解密算法 21 | * sourceFilePath:加密的文件路径 22 | * destFilePath:解密后的文件路径 23 | */ 24 | void decrypt(JNIEnv* env,jstring sourceFilePath,jstring destFilePath){ 25 | jclass CipherClass = env->FindClass("javax/crypto/Cipher"); 26 | jmethodID getInstanceId = env->GetStaticMethodID(CipherClass,"getInstance","(Ljava/lang/String;)Ljavax/crypto/Cipher;"); 27 | jobject cipher = env->CallStaticObjectMethod(CipherClass,getInstanceId,env->NewStringUTF("DES")); 28 | 29 | jclass DESKeySpecClass = env->FindClass("javax/crypto/spec/DESKeySpec"); 30 | jmethodID initDESKeySpecId = env->GetMethodID(DESKeySpecClass,"","([B)V"); 31 | 32 | jbyteArray jPwd=env->NewByteArray(100); 33 | env->SetByteArrayRegion(jPwd,0,100,pwd); 34 | jobject desKeySpec = env->NewObject(DESKeySpecClass,initDESKeySpecId,jPwd); 35 | 36 | jclass SecretKeyFactoryClass = env->FindClass("javax/crypto/SecretKeyFactory"); 37 | jmethodID getSKFactoryInstanceId = env->GetStaticMethodID(SecretKeyFactoryClass,"getInstance","(Ljava/lang/String;)Ljavax/crypto/SecretKeyFactory;"); 38 | jobject secretKeyFactory = env->CallStaticObjectMethod(SecretKeyFactoryClass,getSKFactoryInstanceId,env->NewStringUTF("DES")); 39 | jmethodID generateSecretId = env->GetMethodID(SecretKeyFactoryClass,"generateSecret","(Ljava/security/spec/KeySpec;)Ljavax/crypto/SecretKey;"); 40 | jobject key = env->CallObjectMethod(secretKeyFactory,generateSecretId,desKeySpec); 41 | 42 | jmethodID initId = env->GetMethodID(CipherClass,"init","(ILjava/security/Key;)V"); 43 | env->CallVoidMethod(cipher,initId,2,key); 44 | 45 | jclass FileInputStreamClass = env->FindClass("java/io/FileInputStream"); 46 | jmethodID initFileInputStream = env->GetMethodID(FileInputStreamClass,"","(Ljava/lang/String;)V"); 47 | jobject fis = env->NewObject(FileInputStreamClass,initFileInputStream,sourceFilePath); 48 | 49 | jclass FileOutputStreamClass = env->FindClass("java/io/FileOutputStream"); 50 | jmethodID initFileOutputStream = env->GetMethodID(FileOutputStreamClass,"","(Ljava/lang/String;)V"); 51 | jobject fos = env->NewObject(FileOutputStreamClass,initFileOutputStream,destFilePath); 52 | 53 | jclass CipherOutputStreamClass = env->FindClass("javax/crypto/CipherOutputStream"); 54 | jmethodID initCipherOutputStream = env->GetMethodID(CipherOutputStreamClass,"","(Ljava/io/OutputStream;Ljavax/crypto/Cipher;)V"); 55 | jobject cos= env->NewObject(CipherOutputStreamClass,initCipherOutputStream,fos,cipher); 56 | 57 | jmethodID fisRead = env->GetMethodID(env->GetObjectClass(fis),"read","([B)I"); 58 | jmethodID cosWrite = env->GetMethodID(CipherOutputStreamClass,"write","([BII)V"); 59 | jmethodID cosFlush = env->GetMethodID(CipherOutputStreamClass,"flush","()V"); 60 | jmethodID fosClose = env->GetMethodID(FileOutputStreamClass,"close","()V"); 61 | jmethodID cosClose = env->GetMethodID(CipherOutputStreamClass,"close","()V"); 62 | jmethodID fisClose = env->GetMethodID(env->GetObjectClass(fis),"close","()V"); 63 | 64 | jbyteArray buffer = env->NewByteArray(1024); 65 | jint bufferSize = 0; 66 | while(bufferSize!=-1){ 67 | bufferSize = env->CallIntMethod(fis,fisRead,buffer); 68 | LOGE("读取 %d 个字节",bufferSize); 69 | if(bufferSize>0){ 70 | env->CallVoidMethod(cos,cosWrite,buffer,0,bufferSize); 71 | LOGE("解密 %d 个字节",bufferSize); 72 | } 73 | } 74 | 75 | env->CallVoidMethod(cos,cosFlush); 76 | env->CallVoidMethod(cos,cosClose); 77 | if(env->ExceptionCheck()){ 78 | env->ExceptionDescribe(); 79 | env->ExceptionClear(); 80 | env->ThrowNew(env->FindClass("java/lang/Exception"),"解密失败"); 81 | } 82 | env->CallVoidMethod(fos,fosClose); 83 | env->CallVoidMethod(fis,fisClose); 84 | } 85 | 86 | void unzipFile(JNIEnv *env, jstring zipPath, jstring folderPath) { 87 | jclass ZipUtilsClass = env->FindClass("dev/mars/secure/ZipUtils"); 88 | if(ZipUtilsClass==NULL){ 89 | LOGE("未找到ZipUtilsClass"); 90 | return; 91 | } 92 | jmethodID unzipFileId = env->GetStaticMethodID(ZipUtilsClass,"unzipFile","(Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); 93 | if(unzipFileId==NULL){ 94 | LOGE("未找到unzipFileId"); 95 | return ; 96 | } 97 | env->CallStaticObjectMethod(ZipUtilsClass,unzipFileId,zipPath,folderPath); 98 | } 99 | 100 | jboolean isFileExist(JNIEnv *env, jobject file) { 101 | jclass FileClass = env->GetObjectClass(file); 102 | jmethodID existsMethodId = env->GetMethodID(FileClass, "exists", "()Z"); 103 | return env->CallBooleanMethod(file, existsMethodId); 104 | } 105 | 106 | jstring getOriginDexPath(JNIEnv *env, jobject instance){ 107 | //得到Application的class 108 | jclass appClass = env->GetObjectClass(instance); 109 | //得到getDir方法 110 | jmethodID getDirMethodId = env->GetMethodID(appClass,"getDir","(Ljava/lang/String;I)Ljava/io/File;"); 111 | if(getDirMethodId==NULL){ 112 | LOGE("未找到getDir"); 113 | return NULL; 114 | } 115 | //得到dex的文件夹路径 116 | jstring dexFolderNameStr = env->NewStringUTF("mdex"); 117 | jint mode = 0; 118 | jobject dexFolderFile = env->CallObjectMethod(instance, getDirMethodId, dexFolderNameStr, mode); 119 | jclass FileClass = env->GetObjectClass(dexFolderFile); 120 | jmethodID getAbsolutePathMethodId = env->GetMethodID(FileClass,"getAbsolutePath","()Ljava/lang/String;"); 121 | if(getAbsolutePathMethodId==NULL){ 122 | LOGE("未找到getAbsolutePathMethodId"); 123 | return NULL; 124 | } 125 | 126 | jstring dexFolderPathJStr = (jstring) env->CallObjectMethod(dexFolderFile, getAbsolutePathMethodId); 127 | const char* dexFolderPath = env->GetStringUTFChars(dexFolderPathJStr,false); 128 | 129 | jmethodID listFileNames = env->GetMethodID(FileClass,"list","()[Ljava/lang/String;"); 130 | jmethodID endsWith = env->GetMethodID(env->GetObjectClass(dexFolderPathJStr),"endsWith","(Ljava/lang/String;)Z"); 131 | 132 | jstring dexFormat = env->NewStringUTF(".dex"); 133 | jobjectArray dexFileNames = (jobjectArray) env->CallObjectMethod(dexFolderFile, listFileNames); 134 | jint totalFiles = env->GetArrayLength(dexFileNames); 135 | std::string dexPaths=""; 136 | if(dexFileNames!=NULL&&totalFiles>0){ 137 | for(int i=0;i GetObjectArrayElement(dexFileNames, i); 139 | const char * fileName = env->GetStringUTFChars(fileNameJStr, false); 140 | LOGE("检测到文件 : %s",fileName); 141 | if(env->CallBooleanMethod(fileNameJStr,endsWith,dexFormat)){ 142 | dexPaths.append(dexFolderPath); 143 | dexPaths.append("/"); 144 | dexPaths.append(fileName); 145 | dexPaths.append(":"); 146 | } 147 | } 148 | LOGE("DEX路径 : %s",dexPaths.c_str()); 149 | if(dexPaths.length()>0) { 150 | return env->NewStringUTF(dexPaths.c_str()); 151 | } 152 | } 153 | LOGE("未找到原DEX,需要解压"); 154 | 155 | //从assets文件夹中找到abc.zip,并复制到dexFolderPath 156 | jmethodID getAssetsId = env->GetMethodID(appClass,"getAssets","()Landroid/content/res/AssetManager;"); 157 | if(getAssetsId==NULL){ 158 | LOGE("未找到getAssetsId"); 159 | return NULL; 160 | } 161 | jobject assetsManager = env->CallObjectMethod(instance,getAssetsId); 162 | jmethodID openId = env->GetMethodID(env->GetObjectClass(assetsManager),"open","(Ljava/lang/String;)Ljava/io/InputStream;"); 163 | if(openId==NULL){ 164 | LOGE("未找到openId"); 165 | return NULL; 166 | } 167 | jstring encryptedFileNameJStr = env->NewStringUTF(encryptedFileName); 168 | jobject is = env->CallObjectMethod(assetsManager,openId,encryptedFileNameJStr); 169 | if(env->ExceptionCheck()){ 170 | env->ExceptionDescribe(); 171 | env->ExceptionClear(); 172 | env->ThrowNew(env->FindClass("java/lang/Exception"),"未找到文件"); 173 | return NULL; 174 | } 175 | jclass FileOutputStreamClass = env->FindClass("java/io/FileOutputStream"); 176 | if(FileOutputStreamClass==NULL){ 177 | LOGE("未找到FileOutputSteamClass"); 178 | return NULL; 179 | } 180 | jmethodID initFileOutputStreamClass = env->GetMethodID(FileOutputStreamClass,"","(Ljava/lang/String;)V"); 181 | std::string encryptedFileCopyPath = env->GetStringUTFChars(dexFolderPathJStr, false); 182 | encryptedFileCopyPath.append(encryptedFileName); 183 | LOGE("加密文件复制后的路径:%s",encryptedFileCopyPath.c_str()); 184 | jstring encryptedFileCopyPathJStr =env->NewStringUTF(encryptedFileCopyPath.c_str()); 185 | jobject fos = env->NewObject(FileOutputStreamClass,initFileOutputStreamClass,encryptedFileCopyPathJStr); 186 | if(fos==NULL){ 187 | LOGE("创建fos失败"); 188 | } 189 | if(is!=NULL&&fos!=NULL){ 190 | LOGE("创建is fos成功"); 191 | } 192 | jmethodID readId = env->GetMethodID(env->GetObjectClass(is),"read","([B)I"); 193 | jmethodID writeId = env->GetMethodID(FileOutputStreamClass,"write","([BII)V"); 194 | jmethodID flushId = env->GetMethodID(FileOutputStreamClass,"flush","()V"); 195 | jmethodID fosCloseId = env->GetMethodID(FileOutputStreamClass,"close","()V"); 196 | jmethodID isCloseId = env->GetMethodID(env->GetObjectClass(is),"close","()V"); 197 | 198 | jbyteArray buffer = env->NewByteArray(1024); 199 | jint bufferSize = 0; 200 | while(bufferSize!=-1){ 201 | bufferSize = env->CallIntMethod(is,readId,buffer); 202 | //LOGE("读取 %d 个字节",bufferSize); 203 | if(bufferSize>0){ 204 | env->CallVoidMethod(fos,writeId,buffer,0,bufferSize); 205 | //LOGE("写出 %d 个字节",bufferSize); 206 | } 207 | } 208 | env->CallVoidMethod(fos,flushId); 209 | env->CallVoidMethod(is,isCloseId); 210 | env->CallVoidMethod(fos,fosCloseId); 211 | 212 | jobject encryptedFile = NewFile(env,FileClass,encryptedFileCopyPathJStr); 213 | if(isFileExist(env,encryptedFile)){ 214 | LOGE("成功复制文件:%s",encryptedFileCopyPath.c_str()); 215 | }else{ 216 | LOGE("未找到文件:%s",encryptedFileCopyPath.c_str()); 217 | } 218 | 219 | std::string zipFilePath = env->GetStringUTFChars(dexFolderPathJStr, false); 220 | zipFilePath.append("/abc.zip"); 221 | jstring zipFilePathJStr = env->NewStringUTF(zipFilePath.c_str()); 222 | 223 | decrypt(env,encryptedFileCopyPathJStr,zipFilePathJStr); 224 | 225 | jobject abcFile = NewFile(env,FileClass,zipFilePathJStr); 226 | if(isFileExist(env,abcFile)){ 227 | LOGE("成功解密文件:%s",zipFilePath.c_str()); 228 | }else{ 229 | LOGE("未找到文件:%s",zipFilePath.c_str()); 230 | } 231 | 232 | unzipFile(env,zipFilePathJStr,dexFolderPathJStr); 233 | 234 | jmethodID fileDelete = env->GetMethodID(FileClass,"delete","()Z"); 235 | jboolean r1 = env->CallBooleanMethod(abcFile, fileDelete); 236 | jboolean r2 = env->CallBooleanMethod(encryptedFile,fileDelete); 237 | if(r1&&r2) { 238 | LOGE("删除加密文件和压缩文件"); 239 | } 240 | dexPaths.clear(); 241 | dexFileNames = (jobjectArray) env->CallObjectMethod(dexFolderFile, listFileNames); 242 | totalFiles = env->GetArrayLength(dexFileNames); 243 | if(dexFileNames!=NULL&&totalFiles>0){ 244 | for(int i=0;i GetObjectArrayElement(dexFileNames, i); 246 | const char * fileName = env->GetStringUTFChars(fileNameJStr, false); 247 | LOGE("检测到文件 : %s",fileName); 248 | if(env->CallBooleanMethod(fileNameJStr,endsWith,dexFormat)){ 249 | dexPaths.append(dexFolderPath); 250 | dexPaths.append("/"); 251 | dexPaths.append(fileName); 252 | dexPaths.append(":"); 253 | } 254 | } 255 | LOGE("DEX路径 : %s",dexPaths.c_str()); 256 | if(dexPaths.length()>0) { 257 | return env->NewStringUTF(dexPaths.c_str()); 258 | } 259 | } 260 | return NULL; 261 | } 262 | 263 | JNIEXPORT void JNICALL 264 | Java_dev_mars_secure_ProxyApplication_onAttachBaseContext(JNIEnv *env, jobject instance,jint build_version) { 265 | //找到原classes.dex 266 | jstring dexFilePaths =getOriginDexPath(env,instance); 267 | if(dexFilePaths==NULL&&env->GetStringLength(dexFilePaths)<=0){ 268 | LOGE("未成功生成DEX"); 269 | return; 270 | } 271 | //到这一步为止,classes.dex已经成功从zip中解密并解压到 dexFilePath,下一步开始替换默认的PathClassLoader 272 | replaceDefaultClassLoader(env, instance,dexFilePaths,build_version); 273 | } 274 | 275 | 276 | void replaceDefaultClassLoader(JNIEnv *env, jobject instance, jstring dexFilePath,jint build_version) { 277 | //得到ActivityThread实例 278 | jclass ActivityThreadClass = env->FindClass("android/app/ActivityThread"); 279 | jmethodID currentActivityThread=env->GetStaticMethodID(ActivityThreadClass,"currentActivityThread","()Landroid/app/ActivityThread;"); 280 | jobject activityThread = env->CallStaticObjectMethod(ActivityThreadClass,currentActivityThread); 281 | 282 | jmethodID getPackageName = env->GetMethodID(env->GetObjectClass(instance),"getPackageName","()Ljava/lang/String;"); 283 | jstring packageName = (jstring) env->CallObjectMethod(instance, getPackageName); 284 | 285 | jfieldID mPackagesField; 286 | if(build_version<19){ 287 | mPackagesField = env->GetFieldID(ActivityThreadClass,"mPackages","Ljava/util/HashMap;"); 288 | }else{ 289 | mPackagesField = env->GetFieldID(ActivityThreadClass,"mPackages","Landroid/util/ArrayMap;"); 290 | } 291 | 292 | jobject mPackages = env->GetObjectField(activityThread,mPackagesField); 293 | 294 | jmethodID arrayMapGet = env->GetMethodID(env->GetObjectClass(mPackages),"get","(Ljava/lang/Object;)Ljava/lang/Object;"); 295 | jobject wr = env->CallObjectMethod(mPackages,arrayMapGet,packageName); 296 | 297 | jmethodID getDir = env->GetMethodID(env->GetObjectClass(instance),"getDir","(Ljava/lang/String;I)Ljava/io/File;"); 298 | jstring optimizedDirName = env->NewStringUTF("optimizedDirectory"); 299 | jobject optimizedDirFolder = env->CallObjectMethod(instance,getDir,optimizedDirName,0); 300 | jmethodID getAbsolutePath = env->GetMethodID(env->GetObjectClass(optimizedDirFolder),"getAbsolutePath","()Ljava/lang/String;"); 301 | jstring optimizedDirFolderPath = (jstring) env->CallObjectMethod(optimizedDirFolder, getAbsolutePath); 302 | 303 | jmethodID getApplicationInfo = env->GetMethodID(env->GetObjectClass(instance),"getApplicationInfo","()Landroid/content/pm/ApplicationInfo;"); 304 | jobject appInfo = env->CallObjectMethod(instance,getApplicationInfo); 305 | jfieldID nativeLibraryDirField= env->GetFieldID(env->GetObjectClass(appInfo),"nativeLibraryDir","Ljava/lang/String;"); 306 | jstring nativeLibraryDir = (jstring) env->GetObjectField(appInfo, nativeLibraryDirField); 307 | 308 | jmethodID weakReferenceGet = env->GetMethodID(env->GetObjectClass(wr),"get","()Ljava/lang/Object;"); 309 | jobject loadedApk = env->CallObjectMethod(wr,weakReferenceGet); 310 | jfieldID mClassLoaderField = env->GetFieldID(env->GetObjectClass(loadedApk),"mClassLoader","Ljava/lang/ClassLoader;"); 311 | jobject mClassLoader = env->GetObjectField(loadedApk,mClassLoaderField); 312 | 313 | //分割dexFilePath 314 | jmethodID split=env->GetMethodID(env->GetObjectClass(dexFilePath),"split","(Ljava/lang/String;)[Ljava/lang/String;"); 315 | //jobjectArray paths = (jobjectArray) env->CallObjectMethod(dexFilePath, split, env->NewStringUTF(":")); 316 | 317 | jclass DexClassLoaderClass = env->FindClass("dalvik/system/DexClassLoader"); 318 | jmethodID initDexClassLoader = env->GetMethodID(DexClassLoaderClass,"","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V"); 319 | LOGE("开始加载DEX %s",env->GetStringUTFChars(dexFilePath,false)); 320 | 321 | //默认用以:分割的路径加载,如果加载的dex很大,在Android5.0以上很耗时 322 | jobject dexClassLoader= env->NewObject(DexClassLoaderClass,initDexClassLoader,dexFilePath,optimizedDirFolderPath,nativeLibraryDir,mClassLoader); 323 | 324 | //将DEX依次加载 325 | /* 326 | jobject dexClassLoader = mClassLoader; 327 | int totalPath = env->GetArrayLength(paths); 328 | if(paths!=NULL&&totalPath>0){ 329 | for(int i=0;i GetObjectArrayElement(paths, i); 331 | const char * fileName = env->GetStringUTFChars(fileNameJStr, false); 332 | LOGE("加载第%d个DEX : %s",i,fileName); 333 | dexClassLoader = env->NewObject(DexClassLoaderClass,initDexClassLoader,fileNameJStr,optimizedDirFolderPath,nativeLibraryDir,dexClassLoader); 334 | } 335 | } 336 | */ 337 | LOGE("所有DEX加载完毕"); 338 | 339 | env->SetObjectField(loadedApk,mClassLoaderField,dexClassLoader); 340 | 341 | LOGE("已用新的DexClassLoader替换默认的PathClassLoader"); 342 | } 343 | 344 | 345 | 346 | JNIEXPORT void JNICALL 347 | Java_dev_mars_secure_ProxyApplication_onShellCreate(JNIEnv *env, jobject instance,jint build_version) { 348 | //首先得到原Application的类名 349 | jclass ProxyApplicationClass = env->GetObjectClass(instance); 350 | jmethodID getPackageManager = env->GetMethodID(ProxyApplicationClass,"getPackageManager","()Landroid/content/pm/PackageManager;"); 351 | jobject packageManager = env->CallObjectMethod(instance,getPackageManager); 352 | jmethodID pmGetApplicationInfo = env->GetMethodID(env->GetObjectClass(packageManager),"getApplicationInfo","(Ljava/lang/String;I)Landroid/content/pm/ApplicationInfo;"); 353 | jmethodID getPackageName = env->GetMethodID(ProxyApplicationClass,"getPackageName","()Ljava/lang/String;"); 354 | jobject pmAppInfo = env->CallObjectMethod(packageManager,pmGetApplicationInfo,env->CallObjectMethod(instance,getPackageName),128); 355 | 356 | jclass PackageItemInfoClass = env->FindClass("android/content/pm/PackageItemInfo"); 357 | jfieldID metaDataField = env->GetFieldID(PackageItemInfoClass,"metaData","Landroid/os/Bundle;"); 358 | jobject metaData = env->GetObjectField(pmAppInfo,metaDataField); 359 | if(metaData==NULL){ 360 | LOGE("未找到Bundle"); 361 | return; 362 | } 363 | jmethodID bundleGetString = env->GetMethodID(env->GetObjectClass(metaData),"getString","(Ljava/lang/String;)Ljava/lang/String;"); 364 | jstring originApplicationName = (jstring) env->CallObjectMethod(metaData, bundleGetString, env->NewStringUTF("APP_NAME")); 365 | if(originApplicationName==NULL){ 366 | LOGE("未找到原始Application Name"); 367 | return; 368 | } 369 | LOGE("原始Application Name : %s",env->GetStringUTFChars(originApplicationName,false)); 370 | //至此以得到原Application的类名 371 | 372 | //将LoadedApk中的mApplication对象替换 373 | jclass ActivityThreadClass = env->FindClass("android/app/ActivityThread"); 374 | jmethodID currentActivityThread=env->GetStaticMethodID(ActivityThreadClass,"currentActivityThread","()Landroid/app/ActivityThread;"); 375 | jobject activityThread = env->CallStaticObjectMethod(ActivityThreadClass,currentActivityThread); 376 | LOGE("得到 ActivityThreadClass"); 377 | //得到AppBindData 378 | jfieldID mBoundApplicationField = env->GetFieldID(ActivityThreadClass,"mBoundApplication","Landroid/app/ActivityThread$AppBindData;"); 379 | jobject mBoundApplication = env->GetObjectField(activityThread,mBoundApplicationField); 380 | LOGE("得到 AppBindData"); 381 | //得到LoadedApk 382 | jfieldID infoField = env->GetFieldID(env->GetObjectClass(mBoundApplication),"info","Landroid/app/LoadedApk;"); 383 | jobject info = env->GetObjectField(mBoundApplication,infoField); 384 | LOGE("得到 LoadedApk"); 385 | //把LoadedApk中的成员变量private Application mApplication;置空 386 | jfieldID mApplicationField = env->GetFieldID(env->GetObjectClass(info),"mApplication","Landroid/app/Application;"); 387 | env->SetObjectField(info,mApplicationField,NULL); 388 | LOGE("mApplication;置空"); 389 | //得到壳Application 390 | jfieldID mInitialApplicationField = env->GetFieldID(ActivityThreadClass,"mInitialApplication","Landroid/app/Application;"); 391 | jobject mInitialApplication = env->GetObjectField(activityThread,mInitialApplicationField); 392 | LOGE("得到壳Application"); 393 | 394 | 395 | //将壳Application移除 396 | jfieldID mAllApplicationsField = env->GetFieldID(ActivityThreadClass,"mAllApplications","Ljava/util/ArrayList;"); 397 | jobject mAllApplications = env->GetObjectField(activityThread,mAllApplicationsField); 398 | jmethodID remove = env->GetMethodID(env->GetObjectClass(mAllApplications),"remove","(Ljava/lang/Object;)Z"); 399 | env->CallBooleanMethod(mAllApplications,remove,mInitialApplication); 400 | LOGE("将壳Application移除"); 401 | //得到AppBindData中的ApplicationInfo 402 | jfieldID appInfoField = env->GetFieldID(env->GetObjectClass(mBoundApplication),"appInfo","Landroid/content/pm/ApplicationInfo;"); 403 | jobject appInfo = env->GetObjectField(mBoundApplication,appInfoField); 404 | LOGE("得到AppBindData中的ApplicationInfo"); 405 | //得到LoadedApk中的ApplicationInfo 406 | jfieldID mApplicationInfoField = env->GetFieldID(env->GetObjectClass(info),"mApplicationInfo","Landroid/content/pm/ApplicationInfo;"); 407 | jobject mApplicationInfo = env->GetObjectField(info,mApplicationInfoField); 408 | LOGE("得到LoadedApk中的ApplicationInfo"); 409 | //替换掉ApplicationInfo中的className 410 | jfieldID classNameField = env->GetFieldID(env->GetObjectClass(appInfo),"className","Ljava/lang/String;"); 411 | env->SetObjectField(appInfo,classNameField,originApplicationName); 412 | env->SetObjectField(mApplicationInfo,classNameField,originApplicationName); 413 | LOGE("替换掉ApplicationInfo中的className"); 414 | //创建新的Application 415 | jmethodID makeApplication = env->GetMethodID(env->GetObjectClass(info),"makeApplication","(ZLandroid/app/Instrumentation;)Landroid/app/Application;"); 416 | jobject originApp = env->CallObjectMethod(info,makeApplication,false,NULL); 417 | LOGE("创建新的Application"); 418 | //将句柄赋值到mInitialApplicationField 419 | env->SetObjectField(activityThread,mInitialApplicationField,originApp); 420 | LOGE("将句柄赋值到mInitialApplicationField"); 421 | jfieldID mProviderMapField; 422 | if(build_version<19){ 423 | mProviderMapField = env->GetFieldID(ActivityThreadClass,"mProviderMap","Ljava/util/HashMap;"); 424 | }else{ 425 | mProviderMapField = env->GetFieldID(ActivityThreadClass,"mProviderMap","Landroid/util/ArrayMap;"); 426 | } 427 | if(mProviderMapField==NULL){ 428 | LOGE("未找到mProviderMapField"); 429 | return; 430 | } 431 | LOGE("找到mProviderMapField"); 432 | jobject mProviderMap = env->GetObjectField(activityThread,mProviderMapField); 433 | LOGE("得到mProviderMap"); 434 | jmethodID values = env->GetMethodID(env->GetObjectClass(mProviderMap),"values","()Ljava/util/Collection;"); 435 | jobject collections = env->CallObjectMethod(mProviderMap,values); 436 | jmethodID iterator = env->GetMethodID(env->GetObjectClass(collections),"iterator","()Ljava/util/Iterator;"); 437 | jobject mIterator = env->CallObjectMethod(collections,iterator); 438 | jmethodID hasNext = env->GetMethodID(env->GetObjectClass(mIterator),"hasNext","()Z"); 439 | jmethodID next = env->GetMethodID(env->GetObjectClass(mIterator),"next","()Ljava/lang/Object;"); 440 | 441 | //替换所有ContentProvider中的Context 442 | LOGE("准备替换所有ContentProvider中的Context"); 443 | while(env->CallBooleanMethod(mIterator,hasNext)){ 444 | jobject providerClientRecord = env->CallObjectMethod(mIterator,next); 445 | if(providerClientRecord==NULL){ 446 | LOGE("providerClientRecord = NULL"); 447 | continue; 448 | } 449 | jclass ProviderClientRecordClass = env->FindClass("android/app/ActivityThread$ProviderClientRecord"); 450 | jfieldID mLocalProviderField = env->GetFieldID(ProviderClientRecordClass,"mLocalProvider","Landroid/content/ContentProvider;"); 451 | if(mLocalProviderField==NULL){ 452 | LOGE("mLocalProviderField not found"); 453 | continue; 454 | } 455 | jobject mLocalProvider = env->GetObjectField(providerClientRecord,mLocalProviderField); 456 | if(mLocalProvider==NULL){ 457 | LOGE("mLocalProvider is NULL"); 458 | continue; 459 | } 460 | jfieldID mContextField = env->GetFieldID(env->GetObjectClass(mLocalProvider),"mContext","Landroid/content/Context;"); 461 | if(mContextField==NULL){ 462 | LOGE("mContextField not found"); 463 | continue; 464 | } 465 | env->SetObjectField(mLocalProvider,mContextField,originApp); 466 | } 467 | 468 | //执行originApp的onCreate 469 | LOGE("已完成脱壳"); 470 | jmethodID onCreate = env->GetMethodID(env->GetObjectClass(originApp),"onCreate","()V"); 471 | env->CallVoidMethod(originApp,onCreate); 472 | LOGE("壳Application执行完毕"); 473 | } 474 | 475 | } 476 | 477 | 478 | 479 | 480 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/dex/apksecure/secure-jni/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | secure 3 | 4 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /dex/apksecure/secure-jni/src/test/java/dev/mars/secure/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package dev.mars.secure; 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() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /dex/apksecure/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':secure-jni', ':testapplication' 2 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.getkeepsafe.dexcount' 3 | 4 | android { 5 | signingConfigs { 6 | release { 7 | keyAlias 'abcdefg' 8 | keyPassword 'abcdefg' 9 | storeFile file('./mysignature.jks') 10 | storePassword 'abcdefg' 11 | } 12 | } 13 | productFlavors { 14 | dev { 15 | // Enable pre-dexing to produce an APK that can be tested on 16 | // Android 5.0+ without the time-consuming DEX build processes. 17 | minSdkVersion 21 18 | } 19 | prod { 20 | // The actual minSdkVersion for the production version. 21 | minSdkVersion 14 22 | } 23 | } 24 | compileSdkVersion 24 25 | buildToolsVersion "25.0.2" 26 | defaultConfig { 27 | applicationId "dev.mars.testapplication" 28 | minSdkVersion 14 29 | targetSdkVersion 24 30 | versionCode 1 31 | versionName "1.0" 32 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 33 | // Enabling multidex support. 34 | multiDexEnabled true 35 | 36 | ndk { 37 | // Specifies the ABI configurations of your native 38 | // libraries Gradle should build and package with your APK. 39 | abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 40 | 'arm64-v8a' 41 | } 42 | } 43 | buildTypes { 44 | release { 45 | multiDexKeepFile file ('./multidex-config.txt') 46 | //为了测试多个dex,关闭proguard优化 47 | minifyEnabled false 48 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 49 | debuggable false 50 | jniDebuggable false 51 | signingConfig signingConfigs.release 52 | renderscriptDebuggable false 53 | zipAlignEnabled true 54 | shrinkResources true 55 | } 56 | debug { 57 | 58 | multiDexKeepFile file ('./multidex-config.txt') 59 | /* 60 | 如果代码压缩在您增量构建应用时非常重要,请尝试适用于 Gradle 的 Android 插件内置的试用代码压缩器。与 ProGuard 不同,此压缩器支持 Instant Run。 61 | 您也可以使用与 ProGuard 相同的配置文件来配置 Android 插件压缩器。但是,Android 插件压缩器不会对您的代码进行混淆处理或优化,它只会删除未使用的代码。因此,您应该仅将其用于调试构建,并为发布构建启用 ProGuard,以便对发布 APK 的代码进行混淆处理和优化。 62 | 要启用 Android 插件压缩器,只需在 "debug" 构建类型中将 useProguard 设置为 false(并保留 minifyEnabled 设置 true): 63 | */ 64 | minifyEnabled false 65 | jniDebuggable true 66 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 67 | 'proguard-rules.pro' 68 | } 69 | } 70 | externalNativeBuild { 71 | cmake { 72 | path './src/main/jni/CMakeLists.txt' 73 | } 74 | } 75 | } 76 | 77 | 78 | 79 | dependencies { 80 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 81 | exclude group: 'com.android.support', module: 'support-annotations' 82 | }) 83 | compile 'com.android.support:appcompat-v7:24.2.1' 84 | //compile 'com.android.support:multidex:1.0.1' 85 | } 86 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/multidex-config.txt: -------------------------------------------------------------------------------- 1 | dev/mars/testapplication/Methods2.class -------------------------------------------------------------------------------- /dex/apksecure/testapplication/mysignature.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/ApkSecure/2174c3d60d83ba8f10c630f97f873df25df5ab91/dex/apksecure/testapplication/mysignature.jks -------------------------------------------------------------------------------- /dex/apksecure/testapplication/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | #将异常发生的类名重命名为 EXCEPTIONCLASS 2 | -renamesourcefileattribute EXCEPTIONCLASS 3 | #保留行号 4 | -keepattributes SourceFile,LineNumberTable 5 | 6 | -keepnames class * implements java.io.Serializable 7 | -keepclassmembers class * implements java.io.Serializable { 8 | static final long serialVersionUID; 9 | private static final java.io.ObjectStreamField[] serialPersistentFields; 10 | !static !transient ; 11 | private void writeObject(java.io.ObjectOutputStream); 12 | private void readObject(java.io.ObjectInputStream); 13 | java.lang.Object writeReplace(); 14 | java.lang.Object readResolve(); 15 | } 16 | 17 | -keep public class * extends android.app.Service 18 | -keep public class * extends android.app.Application 19 | -keep public class * extends android.content.BroadcastReceiver 20 | 21 | -dontwarn android.support.v4.** 22 | -keep class android.support.v4.** { *; } 23 | -keep interface android.support.v4.** { *; } 24 | 25 | -dontwarn android.support.v7.** 26 | -keep class android.support.v7.** { *; } 27 | -keep interface android.support.v7.** { *; } -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/androidTest/java/dev/mars/testapplication/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package dev.mars.testapplication; 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 | * Instrumentation 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() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("dev.mars.testapplication", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/java/dev/mars/testapplication/LogUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.testapplication; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by ma.xuanwei on 2017/5/11. 7 | */ 8 | 9 | public class LogUtils { 10 | private static final String TAG="dev_mars"; 11 | public static void d(String str){ 12 | Log.d(TAG,str); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/java/dev/mars/testapplication/MainActivity.java: -------------------------------------------------------------------------------- 1 | package dev.mars.testapplication; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.ContentValues; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Build; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.os.Bundle; 10 | import android.util.ArrayMap; 11 | import android.util.Log; 12 | import android.view.View; 13 | 14 | import java.lang.ref.WeakReference; 15 | import java.lang.reflect.Field; 16 | import java.lang.reflect.InvocationTargetException; 17 | import java.lang.reflect.Method; 18 | import java.net.URI; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import java.util.Objects; 22 | import java.util.Set; 23 | 24 | public class MainActivity extends AppCompatActivity { 25 | Methods2 methods2 =new Methods2(); 26 | WeakReference testWr; 27 | Object abc =null; 28 | 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | methods2.l(); 34 | setContentView(R.layout.activity_main); 35 | LogUtils.d("MainActivity onCreate"); 36 | ((MyApplication)getApplication()).test(this.getClass().getName()); 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | } 47 | 48 | 49 | /** 50 | * @deprecated 无效的,请使用DDMS的Gause gc 51 | * @param view 52 | */ 53 | public void onGc(View view) { 54 | LogUtils.d("开始GC"); 55 | System.gc(); 56 | LogUtils.d("GC完毕"); 57 | } 58 | 59 | public void showLoadedApk(View view) { 60 | try { 61 | Class ActivityThreadClass = Class.forName("android.app.ActivityThread"); 62 | Method currentActivityThread=ActivityThreadClass.getDeclaredMethod("currentActivityThread"); 63 | Object activityThread = currentActivityThread.invoke(null); 64 | Field mPackagesField = ActivityThreadClass.getDeclaredField("mPackages"); 65 | mPackagesField.setAccessible(true); 66 | Map mPackages; 67 | if(Build.VERSION.SDK_INT> Build.VERSION_CODES.KITKAT){ 68 | mPackages = (ArrayMap) mPackagesField.get(activityThread); 69 | }else{ 70 | mPackages = (HashMap) mPackagesField.get(activityThread); 71 | } 72 | Set keys = mPackages.keySet(); 73 | for(String k : keys){ 74 | LogUtils.d("key : "+k); 75 | } 76 | 77 | LogUtils.d("current package name : "+getPackageName()); 78 | WeakReference wr = mPackages.get(getPackageName()); 79 | if(wr==null){ 80 | LogUtils.d("WeakReference is null"); 81 | }else{ 82 | Object loadedApk = wr.get(); 83 | if(loadedApk!=null){ 84 | LogUtils.d("loadedApk is not null"); 85 | }else{ 86 | LogUtils.d("loadedApk is null"); 87 | } 88 | } 89 | } catch (ClassNotFoundException e) { 90 | e.printStackTrace(); 91 | } catch (NoSuchMethodException e) { 92 | e.printStackTrace(); 93 | } catch (InvocationTargetException e) { 94 | e.printStackTrace(); 95 | } catch (IllegalAccessException e) { 96 | e.printStackTrace(); 97 | } catch (NoSuchFieldException e) { 98 | e.printStackTrace(); 99 | } 100 | } 101 | 102 | public void generateNewWeakReference(View view) { 103 | if(abc==null){ 104 | abc=new Object(); 105 | } 106 | testWr = new WeakReference(abc); 107 | } 108 | 109 | public void showWeakReference(View view) { 110 | if(testWr==null){ 111 | LogUtils.d("wr is null"); 112 | }else{ 113 | Object obj = testWr.get(); 114 | if(obj==null){ 115 | LogUtils.d("obj = null"); 116 | }else{ 117 | LogUtils.d("obj is "+obj.toString()); 118 | } 119 | } 120 | } 121 | 122 | public void removeStrongReference(View view) { 123 | abc=null; 124 | } 125 | 126 | public void useContentProvider(View view) { 127 | ContentValues cv = new ContentValues(); 128 | cv.put("aa","bb"); 129 | ContentResolver cr = getContentResolver(); 130 | String authority = "content://dev.mars"; 131 | Uri uri = Uri.parse(authority); 132 | cr.insert(uri,cv); 133 | } 134 | 135 | public void useService(View view) { 136 | Intent intent = new Intent(MainActivity.this,MyService.class); 137 | startService(intent); 138 | } 139 | 140 | public void sendBroadCast(View view) { 141 | Intent broadcastIntent = new Intent("dev_mars_broadcast_test"); 142 | sendBroadcast(broadcastIntent); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/java/dev/mars/testapplication/MyApplication.java: -------------------------------------------------------------------------------- 1 | package dev.mars.testapplication; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.support.multidex.MultiDex; 6 | 7 | import java.io.OutputStream; 8 | import java.io.PrintWriter; 9 | import java.lang.reflect.InvocationTargetException; 10 | import java.lang.reflect.Method; 11 | 12 | 13 | /** 14 | * Created by ma.xuanwei on 2017/5/11. 15 | */ 16 | 17 | public class MyApplication extends Application { 18 | //public static Methods methods = new Methods(); 19 | // public static Methods2 methods2=new Methods2(); 20 | static { 21 | System.loadLibrary("reflect"); 22 | test(); 23 | } 24 | 25 | private static native void test(); 26 | 27 | /*static { 28 | try { 29 | Class methods2Class = Class.forName("dev.mars.testapplication.Methods2"); 30 | Method l = methods2Class.getDeclaredMethod("l"); 31 | l.invoke(methods2Class.newInstance()); 32 | } catch (Exception e){ 33 | e.printStackTrace(); 34 | } 35 | }*/ 36 | 37 | 38 | @Override 39 | protected void attachBaseContext(Context base) { 40 | super.attachBaseContext(base); 41 | LogUtils.d(getClass().getCanonicalName()+" attachBaseContext"); 42 | // methods2.l(); 43 | MultiDex.install(this); 44 | } 45 | 46 | @Override 47 | public void onCreate() { 48 | super.onCreate(); 49 | LogUtils.d(this.getClass().getName()+" onCreate"); 50 | instance = this; 51 | } 52 | 53 | private static MyApplication instance; 54 | 55 | public static MyApplication getInstance(){ 56 | return instance; 57 | } 58 | 59 | public static void exit(){ 60 | instance=null; 61 | } 62 | 63 | private static final String TEST_WORD = "A field from "+MyApplication.class.getName(); 64 | 65 | public void test(String str){ 66 | LogUtils.d(str+" : "+TEST_WORD); 67 | } 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/java/dev/mars/testapplication/MyBroadCastReceiver.java: -------------------------------------------------------------------------------- 1 | package dev.mars.testapplication; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Handler; 7 | 8 | /** 9 | * Created by ma.xuanwei on 2017/5/11. 10 | */ 11 | 12 | public class MyBroadCastReceiver extends BroadcastReceiver{ 13 | 14 | /** 15 | * This method is called when the BroadcastReceiver is receiving an Intent 16 | * broadcast. During this time you can use the other methods on 17 | * BroadcastReceiver to view/modify the current result values. This method 18 | * is always called within the main thread of its process, unless you 19 | * explicitly asked for it to be scheduled on a different thread using 20 | * {@link Context#registerReceiver(BroadcastReceiver, 21 | * IntentFilter, String, Handler)}. When it runs on the main 22 | * thread you should 23 | * never perform long-running operations in it (there is a timeout of 24 | * 10 seconds that the system allows before considering the receiver to 25 | * be blocked and a candidate to be killed). You cannot launch a popup dialog 26 | * in your implementation of onReceive(). 27 | *

28 | *

If this BroadcastReceiver was launched through a <receiver> tag, 29 | * then the object is no longer alive after returning from this 30 | * function. This means you should not perform any operations that 31 | * return a result to you asynchronously -- in particular, for interacting 32 | * with services, you should use 33 | * {@link Context#startService(Intent)} instead of 34 | * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish 35 | * to interact with a service that is already running, you can use 36 | * {@link #peekService}. 37 | *

38 | *

The Intent filters used in {@link Context#registerReceiver} 39 | * and in application manifests are not guaranteed to be exclusive. They 40 | * are hints to the operating system about how to find suitable recipients. It is 41 | * possible for senders to force delivery to specific recipients, bypassing filter 42 | * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()} 43 | * implementations should respond only to known actions, ignoring any unexpected 44 | * Intents that they may receive. 45 | * 46 | * @param context The Context in which the receiver is running. 47 | * @param intent The Intent being received. 48 | */ 49 | @Override 50 | public void onReceive(Context context, Intent intent) { 51 | LogUtils.d(MyBroadCastReceiver.class.getName()+" onReceive"); 52 | 53 | MyApplication.getInstance().test(this.getClass().getName()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/java/dev/mars/testapplication/MyContentProvider.java: -------------------------------------------------------------------------------- 1 | package dev.mars.testapplication; 2 | 3 | import android.content.ContentProvider; 4 | import android.content.ContentValues; 5 | import android.database.ContentObserver; 6 | import android.database.Cursor; 7 | import android.database.sqlite.SQLiteOpenHelper; 8 | import android.net.Uri; 9 | import android.support.annotation.Nullable; 10 | 11 | /** 12 | * Created by ma.xuanwei on 2017/5/11. 13 | */ 14 | 15 | public class MyContentProvider extends ContentProvider { 16 | /** 17 | * Implement this to initialize your content provider on startup. 18 | * This method is called for all registered content providers on the 19 | * application main thread at application launch time. It must not perform 20 | * lengthy operations, or application startup will be delayed. 21 | *

22 | *

You should defer nontrivial initialization (such as opening, 23 | * upgrading, and scanning databases) until the content provider is used 24 | * (via {@link #query}, {@link #insert}, etc). Deferred initialization 25 | * keeps application startup fast, avoids unnecessary work if the provider 26 | * turns out not to be needed, and stops database errors (such as a full 27 | * disk) from halting application launch. 28 | *

29 | *

If you use SQLite, {@link SQLiteOpenHelper} 30 | * is a helpful utility class that makes it easy to manage databases, 31 | * and will automatically defer opening until first use. If you do use 32 | * SQLiteOpenHelper, make sure to avoid calling 33 | * {@link SQLiteOpenHelper#getReadableDatabase} or 34 | * {@link SQLiteOpenHelper#getWritableDatabase} 35 | * from this method. (Instead, override 36 | * {@link SQLiteOpenHelper#onOpen} to initialize the 37 | * database when it is first opened.) 38 | * 39 | * @return true if the provider was successfully loaded, false otherwise 40 | */ 41 | @Override 42 | public boolean onCreate() { 43 | LogUtils.d(MyContentProvider.class.getName()+" onCreate"); 44 | //Application此时还没有创建 45 | //MyApplication.getInstance().test("MyContentProvider"); 46 | return false; 47 | } 48 | 49 | /** 50 | * Implement this to handle query requests from clients. 51 | * This method can be called from multiple threads, as described in 52 | * Processes 53 | * and Threads. 54 | *

55 | * Example client call:

56 | *

// Request a specific record.
 57 |      * Cursor managedCursor = managedQuery(
 58 |      * ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
 59 |      * projection,    // Which columns to return.
 60 |      * null,          // WHERE clause.
 61 |      * null,          // WHERE clause value substitution
 62 |      * People.NAME + " ASC");   // Sort order.
63 | * Example implementation:

64 | *

// SQLiteQueryBuilder is a helper class that creates the
 65 |      * // proper SQL syntax for us.
 66 |      * SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
 67 |      *
 68 |      * // Set the table we're querying.
 69 |      * qBuilder.setTables(DATABASE_TABLE_NAME);
 70 |      *
 71 |      * // If the query ends in a specific record number, we're
 72 |      * // being asked for a specific record, so set the
 73 |      * // WHERE clause in our query.
 74 |      * if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
 75 |      * qBuilder.appendWhere("_id=" + uri.getPathLeafId());
 76 |      * }
 77 |      *
 78 |      * // Make the query.
 79 |      * Cursor c = qBuilder.query(mDb,
 80 |      * projection,
 81 |      * selection,
 82 |      * selectionArgs,
 83 |      * groupBy,
 84 |      * having,
 85 |      * sortOrder);
 86 |      * c.setNotificationUri(getContext().getContentResolver(), uri);
 87 |      * return c;
88 | * 89 | * @param uri The URI to query. This will be the full URI sent by the client; 90 | * if the client is requesting a specific record, the URI will end in a record number 91 | * that the implementation should parse and add to a WHERE or HAVING clause, specifying 92 | * that _id value. 93 | * @param projection The list of columns to put into the cursor. If 94 | * {@code null} all columns are included. 95 | * @param selection A selection criteria to apply when filtering rows. 96 | * If {@code null} then all rows are included. 97 | * @param selectionArgs You may include ?s in selection, which will be replaced by 98 | * the values from selectionArgs, in order that they appear in the selection. 99 | * The values will be bound as Strings. 100 | * @param sortOrder How the rows in the cursor should be sorted. 101 | * If {@code null} then the provider is free to define the sort order. 102 | * @return a Cursor or {@code null}. 103 | */ 104 | @Nullable 105 | @Override 106 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 107 | return null; 108 | } 109 | 110 | /** 111 | * Implement this to handle requests for the MIME type of the data at the 112 | * given URI. The returned MIME type should start with 113 | * vnd.android.cursor.item for a single record, 114 | * or vnd.android.cursor.dir/ for multiple items. 115 | * This method can be called from multiple threads, as described in 116 | * Processes 117 | * and Threads. 118 | *

119 | *

Note that there are no permissions needed for an application to 120 | * access this information; if your content provider requires read and/or 121 | * write permissions, or is not exported, all applications can still call 122 | * this method regardless of their access permissions. This allows them 123 | * to retrieve the MIME type for a URI when dispatching intents. 124 | * 125 | * @param uri the URI to query. 126 | * @return a MIME type string, or {@code null} if there is no type. 127 | */ 128 | @Nullable 129 | @Override 130 | public String getType(Uri uri) { 131 | return null; 132 | } 133 | 134 | /** 135 | * Implement this to handle requests to insert a new row. 136 | * As a courtesy, call {@link ContentResolver#notifyChange(Uri, ContentObserver) notifyChange()} 137 | * after inserting. 138 | * This method can be called from multiple threads, as described in 139 | * Processes 140 | * and Threads. 141 | * 142 | * @param uri The content:// URI of the insertion request. This must not be {@code null}. 143 | * @param values A set of column_name/value pairs to add to the database. 144 | * This must not be {@code null}. 145 | * @return The URI for the newly inserted item. 146 | */ 147 | @Nullable 148 | @Override 149 | public Uri insert(Uri uri, ContentValues values) { 150 | return null; 151 | } 152 | 153 | /** 154 | * Implement this to handle requests to delete one or more rows. 155 | * The implementation should apply the selection clause when performing 156 | * deletion, allowing the operation to affect multiple rows in a directory. 157 | * As a courtesy, call {@link ContentResolver#notifyChange(Uri, ContentObserver) notifyChange()} 158 | * after deleting. 159 | * This method can be called from multiple threads, as described in 160 | * Processes 161 | * and Threads. 162 | *

163 | *

The implementation is responsible for parsing out a row ID at the end 164 | * of the URI, if a specific row is being deleted. That is, the client would 165 | * pass in content://contacts/people/22 and the implementation is 166 | * responsible for parsing the record number (22) when creating a SQL statement. 167 | * 168 | * @param uri The full URI to query, including a row ID (if a specific record is requested). 169 | * @param selection An optional restriction to apply to rows when deleting. 170 | * @param selectionArgs 171 | * @return The number of rows affected. 172 | * @throws SQLException 173 | */ 174 | @Override 175 | public int delete(Uri uri, String selection, String[] selectionArgs) { 176 | return 0; 177 | } 178 | 179 | /** 180 | * Implement this to handle requests to update one or more rows. 181 | * The implementation should update all rows matching the selection 182 | * to set the columns according to the provided values map. 183 | * As a courtesy, call {@link ContentResolver#notifyChange(Uri, ContentObserver) notifyChange()} 184 | * after updating. 185 | * This method can be called from multiple threads, as described in 186 | * Processes 187 | * and Threads. 188 | * 189 | * @param uri The URI to query. This can potentially have a record ID if this 190 | * is an update request for a specific record. 191 | * @param values A set of column_name/value pairs to update in the database. 192 | * This must not be {@code null}. 193 | * @param selection An optional filter to match rows to update. 194 | * @param selectionArgs 195 | * @return the number of rows affected. 196 | */ 197 | @Override 198 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 199 | return 0; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/java/dev/mars/testapplication/MyService.java: -------------------------------------------------------------------------------- 1 | package dev.mars.testapplication; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.IBinder; 6 | 7 | public class MyService extends Service { 8 | public MyService() { 9 | } 10 | 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | LogUtils.d(MyService.class.getName()+" onCreate"); 15 | ((MyApplication)getApplication()).test(this.getClass().getName()); 16 | } 17 | 18 | @Override 19 | public int onStartCommand(Intent intent, int flags, int startId) { 20 | return super.onStartCommand(intent, flags, startId); 21 | } 22 | 23 | @Override 24 | public IBinder onBind(Intent intent) { 25 | // TODO: Return the communication channel to the service. 26 | throw new UnsupportedOperationException("Not yet implemented"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Sets the minimum version of CMake required to build the native 2 | # library. You should either keep the default value or only pass a 3 | # value of 3.4.0 or lower. 4 | 5 | cmake_minimum_required(VERSION 3.4.1) 6 | 7 | # Creates and names a library, sets it as either STATIC 8 | # or SHARED, and provides the relative paths to its source code. 9 | # You can define multiple libraries, and CMake builds it for you. 10 | # Gradle automatically packages shared libraries with your APK. 11 | 12 | add_library( # Sets the name of the library. 13 | reflect 14 | 15 | # Sets the library as a shared library. 16 | SHARED 17 | 18 | # Provides a relative path to your source file(s). 19 | # Associated headers in the same location as their source 20 | # file are automatically included. 21 | reflect.cpp ) 22 | 23 | # Searches for a specified prebuilt library and stores the path as a 24 | # variable. Because system libraries are included 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 the 38 | # build script, prebuilt third-party libraries, or system libraries. 39 | 40 | target_link_libraries( # Specifies the target library. 41 | reflect 42 | 43 | # Links the target library to the log library 44 | # included in the NDK. 45 | ${log-lib} ) 46 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/jni/reflect.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | extern "C" { 7 | JNIEXPORT void JNICALL 8 | Java_dev_mars_testapplication_MyApplication_test(JNIEnv *env, jobject instance) { 9 | 10 | // TODO 11 | jclass Methods2Class = env->FindClass("dev/mars/testapplication/Methods2"); 12 | if(Methods2Class!=NULL){ 13 | __android_log_print(ANDROID_LOG_DEBUG,"dev_mars_native","找到dev/mars/testapplication/Methods2"); 14 | }else{ 15 | __android_log_print(ANDROID_LOG_DEBUG,"dev_mars_native","未找到dev/mars/testapplication/Methods2"); 16 | return; 17 | } 18 | jmethodID init = env->GetMethodID(Methods2Class,"","()V"); 19 | jobject methods2Obj = env->NewObject(Methods2Class,init); 20 | jmethodID l = env->GetMethodID(Methods2Class,"l","()V"); 21 | env->CallVoidMethod(methods2Obj,l); 22 | 23 | 24 | } 25 | 26 | } 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /dex/apksecure/testapplication/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 |