├── .gitignore ├── .idea ├── .name ├── codeStyles │ └── Project.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── myihk ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zhuotong │ │ └── myihk │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── zhuotong │ │ │ └── myihk │ │ │ └── MainActivity.java │ ├── jni │ │ ├── Android.mk │ │ ├── Application.mk │ │ ├── arm │ │ │ ├── Android.mk │ │ │ ├── asm │ │ │ │ ├── dump.s │ │ │ │ ├── dump_just_ret.s │ │ │ │ ├── dump_with_ret.s │ │ │ │ └── replace.s │ │ │ ├── model │ │ │ │ ├── Android.mk │ │ │ │ ├── iModel.cpp │ │ │ │ └── iModel.h │ │ │ └── src │ │ │ │ ├── Android.mk │ │ │ │ ├── dump │ │ │ │ ├── Android.mk │ │ │ │ └── dump.c │ │ │ │ ├── dump_just_ret │ │ │ │ ├── Android.mk │ │ │ │ └── dump.c │ │ │ │ ├── dump_with_ret │ │ │ │ ├── Android.mk │ │ │ │ ├── dump.c │ │ │ │ ├── lr.cpp │ │ │ │ └── lr.h │ │ │ │ ├── fixPCOpcode.c │ │ │ │ ├── fixPCOpcode.h │ │ │ │ ├── mhk.c │ │ │ │ └── replace │ │ │ │ ├── Android.mk │ │ │ │ ├── lr.cpp │ │ │ │ ├── lr.h │ │ │ │ └── replace.c │ │ ├── arm64 │ │ │ ├── Android.mk │ │ │ ├── asm │ │ │ │ ├── base.s │ │ │ │ ├── dump.s │ │ │ │ ├── dump_just_ret.s │ │ │ │ ├── dump_neon.s │ │ │ │ ├── dump_neon_just_ret.s │ │ │ │ ├── dump_neon_with_ret.s │ │ │ │ ├── dump_with_ret.s │ │ │ │ ├── replace.s │ │ │ │ └── replace_neon.s │ │ │ ├── asm_for_trampoline │ │ │ │ ├── replace.s │ │ │ │ └── trampoline.s │ │ │ ├── model │ │ │ │ ├── Android.mk │ │ │ │ ├── iModel.cpp │ │ │ │ └── iModel.h │ │ │ └── src │ │ │ │ ├── Android.mk │ │ │ │ ├── dump │ │ │ │ ├── Android.mk │ │ │ │ └── dump.c │ │ │ │ ├── dump_just_ret │ │ │ │ ├── Android.mk │ │ │ │ └── dump.c │ │ │ │ ├── dump_with_ret │ │ │ │ ├── Android.mk │ │ │ │ ├── dump.c │ │ │ │ ├── lr.cpp │ │ │ │ └── lr.h │ │ │ │ ├── fixPCOpcode.c │ │ │ │ ├── fixPCOpcode.h │ │ │ │ ├── mhk.c │ │ │ │ └── replace │ │ │ │ ├── Android.mk │ │ │ │ ├── lr.cpp │ │ │ │ ├── lr.h │ │ │ │ └── replace.c │ │ ├── include │ │ │ ├── iModel.h │ │ │ ├── mhk.h │ │ │ └── mhk64.h │ │ ├── system_lib │ │ │ ├── arm64_9 │ │ │ │ ├── ld-android.so │ │ │ │ ├── libdl.so │ │ │ │ ├── libshk.so │ │ │ │ └── linker64 │ │ │ └── arm_9 │ │ │ │ ├── libc.so │ │ │ │ └── libdl.so │ │ └── test │ │ │ ├── Android.mk │ │ │ ├── main.cpp │ │ │ └── main_arm.cpp │ ├── libs │ │ └── arm64-v8a │ │ │ └── libshk.so │ ├── obj │ │ └── local │ │ │ └── arm64-v8a │ │ │ ├── libdump.a │ │ │ ├── libdump_with_ret.a │ │ │ ├── libreplace.a │ │ │ ├── libshk.so │ │ │ └── objs │ │ │ ├── dump │ │ │ ├── __ │ │ │ │ ├── __ │ │ │ │ │ └── asm │ │ │ │ │ │ └── dump.o │ │ │ │ ├── fixPCOpcode.o │ │ │ │ ├── fixPCOpcode.o.d │ │ │ │ ├── mhk.o │ │ │ │ └── mhk.o.d │ │ │ ├── dump.o │ │ │ └── dump.o.d │ │ │ ├── dump_with_ret │ │ │ ├── __ │ │ │ │ ├── __ │ │ │ │ │ └── asm │ │ │ │ │ │ └── dump_with_ret.o │ │ │ │ ├── fixPCOpcode.o │ │ │ │ ├── fixPCOpcode.o.d │ │ │ │ ├── mhk.o │ │ │ │ └── mhk.o.d │ │ │ ├── dump.o │ │ │ ├── dump.o.d │ │ │ ├── dump_with_ret.o │ │ │ └── dump_with_ret.o.d │ │ │ ├── replace │ │ │ ├── __ │ │ │ │ ├── __ │ │ │ │ │ └── asm │ │ │ │ │ │ └── replace.o │ │ │ │ ├── fixPCOpcode.o │ │ │ │ ├── fixPCOpcode.o.d │ │ │ │ ├── mhk.o │ │ │ │ └── mhk.o.d │ │ │ ├── lr.o │ │ │ ├── lr.o.d │ │ │ ├── replace.o │ │ │ └── replace.o.d │ │ │ └── shk │ │ │ ├── main.o │ │ │ └── main.o.d │ └── 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 │ └── com │ └── zhuotong │ └── myihk │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | *main_exportHook.cpp 16 | /app 17 | /myhkzz 18 | /mysighk 19 | /mysubstrate -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | My InHk -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 25 | 26 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /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 | google() 6 | jcenter() 7 | 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.5.3' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /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 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Dec 11 13:47:52 CST 2019 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-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /myihk/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /myihk/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.2" 6 | 7 | 8 | defaultConfig { 9 | applicationId "com.zhuotong.myihk" 10 | minSdkVersion 16 11 | targetSdkVersion 29 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | 17 | ndk { 18 | abiFilters 'arm64-v8a', 'armeabi-v7a' /*, 'armeabi'*/ 19 | } 20 | } 21 | 22 | externalNativeBuild { 23 | ndkBuild { 24 | path 'src/main/jni/Android.mk' 25 | } 26 | } 27 | 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 32 | } 33 | } 34 | 35 | } 36 | 37 | dependencies { 38 | implementation fileTree(dir: 'libs', include: ['*.jar']) 39 | 40 | implementation 'androidx.appcompat:appcompat:1.1.0' 41 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 42 | testImplementation 'junit:junit:4.12' 43 | androidTestImplementation 'androidx.test:runner:1.2.0' 44 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 45 | } 46 | -------------------------------------------------------------------------------- /myihk/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 | -------------------------------------------------------------------------------- /myihk/src/androidTest/java/com/zhuotong/myihk/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.zhuotong.myihk; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.zhuotong.myihk", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /myihk/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /myihk/src/main/java/com/zhuotong/myihk/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhuotong.myihk; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.Button; 8 | 9 | public class MainActivity extends AppCompatActivity { 10 | 11 | static { 12 | try { 13 | System.loadLibrary("shk"); 14 | } catch (Throwable e) { 15 | e.printStackTrace(); 16 | } 17 | } 18 | 19 | public native void testdlopen(); 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | Button bt = findViewById(R.id.bt); 26 | bt.setOnClickListener(new View.OnClickListener() { 27 | @Override 28 | public void onClick(View v) { 29 | testdlopen(); 30 | } 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /myihk/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | include $(call all-subdir-makefiles) -------------------------------------------------------------------------------- /myihk/src/main/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := armeabi-v7a arm64-v8a 2 | #APP_STL := gnustl_static 3 | APP_STL := c++_static 4 | APP_CPPFLAGS += -fexceptions 5 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/Android.mk: -------------------------------------------------------------------------------- 1 | $(warning "abi: $(TARGET_ARCH_ABI)") 2 | include $(call all-subdir-makefiles) 3 | $(warning "abi: $(TARGET_ARCH_ABI)") 4 | 5 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/asm/dump.s: -------------------------------------------------------------------------------- 1 | .global _dump_start 2 | .global _dump_end 3 | .global _hk_info 4 | .global _oriFuc 5 | 6 | .hidden _dump_start 7 | .hidden _dump_end 8 | .hidden _hk_info 9 | .hidden _oriFuc 10 | 11 | //可用于标准的c/c++函数、非标准函数、函数的一部分(用于读写寄存器),前提都是字节长度足够 12 | //非标准函数即非c/c++编译的函数,那么手写汇编可能存在并不遵守约定的情况,比如我们使用了sp寄存器,并在未使用的栈上保存寄存器 13 | //但是可能不是满递减而是反过来满递增,或者不遵守栈平衡,往栈上写数据,但是并不改变sp寄存器。当然应该是很少见的。 14 | 15 | .data 16 | 17 | _dump_start: //用于读写寄存器/栈,需要自己解析参数,不能读写返回值,不能阻止原函数(被hook函数)的执行 18 | //从行为上来我觉得更偏向dump,所以起名为dump。 19 | push {r0-r4} //r0=r0,中转用 r1=sp(push之前的sp), r2=r14/lr, r3=pc, r4=cpsr 20 | mrs r0, cpsr 21 | str r0, [sp, #0x10] //r4的位置存放cpsr 22 | str r14, [sp, #8] //r2的位置存放lr 23 | add r14, sp, #0x14 24 | str r14, [sp, #4] //r1的位置存放真实sp 25 | pop {r0} //恢复r0 26 | push {r0-r12} //保存r-r12,之后是r13-r16/cpsr 27 | mov r0, sp 28 | ldr r1, _hk_info; 29 | ldr r3, [r1]; //onPreCallBack 30 | str pc, [sp, #0x3c]; //存储pc,arm模式,所以pc+8,指向ldr r0, [sp, #0x40] 31 | blx r3 32 | ldr r0, [sp, #0x40] //cpsr 33 | msr cpsr, r0 34 | ldmfd sp!, {r0-r12} //恢复r0-r12 35 | ldr r14, [sp, #4] //恢复r14/lr 36 | ldr sp, [r13] //恢复sp(push之前的sp) 37 | ldr pc, _oriFuc 38 | 39 | _oriFuc: //备份/修复的原方法 40 | .word 0x12345678 41 | 42 | _hk_info: //结构体STR_HK_INFO 43 | .word 0x12345678 44 | 45 | _dump_end: 46 | 47 | .end 48 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/asm/dump_just_ret.s: -------------------------------------------------------------------------------- 1 | .global j_dump_start 2 | .global j_dump_end 3 | .global j_hk_info 4 | 5 | .hidden j_dump_start 6 | .hidden j_dump_end 7 | .hidden j_hk_info 8 | 9 | 10 | .data 11 | 12 | j_dump_start: 13 | 14 | push {r0-r4} //r0=r0,中转用 r1=sp(push之前的sp), r2=r14/lr, r3=pc, r4=cpsr 15 | mrs r0, cpsr 16 | str r0, [sp, #0x10] //r4的位置存放cpsr 17 | str r14, [sp, #8] //r2的位置存放lr 18 | add r14, sp, #0x14 19 | str r14, [sp, #4] //r1的位置存放真实sp 20 | pop {r0} //恢复r0 21 | push {r0-r12} //保存r-r12,之后是r13-r16/cpsr 22 | mov r0, sp 23 | ldr r1, j_hk_info; 24 | ldr r3, [r1]; //onPreCallBack 25 | str pc, [sp, #0x3c]; //存储pc 26 | blx r3 27 | ldr r0, [sp, #0x40] //cpsr 28 | msr cpsr, r0 29 | ldmfd sp!, {r0-r12} //恢复r0-r12 30 | ldr r14, [sp, #4] //恢复r14/lr 31 | ldr sp, [r13] //恢复sp(push之前的sp) 32 | mov pc, lr 33 | 34 | 35 | j_hk_info: //结构体STR_HK_INFO 36 | .word 0x12345678 37 | 38 | j_dump_end: 39 | 40 | .end 41 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/asm/dump_with_ret.s: -------------------------------------------------------------------------------- 1 | 2 | .global r_dump_start 3 | .global r_dump_end 4 | .global r_hk_info 5 | 6 | .hidden r_dump_start 7 | .hidden r_dump_end 8 | .hidden r_hk_info 9 | 10 | 11 | .data 12 | 13 | r_dump_start: //用于读写寄存器/栈,需要自己解析参数,不能读写返回值,不能阻止原函数(被hook函数)的执行 14 | //从行为上来我觉得更偏向dump,所以起名为dump。 15 | push {r0-r4} //r0=r0,中转用 r1=sp(push之前的sp), r2=r14/lr, r3=pc, r4=cpsr 16 | mrs r0, cpsr 17 | str r0, [sp, #0x10] //r4的位置存放cpsr 18 | str r14, [sp, #8] //r2的位置存放lr 19 | add r14, sp, #0x14 20 | str r14, [sp, #4] //r1的位置存放真实sp 21 | pop {r0} //恢复r0 22 | push {r0-r12} //保存r-r12,之后是r13-r16/cpsr 23 | mov r0, sp 24 | ldr r1, r_hk_info; 25 | ldr r3, [r1, #8]; //pre_callback 26 | str pc, [sp, #0x3c]; //存储pc 27 | blx r3 28 | 29 | to_call_oriFun: 30 | ldr r0, [sp, #0x40] //cpsr 31 | msr cpsr, r0 32 | ldmfd sp!, {r0-r12} //恢复r0-r12 33 | ldr r14, [sp, #4] //恢复r14/lr 34 | ldr sp, [r13] //恢复sp(push之前的sp) 35 | ldr lr, r_hk_info 36 | ldr lr, [lr, #4]; //pOriFuncAddr 37 | blx lr; 38 | 39 | to_aft_callback: 40 | push {r0-r4} //r0=r0,中转用 r1=sp(push之前的sp), r2=r14/lr, r3=pc, r4=cpsr 41 | mrs r0, cpsr 42 | str r0, [sp, #0x10] //r4的位置存放cpsr 43 | str r14, [sp, #8] //r2的位置存放lr 44 | add r14, sp, #0x14 45 | str r14, [sp, #4] //r1的位置存放真实sp 46 | pop {r0} //恢复r0 47 | push {r0-r12} //保存r-r12,之后是r13-r16/cpsr 48 | mov r0, sp 49 | ldr r1, r_hk_info; 50 | ldr r3, [r1, #0x10]; //aft_callback 51 | str pc, [sp, #0x3c]; //存储pc 52 | blx r3 53 | 54 | to_popreg: 55 | ldr r0, [sp, #0x40] //cpsr 56 | msr cpsr, r0 57 | ldmfd sp!, {r0-r12} //恢复r0-r12 58 | ldr r14, [sp, #4] //恢复r14/lr 59 | ldr sp, [r13] //恢复sp(push之前的sp) 60 | mov pc, lr; 61 | 62 | r_hk_info: //结构体STR_HK_INFO 63 | .word 0x12345678 64 | 65 | r_dump_end: 66 | 67 | .end 68 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/asm/replace.s: -------------------------------------------------------------------------------- 1 | .global replace_start 2 | .global replace_end 3 | .global p_hk_info 4 | 5 | .hidden replace_start 6 | .hidden replace_end 7 | .hidden p_hk_info 8 | 9 | .data 10 | 11 | //这种方式尽量用于标准的c/c++函数,因为通过hook函数再调用原函数,只能保证参数寄存器和lr寄存器是一致的,其他寄存器可能被修改。 12 | 13 | replace_start: //如果只是替换/跳到hook函数,其实是不用保存寄存器的,只是重新写比较麻烦,所以在之前的基础上 14 | 15 | push {r0-r4} //r0=r0,中转用 r1=sp(push之前的sp), r2=r14/lr, r3=pc, r4=cpsr 16 | mrs r0, cpsr 17 | str r0, [sp, #0x10] //r4的位置存放cpsr 18 | str r14, [sp, #8] //r2的位置存放lr 19 | add r14, sp, #0x14 20 | str r14, [sp, #4] //r1的位置存放真实sp 21 | pop {r0} //恢复r0 22 | push {r0-r12} //保存r-r12,之后是r13-r16/cpsr 23 | mov r0, sp 24 | ldr r1, p_hk_info; 25 | ldr r3, [r1, #8]; //pre_callback,保存lr 26 | str pc, [sp, #0x3c]; //存储pc 27 | blx r3 28 | 29 | to_call_oriFun: 30 | ldr r0, [sp, #0x40] //cpsr 31 | msr cpsr, r0 32 | ldmfd sp!, {r0-r12} //恢复r0-r12 33 | ldr r14, [sp, #4] //恢复r14/lr 34 | ldr sp, [r13] //恢复sp(push之前的sp) 35 | ldr lr, p_hk_info 36 | ldr lr, [lr, #0x14]; //pHkFunAddr 37 | blx lr; 38 | 39 | to_aft_callback: 40 | push {r0-r4} //r0=r0,中转用 r1=sp(push之前的sp), r2=r14/lr, r3=pc, r4=cpsr 41 | mrs r0, cpsr 42 | str r0, [sp, #0x10] //r4的位置存放cpsr 43 | str r14, [sp, #8] //r2的位置存放lr 44 | add r14, sp, #0x14 45 | str r14, [sp, #4] //r1的位置存放真实sp 46 | pop {r0} //恢复r0 47 | push {r0-r12} //保存r-r12,之后是r13-r16/cpsr 48 | mov r0, sp 49 | ldr r1, p_hk_info; 50 | ldr r3, [r1, #0x10]; //aft_callback 51 | str pc, [sp, #0x3c]; //存储pc 52 | blx r3 53 | 54 | to_popreg: 55 | ldr r0, [sp, #0x40] //cpsr 56 | msr cpsr, r0 57 | ldmfd sp!, {r0-r12} //恢复r0-r12 58 | ldr r14, [sp, #4] //恢复r14/lr 59 | ldr sp, [r13] //恢复sp(push之前的sp) 60 | mov pc, lr; 61 | 62 | p_hk_info: //结构体STR_HK_INFO 63 | .word 0x12345678 64 | 65 | 66 | replace_end: 67 | 68 | .end -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/model/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | #ifeq "$(TARGET_ARCH_ABI)" "armeabi-v7a" 9 | ifneq ($(findstring $(TARGET_ARCH_ABI), "armeabi-v7a" "armeabi"),) 10 | 11 | 12 | #LOCAL_CXXFLAGS += -g -O0 13 | #LOCAL_ARM_MODE := arm 14 | LOCAL_MODULE := imodel 15 | LOCAL_STATIC_LIBRARIES := dump dump_just_ret dump_with_ret replace 16 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include 17 | LOCAL_SRC_FILES := iModel.cpp 18 | LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog 19 | 20 | include $(BUILD_STATIC_LIBRARY) 21 | 22 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/model/iModel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "iModel.h" 4 | 5 | static INFOS* infos; 6 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 7 | 8 | static INFOS *getINFOS(){ 9 | pthread_mutex_lock(&mutex); 10 | if (infos == NULL) { 11 | infos = new INFOS; 12 | } 13 | pthread_mutex_unlock(&mutex); 14 | return infos; 15 | } 16 | 17 | static HK_INFO* add(HK_INFO *info){ 18 | INFOS *infos = getINFOS(); 19 | HK_INFO *has = NULL; 20 | pthread_mutex_lock(&mutex); 21 | 22 | for (auto it = infos->begin(); it < infos->end(); ++it) { 23 | HK_INFO *pInfo = *it; 24 | if (pInfo->pBeHookAddr == info->pBeHookAddr) { 25 | has = pInfo; 26 | break; 27 | } 28 | } 29 | if (!has) { 30 | infos->push_back(info); 31 | } 32 | pthread_mutex_unlock(&mutex); 33 | return has; 34 | } 35 | 36 | /** 37 | * 通过被hook函数获取数据结构体 38 | * @param pBeHookAddr 被hook函数 39 | * @return 返回HK_INFO结构体 40 | */ 41 | HK_INFO *isHooked(void* pBeHookAddr){ 42 | INFOS *infos = getINFOS(); 43 | HK_INFO *has = NULL; 44 | pthread_mutex_lock(&mutex); 45 | for (auto it = infos->begin(); it < infos->end(); ++it) { 46 | HK_INFO *pInfo = *it; 47 | if (pInfo->pBeHookAddr == pBeHookAddr) { 48 | has = pInfo; 49 | break; 50 | } 51 | } 52 | pthread_mutex_unlock(&mutex); 53 | return has; 54 | } 55 | 56 | /** 57 | * 通过hook函数获取数据结构体 58 | * @param hkFun hook函数 59 | * @return 返回HK_INFO结构体 60 | */ 61 | HK_INFO *isHookedByHkFun(void* hkFun){ 62 | INFOS *infos = getINFOS(); 63 | HK_INFO *has = NULL; 64 | pthread_mutex_lock(&mutex); 65 | for (auto it = infos->begin(); it < infos->end(); ++it) { 66 | HK_INFO *pInfo = *it; 67 | if (pInfo->pHkFunAddr == hkFun) { 68 | has = pInfo; 69 | break; 70 | } 71 | } 72 | pthread_mutex_unlock(&mutex); 73 | return has; 74 | } 75 | 76 | void remove(HK_INFO *info){ 77 | INFOS *infos = getINFOS(); 78 | pthread_mutex_lock(&mutex); 79 | for (auto it = infos->begin(); it < infos->end(); ++it) { 80 | HK_INFO *pInfo = *it; 81 | if (pInfo == info) { 82 | infos->erase(it); 83 | break; 84 | } 85 | } 86 | pthread_mutex_unlock(&mutex); 87 | } 88 | 89 | /** 90 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 91 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 92 | * @param pInfo 保存了被hook函数、hook函数等的结构体 93 | */ 94 | void default_onPreCallBack(my_pt_regs *regs, HK_INFO *pInfo) //参数regs就是指向栈上的一个数据结构,由第二部分的mov r0, sp所传递。 95 | { 96 | const char* name = "null"; 97 | if (pInfo) { 98 | if (pInfo->methodName) { 99 | name = pInfo->methodName; 100 | } else { 101 | char buf[20]; 102 | sprintf(buf, "%p", pInfo->pBeHookAddr); 103 | name = buf; 104 | } 105 | } 106 | // LE("tid=%d onPreCallBack:%s", gettid(), name); 107 | 108 | LE("tid=%d, onPreCallBack:%s, " 109 | "r0=0x%lx, r1=0x%lx, r2=0x%lx, r3=0x%lx, r4=0x%lx, r5=0x%lx, r6=0x%lx, r7=0x%lx, r8=0x%lx, r9=0x%lx, r10=0x%lx, r11=0x%lx, r12=0x%lx, " 110 | "cur_sp=%p, ori_sp=%p, ori_sp/13=0x%lx, lr=0x%lx, cur_pc=0x%lx, cpsr=0x%lx, " 111 | "arg4=0x%lx, arg5=0x%lx, arg4=0x%lx, arg5=0x%lx;" 112 | , gettid(), name, 113 | regs->uregs[0], regs->uregs[1], regs->uregs[2], regs->uregs[3], regs->uregs[4], regs->uregs[5], 114 | regs->uregs[6], regs->uregs[7], regs->uregs[8], regs->uregs[9], regs->uregs[10], regs->uregs[11], 115 | regs->uregs[12], 116 | regs, ((char*)regs + 0x44), regs->uregs[13], regs->uregs[14], regs->uregs[15], regs->uregs[16], 117 | regs->uregs[17], regs->uregs[18], SP(0), SP(1) 118 | ); 119 | 120 | if (pInfo) { 121 | LE("onPreCallBack: HK_INFO=%p", pInfo); 122 | if ((pInfo->pBeHookAddr == open || pInfo->pBeHookAddr == dlsym(RTLD_DEFAULT, "__open")) && regs->uregs[0]) { 123 | const char* name = (const char *)(regs->uregs[0]); 124 | LE("onPreCallBack: open: %s , %o, %o", name, regs->uregs[1], (mode_t)regs->uregs[2]); 125 | } 126 | } 127 | 128 | } 129 | 130 | /** 131 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 132 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 133 | * @param pInfo 保存了被hook函数、hook函数等的结构体 134 | */ 135 | void default_onCallBack(my_pt_regs *regs, HK_INFO *pInfo) //参数regs就是指向栈上的一个数据结构,由第二部分的mov r0, sp所传递。 136 | { 137 | const char* name = "null"; 138 | if (pInfo) { 139 | if (pInfo->methodName) { 140 | name = pInfo->methodName; 141 | } else { 142 | char buf[20]; 143 | sprintf(buf, "%p", pInfo->pBeHookAddr); 144 | name = buf; 145 | } 146 | } 147 | // LE("tid=%d onPreCallBack:%s", gettid(), name); 148 | 149 | LE("tid=%d, onCallBack:%s, " 150 | "r0=0x%lx, r1=0x%lx, r2=0x%lx, r3=0x%lx, r4=0x%lx, r5=0x%lx, r6=0x%lx, r7=0x%lx, r8=0x%lx, r9=0x%lx, r10=0x%lx, r11=0x%lx, r12=0x%lx, " 151 | "cur_sp=%p, ori_sp=%p, ori_sp/13=0x%lx, lr=0x%lx, cur_pc=0x%lx, cpsr=0x%lx, " 152 | "arg4=0x%lx, arg5=0x%lx, arg4=0x%lx, arg5=0x%lx;" 153 | , gettid(), name, 154 | regs->uregs[0], regs->uregs[1], regs->uregs[2], regs->uregs[3], regs->uregs[4], regs->uregs[5], 155 | regs->uregs[6], regs->uregs[7], regs->uregs[8], regs->uregs[9], regs->uregs[10], regs->uregs[11], 156 | regs->uregs[12], 157 | regs, ((char*)regs + 0x44), regs->uregs[13], regs->uregs[14], regs->uregs[15], regs->uregs[16], 158 | regs->uregs[17], regs->uregs[18], SP(0), SP(1) 159 | ); 160 | 161 | if (pInfo) { 162 | LE("onCallBack: HK_INFO=%p", pInfo); 163 | if (pInfo->pBeHookAddr == open && regs->uregs[0]) { 164 | LE("onCallBack: open ret: %d", regs->uregs[0]); 165 | } 166 | } 167 | 168 | } 169 | 170 | 171 | 172 | /** 173 | * 真实函数执行前调用onPreCallBack,执行后调用onCallBack,通过onPreCallBack控制参数,通过onCallBack控制返回值 174 | * @param pBeHookAddr 要hook的地址,必须 175 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL(onCallBack不为空),当和onCallBack都为NULL的情况使用默认的打印寄存器的函数default_onPreCallBack,因为什么都不做为什么hook? 176 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 177 | * @param methodName 被hook的函数名称,可以为NULL。 178 | * @return success:成功;error:错误;hooked:已被hook; 179 | */ 180 | hk_status dump(void *pBeHookAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo), void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo), const char* methodName) 181 | { 182 | bool bRet = false; 183 | LOGI("dump"); 184 | 185 | enum hk_status status = error; 186 | if(pBeHookAddr == NULL) 187 | { 188 | return status; 189 | } 190 | 191 | auto * pInfo = new HK_INFO; 192 | pInfo->pBeHookAddr = pBeHookAddr; 193 | HK_INFO *pHkInfo = add(pInfo); 194 | if (pHkInfo) { 195 | status = hooked; 196 | delete(pInfo); 197 | LE("has hook !"); 198 | return status; 199 | } 200 | 201 | if (onCallBack) { 202 | pInfo->onPreCallBack = onPreCallBack; 203 | } else { 204 | pInfo->onPreCallBack = onPreCallBack ? onPreCallBack : default_onPreCallBack; 205 | } 206 | pInfo->onCallBack = onCallBack; 207 | pInfo->methodName = methodName; 208 | 209 | pInfo->pHkFunAddr = NULL; 210 | 211 | //DEMO只很对ARM指令进行演示,更通用这里需要判断区分THUMB等指令 212 | if(TEST_BIT0((uint32_t)pInfo->pBeHookAddr)){ //thumb mode 213 | LOGI("HookThumb Start."); 214 | if(!HookThumb(pInfo)) 215 | { 216 | LOGI("HookThumb fail."); 217 | remove(pInfo); 218 | delete pInfo; 219 | return status; 220 | } 221 | } else if(!HookArm(pInfo)) 222 | { 223 | LE("HookArm fail."); 224 | remove(pInfo); 225 | delete(pInfo); 226 | return status; 227 | } 228 | 229 | { 230 | status = success; 231 | } 232 | 233 | return status; 234 | } 235 | 236 | /** 237 | * 不执行真实函数,直接操作寄存器,之后恢复寄存器返回,理论上也是可以在onCallBack其中执行真实函数的,但是需要自己封装参数,调用后自己解析寄存器 238 | * @param pBeHookAddr 要hook的地址,必须 239 | * @param onCallBack 要插入的回调函数(读写参数寄存器),必须 240 | * @param methodName 被hook的函数名称,可以为NULL。 241 | * @return success:成功;error:错误;hooked:已被hook; 242 | */ 243 | hk_status dumpRet(void *pBeHookAddr, void (*onCallBack)(struct my_pt_regs *, HK_INFO *pInfo), const char* methodName){ 244 | bool bRet = false; 245 | LOGI("dumpRet"); 246 | 247 | enum hk_status status = error; 248 | if (pBeHookAddr == NULL || onCallBack == NULL) { 249 | return status; 250 | } 251 | 252 | auto * pInfo = new HK_INFO; 253 | pInfo->pBeHookAddr = pBeHookAddr; 254 | HK_INFO *pHkInfo = add(pInfo); 255 | if (pHkInfo) { 256 | status = hooked; 257 | delete(pInfo); 258 | LE("has hook !"); 259 | return status; 260 | } 261 | 262 | pInfo->onPreCallBack = onCallBack; 263 | pInfo->methodName = methodName; 264 | pInfo->onCallBack = (void (*)(my_pt_regs *, STR_HK_INFO *))(0xffffffff); 265 | pInfo->pHkFunAddr = NULL; 266 | 267 | if(TEST_BIT0((uint32_t)pInfo->pBeHookAddr)){ //thumb mode 268 | LOGI("HookThumb Start."); 269 | if(!HookThumb(pInfo)) 270 | { 271 | LOGI("HookThumb fail."); 272 | remove(pInfo); 273 | delete pInfo; 274 | return status; 275 | } 276 | } else if(!HookArm(pInfo)) 277 | { 278 | LE("HookArm fail."); 279 | remove(pInfo); 280 | delete (pInfo); 281 | return status; 282 | } 283 | 284 | { 285 | status = success; 286 | } 287 | return status; 288 | } 289 | 290 | 291 | /** 292 | * 针对标准函数,最常用的hook接口。定义一个和被hook函数原型一致的函数接收处理参数,可直接返回或者调用被备份/修复的原函数 293 | * @param pBeHookAddr 要hook的地址,必须 294 | * @param pHkFunAddr 和被hook函数原型一致的函数,接收处理参数,可直接返回或者调用被备份/修复的原函数,必须 295 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL 296 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 297 | * @param methodName 被hook的函数名称,可以为NULL 298 | * @return 因为既要区分三种状态,还存在返回备份/修复的原函数的情况,使用结构体存储两个字段,参考demo。 299 | */ 300 | struct RetInfo dump_replace(void *pBeHookAddr, void*pHkFunAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo), void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo), const char* methodName) 301 | { 302 | bool bRet = false; 303 | LOGI("dump_replace"); 304 | 305 | const void* caller_addr = __builtin_return_address(0); 306 | LE("caller_addr=%p", caller_addr); 307 | LE("caller_addr_1=%p", __builtin_return_address(1)); 308 | 309 | struct RetInfo info; 310 | info.info = NULL; 311 | info.status = error; 312 | 313 | if(pBeHookAddr == NULL || pHkFunAddr == NULL) 314 | { 315 | return info; 316 | } 317 | 318 | auto * pInfo = new HK_INFO(); 319 | pInfo->pBeHookAddr = pBeHookAddr; 320 | HK_INFO *pHkInfo = add(pInfo); 321 | if (pHkInfo) { 322 | info.status = hooked; 323 | delete(pInfo); 324 | LE("has hook !"); 325 | return info; 326 | } 327 | pInfo->pHkFunAddr = pHkFunAddr; 328 | pInfo->onPreCallBack = onPreCallBack;// ? onPreCallBack : default_onPreCallBack; 329 | pInfo->onCallBack = onCallBack; 330 | pInfo->methodName = methodName; 331 | 332 | if(TEST_BIT0((uint32_t)pInfo->pBeHookAddr)){ //thumb mode 333 | LOGI("HookThumb Start."); 334 | if(!HookThumb(pInfo)) 335 | { 336 | LOGI("HookThumb fail."); 337 | remove(pInfo); 338 | delete pInfo; 339 | return info; 340 | } 341 | } else if(!HookArm(pInfo)) 342 | { 343 | LE("HookArm fail."); 344 | remove(pInfo); 345 | delete pInfo; 346 | return info; 347 | } 348 | 349 | info.info = pInfo;//(pInfo->pOriFuncAddr); 350 | info.status = success; 351 | 352 | caller_addr = __builtin_return_address(0); 353 | LE("caller_addr=%p", caller_addr); 354 | LE("caller_addr_1=%p", __builtin_return_address(1)); 355 | 356 | return info; 357 | } 358 | 359 | 360 | /** 361 | * 获取备份/修复的被hook函数,主要是不清楚结构体字段的用户或者透明指针的情况 362 | * @param info 363 | * @return 返回备份/修复的被hook函数 364 | */ 365 | void* getOriFun(HK_INFO* info){ 366 | if (info) { 367 | return info->pOriFuncAddr; 368 | } 369 | return NULL; 370 | } 371 | 372 | /** 373 | * 获取备份/修复的被hook函数的指针,二级指针;可用于自己保存,推荐存在取消hook的情况下调用getOriFunByHkFun函数 374 | * @param info 375 | * @return 返回指向存储备份/修复的被hook函数的指针 376 | */ 377 | void** getPoriFun(HK_INFO* info){ 378 | if (info) { 379 | return info->ppOriFuncAddr; 380 | } 381 | return NULL; 382 | } 383 | 384 | /** 385 | * 通过hook函数获取被hook的函数 386 | * @param hkFun hook函数 387 | * @return 返回被hook函数,如果被取消hook或者未被hook返回NULL 388 | */ 389 | void* getOriFunByHkFun(void* hkFun){ 390 | if (hkFun) { 391 | HK_INFO *pInfo = isHookedByHkFun(hkFun); 392 | if (pInfo) { 393 | return pInfo->pOriFuncAddr; 394 | } 395 | } 396 | return NULL; 397 | } 398 | 399 | 400 | /** 401 | * 取消hook,释放shellcode/备份的原方法占用的空间并还原原方法 402 | * @param info 如果成功会释放这个结构体,所以之后这个结构体/指针不能再用 403 | * @return 取消成功true,否则false 404 | */ 405 | bool unHook(HK_INFO* info){ 406 | if (!info) { 407 | return false; 408 | } 409 | bool ret = unHk(info); 410 | if (!ret) { 411 | return false; 412 | } 413 | 414 | remove(info); 415 | free(info); 416 | 417 | return true; 418 | } 419 | 420 | /** 421 | * 取消所有的hook 422 | * @return 423 | */ 424 | bool unHookAll(){ 425 | INFOS *infos = getINFOS(); 426 | 427 | pthread_mutex_lock(&mutex); 428 | for (auto it = infos->begin(); it < infos->end(); ++it) { 429 | HK_INFO *pInfo = *it; 430 | bool ret = unHk(pInfo); 431 | if (!ret) { 432 | pthread_mutex_unlock(&mutex); 433 | return false; 434 | } 435 | 436 | remove(pInfo); 437 | free(pInfo); 438 | } 439 | pthread_mutex_unlock(&mutex); 440 | 441 | return true; 442 | } 443 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/model/iModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/19. 3 | // 4 | 5 | #ifndef MY_INHK_IMODEL_H 6 | #define MY_INHK_IMODEL_H 7 | 8 | #include "mhk.h" 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | typedef std::vector INFOS; 21 | //typedef std::map LR_MAP; 22 | 23 | #endif 24 | 25 | enum hk_status{ 26 | success, hooked, error 27 | }; 28 | 29 | struct RetInfo { 30 | enum hk_status status; 31 | HK_INFO *info; 32 | }; 33 | 34 | //打印寄存器 35 | /** 36 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 37 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 38 | * @param pInfo 保存了被hook函数、hook函数等的结构体 39 | */ 40 | void default_onPreCallBack(my_pt_regs *regs, HK_INFO *pInfo); 41 | /** 42 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 43 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 44 | * @param pInfo 保存了被hook函数、hook函数等的结构体 45 | */ 46 | void default_onCallBack(my_pt_regs *regs, HK_INFO *pInfo); 47 | 48 | /** 49 | * 真实函数执行前调用onPreCallBack,执行后调用onCallBack,通过onPreCallBack控制参数,通过onCallBack控制返回值 50 | * @param pBeHookAddr 要hook的地址,必须 51 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL(onCallBack不为空),当和onCallBack都为NULL的情况使用默认的打印寄存器的函数default_onPreCallBack,因为什么都不做为什么hook? 52 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 53 | * @param methodName 被hook的函数名称,可以为NULL。 54 | * @return success:成功;error:错误;hooked:已被hook; 55 | */ 56 | hk_status dump(void *pBeHookAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo), void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo) = NULL, const char* methodName = NULL); 57 | 58 | /** 59 | * 不执行真实函数,直接操作寄存器,之后恢复寄存器返回,理论上也是可以在onCallBack其中执行真实函数的,但是需要自己封装参数,调用后自己解析寄存器 60 | * @param pBeHookAddr 要hook的地址,必须 61 | * @param onCallBack 要插入的回调函数(读写参数寄存器),必须 62 | * @param methodName 被hook的函数名称,可以为NULL。 63 | * @return success:成功;error:错误;hooked:已被hook; 64 | */ 65 | hk_status dumpRet(void *pBeHookAddr, void (*onCallBack)(struct my_pt_regs *, HK_INFO *pInfo), const char* methodName = NULL); 66 | 67 | /** 68 | * 针对标准函数,最常用的hook接口。定义一个和被hook函数原型一致的函数接收处理参数,可直接返回或者调用被备份/修复的原函数 69 | * @param pBeHookAddr 要hook的地址,必须 70 | * @param pHkFunAddr 和被hook函数原型一致的函数,接收处理参数,可直接返回或者调用被备份/修复的原函数,必须 71 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL 72 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 73 | * @param methodName 被hook的函数名称,可以为NULL 74 | * @return 因为既要区分三种状态,还存在返回备份/修复的原函数的情况,使用结构体存储两个字段,参考demo。 75 | */ 76 | RetInfo dump_replace(void *pBeHookAddr, void*pHkFunAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo) = NULL, void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo) = NULL, const char* methodName = NULL); 77 | 78 | /** 79 | * 通过被hook函数获取数据结构体 80 | * @param pBeHookAddr 被hook函数 81 | * @return 返回HK_INFO结构体 82 | */ 83 | HK_INFO *isHooked(void* pBeHookAddr); 84 | 85 | /** 86 | * 通过hook函数获取数据结构体 87 | * @param hkFun hook函数 88 | * @return 返回HK_INFO结构体 89 | */ 90 | HK_INFO *isHookedByHkFun(void* hkFun); 91 | 92 | /** 93 | * 获取备份/修复的被hook函数,主要是不清楚结构体字段的用户或者透明指针的情况 94 | * @param info 95 | * @return 返回备份/修复的被hook函数 96 | */ 97 | void* getOriFun(HK_INFO* info); 98 | 99 | /** 100 | * 获取备份/修复的被hook函数的指针,二级指针;可用于自己保存,推荐存在取消hook的情况下调用getOriFunByHkFun函数 101 | * @param info 102 | * @return 返回指向存储备份/修复的被hook函数的指针 103 | */ 104 | void** getPoriFun(HK_INFO* info); 105 | 106 | /** 107 | * 通过hook函数获取被hook的函数 108 | * @param hkFun hook函数 109 | * @return 返回被hook函数,如果被取消hook或者未被hook返回NULL 110 | */ 111 | void* getOriFunByHkFun(void* hkFun); 112 | 113 | /** 114 | * 取消hook,释放shellcode/备份的原方法占用的空间并还原原方法 115 | * @param info 如果成功会释放这个结构体,所以之后这个结构体/指针不能再用 116 | * @return 取消成功true,否则false 117 | */ 118 | bool unHook(HK_INFO* info); 119 | 120 | /** 121 | * 取消所有的hook 122 | * @return 123 | */ 124 | bool unHookAll(); 125 | 126 | #endif //MY_INHK_IMODEL_H 127 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/Android.mk: -------------------------------------------------------------------------------- 1 | $(warning "abi: $(TARGET_ARCH_ABI)") 2 | include $(call all-subdir-makefiles) 3 | $(warning "abi: $(TARGET_ARCH_ABI)") 4 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | #ifeq "$(TARGET_ARCH_ABI)" "armeabi-v7a" 9 | ifneq ($(findstring $(TARGET_ARCH_ABI), "armeabi-v7a" "armeabi"),) 10 | 11 | #LOCAL_CXXFLAGS += -g -O0 12 | #LOCAL_ARM_MODE := arm 13 | LOCAL_MODULE := dump 14 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 15 | LOCAL_SRC_FILES := ../mhk.c dump.c ../fixPCOpcode.c ../../asm/dump.s 16 | 17 | 18 | include $(BUILD_STATIC_LIBRARY) 19 | 20 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump/dump.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | 5 | extern unsigned long _dump_start; 6 | extern unsigned long _hk_info; 7 | extern unsigned long _oriFuc; 8 | extern unsigned long _dump_end; 9 | 10 | /** 11 | * 利用dump.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数后,回调老函数 12 | * @param pInfo inlinehook信息 13 | * @return inlinehook桩是否构造成功 14 | */ 15 | bool BuildStub_dump(HK_INFO* pInfo) 16 | { 17 | bool bRet = false; 18 | LE("BuildStub_dump"); 19 | while(1) 20 | { 21 | if(pInfo == NULL) 22 | { 23 | LOGI("pstInlineHook is null"); 24 | break; 25 | } 26 | 27 | void *p_shellcode_start_s = &_dump_start; 28 | void *p_shellcode_end_s = &_dump_end; 29 | void *p_hk_info = &_hk_info; 30 | void *p_oriFuc = &_oriFuc; 31 | 32 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 33 | pInfo->shellCodeLength = sShellCodeLength; 34 | //malloc一段新的stub代码 35 | long pagesize = sysconf(_SC_PAGE_SIZE); 36 | void *pNewShellCode = NULL; 37 | // pNewShellCode = malloc(sShellCodeLength); 38 | int code = 0; 39 | code = posix_memalign(&pNewShellCode, pagesize, pagesize); 40 | 41 | LE("pNewShellCode=%p", pNewShellCode); 42 | if(code || pNewShellCode == NULL) 43 | { 44 | LOGI("shell code malloc fail."); 45 | break; 46 | } 47 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 48 | //更改stub代码页属性,改成可读可写可执行 49 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 50 | { 51 | LOGI("change shell code page property fail."); 52 | break; 53 | } 54 | 55 | 56 | pInfo->hk_infoAddr = pNewShellCode + (p_hk_info - p_shellcode_start_s); 57 | *(pInfo->hk_infoAddr) = pInfo; 58 | 59 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 60 | pInfo->pStubShellCodeAddr = pNewShellCode; 61 | 62 | pInfo->ppOriFuncAddr = pNewShellCode + (p_oriFuc - p_shellcode_start_s); 63 | 64 | 65 | bRet = true; 66 | break; 67 | } 68 | 69 | return bRet; 70 | } 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump_just_ret/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | #ifeq "$(TARGET_ARCH_ABI)" "armeabi-v7a" 9 | ifneq ($(findstring $(TARGET_ARCH_ABI), "armeabi-v7a" "armeabi"),) 10 | 11 | #LOCAL_CXXFLAGS += -g -O0 12 | #LOCAL_ARM_MODE := arm 13 | LOCAL_MODULE := dump_just_ret 14 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 15 | LOCAL_SRC_FILES := ../mhk.c dump.c ../fixPCOpcode.c ../../asm/dump_just_ret.s 16 | 17 | 18 | include $(BUILD_STATIC_LIBRARY) 19 | 20 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump_just_ret/dump.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | 5 | extern unsigned long j_dump_start; 6 | extern unsigned long j_hk_info; 7 | extern unsigned long j_dump_end; 8 | 9 | //extern unsigned long _dump_start; 10 | //extern unsigned long _hk_info; 11 | //extern unsigned long _dump_end; 12 | 13 | 14 | 15 | /** 16 | * 利用dump_just_ret.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数 17 | * @param pInfo inlinehook信息 18 | * @return inlinehook桩是否构造成功 19 | */ 20 | bool BuildStub_dump_just_ret(HK_INFO* pInfo) 21 | { 22 | bool bRet = false; 23 | 24 | LE("BuildStub_dump_just_ret"); 25 | while(1) 26 | { 27 | if(pInfo == NULL) 28 | { 29 | LOGI("pstInlineHook is null"); 30 | break; 31 | } 32 | 33 | 34 | void *p_shellcode_start_s = &j_dump_start; 35 | void *p_shellcode_end_s = &j_dump_end; 36 | void *p_hk_info = &j_hk_info; 37 | 38 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 39 | pInfo->shellCodeLength = sShellCodeLength; 40 | 41 | //malloc一段新的stub代码 42 | long pagesize = sysconf(_SC_PAGE_SIZE); 43 | void *pNewShellCode = NULL;// = malloc(sShellCodeLength); 44 | int code = posix_memalign(&pNewShellCode, pagesize, pagesize); 45 | 46 | LE("pNewShellCode=%p", pNewShellCode); 47 | if(code || pNewShellCode == NULL) 48 | { 49 | LOGI("shell code malloc fail."); 50 | break; 51 | } 52 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 53 | //更改stub代码页属性,改成可读可写可执行 54 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 55 | { 56 | LOGI("change shell code page property fail."); 57 | break; 58 | } 59 | 60 | 61 | pInfo->hk_infoAddr = pNewShellCode + (p_hk_info - p_shellcode_start_s); 62 | *(pInfo->hk_infoAddr) = pInfo; 63 | 64 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 65 | pInfo->pStubShellCodeAddr = pNewShellCode; 66 | pInfo->ppOriFuncAddr = NULL; 67 | 68 | 69 | bRet = true; 70 | break; 71 | } 72 | 73 | return bRet; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump_with_ret/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | #ifeq "$(TARGET_ARCH_ABI)" "armeabi-v7a" 9 | ifneq ($(findstring $(TARGET_ARCH_ABI), "armeabi-v7a" "armeabi"),) 10 | 11 | #LOCAL_CXXFLAGS += -g -O0 12 | #LOCAL_ARM_MODE := arm 13 | LOCAL_MODULE := dump_with_ret 14 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 15 | LOCAL_SRC_FILES := ../mhk.c dump.c lr.cpp ../fixPCOpcode.c ../../asm/dump_with_ret.s 16 | 17 | 18 | include $(BUILD_STATIC_LIBRARY) 19 | 20 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump_with_ret/dump.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | 5 | extern unsigned long r_dump_start; 6 | extern unsigned long r_hk_info; 7 | extern unsigned long r_dump_end; 8 | 9 | //extern unsigned long _dump_start; 10 | //extern unsigned long _hk_info; 11 | //extern unsigned long _dump_end; 12 | 13 | 14 | #include "lr.h" 15 | 16 | /** 17 | * 利用dump_with_ret.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数,之后回调老函数,最好执行pInfo->allBack 18 | * @param pInfo inlinehook信息 19 | * @return inlinehook桩是否构造成功 20 | */ 21 | bool BuildStub_dump_with_ret(HK_INFO* pInfo) 22 | { 23 | bool bRet = false; 24 | 25 | LE("BuildStub_dump_with_ret"); 26 | while(1) 27 | { 28 | if(pInfo == NULL) 29 | { 30 | LOGI("pstInlineHook is null"); 31 | break; 32 | } 33 | 34 | 35 | void *p_shellcode_start_s = &r_dump_start; 36 | void *p_shellcode_end_s = &r_dump_end; 37 | void *p_hk_info = &r_hk_info; 38 | 39 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 40 | pInfo->shellCodeLength = sShellCodeLength; 41 | //malloc一段新的stub代码 42 | long pagesize = sysconf(_SC_PAGE_SIZE); 43 | void *pNewShellCode = NULL;// = malloc(sShellCodeLength); 44 | int code = posix_memalign(&pNewShellCode, pagesize, pagesize); 45 | 46 | LE("pNewShellCode=%p", pNewShellCode); 47 | if(code || pNewShellCode == NULL) 48 | { 49 | LOGI("shell code malloc fail."); 50 | break; 51 | } 52 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 53 | //更改stub代码页属性,改成可读可写可执行 54 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 55 | { 56 | LOGI("change shell code page property fail."); 57 | break; 58 | } 59 | 60 | 61 | pInfo->hk_infoAddr = pNewShellCode + (p_hk_info - p_shellcode_start_s); 62 | *(pInfo->hk_infoAddr) = pInfo; 63 | 64 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 65 | pInfo->pStubShellCodeAddr = pNewShellCode; 66 | 67 | // pInfo->pre_callback = pre_callback; 68 | // pInfo->aft_callback = aft_callback; 69 | 70 | pInfo->pre_callback = d_pre_callback; 71 | pInfo->aft_callback = d_aft_callback; 72 | pInfo->ppOriFuncAddr = NULL; 73 | 74 | bRet = true; 75 | break; 76 | } 77 | 78 | return bRet; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump_with_ret/lr.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "lr.h" 7 | 8 | /*typedef std::vector LRS; 9 | //static LRS lrs; 10 | 11 | struct STR_LR { 12 | 13 | }; 14 | typedef std::map LR_MAP; 15 | 16 | //typedef std::map TID_MAP; 17 | typedef std::map TID_MAP;*/ 18 | 19 | static TID_MAP* tid_map; 20 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 21 | 22 | TID_MAP * getTid_map(){ 23 | // pthread_mutex_init(&mutex, NULL); 24 | pthread_mutex_lock(&mutex); 25 | if (tid_map == NULL) { 26 | tid_map = new TID_MAP; 27 | } 28 | pthread_mutex_unlock(&mutex); 29 | return tid_map; 30 | } 31 | 32 | //因为不清楚tid分配机制,是否存在已死亡线程的tid重新分配给新建线程,所以可以ls -la /proc/8205/task/根据线程时间 33 | //判断是不是一个新线程,若是使用旧tid的新线程可以清空map,不过其实使用的栈结构存数据,理论上不区分也应该没问题的。 34 | void saveLR(void* key_fun, unsigned long lr){ 35 | pid_t tid = gettid(); 36 | TID_MAP *map = getTid_map(); 37 | pthread_mutex_lock(&mutex); 38 | auto it = map->find(tid); 39 | if (it == map->end()) { 40 | auto lr_map = new LR_MAP; 41 | auto ls = new LRS; 42 | ls->push_back(lr); 43 | lr_map->insert(std::make_pair(key_fun, ls)); 44 | map->insert(std::make_pair(tid, lr_map)); 45 | } else { 46 | auto lr_map = it->second; 47 | auto it_vt = lr_map->find(key_fun); 48 | if (it_vt == lr_map->end()) { 49 | auto ls = new LRS; 50 | ls->push_back(lr); 51 | lr_map->insert(std::make_pair(key_fun, ls)); 52 | } else { 53 | std::vector *vt = it_vt->second; 54 | vt->push_back(lr); 55 | } 56 | } 57 | pthread_mutex_unlock(&mutex); 58 | } 59 | 60 | unsigned long getLR(void* key_fun){ 61 | unsigned long lr = 0; 62 | pid_t tid = gettid(); 63 | TID_MAP *map = getTid_map(); 64 | pthread_mutex_lock(&mutex); 65 | auto it = map->find(tid); 66 | if (it == map->end()) { 67 | LE("what's happened ? not found tid=%d", tid);//理论上不应该出现 68 | } else { 69 | auto lr_map = it->second; 70 | auto it_vt = lr_map->find(key_fun); 71 | if (it_vt == lr_map->end()) { 72 | LE("what's happened ? not found LR for=%p in tid=%d", key_fun, tid);//理论上不应该出现 73 | } else { 74 | std::vector *vt = it_vt->second; 75 | if (!vt || vt->empty()) { 76 | LE("what's happened ? null LR for=%p in tid=%d", key_fun, tid); 77 | } else { 78 | unsigned long size = vt->size(); 79 | lr = (*vt)[size - 1]; 80 | vt->pop_back(); 81 | } 82 | } 83 | } 84 | pthread_mutex_unlock(&mutex); 85 | return lr; 86 | } 87 | 88 | void pre_callback(struct my_pt_regs *regs, HK_INFO* info){ 89 | LE("dump_with_ret pre_callback"); 90 | saveLR(info->pBeHookAddr, regs->ARM_lr); 91 | if (info->onPreCallBack) 92 | info->onPreCallBack(regs, info); 93 | } 94 | 95 | void aft_callback(struct my_pt_regs *regs, HK_INFO* info){ 96 | LE("dump_with_ret aft_callback"); 97 | unsigned long lr = getLR(info->pBeHookAddr); 98 | regs->ARM_lr = lr; 99 | if (info->onCallBack) 100 | info->onCallBack(regs, info); 101 | } 102 | 103 | 104 | callback d_pre_callback = pre_callback; 105 | callback d_aft_callback = aft_callback; 106 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/dump_with_ret/lr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/19. 3 | // 4 | 5 | #ifndef MY_INHK_LR_H 6 | #define MY_INHK_LR_H 7 | 8 | #ifdef __cplusplus 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | typedef std::vector LRS; 15 | //static LRS lrs; 16 | 17 | struct STR_LR { 18 | 19 | }; 20 | typedef std::map LR_MAP; 21 | 22 | //typedef std::map TID_MAP; 23 | typedef std::map TID_MAP; 24 | 25 | static TID_MAP * getTid_map(); 26 | 27 | static void saveLR(void* key_fun, unsigned long lr); 28 | 29 | static unsigned long getLR(void* key_fun); 30 | 31 | #endif 32 | 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #include "mhk.h" 39 | 40 | //因为会被导出,所以两个静态库中存在两个同名函数,另一个被覆盖了。 41 | //extern void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 42 | static void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 43 | 44 | //extern void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 45 | static void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 46 | typedef void (*callback)(struct my_pt_regs *regs, HK_INFO* info); 47 | extern callback d_pre_callback;// = pre_callback; 48 | extern callback d_aft_callback;// = aft_callback; 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | 55 | #endif //MY_INHK_LR_H 56 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/fixPCOpcode.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIXOPCODE_H 2 | #define _FIXOPCODE_H 3 | 4 | #include 5 | #include "mhk.h" 6 | 7 | #define ALIGN_PC(pc) (pc & 0xFFFFFFFC) 8 | 9 | bool isThumb32(uint16_t opcode); 10 | bool isTargetAddrInBackup(uint32_t target_addr, uint32_t hook_addr, int backup_length); 11 | 12 | int lengthFixThumb32(uint32_t opcode); 13 | int lengthFixArm32(uint32_t opcode); 14 | int lengthFixThumb16(uint16_t opcode); 15 | 16 | static int getTypeInArm32(uint32_t instruction); 17 | static int getTypeInThumb16(uint16_t instruction); 18 | static int getTypeInThumb32(uint32_t instruction); 19 | 20 | 21 | int fixPCOpcodeArm(void *fixOpcodes , HK_INFO* info); 22 | int fixPCOpcodeThumb(void *fixOpcodes , HK_INFO* info); 23 | int fixPCOpcodeArm32(uint32_t pc, uint32_t lr, uint32_t instruction, uint32_t *trampoline_instructions, HK_INFO* info); 24 | int fixPCOpcodeThumb16(uint32_t pc, uint16_t instruction, uint16_t *trampoline_instructions, HK_INFO* info); 25 | int fixPCOpcodeThumb32(uint32_t pc, uint16_t high_instruction, uint16_t low_instruction, uint16_t *trampoline_instructions, HK_INFO* info); 26 | 27 | #endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/replace/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | #ifeq ($(TARGET_ARCH_ABI)_$(TARGET_ARCH_ABI) armeabi-v7a_armeabi) 9 | ifneq ($(findstring $(TARGET_ARCH_ABI), "armeabi-v7a" "armeabi"),) 10 | 11 | #LOCAL_CXXFLAGS += -g -O0 12 | #LOCAL_ARM_MODE := arm 13 | LOCAL_MODULE := replace 14 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 15 | LOCAL_SRC_FILES := ../mhk.c replace.c lr.cpp ../fixPCOpcode.c ../../asm/replace.s 16 | 17 | 18 | include $(BUILD_STATIC_LIBRARY) 19 | 20 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/replace/lr.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "lr.h" 7 | 8 | /*typedef std::vector LRS; 9 | //static LRS lrs; 10 | 11 | struct STR_LR { 12 | 13 | }; 14 | typedef std::map LR_MAP; 15 | 16 | //typedef std::map TID_MAP; 17 | typedef std::map TID_MAP;*/ 18 | 19 | static TID_MAP* tid_map; 20 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 21 | 22 | TID_MAP * getTid_map(){ 23 | // pthread_mutex_init(&mutex, NULL); 24 | pthread_mutex_lock(&mutex); 25 | if (tid_map == NULL) { 26 | tid_map = new TID_MAP; 27 | } 28 | pthread_mutex_unlock(&mutex); 29 | return tid_map; 30 | } 31 | 32 | 33 | void saveLR(void* key_fun, unsigned long lr){ 34 | pid_t tid = gettid(); 35 | TID_MAP *map = getTid_map(); 36 | pthread_mutex_lock(&mutex); 37 | auto it = map->find(tid); 38 | if (it == map->end()) { 39 | auto lr_map = new LR_MAP; 40 | auto ls = new LRS; 41 | ls->push_back(lr); 42 | lr_map->insert(std::make_pair(key_fun, ls)); 43 | map->insert(std::make_pair(tid, lr_map)); 44 | } else { 45 | auto lr_map = it->second; 46 | auto it_vt = lr_map->find(key_fun); 47 | if (it_vt == lr_map->end()) { 48 | auto ls = new LRS; 49 | ls->push_back(lr); 50 | lr_map->insert(std::make_pair(key_fun, ls)); 51 | } else { 52 | std::vector *vt = it_vt->second; 53 | vt->push_back(lr); 54 | } 55 | } 56 | pthread_mutex_unlock(&mutex); 57 | } 58 | 59 | unsigned long getLR(void* key_fun){ 60 | unsigned long lr = 0; 61 | pid_t tid = gettid(); 62 | TID_MAP *map = getTid_map(); 63 | pthread_mutex_lock(&mutex); 64 | auto it = map->find(tid); 65 | if (it == map->end()) { 66 | LE("what's happened ? not found tid=%d", tid);//理论上不应该出现 67 | } else { 68 | auto lr_map = it->second; 69 | auto it_vt = lr_map->find(key_fun); 70 | if (it_vt == lr_map->end()) { 71 | LE("what's happened ? not found LR for=%p in tid=%d", key_fun, tid);//理论上不应该出现 72 | } else { 73 | std::vector *vt = it_vt->second; 74 | if (!vt || vt->empty()) { 75 | LE("what's happened ? null LR for=%p in tid=%d", key_fun, tid); 76 | } else { 77 | unsigned long size = vt->size(); 78 | lr = (*vt)[size - 1]; 79 | vt->pop_back(); 80 | } 81 | } 82 | } 83 | pthread_mutex_unlock(&mutex); 84 | return lr; 85 | } 86 | 87 | void pre_callback(struct my_pt_regs *regs, HK_INFO* info){ 88 | LE("lr pre_callback"); 89 | saveLR(info->pBeHookAddr, regs->ARM_lr); 90 | if (info->onPreCallBack) 91 | info->onPreCallBack(regs, info); 92 | } 93 | 94 | void aft_callback(struct my_pt_regs *regs, HK_INFO* info){ 95 | LE("lr aft_callback"); 96 | unsigned long lr = getLR(info->pBeHookAddr); 97 | regs->ARM_lr = lr; 98 | if (info->onCallBack) 99 | info->onCallBack(regs, info); 100 | } 101 | 102 | callback r_pre_callback = pre_callback; 103 | callback r_aft_callback = aft_callback; -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/replace/lr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/19. 3 | // 4 | 5 | #ifndef MY_INHK_LR_H 6 | #define MY_INHK_LR_H 7 | 8 | #ifdef __cplusplus 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | typedef std::vector LRS; 15 | //static LRS lrs; 16 | 17 | struct STR_LR { 18 | 19 | }; 20 | typedef std::map LR_MAP; 21 | 22 | //typedef std::map TID_MAP; 23 | typedef std::map TID_MAP; 24 | 25 | static TID_MAP * getTid_map(); 26 | 27 | static void saveLR(void* key_fun, unsigned long lr); 28 | 29 | static unsigned long getLR(void* key_fun); 30 | 31 | #endif 32 | 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #include "mhk.h" 39 | 40 | //因为会被导出,所以两个静态库中存在两个同名函数,另一个被覆盖了。 41 | //extern void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 42 | static void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 43 | 44 | //extern void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 45 | static void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 46 | typedef void (*callback)(struct my_pt_regs *regs, HK_INFO* info); 47 | extern callback r_pre_callback;// = pre_callback; 48 | extern callback r_aft_callback;// = aft_callback; 49 | 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | 56 | #endif //MY_INHK_LR_H 57 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm/src/replace/replace.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | #define ALIGN_PC(pc) (pc & 0xFFFFFFFC) 5 | 6 | extern unsigned long replace_start; 7 | extern unsigned long p_hk_info; 8 | extern unsigned long replace_end; 9 | 10 | //extern unsigned long _dump_start; 11 | //extern unsigned long _hk_info; 12 | //extern unsigned long _dump_end; 13 | 14 | 15 | #include "lr.h" 16 | 17 | /** 18 | * 利用replace.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数,之后回调hook函数,最后执行pInfo->allBack 19 | * @param pInfo inlinehook信息 20 | * @return inlinehook桩是否构造成功 21 | */ 22 | bool BuildStub_replace(HK_INFO* pInfo) 23 | { 24 | bool bRet = false; 25 | 26 | LE("BuildStub_replace"); 27 | while(1) 28 | { 29 | if(pInfo == NULL) 30 | { 31 | LOGI("HK_INFO is null"); 32 | break; 33 | } 34 | 35 | 36 | void *p_shellcode_start_s = &replace_start; 37 | void *p_shellcode_end_s = &replace_end; 38 | void *t_hk_info = &p_hk_info; 39 | 40 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 41 | pInfo->shellCodeLength = sShellCodeLength; 42 | LE("sShellCodeLength=%ld", sShellCodeLength); 43 | //malloc一段新的stub代码 44 | //signal 11 (SIGSEGV), code 2 (SEGV_ACCERR) 45 | long pagesize = sysconf(_SC_PAGE_SIZE); 46 | void *pNewShellCode = NULL;// = malloc(sShellCodeLength); 47 | // void *pNewShellCode = malloc(sShellCodeLength); 48 | int code = posix_memalign(&pNewShellCode, pagesize, pagesize); 49 | LE("pNewShellCode=%p", pNewShellCode); 50 | if(code || pNewShellCode == NULL) 51 | { 52 | LOGI("shell code malloc fail."); 53 | break; 54 | } 55 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 56 | //更改stub代码页属性,改成可读可写可执行 57 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 58 | { 59 | LOGI("change shell code page property fail."); 60 | break; 61 | } 62 | 63 | 64 | pInfo->hk_infoAddr = pNewShellCode + (t_hk_info - p_shellcode_start_s); 65 | *(pInfo->hk_infoAddr) = pInfo; 66 | 67 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 68 | pInfo->pStubShellCodeAddr = pNewShellCode; 69 | 70 | // pInfo->pre_callback = pre_callback; 71 | pInfo->pre_callback = r_pre_callback; 72 | // pInfo->aft_callback = aft_callback; 73 | pInfo->aft_callback = r_aft_callback; 74 | 75 | pInfo->ppOriFuncAddr = NULL; 76 | 77 | bRet = true; 78 | break; 79 | } 80 | 81 | return bRet; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/Android.mk: -------------------------------------------------------------------------------- 1 | $(warning "abi: $(TARGET_ARCH_ABI)") 2 | include $(call all-subdir-makefiles) 3 | $(warning "abi: $(TARGET_ARCH_ABI)") 4 | 5 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/base.s: -------------------------------------------------------------------------------- 1 | .global _dump_start 2 | .global _dump_end 3 | .global _hk_info 4 | 5 | .hidden _dump_start 6 | .hidden _dump_end 7 | .hidden _hk_info -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/dump.s: -------------------------------------------------------------------------------- 1 | .include "../../asm/base.s" 2 | 3 | //.extern _dump_start 4 | //.extern _dump_end 5 | //.extern _hk_info 6 | 7 | //.set _dump_start, r_dump_start 8 | //.set _dump_end, r__dump_end 9 | //.set _hk_info, r__hk_info 10 | 11 | //.global _dump_start 12 | //.global _dump_end 13 | //.global _hk_info 14 | 15 | //.hidden _dump_start 16 | //.hidden _dump_end 17 | //.hidden _hk_info 18 | 19 | //可用于标准的c/c++函数、非标准函数、函数的一部分(用于读写寄存器),前提都是字节长度足够 20 | //非标准函数即非c/c++编译的函数,那么手写汇编可能存在并不遵守约定的情况,比如我们使用了sp寄存器,并在未使用的栈上保存寄存器 21 | //但是可能不是满递减而是反过来满递增,或者不遵守栈平衡,往栈上写数据,但是并不改变sp寄存器。当然应该是很少见的。 22 | 23 | .data 24 | 25 | _dump_start: //用于读写寄存器/栈,需要自己解析参数,不能读写返回值,不能阻止原函数(被hook函数)的执行 26 | //从行为上来我觉得更偏向dump,所以起名为dump。 27 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 28 | 29 | mrs x0, NZCV 30 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 31 | str x30, [sp]; //存储x30 32 | add x30, sp, #0x20 33 | str x30, [sp, #0x8]; //存储真实的sp 34 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 35 | 36 | save_x0_x29://保存寄存器x0-x29 37 | sub sp, sp, #0xf0; //分配栈空间 38 | stp X0, X1, [SP]; //存储x0-x29 39 | stp X2, X3, [SP,#0x10] 40 | stp X4, X5, [SP,#0x20] 41 | stp X6, X7, [SP,#0x30] 42 | stp X8, X9, [SP,#0x40] 43 | stp X10, X11, [SP,#0x50] 44 | stp X12, X13, [SP,#0x60] 45 | stp X14, X15, [SP,#0x70] 46 | stp X16, X17, [SP,#0x80] 47 | stp X18, X19, [SP,#0x90] 48 | stp X20, X21, [SP,#0xa0] 49 | stp X22, X23, [SP,#0xb0] 50 | stp X24, X25, [SP,#0xc0] 51 | stp X26, X27, [SP,#0xd0] 52 | stp X28, X29, [SP,#0xe0] 53 | 54 | call_onPreCallBack://调用onPreCallBack函数,第一个参数是sp,第二个参数是STR_HK_INFO结构体指针 55 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 56 | ldr x1, _hk_info; 57 | ldr x3, [x1]; //onPreCallBack 58 | bl get_lr_pc; //lr为下条指令 59 | add lr, lr, #8; //lr为blr x3的地址 60 | str lr, [sp, #0x108]; //lr当作pc,覆盖栈上的x0 61 | blr x3 62 | 63 | restore_regs://恢复寄存器 64 | ldr x0, [sp, #0x100]; //取出状态寄存器 65 | msr NZCV, x0 66 | 67 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 68 | ldp X2, X3, [SP,#0x10] 69 | ldp X4, X5, [SP,#0x20] 70 | ldp X6, X7, [SP,#0x30] 71 | ldp X8, X9, [SP,#0x40] 72 | ldp X10, X11, [SP,#0x50] 73 | ldp X12, X13, [SP,#0x60] 74 | ldp X14, X15, [SP,#0x70] 75 | ldp X16, X17, [SP,#0x80] 76 | ldp X18, X19, [SP,#0x90] 77 | ldp X20, X21, [SP,#0xa0] 78 | ldp X22, X23, [SP,#0xb0] 79 | ldp X24, X25, [SP,#0xc0] 80 | ldp X26, X27, [SP,#0xd0] 81 | ldp X28, X29, [SP,#0xe0] 82 | add sp, sp, #0xf0 83 | 84 | ldr x30, [sp]; //恢复x30 85 | add sp, sp, #0x20; //恢复为真实sp 86 | 87 | call_oriFun: 88 | stp X1, X0, [SP, #-0x10]; //因为跳转还要占用一个寄存器,所以保存 89 | ldr x0, _hk_info; 90 | ldr x0, [x0, #8]; //pOriFuncAddr 91 | br x0 92 | 93 | get_lr_pc: 94 | ret; //仅用于获取LR/PC 95 | 96 | _hk_info: //结构体STR_HK_INFO 97 | .double 0xffffffffffffffff 98 | 99 | _dump_end: 100 | 101 | .end 102 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/dump_just_ret.s: -------------------------------------------------------------------------------- 1 | .global j_dump_start 2 | .global j_dump_end 3 | .global j_hk_info 4 | 5 | .hidden j_dump_start 6 | .hidden j_dump_end 7 | .hidden j_hk_info 8 | 9 | 10 | .data 11 | 12 | j_dump_start: 13 | 14 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 15 | 16 | mrs x0, NZCV 17 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 18 | str x30, [sp]; //存储x30 19 | add x30, sp, #0x20 20 | str x30, [sp, #0x8]; //存储真实的sp 21 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 22 | 23 | sub sp, sp, #0xf0; //分配栈空间 24 | stp X0, X1, [SP]; //存储x0-x29 25 | stp X2, X3, [SP,#0x10] 26 | stp X4, X5, [SP,#0x20] 27 | stp X6, X7, [SP,#0x30] 28 | stp X8, X9, [SP,#0x40] 29 | stp X10, X11, [SP,#0x50] 30 | stp X12, X13, [SP,#0x60] 31 | stp X14, X15, [SP,#0x70] 32 | stp X16, X17, [SP,#0x80] 33 | stp X18, X19, [SP,#0x90] 34 | stp X20, X21, [SP,#0xa0] 35 | stp X22, X23, [SP,#0xb0] 36 | stp X24, X25, [SP,#0xc0] 37 | stp X26, X27, [SP,#0xd0] 38 | stp X28, X29, [SP,#0xe0] 39 | 40 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 41 | ldr x1, j_hk_info; 42 | ldr x3, [x1]; //onPreCallBack 43 | bl get_lr_pc; //lr为下条指令 44 | add lr, lr, 8; //lr为blr x3的地址 45 | str lr, [sp, #0x108]; //lr当作pc,覆盖栈上的x0 46 | blr x3 47 | 48 | to_popreg: 49 | ldr x0, [sp, #0x100]; //取出状态寄存器 50 | msr NZCV, x0 51 | 52 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 53 | ldp X2, X3, [SP,#0x10] 54 | ldp X4, X5, [SP,#0x20] 55 | ldp X6, X7, [SP,#0x30] 56 | ldp X8, X9, [SP,#0x40] 57 | ldp X10, X11, [SP,#0x50] 58 | ldp X12, X13, [SP,#0x60] 59 | ldp X14, X15, [SP,#0x70] 60 | ldp X16, X17, [SP,#0x80] 61 | ldp X18, X19, [SP,#0x90] 62 | ldp X20, X21, [SP,#0xa0] 63 | ldp X22, X23, [SP,#0xb0] 64 | ldp X24, X25, [SP,#0xc0] 65 | ldp X26, X27, [SP,#0xd0] 66 | ldp X28, X29, [SP,#0xe0] 67 | add sp, sp, #0xf0 68 | 69 | ldr x30, [sp]; //恢复x30 70 | add sp, sp, #0x20; //恢复为真实sp 71 | 72 | 73 | get_lr_pc: 74 | ret; //仅用于获取LR/PC 75 | 76 | j_hk_info: //结构体STR_HK_INFO 77 | .double 0xffffffffffffffff 78 | 79 | j_dump_end: 80 | 81 | .end 82 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/dump_neon.s: -------------------------------------------------------------------------------- 1 | .include "../../asm/base.s" 2 | 3 | //.extern _dump_start 4 | //.extern _dump_end 5 | //.extern _hk_info 6 | 7 | //.set _dump_start, r_dump_start 8 | //.set _dump_end, r__dump_end 9 | //.set _hk_info, r__hk_info 10 | 11 | //.global _dump_start 12 | //.global _dump_end 13 | //.global _hk_info 14 | 15 | //.hidden _dump_start 16 | //.hidden _dump_end 17 | //.hidden _hk_info 18 | 19 | //可用于标准的c/c++函数、非标准函数、函数的一部分(用于读写寄存器),前提都是字节长度足够 20 | //非标准函数即非c/c++编译的函数,那么手写汇编可能存在并不遵守约定的情况,比如我们使用了sp寄存器,并在未使用的栈上保存寄存器 21 | //但是可能不是满递减而是反过来满递增,或者不遵守栈平衡,往栈上写数据,但是并不改变sp寄存器。当然应该是很少见的。 22 | 23 | .data 24 | 25 | _dump_start: //用于读写寄存器/栈,需要自己解析参数,不能读写返回值,不能阻止原函数(被hook函数)的执行 26 | //从行为上来我觉得更偏向dump,所以起名为dump。 27 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 28 | 29 | mrs x0, NZCV 30 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 31 | str x30, [sp]; //存储x30 32 | add x30, sp, #0x20 33 | str x30, [sp, #0x8]; //存储真实的sp 34 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 35 | 36 | save_x0_x29://保存寄存器x0-x29 37 | sub sp, sp, #0xf0; //分配栈空间 38 | stp X0, X1, [SP]; //存储x0-x29 39 | stp X2, X3, [SP,#0x10] 40 | stp X4, X5, [SP,#0x20] 41 | stp X6, X7, [SP,#0x30] 42 | stp X8, X9, [SP,#0x40] 43 | stp X10, X11, [SP,#0x50] 44 | stp X12, X13, [SP,#0x60] 45 | stp X14, X15, [SP,#0x70] 46 | stp X16, X17, [SP,#0x80] 47 | stp X18, X19, [SP,#0x90] 48 | stp X20, X21, [SP,#0xa0] 49 | stp X22, X23, [SP,#0xb0] 50 | stp X24, X25, [SP,#0xc0] 51 | stp X26, X27, [SP,#0xd0] 52 | stp X28, X29, [SP,#0xe0] 53 | 54 | save_v0_v31: 55 | sub sp, sp, #0x200; //分配栈空间 56 | #stp D0, D1, [SP]; //理论上是不是只保存存储double的部分就可以? 57 | stp Q0, Q1, [SP]; //不支持V0-V31,但是支持Q0-Q31,一致,每个寄存器占128位,低64位保存double,低32位float 58 | stp Q2, Q3, [SP, #0x20]; 59 | stp Q4, Q5, [SP, #0x40]; 60 | stp Q6, Q7, [SP, #0x60]; 61 | stp Q8, Q9, [SP, #0x80]; 62 | stp Q10, Q11, [SP, #0xa0]; 63 | stp Q12, Q13, [SP, #0xc0]; 64 | stp Q14, Q15, [SP, #0xe0]; 65 | 66 | stp Q16, Q17, [SP, #0x100]; 67 | stp Q18, Q19, [SP, #0x120]; 68 | stp Q20, Q21, [SP, #0x140]; 69 | stp Q22, Q23, [SP, #0x160]; 70 | stp Q24, Q25, [SP, #0x180]; 71 | stp Q26, Q27, [SP, #0x1a0]; 72 | stp Q28, Q29, [SP, #0x1c0]; 73 | stp Q30, Q31, [SP, #0x1e0]; 74 | 75 | call_onPreCallBack://调用onPreCallBack函数,第一个参数是sp,第二个参数是STR_HK_INFO结构体指针 76 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 77 | ldr x1, _hk_info; 78 | ldr x3, [x1]; //onPreCallBack 79 | bl get_lr_pc; //lr为下条指令 80 | add lr, lr, #8; //lr为blr x3的地址 81 | str lr, [sp, #0x308]; //lr当作pc,覆盖栈上的x0 82 | blr x3 83 | 84 | restore_regs://恢复寄存器 85 | #ldp D0, D1, [SP]; 86 | ldp Q0, Q1, [SP]; 87 | ldp Q2, Q3, [SP, #0x20]; 88 | ldp Q4, Q5, [SP, #0x40]; 89 | ldp Q6, Q7, [SP, #0x60]; 90 | ldp Q8, Q9, [SP, #0x80]; 91 | ldp Q10, Q11, [SP, #0xa0]; 92 | ldp Q12, Q13, [SP, #0xc0]; 93 | ldp Q14, Q15, [SP, #0xe0]; 94 | 95 | ldp Q16, Q17, [SP, #0x100]; 96 | ldp Q18, Q19, [SP, #0x120]; 97 | ldp Q20, Q21, [SP, #0x140]; 98 | ldp Q22, Q23, [SP, #0x160]; 99 | ldp Q24, Q25, [SP, #0x180]; 100 | ldp Q26, Q27, [SP, #0x1a0]; 101 | ldp Q28, Q29, [SP, #0x1c0]; 102 | ldp Q30, Q31, [SP, #0x1e0]; 103 | add sp, sp, #0x200; 104 | 105 | ldr x0, [sp, #0x100]; //取出状态寄存器 106 | msr NZCV, x0 107 | 108 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 109 | ldp X2, X3, [SP,#0x10] 110 | ldp X4, X5, [SP,#0x20] 111 | ldp X6, X7, [SP,#0x30] 112 | ldp X8, X9, [SP,#0x40] 113 | ldp X10, X11, [SP,#0x50] 114 | ldp X12, X13, [SP,#0x60] 115 | ldp X14, X15, [SP,#0x70] 116 | ldp X16, X17, [SP,#0x80] 117 | ldp X18, X19, [SP,#0x90] 118 | ldp X20, X21, [SP,#0xa0] 119 | ldp X22, X23, [SP,#0xb0] 120 | ldp X24, X25, [SP,#0xc0] 121 | ldp X26, X27, [SP,#0xd0] 122 | ldp X28, X29, [SP,#0xe0] 123 | add sp, sp, #0xf0 124 | 125 | ldr x30, [sp]; //恢复x30 126 | add sp, sp, #0x20; //恢复为真实sp 127 | 128 | call_oriFun: 129 | stp X1, X0, [SP, #-0x10]; //因为跳转还要占用一个寄存器,所以保存 130 | ldr x0, _hk_info; 131 | ldr x0, [x0, #8]; //pOriFuncAddr 132 | br x0 133 | 134 | get_lr_pc: 135 | ret; //仅用于获取LR/PC 136 | 137 | _hk_info: //结构体STR_HK_INFO 138 | .double 0xffffffffffffffff 139 | 140 | _dump_end: 141 | 142 | .end 143 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/dump_neon_just_ret.s: -------------------------------------------------------------------------------- 1 | .global j_dump_start 2 | .global j_dump_end 3 | .global j_hk_info 4 | 5 | .hidden j_dump_start 6 | .hidden j_dump_end 7 | .hidden j_hk_info 8 | 9 | 10 | .data 11 | 12 | j_dump_start: 13 | 14 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 15 | 16 | mrs x0, NZCV 17 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 18 | str x30, [sp]; //存储x30 19 | add x30, sp, #0x20 20 | str x30, [sp, #0x8]; //存储真实的sp 21 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 22 | 23 | sub sp, sp, #0xf0; //分配栈空间 24 | stp X0, X1, [SP]; //存储x0-x29 25 | stp X2, X3, [SP,#0x10] 26 | stp X4, X5, [SP,#0x20] 27 | stp X6, X7, [SP,#0x30] 28 | stp X8, X9, [SP,#0x40] 29 | stp X10, X11, [SP,#0x50] 30 | stp X12, X13, [SP,#0x60] 31 | stp X14, X15, [SP,#0x70] 32 | stp X16, X17, [SP,#0x80] 33 | stp X18, X19, [SP,#0x90] 34 | stp X20, X21, [SP,#0xa0] 35 | stp X22, X23, [SP,#0xb0] 36 | stp X24, X25, [SP,#0xc0] 37 | stp X26, X27, [SP,#0xd0] 38 | stp X28, X29, [SP,#0xe0] 39 | 40 | save_v0_v31: 41 | sub sp, sp, #0x200; //分配栈空间 42 | #stp D0, D1, [SP]; //理论上是不是只保存存储double的部分就可以? 43 | stp Q0, Q1, [SP]; //不支持V0-V31,但是支持Q0-Q31,一致,每个寄存器占128位,低64位保存double,低32位float 44 | stp Q2, Q3, [SP, #0x20]; 45 | stp Q4, Q5, [SP, #0x40]; 46 | stp Q6, Q7, [SP, #0x60]; 47 | stp Q8, Q9, [SP, #0x80]; 48 | stp Q10, Q11, [SP, #0xa0]; 49 | stp Q12, Q13, [SP, #0xc0]; 50 | stp Q14, Q15, [SP, #0xe0]; 51 | 52 | stp Q16, Q17, [SP, #0x100]; 53 | stp Q18, Q19, [SP, #0x120]; 54 | stp Q20, Q21, [SP, #0x140]; 55 | stp Q22, Q23, [SP, #0x160]; 56 | stp Q24, Q25, [SP, #0x180]; 57 | stp Q26, Q27, [SP, #0x1a0]; 58 | stp Q28, Q29, [SP, #0x1c0]; 59 | stp Q30, Q31, [SP, #0x1e0]; 60 | 61 | call_onPreCallBack: 62 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 63 | ldr x1, j_hk_info; 64 | ldr x3, [x1]; //onPreCallBack 65 | bl get_lr_pc; //lr为下条指令 66 | add lr, lr, 8; //lr为blr x3的地址 67 | str lr, [sp, #0x308]; //lr当作pc,覆盖栈上的x0 68 | blr x3 69 | 70 | to_popreg: 71 | #ldp D0, D1, [SP]; 72 | ldp Q0, Q1, [SP]; 73 | ldp Q2, Q3, [SP, #0x20]; 74 | ldp Q4, Q5, [SP, #0x40]; 75 | ldp Q6, Q7, [SP, #0x60]; 76 | ldp Q8, Q9, [SP, #0x80]; 77 | ldp Q10, Q11, [SP, #0xa0]; 78 | ldp Q12, Q13, [SP, #0xc0]; 79 | ldp Q14, Q15, [SP, #0xe0]; 80 | 81 | ldp Q16, Q17, [SP, #0x100]; 82 | ldp Q18, Q19, [SP, #0x120]; 83 | ldp Q20, Q21, [SP, #0x140]; 84 | ldp Q22, Q23, [SP, #0x160]; 85 | ldp Q24, Q25, [SP, #0x180]; 86 | ldp Q26, Q27, [SP, #0x1a0]; 87 | ldp Q28, Q29, [SP, #0x1c0]; 88 | ldp Q30, Q31, [SP, #0x1e0]; 89 | add sp, sp, #0x200; 90 | 91 | ldr x0, [sp, #0x100]; //取出状态寄存器 92 | msr NZCV, x0 93 | 94 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 95 | ldp X2, X3, [SP,#0x10] 96 | ldp X4, X5, [SP,#0x20] 97 | ldp X6, X7, [SP,#0x30] 98 | ldp X8, X9, [SP,#0x40] 99 | ldp X10, X11, [SP,#0x50] 100 | ldp X12, X13, [SP,#0x60] 101 | ldp X14, X15, [SP,#0x70] 102 | ldp X16, X17, [SP,#0x80] 103 | ldp X18, X19, [SP,#0x90] 104 | ldp X20, X21, [SP,#0xa0] 105 | ldp X22, X23, [SP,#0xb0] 106 | ldp X24, X25, [SP,#0xc0] 107 | ldp X26, X27, [SP,#0xd0] 108 | ldp X28, X29, [SP,#0xe0] 109 | add sp, sp, #0xf0 110 | 111 | ldr x30, [sp]; //恢复x30 112 | add sp, sp, #0x20; //恢复为真实sp 113 | 114 | 115 | get_lr_pc: 116 | ret; //仅用于获取LR/PC 117 | 118 | j_hk_info: //结构体STR_HK_INFO 119 | .double 0xffffffffffffffff 120 | 121 | j_dump_end: 122 | 123 | .end 124 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/dump_neon_with_ret.s: -------------------------------------------------------------------------------- 1 | //.include "../../asm/base.s" 2 | 3 | .global r_dump_start 4 | .global r_dump_end 5 | .global r_hk_info 6 | 7 | .hidden r_dump_start 8 | .hidden r_dump_end 9 | .hidden r_hk_info 10 | 11 | 12 | .data 13 | 14 | r_dump_start: //用于读写寄存器/栈,需要自己解析参数,不能读写返回值,不能阻止原函数(被hook函数)的执行 15 | //从行为上来我觉得更偏向dump,所以起名为dump。 16 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 17 | 18 | mrs x0, NZCV 19 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 20 | str x30, [sp]; //存储x30 21 | add x30, sp, #0x20 22 | str x30, [sp, #0x8]; //存储真实的sp 23 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 24 | 25 | save_x0_x29://保存寄存器x0-x29 26 | sub sp, sp, #0xf0; //分配栈空间 27 | stp X0, X1, [SP]; //存储x0-x29 28 | stp X2, X3, [SP,#0x10] 29 | stp X4, X5, [SP,#0x20] 30 | stp X6, X7, [SP,#0x30] 31 | stp X8, X9, [SP,#0x40] 32 | stp X10, X11, [SP,#0x50] 33 | stp X12, X13, [SP,#0x60] 34 | stp X14, X15, [SP,#0x70] 35 | stp X16, X17, [SP,#0x80] 36 | stp X18, X19, [SP,#0x90] 37 | stp X20, X21, [SP,#0xa0] 38 | stp X22, X23, [SP,#0xb0] 39 | stp X24, X25, [SP,#0xc0] 40 | stp X26, X27, [SP,#0xd0] 41 | stp X28, X29, [SP,#0xe0] 42 | 43 | save_v0_v31: 44 | sub sp, sp, #0x200; //分配栈空间 45 | #stp D0, D1, [SP]; //理论上是不是只保存存储double的部分就可以? 46 | stp Q0, Q1, [SP]; //不支持V0-V31,但是支持Q0-Q31,一致,每个寄存器占128位,低64位保存double,低32位float 47 | stp Q2, Q3, [SP, #0x20]; 48 | stp Q4, Q5, [SP, #0x40]; 49 | stp Q6, Q7, [SP, #0x60]; 50 | stp Q8, Q9, [SP, #0x80]; 51 | stp Q10, Q11, [SP, #0xa0]; 52 | stp Q12, Q13, [SP, #0xc0]; 53 | stp Q14, Q15, [SP, #0xe0]; 54 | 55 | stp Q16, Q17, [SP, #0x100]; 56 | stp Q18, Q19, [SP, #0x120]; 57 | stp Q20, Q21, [SP, #0x140]; 58 | stp Q22, Q23, [SP, #0x160]; 59 | stp Q24, Q25, [SP, #0x180]; 60 | stp Q26, Q27, [SP, #0x1a0]; 61 | stp Q28, Q29, [SP, #0x1c0]; 62 | stp Q30, Q31, [SP, #0x1e0]; 63 | 64 | call_onPreCallBack://调用onPreCallBack函数,第一个参数是sp,第二个参数是STR_HK_INFO结构体指针 65 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 66 | ldr x1, r_hk_info; 67 | ldr x3, [x1, #0x10]; //pre_callback 68 | bl get_lr_pc; //lr为下条指令 69 | add lr, lr, 8; //lr为blr x3的地址 70 | str lr, [sp, #0x308]; //lr当作pc,覆盖栈上的x0 71 | blr x3 72 | 73 | to_call_oriFun: 74 | #ldp D0, D1, [SP]; 75 | ldp Q0, Q1, [SP]; 76 | ldp Q2, Q3, [SP, #0x20]; 77 | ldp Q4, Q5, [SP, #0x40]; 78 | ldp Q6, Q7, [SP, #0x60]; 79 | ldp Q8, Q9, [SP, #0x80]; 80 | ldp Q10, Q11, [SP, #0xa0]; 81 | ldp Q12, Q13, [SP, #0xc0]; 82 | ldp Q14, Q15, [SP, #0xe0]; 83 | 84 | ldp Q16, Q17, [SP, #0x100]; 85 | ldp Q18, Q19, [SP, #0x120]; 86 | ldp Q20, Q21, [SP, #0x140]; 87 | ldp Q22, Q23, [SP, #0x160]; 88 | ldp Q24, Q25, [SP, #0x180]; 89 | ldp Q26, Q27, [SP, #0x1a0]; 90 | ldp Q28, Q29, [SP, #0x1c0]; 91 | ldp Q30, Q31, [SP, #0x1e0]; 92 | add sp, sp, #0x200; 93 | 94 | ldr x0, [sp, #0x100]; //取出状态寄存器 95 | msr NZCV, x0 96 | 97 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 98 | ldp X2, X3, [SP,#0x10] 99 | ldp X4, X5, [SP,#0x20] 100 | ldp X6, X7, [SP,#0x30] 101 | ldp X8, X9, [SP,#0x40] 102 | ldp X10, X11, [SP,#0x50] 103 | ldp X12, X13, [SP,#0x60] 104 | ldp X14, X15, [SP,#0x70] 105 | ldp X16, X17, [SP,#0x80] 106 | ldp X18, X19, [SP,#0x90] 107 | ldp X20, X21, [SP,#0xa0] 108 | ldp X22, X23, [SP,#0xb0] 109 | ldp X24, X25, [SP,#0xc0] 110 | ldp X26, X27, [SP,#0xd0] 111 | ldp X28, X29, [SP,#0xe0] 112 | add sp, sp, #0xf0 113 | 114 | ldr x30, [sp]; //恢复x30 115 | add sp, sp, #0x20; //恢复为真实sp 116 | 117 | stp X1, X0, [SP, #-0x10]; //因为跳转还要占用一个寄存器,所以保存 118 | ldr x0, r_hk_info; 119 | ldr x0, [x0, #8]; //pOriFuncAddr 120 | blr x0; 121 | 122 | to_aft_callback: //有时间再把这部分代码优化掉,是可以再跳转到开头的,因为这部分代码都是一样的,判断lr可以区分出来的 123 | STP X1, X0, [SP, #-0x10] 124 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 125 | 126 | mrs x0, NZCV 127 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 128 | str x30, [sp]; //存储x30 129 | add x30, sp, #0x20 130 | str x30, [sp, #0x8]; //存储真实的sp 131 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 132 | 133 | sub sp, sp, #0xf0; //分配栈空间 134 | stp X0, X1, [SP]; //存储x0-x29 135 | stp X2, X3, [SP,#0x10] 136 | stp X4, X5, [SP,#0x20] 137 | stp X6, X7, [SP,#0x30] 138 | stp X8, X9, [SP,#0x40] 139 | stp X10, X11, [SP,#0x50] 140 | stp X12, X13, [SP,#0x60] 141 | stp X14, X15, [SP,#0x70] 142 | stp X16, X17, [SP,#0x80] 143 | stp X18, X19, [SP,#0x90] 144 | stp X20, X21, [SP,#0xa0] 145 | stp X22, X23, [SP,#0xb0] 146 | stp X24, X25, [SP,#0xc0] 147 | stp X26, X27, [SP,#0xd0] 148 | stp X28, X29, [SP,#0xe0] 149 | 150 | save_q0_q31: 151 | sub sp, sp, #0x200; //分配栈空间 152 | #stp D0, D1, [SP]; //理论上是不是只保存存储double的部分就可以? 153 | stp Q0, Q1, [SP]; //不支持V0-V31,但是支持Q0-Q31,一致,每个寄存器占128位,低64位保存double,低32位float 154 | stp Q2, Q3, [SP, #0x20]; 155 | stp Q4, Q5, [SP, #0x40]; 156 | stp Q6, Q7, [SP, #0x60]; 157 | stp Q8, Q9, [SP, #0x80]; 158 | stp Q10, Q11, [SP, #0xa0]; 159 | stp Q12, Q13, [SP, #0xc0]; 160 | stp Q14, Q15, [SP, #0xe0]; 161 | 162 | stp Q16, Q17, [SP, #0x100]; 163 | stp Q18, Q19, [SP, #0x120]; 164 | stp Q20, Q21, [SP, #0x140]; 165 | stp Q22, Q23, [SP, #0x160]; 166 | stp Q24, Q25, [SP, #0x180]; 167 | stp Q26, Q27, [SP, #0x1a0]; 168 | stp Q28, Q29, [SP, #0x1c0]; 169 | stp Q30, Q31, [SP, #0x1e0]; 170 | 171 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 172 | ldr x1, r_hk_info; 173 | ldr x3, [x1, #0x20]; //aft_callback 174 | bl get_lr_pc; //lr为下条指令 175 | add lr, lr, 8; //lr为blr x3的地址 176 | str lr, [sp, #0x108]; //lr当作pc,覆盖栈上的x0 177 | blr x3; //执行aft_callback 178 | 179 | to_popreg: 180 | #ldp D0, D1, [SP]; 181 | ldp Q0, Q1, [SP]; 182 | ldp Q2, Q3, [SP, #0x20]; 183 | ldp Q4, Q5, [SP, #0x40]; 184 | ldp Q6, Q7, [SP, #0x60]; 185 | ldp Q8, Q9, [SP, #0x80]; 186 | ldp Q10, Q11, [SP, #0xa0]; 187 | ldp Q12, Q13, [SP, #0xc0]; 188 | ldp Q14, Q15, [SP, #0xe0]; 189 | 190 | ldp Q16, Q17, [SP, #0x100]; 191 | ldp Q18, Q19, [SP, #0x120]; 192 | ldp Q20, Q21, [SP, #0x140]; 193 | ldp Q22, Q23, [SP, #0x160]; 194 | ldp Q24, Q25, [SP, #0x180]; 195 | ldp Q26, Q27, [SP, #0x1a0]; 196 | ldp Q28, Q29, [SP, #0x1c0]; 197 | ldp Q30, Q31, [SP, #0x1e0]; 198 | add sp, sp, #0x200; 199 | 200 | ldr x0, [sp, #0x100]; //取出状态寄存器 201 | msr NZCV, x0 202 | 203 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 204 | ldp X2, X3, [SP,#0x10] 205 | ldp X4, X5, [SP,#0x20] 206 | ldp X6, X7, [SP,#0x30] 207 | ldp X8, X9, [SP,#0x40] 208 | ldp X10, X11, [SP,#0x50] 209 | ldp X12, X13, [SP,#0x60] 210 | ldp X14, X15, [SP,#0x70] 211 | ldp X16, X17, [SP,#0x80] 212 | ldp X18, X19, [SP,#0x90] 213 | ldp X20, X21, [SP,#0xa0] 214 | ldp X22, X23, [SP,#0xb0] 215 | ldp X24, X25, [SP,#0xc0] 216 | ldp X26, X27, [SP,#0xd0] 217 | ldp X28, X29, [SP,#0xe0] 218 | add sp, sp, #0xf0 219 | 220 | ldr x30, [sp]; //恢复x30 221 | add sp, sp, #0x20; //恢复为真实sp 222 | 223 | //巧的是下条指令也是ret或者br lr,共用一条指令。 224 | 225 | get_lr_pc: 226 | ret; //仅用于获取LR/PC 227 | 228 | r_hk_info: //结构体STR_HK_INFO 229 | .double 0xffffffffffffffff 230 | 231 | r_dump_end: 232 | 233 | .end 234 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/dump_with_ret.s: -------------------------------------------------------------------------------- 1 | //.include "../../asm/base.s" 2 | 3 | .global r_dump_start 4 | .global r_dump_end 5 | .global r_hk_info 6 | 7 | .hidden r_dump_start 8 | .hidden r_dump_end 9 | .hidden r_hk_info 10 | 11 | 12 | .data 13 | 14 | r_dump_start: //用于读写寄存器/栈,需要自己解析参数,不能读写返回值,不能阻止原函数(被hook函数)的执行 15 | //从行为上来我觉得更偏向dump,所以起名为dump。 16 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 17 | 18 | mrs x0, NZCV 19 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 20 | str x30, [sp]; //存储x30 21 | add x30, sp, #0x20 22 | str x30, [sp, #0x8]; //存储真实的sp 23 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 24 | 25 | save_x0_x29://保存寄存器x0-x29 26 | sub sp, sp, #0xf0; //分配栈空间 27 | stp X0, X1, [SP]; //存储x0-x29 28 | stp X2, X3, [SP,#0x10] 29 | stp X4, X5, [SP,#0x20] 30 | stp X6, X7, [SP,#0x30] 31 | stp X8, X9, [SP,#0x40] 32 | stp X10, X11, [SP,#0x50] 33 | stp X12, X13, [SP,#0x60] 34 | stp X14, X15, [SP,#0x70] 35 | stp X16, X17, [SP,#0x80] 36 | stp X18, X19, [SP,#0x90] 37 | stp X20, X21, [SP,#0xa0] 38 | stp X22, X23, [SP,#0xb0] 39 | stp X24, X25, [SP,#0xc0] 40 | stp X26, X27, [SP,#0xd0] 41 | stp X28, X29, [SP,#0xe0] 42 | 43 | call_onPreCallBack://调用onPreCallBack函数,第一个参数是sp,第二个参数是STR_HK_INFO结构体指针 44 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 45 | ldr x1, r_hk_info; 46 | ldr x3, [x1, #0x10]; //pre_callback 47 | bl get_lr_pc; //lr为下条指令 48 | add lr, lr, 8; //lr为blr x3的地址 49 | str lr, [sp, #0x108]; //lr当作pc,覆盖栈上的x0 50 | blr x3 51 | 52 | to_call_oriFun: 53 | ldr x0, [sp, #0x100]; //取出状态寄存器 54 | msr NZCV, x0 55 | 56 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 57 | ldp X2, X3, [SP,#0x10] 58 | ldp X4, X5, [SP,#0x20] 59 | ldp X6, X7, [SP,#0x30] 60 | ldp X8, X9, [SP,#0x40] 61 | ldp X10, X11, [SP,#0x50] 62 | ldp X12, X13, [SP,#0x60] 63 | ldp X14, X15, [SP,#0x70] 64 | ldp X16, X17, [SP,#0x80] 65 | ldp X18, X19, [SP,#0x90] 66 | ldp X20, X21, [SP,#0xa0] 67 | ldp X22, X23, [SP,#0xb0] 68 | ldp X24, X25, [SP,#0xc0] 69 | ldp X26, X27, [SP,#0xd0] 70 | ldp X28, X29, [SP,#0xe0] 71 | add sp, sp, #0xf0 72 | 73 | ldr x30, [sp]; //恢复x30 74 | add sp, sp, #0x20; //恢复为真实sp 75 | 76 | stp X1, X0, [SP, #-0x10]; //因为跳转还要占用一个寄存器,所以保存 77 | ldr x0, r_hk_info; 78 | ldr x0, [x0, #8]; //pOriFuncAddr 79 | blr x0; 80 | 81 | to_aft_callback: //有时间再把这部分代码优化掉,是可以再跳转到开头的,因为这部分代码都是一样的,判断lr可以区分出来的 82 | STP X1, X0, [SP, #-0x10] 83 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 84 | 85 | mrs x0, NZCV 86 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 87 | str x30, [sp]; //存储x30 88 | add x30, sp, #0x20 89 | str x30, [sp, #0x8]; //存储真实的sp 90 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 91 | 92 | sub sp, sp, #0xf0; //分配栈空间 93 | stp X0, X1, [SP]; //存储x0-x29 94 | stp X2, X3, [SP,#0x10] 95 | stp X4, X5, [SP,#0x20] 96 | stp X6, X7, [SP,#0x30] 97 | stp X8, X9, [SP,#0x40] 98 | stp X10, X11, [SP,#0x50] 99 | stp X12, X13, [SP,#0x60] 100 | stp X14, X15, [SP,#0x70] 101 | stp X16, X17, [SP,#0x80] 102 | stp X18, X19, [SP,#0x90] 103 | stp X20, X21, [SP,#0xa0] 104 | stp X22, X23, [SP,#0xb0] 105 | stp X24, X25, [SP,#0xc0] 106 | stp X26, X27, [SP,#0xd0] 107 | stp X28, X29, [SP,#0xe0] 108 | 109 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 110 | ldr x1, r_hk_info; 111 | ldr x3, [x1, #0x20]; //aft_callback 112 | bl get_lr_pc; //lr为下条指令 113 | add lr, lr, 8; //lr为blr x3的地址 114 | str lr, [sp, #0x108]; //lr当作pc,覆盖栈上的x0 115 | blr x3; //执行aft_callback 116 | 117 | to_popreg: 118 | ldr x0, [sp, #0x100]; //取出状态寄存器 119 | msr NZCV, x0 120 | 121 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 122 | ldp X2, X3, [SP,#0x10] 123 | ldp X4, X5, [SP,#0x20] 124 | ldp X6, X7, [SP,#0x30] 125 | ldp X8, X9, [SP,#0x40] 126 | ldp X10, X11, [SP,#0x50] 127 | ldp X12, X13, [SP,#0x60] 128 | ldp X14, X15, [SP,#0x70] 129 | ldp X16, X17, [SP,#0x80] 130 | ldp X18, X19, [SP,#0x90] 131 | ldp X20, X21, [SP,#0xa0] 132 | ldp X22, X23, [SP,#0xb0] 133 | ldp X24, X25, [SP,#0xc0] 134 | ldp X26, X27, [SP,#0xd0] 135 | ldp X28, X29, [SP,#0xe0] 136 | add sp, sp, #0xf0 137 | 138 | ldr x30, [sp]; //恢复x30 139 | add sp, sp, #0x20; //恢复为真实sp 140 | 141 | //巧的是下条指令也是ret或者br lr,共用一条指令。 142 | 143 | get_lr_pc: 144 | ret; //仅用于获取LR/PC 145 | 146 | r_hk_info: //结构体STR_HK_INFO 147 | .double 0xffffffffffffffff 148 | 149 | r_dump_end: 150 | 151 | .end 152 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/replace.s: -------------------------------------------------------------------------------- 1 | .global replace_start 2 | .global replace_end 3 | .global p_hk_info 4 | 5 | .hidden replace_start 6 | .hidden replace_end 7 | .hidden p_hk_info 8 | 9 | .data 10 | 11 | //这种方式尽量用于标准的c/c++函数,因为通过hook函数再调用原函数,只能保证参数寄存器和lr寄存器是一致的,其他寄存器可能被修改。 12 | 13 | replace_start: //如果只是替换/跳到hook函数,其实是不用保存寄存器的,只是重新写比较麻烦,所以在之前的基础上 14 | 15 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 16 | 17 | mrs x0, NZCV 18 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 19 | str x30, [sp]; //存储x30 20 | add x30, sp, #0x20 21 | str x30, [sp, #0x8]; //存储真实的sp 22 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 23 | 24 | sub sp, sp, #0xf0; //分配栈空间 25 | stp X0, X1, [SP]; //存储x0-x29 26 | stp X2, X3, [SP,#0x10] //10 27 | stp X4, X5, [SP,#0x20] 28 | stp X6, X7, [SP,#0x30] 29 | stp X8, X9, [SP,#0x40] 30 | stp X10, X11, [SP,#0x50] 31 | stp X12, X13, [SP,#0x60] 32 | stp X14, X15, [SP,#0x70] 33 | stp X16, X17, [SP,#0x80] 34 | stp X18, X19, [SP,#0x90] 35 | stp X20, X21, [SP,#0xa0] 36 | stp X22, X23, [SP,#0xb0] //20 37 | stp X24, X25, [SP,#0xc0] 38 | stp X26, X27, [SP,#0xd0] 39 | stp X28, X29, [SP,#0xe0] 40 | 41 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 42 | ldr x1, p_hk_info; 43 | ldr x3, [x1, #0x10]; //pre_callback,保存lr 44 | bl get_lr_pc; //lr为下条指令 45 | add lr, lr, 8; //lr为blr x3的地址 46 | str lr, [sp, #0x108]; //lr当作pc,覆盖栈上的x0 47 | blr x3 //30 48 | 49 | to_call_hkFun: 50 | ldr x0, [sp, #0x100]; //取出状态寄存器 51 | msr NZCV, x0 52 | 53 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 54 | ldp X2, X3, [SP,#0x10] 55 | ldp X4, X5, [SP,#0x20] 56 | ldp X6, X7, [SP,#0x30] 57 | ldp X8, X9, [SP,#0x40] 58 | ldp X10, X11, [SP,#0x50] 59 | ldp X12, X13, [SP,#0x60] 60 | ldp X14, X15, [SP,#0x70] //40 61 | ldp X16, X17, [SP,#0x80] 62 | ldp X18, X19, [SP,#0x90] 63 | ldp X20, X21, [SP,#0xa0] 64 | ldp X22, X23, [SP,#0xb0] 65 | ldp X24, X25, [SP,#0xc0] 66 | ldp X26, X27, [SP,#0xd0] 67 | ldp X28, X29, [SP,#0xe0] 68 | add sp, sp, #0xf0 69 | 70 | ldr x30, [sp]; //恢复x30 71 | add sp, sp, #0x20; //恢复为真实sp,50 72 | 73 | ldr lr, p_hk_info; 74 | ldr lr, [lr, #0x28]; //pHkFunAddr 75 | blr lr; //既跳到pHkFunAddr执行,也设置了lr 76 | 77 | to_aft_callback: //其实这里可能存在问题,即如果hook函数或者其调用了原函数,非标准函数(非c/c++)未实现栈平衡 78 | //比如手写的精心构造的汇编函数,可能存在覆盖栈上数据 79 | STP X1, X0, [SP, #-0x10] 80 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 81 | 82 | mrs x0, NZCV 83 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 84 | str x30, [sp]; //存储x30 85 | add x30, sp, #0x20 86 | str x30, [sp, #0x8]; //存储真实的sp 87 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 88 | 89 | sub sp, sp, #0xf0; //分配栈空间 90 | stp X0, X1, [SP]; //存储x0-x29 91 | stp X2, X3, [SP,#0x10] 92 | stp X4, X5, [SP,#0x20] 93 | stp X6, X7, [SP,#0x30] 94 | stp X8, X9, [SP,#0x40] 95 | stp X10, X11, [SP,#0x50] 96 | stp X12, X13, [SP,#0x60] 97 | stp X14, X15, [SP,#0x70] 98 | stp X16, X17, [SP,#0x80] 99 | stp X18, X19, [SP,#0x90] 100 | stp X20, X21, [SP,#0xa0] 101 | stp X22, X23, [SP,#0xb0] 102 | stp X24, X25, [SP,#0xc0] 103 | stp X26, X27, [SP,#0xd0] 104 | stp X28, X29, [SP,#0xe0] 105 | 106 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 107 | ldr x1, p_hk_info; 108 | ldr x3, [x1, #0x20]; //aft_callback, 恢复lr寄存器 109 | bl get_lr_pc; //lr为下条指令 110 | add lr, lr, 8; //lr为blr x3的地址 111 | str lr, [sp, #0x108]; //lr当作pc,覆盖栈上的x0 112 | blr x3; //执行aft_callback 113 | 114 | to_popreg: 115 | ldr x0, [sp, #0x100]; //取出状态寄存器 116 | msr NZCV, x0 117 | 118 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 119 | ldp X2, X3, [SP,#0x10] 120 | ldp X4, X5, [SP,#0x20] 121 | ldp X6, X7, [SP,#0x30] 122 | ldp X8, X9, [SP,#0x40] 123 | ldp X10, X11, [SP,#0x50] 124 | ldp X12, X13, [SP,#0x60] 125 | ldp X14, X15, [SP,#0x70] 126 | ldp X16, X17, [SP,#0x80] 127 | ldp X18, X19, [SP,#0x90] 128 | ldp X20, X21, [SP,#0xa0] 129 | ldp X22, X23, [SP,#0xb0] 130 | ldp X24, X25, [SP,#0xc0] 131 | ldp X26, X27, [SP,#0xd0] 132 | ldp X28, X29, [SP,#0xe0] 133 | add sp, sp, #0xf0 134 | 135 | ldr x30, [sp]; //恢复x30 136 | add sp, sp, #0x20; //恢复为真实sp 137 | 138 | get_lr_pc: 139 | br lr; //仅用于获取LR/PC,最后相当于br lr 140 | nop; 141 | 142 | p_hk_info: //结构体STR_HK_INFO 143 | .double 0xffffffffffffffff 144 | 145 | replace_end: 146 | 147 | .end -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm/replace_neon.s: -------------------------------------------------------------------------------- 1 | .global replace_start 2 | .global replace_end 3 | .global p_hk_info 4 | 5 | .hidden replace_start 6 | .hidden replace_end 7 | .hidden p_hk_info 8 | 9 | .data 10 | 11 | //这种方式尽量用于标准的c/c++函数,因为通过hook函数再调用原函数,只能保证参数寄存器和lr寄存器是一致的,其他寄存器可能被修改。 12 | 13 | replace_start: //如果只是替换/跳到hook函数,其实是不用保存寄存器的,只是重新写比较麻烦,所以在之前的基础上 14 | 15 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 16 | 17 | mrs x0, NZCV 18 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 19 | str x30, [sp]; //存储x30 20 | add x30, sp, #0x20 21 | str x30, [sp, #0x8]; //存储真实的sp 22 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 23 | 24 | sub sp, sp, #0xf0; //分配栈空间 25 | stp X0, X1, [SP]; //存储x0-x29 26 | stp X2, X3, [SP,#0x10] //10 27 | stp X4, X5, [SP,#0x20] 28 | stp X6, X7, [SP,#0x30] 29 | stp X8, X9, [SP,#0x40] 30 | stp X10, X11, [SP,#0x50] 31 | stp X12, X13, [SP,#0x60] 32 | stp X14, X15, [SP,#0x70] 33 | stp X16, X17, [SP,#0x80] 34 | stp X18, X19, [SP,#0x90] 35 | stp X20, X21, [SP,#0xa0] 36 | stp X22, X23, [SP,#0xb0] //20 37 | stp X24, X25, [SP,#0xc0] 38 | stp X26, X27, [SP,#0xd0] 39 | stp X28, X29, [SP,#0xe0] 40 | 41 | save_v0_v31: 42 | sub sp, sp, #0x200; //分配栈空间 43 | #stp D0, D1, [SP]; //理论上是不是只保存存储double的部分就可以? 44 | stp Q0, Q1, [SP]; //不支持V0-V31,但是支持Q0-Q31,一致,每个寄存器占128位,低64位保存double,低32位float 45 | stp Q2, Q3, [SP, #0x20]; 46 | stp Q4, Q5, [SP, #0x40]; 47 | stp Q6, Q7, [SP, #0x60]; 48 | stp Q8, Q9, [SP, #0x80]; 49 | stp Q10, Q11, [SP, #0xa0]; 50 | stp Q12, Q13, [SP, #0xc0]; 51 | stp Q14, Q15, [SP, #0xe0]; 52 | 53 | stp Q16, Q17, [SP, #0x100]; 54 | stp Q18, Q19, [SP, #0x120]; 55 | stp Q20, Q21, [SP, #0x140]; 56 | stp Q22, Q23, [SP, #0x160]; 57 | stp Q24, Q25, [SP, #0x180]; 58 | stp Q26, Q27, [SP, #0x1a0]; 59 | stp Q28, Q29, [SP, #0x1c0]; 60 | stp Q30, Q31, [SP, #0x1e0]; 61 | 62 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 63 | ldr x1, p_hk_info; 64 | ldr x3, [x1, #0x10]; //pre_callback,保存lr 65 | bl get_lr_pc; //lr为下条指令 66 | add lr, lr, 8; //lr为blr x3的地址 67 | str lr, [sp, #0x308]; //lr当作pc,覆盖栈上的x0 68 | blr x3 //30 69 | 70 | to_call_hkFun: 71 | #ldp D0, D1, [SP]; 72 | ldp Q0, Q1, [SP]; 73 | ldp Q2, Q3, [SP, #0x20]; 74 | ldp Q4, Q5, [SP, #0x40]; 75 | ldp Q6, Q7, [SP, #0x60]; 76 | ldp Q8, Q9, [SP, #0x80]; 77 | ldp Q10, Q11, [SP, #0xa0]; 78 | ldp Q12, Q13, [SP, #0xc0]; 79 | ldp Q14, Q15, [SP, #0xe0]; 80 | 81 | ldp Q16, Q17, [SP, #0x100]; 82 | ldp Q18, Q19, [SP, #0x120]; 83 | ldp Q20, Q21, [SP, #0x140]; 84 | ldp Q22, Q23, [SP, #0x160]; 85 | ldp Q24, Q25, [SP, #0x180]; 86 | ldp Q26, Q27, [SP, #0x1a0]; 87 | ldp Q28, Q29, [SP, #0x1c0]; 88 | ldp Q30, Q31, [SP, #0x1e0]; 89 | add sp, sp, #0x200; 90 | 91 | ldr x0, [sp, #0x100]; //取出状态寄存器 92 | msr NZCV, x0 93 | 94 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 95 | ldp X2, X3, [SP,#0x10] 96 | ldp X4, X5, [SP,#0x20] 97 | ldp X6, X7, [SP,#0x30] 98 | ldp X8, X9, [SP,#0x40] 99 | ldp X10, X11, [SP,#0x50] 100 | ldp X12, X13, [SP,#0x60] 101 | ldp X14, X15, [SP,#0x70] //40 102 | ldp X16, X17, [SP,#0x80] 103 | ldp X18, X19, [SP,#0x90] 104 | ldp X20, X21, [SP,#0xa0] 105 | ldp X22, X23, [SP,#0xb0] 106 | ldp X24, X25, [SP,#0xc0] 107 | ldp X26, X27, [SP,#0xd0] 108 | ldp X28, X29, [SP,#0xe0] 109 | add sp, sp, #0xf0 110 | 111 | ldr x30, [sp]; //恢复x30 112 | add sp, sp, #0x20; //恢复为真实sp,50 113 | 114 | ldr lr, p_hk_info; 115 | ldr lr, [lr, #0x28]; //pHkFunAddr 116 | blr lr; //既跳到pHkFunAddr执行,也设置了lr 117 | 118 | to_aft_callback: //其实这里可能存在问题,即如果hook函数或者其调用了原函数,非标准函数(非c/c++)未实现栈平衡 119 | //比如手写的精心构造的汇编函数,可能存在覆盖栈上数据 120 | STP X1, X0, [SP, #-0x10] 121 | sub sp, sp, #0x20; //跳板在栈上存储了x0、x1,但是未改变sp的值 122 | 123 | mrs x0, NZCV 124 | str x0, [sp, #0x10]; //覆盖跳板存储的x1,存储状态寄存器 125 | str x30, [sp]; //存储x30 126 | add x30, sp, #0x20 127 | str x30, [sp, #0x8]; //存储真实的sp 128 | ldr x0, [sp, #0x18]; //取出跳板存储的x0 129 | 130 | sub sp, sp, #0xf0; //分配栈空间 131 | stp X0, X1, [SP]; //存储x0-x29 132 | stp X2, X3, [SP,#0x10] 133 | stp X4, X5, [SP,#0x20] 134 | stp X6, X7, [SP,#0x30] 135 | stp X8, X9, [SP,#0x40] 136 | stp X10, X11, [SP,#0x50] 137 | stp X12, X13, [SP,#0x60] 138 | stp X14, X15, [SP,#0x70] 139 | stp X16, X17, [SP,#0x80] 140 | stp X18, X19, [SP,#0x90] 141 | stp X20, X21, [SP,#0xa0] 142 | stp X22, X23, [SP,#0xb0] 143 | stp X24, X25, [SP,#0xc0] 144 | stp X26, X27, [SP,#0xd0] 145 | stp X28, X29, [SP,#0xe0] 146 | 147 | save_q0_q31: 148 | sub sp, sp, #0x200; //分配栈空间 149 | #stp D0, D1, [SP]; //理论上是不是只保存存储double的部分就可以? 150 | stp Q0, Q1, [SP]; //不支持V0-V31,但是支持Q0-Q31,一致,每个寄存器占128位,低64位保存double,低32位float 151 | stp Q2, Q3, [SP, #0x20]; 152 | stp Q4, Q5, [SP, #0x40]; 153 | stp Q6, Q7, [SP, #0x60]; 154 | stp Q8, Q9, [SP, #0x80]; 155 | stp Q10, Q11, [SP, #0xa0]; 156 | stp Q12, Q13, [SP, #0xc0]; 157 | stp Q14, Q15, [SP, #0xe0]; 158 | 159 | stp Q16, Q17, [SP, #0x100]; 160 | stp Q18, Q19, [SP, #0x120]; 161 | stp Q20, Q21, [SP, #0x140]; 162 | stp Q22, Q23, [SP, #0x160]; 163 | stp Q24, Q25, [SP, #0x180]; 164 | stp Q26, Q27, [SP, #0x1a0]; 165 | stp Q28, Q29, [SP, #0x1c0]; 166 | stp Q30, Q31, [SP, #0x1e0]; 167 | 168 | mov x0, sp; //x0作为第一个参数,那么操作x0=sp,即操作栈读写保存的寄存器 169 | ldr x1, p_hk_info; 170 | ldr x3, [x1, #0x20]; //aft_callback, 恢复lr寄存器 171 | bl get_lr_pc; //lr为下条指令 172 | add lr, lr, 8; //lr为blr x3的地址 173 | str lr, [sp, #0x308]; //lr当作pc,覆盖栈上的x0 174 | blr x3; //执行aft_callback 175 | 176 | to_popreg: 177 | #ldp D0, D1, [SP]; 178 | ldp Q0, Q1, [SP]; 179 | ldp Q2, Q3, [SP, #0x20]; 180 | ldp Q4, Q5, [SP, #0x40]; 181 | ldp Q6, Q7, [SP, #0x60]; 182 | ldp Q8, Q9, [SP, #0x80]; 183 | ldp Q10, Q11, [SP, #0xa0]; 184 | ldp Q12, Q13, [SP, #0xc0]; 185 | ldp Q14, Q15, [SP, #0xe0]; 186 | 187 | ldp Q16, Q17, [SP, #0x100]; 188 | ldp Q18, Q19, [SP, #0x120]; 189 | ldp Q20, Q21, [SP, #0x140]; 190 | ldp Q22, Q23, [SP, #0x160]; 191 | ldp Q24, Q25, [SP, #0x180]; 192 | ldp Q26, Q27, [SP, #0x1a0]; 193 | ldp Q28, Q29, [SP, #0x1c0]; 194 | ldp Q30, Q31, [SP, #0x1e0]; 195 | add sp, sp, #0x200; 196 | 197 | ldr x0, [sp, #0x100]; //取出状态寄存器 198 | msr NZCV, x0 199 | 200 | ldp X0, X1, [SP]; //恢复x0-x29寄存器 201 | ldp X2, X3, [SP,#0x10] 202 | ldp X4, X5, [SP,#0x20] 203 | ldp X6, X7, [SP,#0x30] 204 | ldp X8, X9, [SP,#0x40] 205 | ldp X10, X11, [SP,#0x50] 206 | ldp X12, X13, [SP,#0x60] 207 | ldp X14, X15, [SP,#0x70] 208 | ldp X16, X17, [SP,#0x80] 209 | ldp X18, X19, [SP,#0x90] 210 | ldp X20, X21, [SP,#0xa0] 211 | ldp X22, X23, [SP,#0xb0] 212 | ldp X24, X25, [SP,#0xc0] 213 | ldp X26, X27, [SP,#0xd0] 214 | ldp X28, X29, [SP,#0xe0] 215 | add sp, sp, #0xf0 216 | 217 | ldr x30, [sp]; //恢复x30 218 | add sp, sp, #0x20; //恢复为真实sp 219 | 220 | get_lr_pc: 221 | br lr; //仅用于获取LR/PC,最后相当于br lr 222 | nop; 223 | 224 | p_hk_info: //结构体STR_HK_INFO 225 | .double 0xffffffffffffffff 226 | 227 | replace_end: 228 | 229 | .end -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm_for_trampoline/replace.s: -------------------------------------------------------------------------------- 1 | //用于演示,因为不是最终方案,不写完整代码了。 2 | 3 | //修改trampoline指向蹦床即可 4 | 5 | .data 6 | 7 | replace_start: 8 | 9 | ldr x0, trampoline; //如果每一个函数都在源码中新建一个shellcode的话,而不是动态复制生成,那么这个shellcode和蹦床可以合为一个。 10 | br x0; //不能改变lr寄存器 11 | 12 | 13 | trampoline: //蹦床的地址 14 | .double 0xffffffffffffffff 15 | 16 | replace_end: 17 | 18 | //预先在一个section分配足够的空间,存储蹦床,其实和上面一样。 19 | replace_start_0: 20 | 21 | ldr x0, trampolines; 22 | br x0; 23 | 24 | 25 | trampolines: //蹦床的地址 26 | .double 0xffffffffffffffff 27 | 28 | replace_end_0: 29 | 30 | //下面为伪代码,通过这样也可以实现不修改/保存寄存器、不修改hook函数,动态生成蹦床完成hook。 31 | 32 | //优点是不用保存寄存器,缺点是因为正负64m的限制,hook函数应该和hook库是一起编译成动态库/可执行文件的。不能单独使用hook库。 33 | 34 | //256个蹦床,实际使用可能要考虑这个hkArry内存对齐的问题(如果编译器未做内存对齐)。 35 | //unsigned int hkArry[256 * 2] __attribute__ ((section(".my_sec"))); 36 | 37 | //void test_trampoline(){ 38 | //仅用于演示,应该先设置内存为可读写/执行, 39 | // hkArry[0] = 0xf85f83e0;//或者memcpy, ldr x0, [sp, #-0x8]; 40 | //例如这样计算偏移,组合b指令。 41 | // unsigned long offset = (unsigned long) my_open - ((unsigned long) hkArry + 1 * 4); 42 | // hkArry[1] = 0x14000000;//计算偏移,生成指令,b 0; 43 | //} -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/asm_for_trampoline/trampoline.s: -------------------------------------------------------------------------------- 1 | .section ".my_sec", "awx" 2 | 3 | .global _myopen_start 4 | 5 | .text 6 | 7 | _myopen_start: 8 | ldr x0, [sp, #-0x8]; //恢复x0 9 | b my_open; //未改变任何寄存器,执行hook函数。 10 | 11 | .end 12 | 13 | //用于手动生成蹦床代码,因为hook代码和这个蹦床一起编译的,所以基本上不会超出加减64m,那么就可以使用b跳转 14 | //到偏移,就不用占用一个寄存器了。需要每增加一个hook函数,就加一个蹦床,相应的生成shellcode中跳转到hook 15 | //函数的地方都要改成这个蹦床的地址。难就难在这个不好通过内嵌汇编实现,因为b跟的是个偏移值,在汇编中可以使用 16 | //函数名称,编译器替换,但是内嵌汇编中不行。而自己计算 -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/model/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | ifeq "$(TARGET_ARCH_ABI)" "arm64-v8a" 9 | 10 | #LOCAL_CXXFLAGS += -g -O0 11 | #LOCAL_ARM_MODE := arm 12 | LOCAL_MODULE := imodel 13 | LOCAL_STATIC_LIBRARIES := dump_with_ret dump replace dump_just_ret 14 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include 15 | LOCAL_SRC_FILES := iModel.cpp 16 | LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog 17 | 18 | include $(BUILD_STATIC_LIBRARY) 19 | 20 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/model/iModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/19. 3 | // 4 | 5 | #ifndef MY_INHK_IMODEL_H 6 | #define MY_INHK_IMODEL_H 7 | 8 | #include "mhk.h" 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | typedef std::vector INFOS; 21 | //typedef std::map LR_MAP; 22 | 23 | #endif 24 | 25 | enum hk_status{ 26 | success, hooked, error 27 | }; 28 | 29 | struct RetInfo { 30 | enum hk_status status; 31 | HK_INFO *info; 32 | }; 33 | 34 | //打印寄存器 35 | /** 36 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 37 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 38 | * @param pInfo 保存了被hook函数、hook函数等的结构体 39 | */ 40 | void default_onPreCallBack(my_pt_regs *regs, HK_INFO *pInfo); 41 | /** 42 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 43 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 44 | * @param pInfo 保存了被hook函数、hook函数等的结构体 45 | */ 46 | void default_onCallBack(my_pt_regs *regs, HK_INFO *pInfo); 47 | 48 | /** 49 | * 真实函数执行前调用onPreCallBack,执行后调用onCallBack,通过onPreCallBack控制参数,通过onCallBack控制返回值 50 | * @param pBeHookAddr 要hook的地址,必须 51 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL(onCallBack不为空),当和onCallBack都为NULL的情况使用默认的打印寄存器的函数default_onPreCallBack,因为什么都不做为什么hook? 52 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 53 | * @param methodName 被hook的函数名称,可以为NULL。 54 | * @return success:成功;error:错误;hooked:已被hook; 55 | */ 56 | hk_status dump(void *pBeHookAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo), void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo) = NULL, const char* methodName = NULL); 57 | 58 | /** 59 | * 不执行真实函数,直接操作寄存器,之后恢复寄存器返回,理论上也是可以在onCallBack其中执行真实函数的,但是需要自己封装参数,调用后自己解析寄存器 60 | * @param pBeHookAddr 要hook的地址,必须 61 | * @param onCallBack 要插入的回调函数(读写参数寄存器),必须 62 | * @param methodName 被hook的函数名称,可以为NULL。 63 | * @return success:成功;error:错误;hooked:已被hook; 64 | */ 65 | hk_status dumpRet(void *pBeHookAddr, void (*onCallBack)(struct my_pt_regs *, HK_INFO *pInfo), const char* methodName = NULL); 66 | 67 | /** 68 | * 针对标准函数,最常用的hook接口。定义一个和被hook函数原型一致的函数接收处理参数,可直接返回或者调用被备份/修复的原函数 69 | * @param pBeHookAddr 要hook的地址,必须 70 | * @param pHkFunAddr 和被hook函数原型一致的函数,接收处理参数,可直接返回或者调用被备份/修复的原函数,必须 71 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL 72 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 73 | * @param methodName 被hook的函数名称,可以为NULL 74 | * @return 因为既要区分三种状态,还存在返回备份/修复的原函数的情况,使用结构体存储两个字段,参考demo。 75 | */ 76 | RetInfo dump_replace(void *pBeHookAddr, void*pHkFunAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo) = NULL, void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo) = NULL, const char* methodName = NULL); 77 | 78 | /** 79 | * 通过被hook函数获取数据结构体 80 | * @param pBeHookAddr 被hook函数 81 | * @return 返回HK_INFO结构体 82 | */ 83 | HK_INFO *isHooked(void* pBeHookAddr); 84 | 85 | /** 86 | * 通过hook函数获取数据结构体 87 | * @param hkFun hook函数 88 | * @return 返回HK_INFO结构体 89 | */ 90 | HK_INFO *isHookedByHkFun(void* hkFun); 91 | 92 | /** 93 | * 获取备份/修复的被hook函数,主要是不清楚结构体字段的用户或者透明指针的情况 94 | * @param info 95 | * @return 返回备份/修复的被hook函数 96 | */ 97 | void* getOriFun(HK_INFO* info); 98 | 99 | /** 100 | * 获取备份/修复的被hook函数的指针,二级指针;可用于自己保存,推荐存在取消hook的情况下调用getOriFunByHkFun函数 101 | * @param info 102 | * @return 返回指向存储备份/修复的被hook函数的指针 103 | */ 104 | void** getPoriFun(HK_INFO* info); 105 | 106 | /** 107 | * 通过hook函数获取被hook的函数 108 | * @param hkFun hook函数 109 | * @return 返回被hook函数,如果被取消hook或者未被hook返回NULL 110 | */ 111 | void* getOriFunByHkFun(void* hkFun); 112 | 113 | /** 114 | * 取消hook,释放shellcode/备份的原方法占用的空间并还原原方法 115 | * @param info 如果成功会释放这个结构体,所以之后这个结构体/指针不能再用 116 | * @return 取消成功true,否则false 117 | */ 118 | bool unHook(HK_INFO* info); 119 | 120 | /** 121 | * 取消所有的hook 122 | * @return 123 | */ 124 | bool unHookAll(); 125 | 126 | #endif //MY_INHK_IMODEL_H 127 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/Android.mk: -------------------------------------------------------------------------------- 1 | $(warning "abi: $(TARGET_ARCH_ABI)") 2 | include $(call all-subdir-makefiles) 3 | $(warning "abi: $(TARGET_ARCH_ABI)") 4 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | ifeq "$(TARGET_ARCH_ABI)" "arm64-v8a" 9 | 10 | #LOCAL_CXXFLAGS += -g -O0 11 | #LOCAL_ARM_MODE := arm 12 | LOCAL_MODULE := dump 13 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 14 | LOCAL_SRC_FILES := ../mhk.c dump.c ../fixPCOpcode.c ../../asm/dump_neon.s 15 | 16 | 17 | include $(BUILD_STATIC_LIBRARY) 18 | 19 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump/dump.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | 5 | extern unsigned long _dump_start; 6 | extern unsigned long _hk_info; 7 | extern unsigned long _dump_end; 8 | 9 | /** 10 | * 利用dump.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数后,回调老函数 11 | * @param pInfo inlinehook信息 12 | * @return inlinehook桩是否构造成功 13 | */ 14 | bool BuildStub_dump(HK_INFO* pInfo) 15 | { 16 | bool bRet = false; 17 | LE("BuildStub_dump"); 18 | while(1) 19 | { 20 | if(pInfo == NULL) 21 | { 22 | LOGI("pstInlineHook is null"); 23 | break; 24 | } 25 | 26 | void *p_shellcode_start_s = &_dump_start; 27 | void *p_shellcode_end_s = &_dump_end; 28 | void *p_hk_info = &_hk_info; 29 | 30 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 31 | pInfo->shellCodeLength = sShellCodeLength; 32 | //malloc一段新的stub代码 33 | long pagesize = sysconf(_SC_PAGE_SIZE); 34 | void *pNewShellCode = NULL;// = malloc(sShellCodeLength); 35 | int code = posix_memalign(&pNewShellCode, pagesize, pagesize); 36 | 37 | LE("pNewShellCode=%p", pNewShellCode); 38 | if(code || pNewShellCode == NULL) 39 | { 40 | LOGI("shell code malloc fail."); 41 | break; 42 | } 43 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 44 | //更改stub代码页属性,改成可读可写可执行 45 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 46 | { 47 | LOGI("change shell code page property fail."); 48 | break; 49 | } 50 | 51 | 52 | pInfo->hk_infoAddr = pNewShellCode + (p_hk_info - p_shellcode_start_s); 53 | *(pInfo->hk_infoAddr) = pInfo; 54 | 55 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 56 | pInfo->pStubShellCodeAddr = pNewShellCode; 57 | 58 | 59 | 60 | bRet = true; 61 | break; 62 | } 63 | 64 | return bRet; 65 | } 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump_just_ret/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | ifeq "$(TARGET_ARCH_ABI)" "arm64-v8a" 9 | 10 | #LOCAL_CXXFLAGS += -g -O0 11 | #LOCAL_ARM_MODE := arm 12 | LOCAL_MODULE := dump_just_ret 13 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 14 | LOCAL_SRC_FILES := ../mhk.c dump.c ../fixPCOpcode.c ../../asm/dump_neon_just_ret.s 15 | 16 | 17 | include $(BUILD_STATIC_LIBRARY) 18 | 19 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump_just_ret/dump.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | 5 | extern unsigned long j_dump_start; 6 | extern unsigned long j_hk_info; 7 | extern unsigned long j_dump_end; 8 | 9 | //extern unsigned long _dump_start; 10 | //extern unsigned long _hk_info; 11 | //extern unsigned long _dump_end; 12 | 13 | 14 | 15 | /** 16 | * 利用dump_just_ret.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数 17 | * @param pInfo inlinehook信息 18 | * @return inlinehook桩是否构造成功 19 | */ 20 | bool BuildStub_dump_just_ret(HK_INFO* pInfo) 21 | { 22 | bool bRet = false; 23 | 24 | LE("BuildStub_dump_just_ret"); 25 | while(1) 26 | { 27 | if(pInfo == NULL) 28 | { 29 | LOGI("pstInlineHook is null"); 30 | break; 31 | } 32 | 33 | 34 | void *p_shellcode_start_s = &j_dump_start; 35 | void *p_shellcode_end_s = &j_dump_end; 36 | void *p_hk_info = &j_hk_info; 37 | 38 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 39 | pInfo->shellCodeLength = sShellCodeLength; 40 | 41 | //malloc一段新的stub代码 42 | long pagesize = sysconf(_SC_PAGE_SIZE); 43 | void *pNewShellCode = NULL;// = malloc(sShellCodeLength); 44 | int code = posix_memalign(&pNewShellCode, pagesize, pagesize); 45 | 46 | LE("pNewShellCode=%p", pNewShellCode); 47 | if(code || pNewShellCode == NULL) 48 | { 49 | LOGI("shell code malloc fail."); 50 | break; 51 | } 52 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 53 | //更改stub代码页属性,改成可读可写可执行 54 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 55 | { 56 | LOGI("change shell code page property fail."); 57 | break; 58 | } 59 | 60 | //设置跳转到外部stub函数去 61 | /*LOGI("_hookstub_function_addr_s : %lx",p_hookstub_function_addr_s); 62 | void **ppHookStubFunctionAddr = pNewShellCode + (p_hookstub_function_addr_s - p_shellcode_start_s); 63 | *ppHookStubFunctionAddr = pInfo->onCallBack; 64 | LOGI("ppHookStubFunctionAddr : %lx",ppHookStubFunctionAddr); 65 | LOGI("*ppHookStubFunctionAddr : %lx",*ppHookStubFunctionAddr); 66 | 67 | //备份外部stub函数运行完后跳转的函数地址指针,用于填充老函数的新地址 68 | pInfo->ppOriFuncAddr = pNewShellCode + (p_old_function_addr_s - p_shellcode_start_s);*/ 69 | 70 | pInfo->hk_infoAddr = pNewShellCode + (p_hk_info - p_shellcode_start_s); 71 | *(pInfo->hk_infoAddr) = pInfo; 72 | 73 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 74 | pInfo->pStubShellCodeAddr = pNewShellCode; 75 | 76 | 77 | 78 | bRet = true; 79 | break; 80 | } 81 | 82 | return bRet; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump_with_ret/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | ifeq "$(TARGET_ARCH_ABI)" "arm64-v8a" 9 | 10 | #LOCAL_CXXFLAGS += -g -O0 11 | #LOCAL_ARM_MODE := arm 12 | LOCAL_MODULE := dump_with_ret 13 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 14 | LOCAL_SRC_FILES := ../mhk.c dump.c lr.cpp ../fixPCOpcode.c ../../asm/dump_neon_with_ret.s 15 | 16 | 17 | include $(BUILD_STATIC_LIBRARY) 18 | 19 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump_with_ret/dump.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | 5 | extern unsigned long r_dump_start; 6 | extern unsigned long r_hk_info; 7 | extern unsigned long r_dump_end; 8 | 9 | //extern unsigned long _dump_start; 10 | //extern unsigned long _hk_info; 11 | //extern unsigned long _dump_end; 12 | 13 | 14 | #include "lr.h" 15 | 16 | /** 17 | * 利用dump_with_ret.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数,之后回调老函数,最好执行pInfo->allBack 18 | * @param pInfo inlinehook信息 19 | * @return inlinehook桩是否构造成功 20 | */ 21 | bool BuildStub_dump_with_ret(HK_INFO* pInfo) 22 | { 23 | bool bRet = false; 24 | 25 | LE("BuildStub_dump_with_ret"); 26 | while(1) 27 | { 28 | if(pInfo == NULL) 29 | { 30 | LOGI("pstInlineHook is null"); 31 | break; 32 | } 33 | 34 | 35 | void *p_shellcode_start_s = &r_dump_start; 36 | void *p_shellcode_end_s = &r_dump_end; 37 | void *p_hk_info = &r_hk_info; 38 | 39 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 40 | pInfo->shellCodeLength = sShellCodeLength; 41 | //malloc一段新的stub代码 42 | long pagesize = sysconf(_SC_PAGE_SIZE); 43 | void *pNewShellCode = NULL;// = malloc(sShellCodeLength); 44 | int code = posix_memalign(&pNewShellCode, pagesize, pagesize); 45 | 46 | LE("pNewShellCode=%p", pNewShellCode); 47 | if(code || pNewShellCode == NULL) 48 | { 49 | LOGI("shell code malloc fail."); 50 | break; 51 | } 52 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 53 | //更改stub代码页属性,改成可读可写可执行 54 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 55 | { 56 | LOGI("change shell code page property fail."); 57 | break; 58 | } 59 | 60 | //设置跳转到外部stub函数去 61 | /*LOGI("_hookstub_function_addr_s : %lx",p_hookstub_function_addr_s); 62 | void **ppHookStubFunctionAddr = pNewShellCode + (p_hookstub_function_addr_s - p_shellcode_start_s); 63 | *ppHookStubFunctionAddr = pInfo->onCallBack; 64 | LOGI("ppHookStubFunctionAddr : %lx",ppHookStubFunctionAddr); 65 | LOGI("*ppHookStubFunctionAddr : %lx",*ppHookStubFunctionAddr); 66 | 67 | //备份外部stub函数运行完后跳转的函数地址指针,用于填充老函数的新地址 68 | pInfo->ppOriFuncAddr = pNewShellCode + (p_old_function_addr_s - p_shellcode_start_s);*/ 69 | 70 | pInfo->hk_infoAddr = pNewShellCode + (p_hk_info - p_shellcode_start_s); 71 | *(pInfo->hk_infoAddr) = pInfo; 72 | 73 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 74 | pInfo->pStubShellCodeAddr = pNewShellCode; 75 | 76 | // pInfo->pre_callback = pre_callback; 77 | // pInfo->aft_callback = aft_callback; 78 | 79 | pInfo->pre_callback = d_pre_callback; 80 | pInfo->aft_callback = d_aft_callback; 81 | 82 | 83 | bRet = true; 84 | break; 85 | } 86 | 87 | return bRet; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump_with_ret/lr.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "lr.h" 7 | 8 | /*typedef std::vector LRS; 9 | //static LRS lrs; 10 | 11 | struct STR_LR { 12 | 13 | }; 14 | typedef std::map LR_MAP; 15 | 16 | //typedef std::map TID_MAP; 17 | typedef std::map TID_MAP;*/ 18 | 19 | static TID_MAP* tid_map; 20 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 21 | 22 | TID_MAP * getTid_map(){ 23 | // pthread_mutex_init(&mutex, NULL); 24 | pthread_mutex_lock(&mutex); 25 | if (tid_map == NULL) { 26 | tid_map = new TID_MAP; 27 | } 28 | pthread_mutex_unlock(&mutex); 29 | return tid_map; 30 | } 31 | 32 | //因为不清楚tid分配机制,是否存在已死亡线程的tid重新分配给新建线程,所以可以ls -la /proc/8205/task/根据线程时间 33 | //判断是不是一个新线程,若是使用旧tid的新线程可以清空map,不过其实使用的栈结构存数据,理论上不区分也应该没问题的。 34 | void saveLR(void* key_fun, unsigned long lr){ 35 | pid_t tid = gettid(); 36 | TID_MAP *map = getTid_map(); 37 | pthread_mutex_lock(&mutex); 38 | auto it = map->find(tid); 39 | if (it == map->end()) { 40 | auto lr_map = new LR_MAP; 41 | auto ls = new LRS; 42 | ls->push_back(lr); 43 | lr_map->insert(std::make_pair(key_fun, ls)); 44 | map->insert(std::make_pair(tid, lr_map)); 45 | } else { 46 | auto lr_map = it->second; 47 | auto it_vt = lr_map->find(key_fun); 48 | if (it_vt == lr_map->end()) { 49 | auto ls = new LRS; 50 | ls->push_back(lr); 51 | lr_map->insert(std::make_pair(key_fun, ls)); 52 | } else { 53 | std::vector *vt = it_vt->second; 54 | vt->push_back(lr); 55 | } 56 | } 57 | pthread_mutex_unlock(&mutex); 58 | } 59 | 60 | unsigned long getLR(void* key_fun){ 61 | unsigned long lr = 0; 62 | pid_t tid = gettid(); 63 | TID_MAP *map = getTid_map(); 64 | pthread_mutex_lock(&mutex); 65 | auto it = map->find(tid); 66 | 67 | if (it == map->end()) { 68 | LE("what's happened ? not found tid=%d", tid);//理论上不应该出现 69 | } else { 70 | auto lr_map = it->second; 71 | auto it_vt = lr_map->find(key_fun); 72 | if (it_vt == lr_map->end()) { 73 | LE("what's happened ? not found LR for=%p in tid=%d", key_fun, tid);//理论上不应该出现 74 | } else { 75 | std::vector *vt = it_vt->second; 76 | if (!vt || vt->empty()) { 77 | LE("what's happened ? null LR for=%p in tid=%d", key_fun, tid); 78 | } else { 79 | unsigned long size = vt->size(); 80 | lr = (*vt)[size - 1]; 81 | vt->pop_back(); 82 | } 83 | } 84 | } 85 | pthread_mutex_unlock(&mutex); 86 | return lr; 87 | } 88 | 89 | void pre_callback(struct my_pt_regs *regs, HK_INFO* info){ 90 | LE("dump_with_ret pre_callback"); 91 | saveLR(info->pBeHookAddr, regs->ARM_lr); 92 | if (info->onPreCallBack) 93 | info->onPreCallBack(regs, info); 94 | } 95 | 96 | void aft_callback(struct my_pt_regs *regs, HK_INFO* info){ 97 | LE("dump_with_ret aft_callback"); 98 | unsigned long lr = getLR(info->pBeHookAddr); 99 | regs->ARM_lr = lr; 100 | if (info->onCallBack) 101 | info->onCallBack(regs, info); 102 | } 103 | 104 | 105 | callback d_pre_callback = pre_callback; 106 | callback d_aft_callback = aft_callback; 107 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/dump_with_ret/lr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/19. 3 | // 4 | 5 | #ifndef MY_INHK_LR_H 6 | #define MY_INHK_LR_H 7 | 8 | #ifdef __cplusplus 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | typedef std::vector LRS; 15 | //static LRS lrs; 16 | 17 | struct STR_LR { 18 | 19 | }; 20 | typedef std::map LR_MAP; 21 | 22 | //typedef std::map TID_MAP; 23 | typedef std::map TID_MAP; 24 | 25 | static TID_MAP * getTid_map(); 26 | 27 | static void saveLR(void* key_fun, unsigned long lr); 28 | 29 | static unsigned long getLR(void* key_fun); 30 | 31 | #endif 32 | 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #include "mhk.h" 39 | 40 | //因为会被导出,所以两个静态库中存在两个同名函数,另一个被覆盖了。 41 | //extern void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 42 | static void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 43 | 44 | //extern void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 45 | static void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 46 | typedef void (*callback)(struct my_pt_regs *regs, HK_INFO* info); 47 | extern callback d_pre_callback;// = pre_callback; 48 | extern callback d_aft_callback;// = aft_callback; 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | 55 | #endif //MY_INHK_LR_H 56 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/fixPCOpcode.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIXOPCODE_H 2 | #define _FIXOPCODE_H 3 | 4 | #include 5 | #include "../include/mhk.h" 6 | 7 | #define ALIGN_PC(pc) (pc & 0xFFFFFFFC) 8 | 9 | bool isTargetAddrInBackup(uint64_t target_addr, uint64_t hook_addr, int backup_length); 10 | 11 | int lengthFixArm64(uint32_t opcode); 12 | int lengthFixArm32(uint32_t opcode); 13 | 14 | static int getTypeInArm64(uint32_t instruction); 15 | static int getTypeInArm32(uint32_t instruction); 16 | 17 | int fixPCOpcodeArm(void *fixOpcodes , HK_INFO* info); 18 | 19 | int fixPCOpcodeArm64(uint64_t pc, uint64_t lr, uint32_t instruction, uint32_t *trampoline_instructions, HK_INFO* pstInlineHook); 20 | 21 | 22 | #endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/mhk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mhk.h" 3 | #include "fixPCOpcode.h" 4 | 5 | #define ALIGN_PC(pc) (pc & 0xFFFFFFFC) 6 | 7 | void clear_cache_addr(void* addr, int size){ 8 | 9 | __builtin___clear_cache((char *) addr, 10 | (char *) addr + size); 11 | } 12 | 13 | /** 14 | * 修改页属性,改成可读可写可执行 15 | * @param pAddress 需要修改属性起始地址 16 | * @param size 需要修改页属性的长度,byte为单位 17 | * @return bool 修改是否成功 18 | */ 19 | bool ChangePageProperty(void *pAddress, size_t size) 20 | { 21 | bool bRet = false; 22 | 23 | if(pAddress == NULL) 24 | { 25 | LOGI("change page property error."); 26 | return bRet; 27 | } 28 | 29 | //计算包含的页数、对齐起始地址 30 | unsigned long ulPageSize = sysconf(_SC_PAGESIZE); //得到页的大小 31 | int iProtect = PROT_READ | PROT_WRITE | PROT_EXEC; 32 | 33 | if (true) { 34 | uintptr_t start = MY_PAGE_START((uintptr_t)pAddress, ulPageSize); 35 | uintptr_t end = MY_PAGE_END((uintptr_t) pAddress + size, ulPageSize); 36 | LE("start=%p, end=%p, size=%p", start, end, end-start); 37 | //高版本mprotect即使第二个参数size为0,也是改变一页的内存 38 | int code = mprotect((void *) (start), end - start, iProtect); 39 | if(code) 40 | { 41 | LE("mprotect error:%s", strerror(errno)); 42 | return bRet; 43 | } 44 | return true; 45 | } 46 | 47 | unsigned long ulNewPageStartAddress = (unsigned long)(pAddress) & ~(ulPageSize - 1); //pAddress & 0x1111 0000 0000 0000 48 | long lPageCount = (size / ulPageSize) + 1; 49 | LE("ulPageSize=%lu, lPageCount=%ld, size=%ld", ulPageSize, lPageCount, size); 50 | LE("pAddress=%p, ulNewPageStartAddress=%p, %d, %d", pAddress, ulNewPageStartAddress, (unsigned long)pAddress%4, ulNewPageStartAddress%4) 51 | 52 | long l = 0; 53 | while(l < lPageCount) 54 | { 55 | // LE("mprotect"); 56 | //利用mprotect改页属性 57 | int iRet = mprotect((void *)(ulNewPageStartAddress), ulPageSize, iProtect); 58 | if(-1 == iRet) 59 | { 60 | LE("mprotect error:%s", strerror(errno)); 61 | return bRet; 62 | } 63 | l++; 64 | } 65 | 66 | return true; 67 | } 68 | 69 | /** 70 | * 通过/proc/$pid/maps,获取模块基址 71 | * @param pid 模块所在进程pid,如果访问自身进程,可填小余0的值,如-1 72 | * @param pszModuleName 模块名字 73 | * @return void* 模块基址,错误则返回0 74 | */ 75 | void * GetModuleBaseAddr(pid_t pid, char* pszModuleName) 76 | { 77 | FILE *pFileMaps = NULL; 78 | unsigned long ulBaseValue = 0; 79 | char szMapFilePath[256] = {0}; 80 | char szFileLineBuffer[1024] = {0}; 81 | LOGI("first fork(): I'am father pid=%d", getpid()); 82 | 83 | LOGI("Pid is %d\n",pid); 84 | 85 | //pid判断,确定maps文件 86 | if (pid < 0) 87 | { 88 | snprintf(szMapFilePath, sizeof(szMapFilePath), "/proc/self/maps"); 89 | } 90 | else 91 | { 92 | snprintf(szMapFilePath, sizeof(szMapFilePath), "/proc/%d/maps", pid); 93 | } 94 | 95 | pFileMaps = fopen(szMapFilePath, "r"); 96 | if (NULL == pFileMaps) 97 | { 98 | return (void *)ulBaseValue; 99 | } 100 | LOGI("%d",pFileMaps); 101 | 102 | LOGI("Get map.\n"); 103 | 104 | //循环遍历maps文件,找到相应模块,截取地址信息 105 | while (fgets(szFileLineBuffer, sizeof(szFileLineBuffer), pFileMaps) != NULL) 106 | { 107 | //LOGI("%s\n",szFileLineBuffer); 108 | //LOGI("%s\n",pszModuleName); 109 | if (strstr(szFileLineBuffer, pszModuleName)) 110 | { 111 | LOGI("%s\n",szFileLineBuffer); 112 | char *pszModuleAddress = strtok(szFileLineBuffer, "-"); 113 | if (pszModuleAddress) 114 | { 115 | ulBaseValue = strtoul(pszModuleAddress, NULL, 16); 116 | 117 | if (ulBaseValue == 0x8000) 118 | ulBaseValue = 0; 119 | 120 | break; 121 | } 122 | } 123 | } 124 | fclose(pFileMaps); 125 | return (void *)ulBaseValue; 126 | } 127 | 128 | /** 129 | * arm下inline hook基础信息备份(备份原先的opcodes) 130 | * @param pInfo inlinehook信息 131 | * @return 初始化信息是否成功 132 | */ 133 | bool InitArmHookInfo(HK_INFO* pInfo) 134 | { 135 | bool bRet = false; 136 | uint32_t *currentOpcode = pInfo->pBeHookAddr; 137 | 138 | for(int i=0;ibackUpFixLengthList[i] = -1; 140 | } 141 | LOGI("pstInlineHook->szbyBackupOpcodes is at %p",&pInfo->szbyBackupOpcodes); 142 | 143 | 144 | if(!pInfo) 145 | { 146 | LOGI("pstInlineHook is null"); 147 | return bRet; 148 | } 149 | 150 | pInfo->backUpLength = 24; 151 | 152 | memcpy(pInfo->szbyBackupOpcodes, pInfo->pBeHookAddr, pInfo->backUpLength); 153 | 154 | for(int i=0;i<6;i++){ 155 | //currentOpcode += i; //GToad BUG 156 | LOGI("Arm64 Opcode to fix %d : %x",i,*currentOpcode); 157 | LOGI("Fix length : %d",lengthFixArm32(*currentOpcode)); 158 | pInfo->backUpFixLengthList[i] = lengthFixArm64(*currentOpcode); 159 | currentOpcode += 1; //GToad BUG 160 | } 161 | 162 | return true; 163 | } 164 | 165 | 166 | 167 | void clear_cache(HK_INFO* info) 168 | { 169 | // PAGE_MASK 170 | 171 | // __builtin___clear_cache((void *)PAGE_START(addr), (void *)PAGE_END(addr)); 172 | __builtin___clear_cache((char*)info->pBeHookAddr, (char*)info->pBeHookAddr + info->backUpLength); 173 | } 174 | 175 | bool unHk(HK_INFO* info) { 176 | if (!ChangePageProperty(info->pBeHookAddr, info->backUpLength)) { 177 | LOGI("change page property error."); 178 | return false; 179 | } 180 | memcpy(info->pBeHookAddr, info->szbyBackupOpcodes, info->backUpLength); 181 | clear_cache(info); 182 | 183 | free(info->pStubShellCodeAddr); 184 | // free(info->pOriFuncAddr);//如果和pStubShellCodeAddr共用内存页面,不能free 185 | info->pStubShellCodeAddr = NULL; 186 | info->pOriFuncAddr = NULL; 187 | 188 | return true; 189 | } 190 | 191 | 192 | /** 193 | * 构造并填充ARM下32的跳转指令,需要外部保证可读可写,且pCurAddress至少8个bytes大小 194 | * @param pCurAddress 当前地址,要构造跳转指令的位置 195 | * @param pJumpAddress 目的地址,要从当前位置跳过去的地址 196 | * @return 跳转指令是否构造成功 197 | */ 198 | bool BuildArmJumpCode(void *pCurAddress , void *pJumpAddress, HK_INFO* info) 199 | { 200 | LOGI("LIVE4.3.1"); 201 | bool bRet = false; 202 | while(1) 203 | { 204 | LOGI("LIVE4.3.2"); 205 | if(pCurAddress == NULL) 206 | { 207 | LE("pCurAddress address null."); 208 | break; 209 | } else if (pJumpAddress == NULL) { 210 | LE("pJumpAddress address null."); 211 | break; 212 | } 213 | LOGI("LIVE4.3.3"); 214 | //LDR PC, [PC, #-4] 215 | //addr 216 | //LDR PC, [PC, #-4]对应的机器码为:0xE51FF004 217 | //addr为要跳转的地址。该跳转指令范围为32位,对于32位系统来说即为全地址跳转。 218 | //缓存构造好的跳转指令(ARM下32位,两条指令只需要8个bytes) 219 | //BYTE szLdrPCOpcodes[8] = {0x04, 0xF0, 0x1F, 0xE5}; 220 | 221 | // 222 | BYTE szLdrPCOpcodes[24] = {0xe1, 0x03, 0x3f, 0xa9, 0x40, 0x00, 0x00, 0x58, 0x00, 0x00, 0x1f, 0xd6}; 223 | //将目的地址拷贝到跳转指令缓存位置 224 | memcpy(szLdrPCOpcodes + 12, &pJumpAddress, 8); 225 | szLdrPCOpcodes[20] = 0xE0; 226 | szLdrPCOpcodes[21] = 0x83; 227 | szLdrPCOpcodes[22] = 0x5F; 228 | szLdrPCOpcodes[23] = 0xF8; 229 | LOGI("LIVE4.3.4"); 230 | 231 | //将构造好的跳转指令刷进去 232 | memcpy(pCurAddress, szLdrPCOpcodes, 24); 233 | LOGI("LIVE4.3.5"); 234 | //__flush_cache(*((uint32_t*)pCurAddress), 20); 235 | //__builtin___clear_cache (*((uint64_t*)pCurAddress), *((uint64_t*)(pCurAddress+20))); 236 | // cacheflush(((char*)pCurAddress), 24, 0); 237 | clear_cache_addr(pCurAddress, 24); 238 | LOGI("LIVE4.3.6"); 239 | bRet = true; 240 | break; 241 | } 242 | LOGI("LIVE4.3.7"); 243 | return bRet; 244 | } 245 | 246 | 247 | 248 | 249 | /** 250 | * 在要HOOK的位置,构造跳转,跳转到shellcode stub中 251 | * @param pInfo inlinehook信息 252 | * @return 原地跳转指令是否构造成功 253 | */ 254 | bool RebuildHookTarget(HK_INFO* pInfo) 255 | { 256 | bool bRet = false; 257 | 258 | while(1) 259 | { 260 | LOGI("LIVE4.1"); 261 | if(pInfo == NULL) 262 | { 263 | LOGI("pstInlineHook is null"); 264 | break; 265 | } 266 | LOGI("LIVE4.2"); 267 | //修改原位置的页属性,保证可写 268 | if(ChangePageProperty(pInfo->pBeHookAddr, 24) == false) 269 | { 270 | LOGI("change page property error."); 271 | break; 272 | } 273 | LOGI("LIVE4.3"); 274 | //填充跳转指令 275 | if(BuildArmJumpCode(pInfo->pBeHookAddr, pInfo->pStubShellCodeAddr, pInfo) == false) 276 | { 277 | LOGI("build jump opcodes for new entry fail."); 278 | break; 279 | } 280 | LOGI("LIVE4.4"); 281 | bRet = true; 282 | break; 283 | } 284 | LOGI("LIVE4.5"); 285 | 286 | return bRet; 287 | } 288 | 289 | 290 | extern bool BuildStub_dump(HK_INFO* pInfo); 291 | extern bool BuildStub_dump_with_ret(HK_INFO* pInfo); 292 | extern bool BuildStub_replace(HK_INFO* pInfo); 293 | extern bool BuildStub_dump_just_ret(HK_INFO* pInfo); 294 | 295 | 296 | /** 297 | * ARM下的inlinehook 298 | * @param pInfo inlinehook信息 299 | * @return inlinehook是否设置成功 300 | */ 301 | bool HookArm(HK_INFO* pInfo) 302 | { 303 | bool bRet = false; 304 | LOGI("HookArm()"); 305 | 306 | 307 | while(1) 308 | { 309 | //LOGI("pstInlineHook is null 1."); 310 | if(pInfo == NULL) 311 | { 312 | LOGI("pstInlineHook is null."); 313 | break; 314 | } 315 | LOGI("LIVE1"); 316 | 317 | //LOGI("Init Arm HookInfo fail 1."); 318 | //第零步,设置ARM下inline hook的基础信息 319 | if(InitArmHookInfo(pInfo) == false) 320 | { 321 | LOGI("Init Arm HookInfo fail."); 322 | break; 323 | } 324 | LOGI("LIVE2"); 325 | 326 | //LOGI("BuildStub fail 1."); 327 | //第二步,构造stub,功能是保存寄存器状态,同时跳转到目标函数,然后跳转回原函数 328 | //需要目标地址,返回stub地址,同时还有old指针给后续填充 329 | if (pInfo->pHkFunAddr) { 330 | if(BuildStub_replace(pInfo) == false) 331 | { 332 | LOGI("BuildStub_replace fail."); 333 | break; 334 | } 335 | } else if(pInfo->onCallBack) 336 | { 337 | if (!BuildStub_dump_with_ret(pInfo)) { 338 | LOGI("BuildStub_dump_with_ret fail."); 339 | break; 340 | } 341 | } else if (pInfo->onPreCallBack) { 342 | unsigned long addr = (unsigned long)(pInfo->onPreCallBack); 343 | unsigned long mask = 0xff00000000000000; 344 | if (addr > mask) { 345 | pInfo->onPreCallBack = (void (*)(struct my_pt_regs *, struct STR_HK_INFO *)) (addr & 346 | 0x00ffffffffffffff); 347 | if (!BuildStub_dump_just_ret(pInfo)) { 348 | LOGI("BuildStub_dump_just_ret fail."); 349 | break; 350 | } 351 | } else if (!BuildStub_dump(pInfo)) { 352 | LOGI("BuildStub_dump fail."); 353 | break; 354 | } 355 | } else { 356 | LE("what do you want to do ?"); 357 | return bRet; 358 | } 359 | LOGI("LIVE3"); 360 | 361 | //LOGI("BuildOldFunction fail 1."); 362 | //第四步,负责重构原函数头,功能是修复指令,构造跳转回到原地址下 363 | //需要原函数地址 364 | 365 | if(BuildOldFunction(pInfo) == false) 366 | { 367 | LOGI("BuildOldFunction fail."); 368 | break; 369 | } 370 | LOGI("LIVE4"); 371 | 372 | //LOGI("RebuildHookAddress fail 1."); 373 | //第一步,负责重写原函数头,功能是实现inline hook的最后一步,改写跳转 374 | //需要cacheflush,防止崩溃 375 | if(RebuildHookTarget(pInfo) == false) 376 | { 377 | LOGI("RebuildHookAddress fail."); 378 | break; 379 | } 380 | LOGI("LIVE5"); 381 | 382 | bRet = true; 383 | break; 384 | } 385 | LOGI("LIVE6"); 386 | 387 | return bRet; 388 | } 389 | 390 | 391 | /** 392 | * 构造被inline hook的函数头,还原原函数头+增加跳转 393 | * 仅是拷贝跳转即可,同时填充stub shellcode中的oldfunction地址及hookinfo里面的old函数地址 394 | * 这个实现没有指令修复功能,即是HOOK的位置指令不能涉及PC等需要重定向指令 395 | * @param pInfo inlinehook信息 396 | * @return 原函数构造是否成功 397 | */ 398 | bool BuildOldFunction(HK_INFO* pInfo) 399 | { 400 | bool bRet = false; 401 | 402 | void *fixOpcodes; 403 | int fixLength; 404 | LOGI("LIVE3.1"); 405 | 406 | fixOpcodes = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 407 | LOGI("LIVE3.2"); 408 | while(1) 409 | { 410 | if(pInfo == NULL) 411 | { 412 | LOGI("pstInlineHook is null"); 413 | break; 414 | } 415 | LOGI("LIVE3.3"); 416 | 417 | //8个bytes存放原来的opcodes,另外8个bytes存放跳转回hook点下面的跳转指令 418 | // void * pNewEntryForOldFunction = malloc(200); 419 | // long pagesize = sysconf(_SC_PAGE_SIZE); 420 | void *pNewEntryForOldFunction = NULL; 421 | // pNewEntryForOldFunction = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 422 | // posix_memalign(&pNewEntryForOldFunction,pagesize, pagesize); 423 | 424 | //因为确定最大的shellcode才432,分配了4096的空间,应该是足够的,当然可以再加上容错处理,不够的话分配新的内存。 425 | pNewEntryForOldFunction = (char*)(pInfo->pStubShellCodeAddr) + pInfo->shellCodeLength; 426 | 427 | if(pNewEntryForOldFunction == NULL) 428 | { 429 | LOGI("new entry for old function malloc fail."); 430 | break; 431 | } 432 | LOGI("LIVE3.4"); 433 | 434 | pInfo->pNewEntryForOriFuncAddr = pNewEntryForOldFunction; 435 | LOGI("%p",pNewEntryForOldFunction); 436 | 437 | fixLength = fixPCOpcodeArm(fixOpcodes, pInfo); //把第三部分的起始地址传过去 438 | 439 | //可以省略了,如果使用已分配好的内存 440 | if(ChangePageProperty(pNewEntryForOldFunction, fixLength) == false) 441 | { 442 | LOGI("change new entry page property fail."); 443 | break; 444 | } 445 | LOGI("LIVE3.5"); 446 | 447 | memcpy(pNewEntryForOldFunction, fixOpcodes, fixLength); 448 | LOGI("LIVE3.6"); 449 | //memcpy(pNewEntryForOldFunction, pstInlineHook->szbyBackupOpcodes, 8); 450 | //填充跳转指令 451 | if(BuildArmJumpCode(pNewEntryForOldFunction + fixLength, pInfo->pBeHookAddr + pInfo->backUpLength - 4, pInfo) == false) 452 | { 453 | LOGI("build jump opcodes for new entry fail."); 454 | break; 455 | } 456 | LOGI("LIVE3.7"); 457 | //填充shellcode里stub的回调地址 458 | // *(pInfo->ppOriFuncAddr) = pNewEntryForOldFunction; 459 | pInfo->pOriFuncAddr = pNewEntryForOldFunction; 460 | pInfo->ppOriFuncAddr = &(pInfo->pOriFuncAddr); 461 | // pInfo->ppStubShellCodeAddr = &(pInfo->pStubShellCodeAddr); 462 | if (pInfo->pHkFunAddr) { 463 | // *(pInfo->ppHkFunAddr) = pInfo->pHkFunAddr; 464 | } 465 | LOGI("LIVE3.8"); 466 | 467 | bRet = true; 468 | break; 469 | } 470 | LOGI("LIVE3.9"); 471 | if (fixOpcodes) { 472 | munmap(fixOpcodes, PAGE_SIZE); 473 | } 474 | 475 | return bRet; 476 | } 477 | 478 | 479 | 480 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/replace/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | ifeq "$(TARGET_ARCH_ABI)" "arm64-v8a" 9 | 10 | #LOCAL_CXXFLAGS += -g -O0 11 | #LOCAL_ARM_MODE := arm 12 | LOCAL_MODULE := replace 13 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../include $(LOCAL_PATH)/../../asm 14 | LOCAL_SRC_FILES := ../mhk.c replace.c lr.cpp ../fixPCOpcode.c ../../asm/replace_neon.s 15 | 16 | 17 | include $(BUILD_STATIC_LIBRARY) 18 | 19 | endif -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/replace/lr.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "lr.h" 7 | 8 | /*typedef std::vector LRS; 9 | //static LRS lrs; 10 | 11 | struct STR_LR { 12 | 13 | }; 14 | typedef std::map LR_MAP; 15 | 16 | //typedef std::map TID_MAP; 17 | typedef std::map TID_MAP;*/ 18 | 19 | static TID_MAP* tid_map; 20 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 21 | 22 | TID_MAP * getTid_map(){ 23 | // pthread_mutex_init(&mutex, NULL); 24 | pthread_mutex_lock(&mutex); 25 | if (tid_map == NULL) { 26 | tid_map = new TID_MAP; 27 | } 28 | pthread_mutex_unlock(&mutex); 29 | return tid_map; 30 | } 31 | 32 | 33 | void saveLR(void* key_fun, unsigned long lr){ 34 | pid_t tid = gettid(); 35 | TID_MAP *map = getTid_map(); 36 | pthread_mutex_lock(&mutex); 37 | auto it = map->find(tid); 38 | if (it == map->end()) { 39 | auto lr_map = new LR_MAP; 40 | auto ls = new LRS; 41 | ls->push_back(lr); 42 | lr_map->insert(std::make_pair(key_fun, ls)); 43 | map->insert(std::make_pair(tid, lr_map)); 44 | } else { 45 | auto lr_map = it->second; 46 | auto it_vt = lr_map->find(key_fun); 47 | if (it_vt == lr_map->end()) { 48 | auto ls = new LRS; 49 | ls->push_back(lr); 50 | lr_map->insert(std::make_pair(key_fun, ls)); 51 | } else { 52 | std::vector *vt = it_vt->second; 53 | vt->push_back(lr); 54 | } 55 | } 56 | pthread_mutex_unlock(&mutex); 57 | } 58 | 59 | unsigned long getLR(void* key_fun){ 60 | unsigned long lr = 0; 61 | pid_t tid = gettid(); 62 | TID_MAP *map = getTid_map(); 63 | pthread_mutex_lock(&mutex); 64 | auto it = map->find(tid); 65 | if (it == map->end()) { 66 | LE("what's happened ? not found tid=%d", tid);//理论上不应该出现 67 | } else { 68 | auto lr_map = it->second; 69 | auto it_vt = lr_map->find(key_fun); 70 | if (it_vt == lr_map->end()) { 71 | LE("what's happened ? not found LR for=%p in tid=%d", key_fun, tid);//理论上不应该出现 72 | } else { 73 | std::vector *vt = it_vt->second; 74 | if (!vt || vt->empty()) { 75 | LE("what's happened ? null LR for=%p in tid=%d", key_fun, tid); 76 | } else { 77 | unsigned long size = vt->size(); 78 | lr = (*vt)[size - 1]; 79 | vt->pop_back(); 80 | } 81 | } 82 | } 83 | pthread_mutex_unlock(&mutex); 84 | return lr; 85 | } 86 | 87 | void pre_callback(struct my_pt_regs *regs, HK_INFO* info){ 88 | LE("lr pre_callback"); 89 | saveLR(info->pBeHookAddr, regs->ARM_lr); 90 | if (info->onPreCallBack) 91 | info->onPreCallBack(regs, info); 92 | } 93 | 94 | void aft_callback(struct my_pt_regs *regs, HK_INFO* info){ 95 | LE("lr aft_callback"); 96 | unsigned long lr = getLR(info->pBeHookAddr); 97 | regs->ARM_lr = lr; 98 | if (info->onCallBack) 99 | info->onCallBack(regs, info); 100 | } 101 | 102 | callback r_pre_callback = pre_callback; 103 | callback r_aft_callback = aft_callback; -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/replace/lr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/19. 3 | // 4 | 5 | #ifndef MY_INHK_LR_H 6 | #define MY_INHK_LR_H 7 | 8 | #ifdef __cplusplus 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | typedef std::vector LRS; 15 | //static LRS lrs; 16 | 17 | struct STR_LR { 18 | 19 | }; 20 | typedef std::map LR_MAP; 21 | 22 | //typedef std::map TID_MAP; 23 | typedef std::map TID_MAP; 24 | 25 | static TID_MAP * getTid_map(); 26 | 27 | static void saveLR(void* key_fun, unsigned long lr); 28 | 29 | static unsigned long getLR(void* key_fun); 30 | 31 | #endif 32 | 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #include "mhk.h" 39 | 40 | //因为会被导出,所以两个静态库中存在两个同名函数,另一个被覆盖了。 41 | //extern void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 42 | static void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 43 | 44 | //extern void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 45 | static void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 46 | typedef void (*callback)(struct my_pt_regs *regs, HK_INFO* info); 47 | extern callback r_pre_callback;// = pre_callback; 48 | extern callback r_aft_callback;// = aft_callback; 49 | 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | 56 | #endif //MY_INHK_LR_H 57 | -------------------------------------------------------------------------------- /myihk/src/main/jni/arm64/src/replace/replace.c: -------------------------------------------------------------------------------- 1 | #include "mhk.h" 2 | #include "../fixPCOpcode.h" 3 | 4 | 5 | extern unsigned long replace_start; 6 | extern unsigned long p_hk_info; 7 | extern unsigned long replace_end; 8 | 9 | //extern unsigned long _dump_start; 10 | //extern unsigned long _hk_info; 11 | //extern unsigned long _dump_end; 12 | 13 | 14 | #include "lr.h" 15 | 16 | /** 17 | * 利用replace.s中的shellcode构造桩,跳转到pInfo->onPreCallBack函数,之后回调hook函数,最后执行pInfo->allBack 18 | * @param pInfo inlinehook信息 19 | * @return inlinehook桩是否构造成功 20 | */ 21 | bool BuildStub_replace(HK_INFO* pInfo) 22 | { 23 | bool bRet = false; 24 | 25 | LE("BuildStub_replace"); 26 | while(1) 27 | { 28 | if(pInfo == NULL) 29 | { 30 | LOGI("HK_INFO is null"); 31 | break; 32 | } 33 | 34 | 35 | void *p_shellcode_start_s = &replace_start; 36 | void *p_shellcode_end_s = &replace_end; 37 | void *t_hk_info = &p_hk_info; 38 | 39 | size_t sShellCodeLength = p_shellcode_end_s - p_shellcode_start_s; 40 | pInfo->shellCodeLength = sShellCodeLength; 41 | LE("sShellCodeLength=%ld", sShellCodeLength); 42 | //malloc一段新的stub代码 43 | //signal 11 (SIGSEGV), code 2 (SEGV_ACCERR) 44 | long pagesize = sysconf(_SC_PAGE_SIZE); 45 | void *pNewShellCode = NULL;// = malloc(sShellCodeLength); 46 | // void *pNewShellCode = malloc(sShellCodeLength); 47 | int code = posix_memalign(&pNewShellCode, pagesize, pagesize); 48 | LE("pNewShellCode=%p", pNewShellCode); 49 | if(code || pNewShellCode == NULL) 50 | { 51 | LOGI("shell code malloc fail."); 52 | break; 53 | } 54 | memcpy(pNewShellCode, p_shellcode_start_s, sShellCodeLength); 55 | //更改stub代码页属性,改成可读可写可执行 56 | if(ChangePageProperty(pNewShellCode, sShellCodeLength) == false) 57 | { 58 | LOGI("change shell code page property fail."); 59 | break; 60 | } 61 | 62 | //设置跳转到外部stub函数去 63 | /*LOGI("_hookstub_function_addr_s : %lx",p_hookstub_function_addr_s); 64 | void **ppHookStubFunctionAddr = pNewShellCode + (p_hookstub_function_addr_s - p_shellcode_start_s); 65 | *ppHookStubFunctionAddr = pInfo->onCallBack; 66 | LOGI("ppHookStubFunctionAddr : %lx",ppHookStubFunctionAddr); 67 | LOGI("*ppHookStubFunctionAddr : %lx",*ppHookStubFunctionAddr); 68 | 69 | //备份外部stub函数运行完后跳转的函数地址指针,用于填充老函数的新地址 70 | pInfo->ppOriFuncAddr = pNewShellCode + (p_old_function_addr_s - p_shellcode_start_s);*/ 71 | 72 | pInfo->hk_infoAddr = pNewShellCode + (t_hk_info - p_shellcode_start_s); 73 | *(pInfo->hk_infoAddr) = pInfo; 74 | 75 | //填充shellcode地址到hookinfo中,用于构造hook点位置的跳转指令 76 | pInfo->pStubShellCodeAddr = pNewShellCode; 77 | 78 | // pInfo->pre_callback = pre_callback; 79 | pInfo->pre_callback = r_pre_callback; 80 | // pInfo->aft_callback = aft_callback; 81 | pInfo->aft_callback = r_aft_callback; 82 | 83 | 84 | bRet = true; 85 | break; 86 | } 87 | 88 | return bRet; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /myihk/src/main/jni/include/iModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/19. 3 | // 4 | 5 | #ifndef MY_INHK_IMODEL_H 6 | #define MY_INHK_IMODEL_H 7 | 8 | #include "mhk.h" 9 | 10 | #include 11 | #include 12 | 13 | #ifdef __cplusplus 14 | 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | typedef std::vector INFOS; 21 | //typedef std::map LR_MAP; 22 | 23 | #endif 24 | 25 | enum hk_status{ 26 | success, hooked, error 27 | }; 28 | 29 | struct RetInfo { 30 | enum hk_status status; 31 | HK_INFO *info; 32 | }; 33 | 34 | //打印寄存器 35 | /** 36 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 37 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 38 | * @param pInfo 保存了被hook函数、hook函数等的结构体 39 | */ 40 | void default_onPreCallBack(my_pt_regs *regs, HK_INFO *pInfo); 41 | /** 42 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 43 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 44 | * @param pInfo 保存了被hook函数、hook函数等的结构体 45 | */ 46 | void default_onCallBack(my_pt_regs *regs, HK_INFO *pInfo); 47 | 48 | /** 49 | * 真实函数执行前调用onPreCallBack,执行后调用onCallBack,通过onPreCallBack控制参数,通过onCallBack控制返回值 50 | * @param pBeHookAddr 要hook的地址,必须 51 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL(onCallBack不为空),当和onCallBack都为NULL的情况使用默认的打印寄存器的函数default_onPreCallBack,因为什么都不做为什么hook? 52 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 53 | * @param methodName 被hook的函数名称,可以为NULL。 54 | * @return success:成功;error:错误;hooked:已被hook; 55 | */ 56 | hk_status dump(void *pBeHookAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo), void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo) = NULL, const char* methodName = NULL); 57 | 58 | /** 59 | * 不执行真实函数,直接操作寄存器,之后恢复寄存器返回,理论上也是可以在onCallBack其中执行真实函数的,但是需要自己封装参数,调用后自己解析寄存器 60 | * @param pBeHookAddr 要hook的地址,必须 61 | * @param onCallBack 要插入的回调函数(读写参数寄存器),必须 62 | * @param methodName 被hook的函数名称,可以为NULL。 63 | * @return success:成功;error:错误;hooked:已被hook; 64 | */ 65 | hk_status dumpRet(void *pBeHookAddr, void (*onCallBack)(struct my_pt_regs *, HK_INFO *pInfo), const char* methodName = NULL); 66 | 67 | /** 68 | * 针对标准函数,最常用的hook接口。定义一个和被hook函数原型一致的函数接收处理参数,可直接返回或者调用被备份/修复的原函数 69 | * @param pBeHookAddr 要hook的地址,必须 70 | * @param pHkFunAddr 和被hook函数原型一致的函数,接收处理参数,可直接返回或者调用被备份/修复的原函数,必须 71 | * @param onPreCallBack 要插入的回调函数(读写参数寄存器), 可以为NULL 72 | * @param onCallBack 要插入的回调函数(读写返回值寄存器),可以为NULL,如果只关心函数执行后的结果 73 | * @param methodName 被hook的函数名称,可以为NULL 74 | * @return 因为既要区分三种状态,还存在返回备份/修复的原函数的情况,使用结构体存储两个字段,参考demo。 75 | */ 76 | RetInfo dump_replace(void *pBeHookAddr, void*pHkFunAddr, void (*onPreCallBack)(struct my_pt_regs *, HK_INFO *pInfo) = NULL, void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo) = NULL, const char* methodName = NULL); 77 | 78 | /** 79 | * 通过被hook函数获取数据结构体 80 | * @param pBeHookAddr 被hook函数 81 | * @return 返回HK_INFO结构体 82 | */ 83 | HK_INFO *isHooked(void* pBeHookAddr); 84 | 85 | /** 86 | * 通过hook函数获取数据结构体 87 | * @param hkFun hook函数 88 | * @return 返回HK_INFO结构体 89 | */ 90 | HK_INFO *isHookedByHkFun(void* hkFun); 91 | 92 | /** 93 | * 获取备份/修复的被hook函数,主要是不清楚结构体字段的用户或者透明指针的情况 94 | * @param info 95 | * @return 返回备份/修复的被hook函数 96 | */ 97 | void* getOriFun(HK_INFO* info); 98 | 99 | /** 100 | * 获取备份/修复的被hook函数的指针,二级指针;可用于自己保存,推荐存在取消hook的情况下调用getOriFunByHkFun函数 101 | * @param info 102 | * @return 返回指向存储备份/修复的被hook函数的指针 103 | */ 104 | void** getPoriFun(HK_INFO* info); 105 | 106 | /** 107 | * 通过hook函数获取被hook的函数 108 | * @param hkFun hook函数 109 | * @return 返回被hook函数,如果被取消hook或者未被hook返回NULL 110 | */ 111 | void* getOriFunByHkFun(void* hkFun); 112 | 113 | /** 114 | * 取消hook,释放shellcode/备份的原方法占用的空间并还原原方法 115 | * @param info 如果成功会释放这个结构体,所以之后这个结构体/指针不能再用 116 | * @return 取消成功true,否则false 117 | */ 118 | bool unHook(HK_INFO* info); 119 | 120 | /** 121 | * 取消所有的hook 122 | * @return 123 | */ 124 | bool unHookAll(); 125 | 126 | #endif //MY_INHK_IMODEL_H 127 | -------------------------------------------------------------------------------- /myihk/src/main/jni/include/mhk.h: -------------------------------------------------------------------------------- 1 | #ifndef _MHK_H 2 | #define _MHK_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | //#include 14 | 15 | 16 | #ifndef BYTE 17 | #define BYTE unsigned char 18 | #endif 19 | 20 | #define OPCODEMAXLEN 24 //inline hook所需要的opcodes最大长度,arm64为20 21 | #define BACKUP_CODE_NUM_MAX 6 //尽管备份原程序6条arm64指令。 22 | 23 | #define LOG_TAG "zhuo" 24 | #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##args); 25 | #define LE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args); 26 | 27 | #define PAGE_START(addr) (~(PAGE_SIZE - 1) & (addr)) 28 | #define PAGE_END(addr) (((addr) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) 29 | 30 | #define MY_PAGE_START(addr, page_size) (~(page_size - 1) & (addr)) 31 | #define MY_PAGE_END(addr, page_size) (((addr) + page_size - 1) & ~(page_size - 1)) 32 | 33 | #define SET_BIT0(addr) (addr | 1) 34 | #define CLEAR_BIT0(addr) (addr & 0xFFFFFFFE) 35 | #define TEST_BIT0(addr) (addr & 1) 36 | 37 | #define ACTION_ENABLE 0 38 | #define ACTION_DISABLE 1 39 | 40 | //#define __flush_cache(c, n) __builtin___clear_cache(reinterpret_cast(c), reinterpret_cast(c) + n) 41 | 42 | 43 | 44 | 45 | #if defined(__aarch64__) 46 | 47 | union my_neon_regs { 48 | long double qregs[32]; 49 | double dregs[32][2]; 50 | // float fregs[64*2]; 51 | float fregs[32][4]; 52 | }; 53 | 54 | #define DREGS(i) regs->neon.dregs(i) 55 | #define FREGS(i) regs->neon.fregs(i) 56 | #define QREGS(i) regs->neon.qregs[i] 57 | 58 | #define dregs(i) dregs[i][0] 59 | #define fregs(i) fregs[i][0] 60 | 61 | struct my_pt_regs { 62 | union my_neon_regs neon; 63 | __u64 uregs[31]; 64 | __u64 sp; 65 | __u64 pstate; //有时间应该修复,pc在前,但是涉及到栈和生成shellcode都要改,先这么用吧,和系统结构体有这点不同 66 | __u64 pc; 67 | 68 | }; 69 | 70 | #define ARM_lr uregs[30] 71 | #define ARM_sp sp 72 | //#define SP (__u64*)sp 73 | //#define SP_32(i) *(__u32*)((__u64)(regs->sp) + i*4) 74 | //#define SP_32(i) *((__u32*)regs->sp+i) 75 | //#define SP_32(i) *((__u64*)regs->sp+i) 76 | #define SP(i) *((__u64*)regs->sp+i) 77 | 78 | 79 | #elif defined(__arm__) 80 | 81 | struct my_pt_regs { 82 | long uregs[18]; 83 | }; 84 | 85 | #ifndef __ASSEMBLY__ 86 | 87 | #define ARM_cpsr uregs[16] 88 | #define ARM_pc uregs[15] 89 | #define ARM_lr uregs[14] 90 | #define ARM_sp uregs[13] 91 | #define ARM_ip uregs[12] 92 | #define ARM_fp uregs[11] 93 | #define ARM_r10 uregs[10] 94 | #define ARM_r9 uregs[9] 95 | #define ARM_r8 uregs[8] 96 | #define ARM_r7 uregs[7] 97 | #define ARM_r6 uregs[6] 98 | #define ARM_r5 uregs[5] 99 | #define ARM_r4 uregs[4] 100 | #define ARM_r3 uregs[3] 101 | #define ARM_r2 uregs[2] 102 | #define ARM_r1 uregs[1] 103 | #define ARM_r0 uregs[0] 104 | #define ARM_ORIG_r0 uregs[17] 105 | #define ARM_VFPREGS_SIZE (32 * 8 + 4) 106 | 107 | #endif 108 | 109 | #define SP(i) *((__u32*)regs->ARM_sp+i) 110 | 111 | #endif 112 | 113 | 114 | //hook信息 115 | typedef struct STR_HK_INFO{ 116 | void (*onPreCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo); //回调函数,在执行原函数之前获取参数/寄存器的函数 117 | void * pOriFuncAddr; //存放备份/修复后原函数的地址 118 | void (*pre_callback)(struct my_pt_regs *, struct STR_HK_INFO *pInfo); //pre_callback,内部做保存lr的操作,之后回调onPreCallBack,不能被用户操作 119 | void (*onCallBack)(struct my_pt_regs *, struct STR_HK_INFO *pInfo); //回调函数,执行原函数之后获取返回值/寄存器的函数 120 | void (*aft_callback)(struct my_pt_regs *, struct STR_HK_INFO *pInfo); //aft_callback,内部做恢复lr的操作,之后回调onCallBack,不能被用户操作 121 | void *pHkFunAddr; //hook函数,即自定义按照被hook的函数原型构造,处理参数/返回值的函数 122 | //以上为在shellcode中通过偏移直接或间接用到的,所以如果有变动,相应的shellcode也要跟着变动 123 | 124 | void **ppHkFunAddr; //上面pHkFunAddr函数在shellcode中的地址,已废弃; 125 | void **hk_infoAddr; //shellcode中HK_INFO的地址 126 | void *pBeHookAddr; //被hook的地址/函数 127 | void *pStubShellCodeAddr; //跳过去的shellcode stub的地址 128 | size_t shellCodeLength; //上面pStubShellCodeAddr的字节数 129 | void ** ppOriFuncAddr; //shellcode 中存放备份/修复后原函数的地址,已废弃,待去除;改成上面pHkFunAddr函数的指针,应用于解除hook 130 | void *pNewEntryForOriFuncAddr; //和pOriFuncAddr一致 131 | BYTE szbyBackupOpcodes[OPCODEMAXLEN]; //原来的opcodes 132 | int backUpLength; //备份代码的长度,arm64模式下为24 133 | int backUpFixLengthList[BACKUP_CODE_NUM_MAX]; //保存 134 | const char* methodName; 135 | } HK_INFO; 136 | 137 | #ifdef __cplusplus 138 | extern "C" { 139 | #endif 140 | 141 | bool ChangePageProperty(void *pAddress, size_t size); 142 | 143 | extern void * GetModuleBaseAddr(pid_t pid, char* pszModuleName); 144 | 145 | bool InitArmHookInfo(HK_INFO* info); 146 | 147 | bool BuildStub(HK_INFO* pInfo); 148 | 149 | bool BuildArmJumpCode(void *pCurAddress , void *pJumpAddress, HK_INFO* info); 150 | 151 | bool BuildOldFunction(HK_INFO* info); 152 | 153 | bool RebuildHookTarget(HK_INFO* info); 154 | 155 | extern bool HookArm(HK_INFO* info); 156 | 157 | extern bool HookThumb(HK_INFO* info); 158 | 159 | bool unHk(HK_INFO* info); 160 | 161 | #ifdef __cplusplus 162 | } 163 | #endif 164 | 165 | #endif 166 | 167 | -------------------------------------------------------------------------------- /myihk/src/main/jni/include/mhk64.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/18. 3 | // 4 | 5 | #ifndef MY_INHK_MHK64_H 6 | #define MY_INHK_MHK64_H 7 | 8 | //废弃,因为多个文件包含但是不是单独编译成动态库的话就会出现覆盖的情况 9 | 10 | 11 | #ifdef __cplusplus 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | typedef std::vector LRS; 18 | //static LRS lrs; 19 | 20 | struct STR_LR { 21 | 22 | }; 23 | typedef std::map LR_MAP; 24 | 25 | //typedef std::map TID_MAP; 26 | typedef std::map TID_MAP; 27 | 28 | extern TID_MAP * getTid_map(); 29 | 30 | extern void saveLR(void* key_fun, unsigned long lr); 31 | 32 | extern unsigned long getLR(void* key_fun); 33 | 34 | #endif 35 | 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | extern void pre_callback(struct my_pt_regs *regs, HK_INFO* info); 42 | 43 | extern void aft_callback(struct my_pt_regs *regs, HK_INFO* info); 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif //MY_INHK_MHK64_H 50 | -------------------------------------------------------------------------------- /myihk/src/main/jni/system_lib/arm64_9/ld-android.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/jni/system_lib/arm64_9/ld-android.so -------------------------------------------------------------------------------- /myihk/src/main/jni/system_lib/arm64_9/libdl.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/jni/system_lib/arm64_9/libdl.so -------------------------------------------------------------------------------- /myihk/src/main/jni/system_lib/arm64_9/libshk.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/jni/system_lib/arm64_9/libshk.so -------------------------------------------------------------------------------- /myihk/src/main/jni/system_lib/arm64_9/linker64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/jni/system_lib/arm64_9/linker64 -------------------------------------------------------------------------------- /myihk/src/main/jni/system_lib/arm_9/libc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/jni/system_lib/arm_9/libc.so -------------------------------------------------------------------------------- /myihk/src/main/jni/system_lib/arm_9/libdl.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/jni/system_lib/arm_9/libdl.so -------------------------------------------------------------------------------- /myihk/src/main/jni/test/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | $(warning "abi: $(TARGET_ARCH_ABI)") 7 | 8 | #ifeq "$(TARGET_ARCH_ABI)" "arm64-v8a" 9 | 10 | #LOCAL_CXXFLAGS += -g -O0 11 | #LOCAL_ARM_MODE := arm 12 | LOCAL_MODULE := shk 13 | LOCAL_STATIC_LIBRARIES := imodel #dump_with_ret dump replace 14 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include 15 | LOCAL_SRC_FILES := main.cpp 16 | #LOCAL_SRC_FILES := main_exportHook.cpp 17 | #LOCAL_SRC_FILES := main_arm.cpp 18 | LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog 19 | 20 | include $(BUILD_SHARED_LIBRARY) 21 | 22 | #endif -------------------------------------------------------------------------------- /myihk/src/main/jni/test/main_arm.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by EDZ on 2019/12/23. 3 | // 初期单独测试arm/thumb的,可用删除,已无用。 4 | // 5 | 6 | #include 7 | #include 8 | #include "mhk.h" 9 | #include "../arm/model/iModel.h" 10 | 11 | #include 12 | #include 13 | 14 | 15 | /** 16 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 17 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 18 | * @param pInfo 保存了被hook函数、hook函数等的结构体 19 | */ 20 | void onPreCallBack(my_pt_regs *regs, HK_INFO *pInfo) //参数regs就是指向栈上的一个数据结构,由第二部分的mov r0, sp所传递。 21 | { 22 | const char* name = "null"; 23 | if (pInfo) { 24 | if (pInfo->methodName) { 25 | name = pInfo->methodName; 26 | } else { 27 | char buf[20]; 28 | sprintf(buf, "%p", pInfo->pBeHookAddr); 29 | name = buf; 30 | } 31 | } 32 | // LE("tid=%d onPreCallBack:%s", gettid(), name); 33 | 34 | LE("tid=%d, onPreCallBack:%s, " 35 | "r0=0x%lx, r1=0x%lx, r2=0x%lx, r3=0x%lx, r4=0x%lx, r5=0x%lx, r6=0x%lx, r7=0x%lx, r8=0x%lx, r9=0x%lx, r10=0x%lx, r11=0x%lx, r12=0x%lx, " 36 | "cur_sp=%p, ori_sp=%p, ori_sp/13=0x%lx, lr=0x%lx, cur_pc=0x%lx, cpsr=0x%lx, " 37 | "arg4=0x%lx, arg5=0x%lx, arg4=0x%lx, arg5=0x%lx;" 38 | , gettid(), name, 39 | regs->uregs[0], regs->uregs[1], regs->uregs[2], regs->uregs[3], regs->uregs[4], regs->uregs[5], 40 | regs->uregs[6], regs->uregs[7], regs->uregs[8], regs->uregs[9], regs->uregs[10], regs->uregs[11], 41 | regs->uregs[12], 42 | regs, ((char*)regs + 0x44), regs->uregs[13], regs->uregs[14], regs->uregs[15], regs->uregs[16], 43 | regs->uregs[17], regs->uregs[18], SP(0), SP(1) 44 | ); 45 | 46 | // LE("code=0x%lx", *(unsigned long*)(regs->uregs[15])); 47 | 48 | if (pInfo) { 49 | LE("onPreCallBack: HK_INFO=%p", pInfo); 50 | if ((pInfo->pBeHookAddr == open || pInfo->pBeHookAddr == dlsym(RTLD_DEFAULT, "__open")) && regs->uregs[0]) { 51 | const char* name = (const char *)(regs->uregs[0]); 52 | LE("onPreCallBack: open: %s , %o, %o", name, regs->uregs[1], (mode_t)regs->uregs[2]); 53 | } 54 | } 55 | 56 | // abort(); 57 | // _exit(127); 58 | // syscall(__NR_tgkill, getpid(), gettid(), SIGABRT); 59 | 60 | } 61 | 62 | /** 63 | * 用户自定义的stub函数,嵌入在hook点中,可直接操作寄存器等 64 | * @param regs 寄存器结构,保存寄存器当前hook点的寄存器信息 65 | * @param pInfo 保存了被hook函数、hook函数等的结构体 66 | */ 67 | void onCallBack(my_pt_regs *regs, HK_INFO *pInfo) //参数regs就是指向栈上的一个数据结构,由第二部分的mov r0, sp所传递。 68 | { 69 | const char* name = "null"; 70 | if (pInfo) { 71 | if (pInfo->methodName) { 72 | name = pInfo->methodName; 73 | } else { 74 | char buf[20]; 75 | sprintf(buf, "%p", pInfo->pBeHookAddr); 76 | name = buf; 77 | } 78 | } 79 | // LE("tid=%d onCallBack:%s", gettid(), name); 80 | 81 | LE("tid=%d, onCallBack:%s, " 82 | "r0=0x%lx, r1=0x%lx, r2=0x%lx, r3=0x%lx, r4=0x%lx, r5=0x%lx, r6=0x%lx, r7=0x%lx, r8=0x%lx, r9=0x%lx, r10=0x%lx, r11=0x%lx, r12=0x%lx, " 83 | "cur_sp=%p, ori_sp=%p, ori_sp/13=0x%lx, lr=0x%lx, cur_pc=0x%lx, cpsr=0x%lx, " 84 | "arg4=0x%lx, arg5=0x%lx, arg4=0x%lx, arg5=0x%lx;" 85 | , gettid(), name, 86 | regs->uregs[0], regs->uregs[1], regs->uregs[2], regs->uregs[3], regs->uregs[4], regs->uregs[5], 87 | regs->uregs[6], regs->uregs[7], regs->uregs[8], regs->uregs[9], regs->uregs[10], regs->uregs[11], 88 | regs->uregs[12], 89 | regs, ((char*)regs + 0x44), regs->uregs[13], regs->uregs[14], regs->uregs[15], regs->uregs[16], 90 | regs->uregs[17], regs->uregs[18], SP(0), SP(1) 91 | ); 92 | 93 | if (pInfo) { 94 | LE("onCallBack: HK_INFO=%p", pInfo); 95 | if (pInfo->pBeHookAddr == open && regs->uregs[0]) { 96 | LE("onCallBack: open ret: %ld", regs->uregs[0]); 97 | } 98 | } 99 | 100 | } 101 | 102 | typedef FILE* (*old_fopen)(const char* __path, const char* __mode); 103 | FILE* my_fopen(const char* pathname,const char* mode){ 104 | LE("hk: fopen %s , %s", pathname ? pathname : "is null", mode); 105 | 106 | FILE* fd = NULL; 107 | //理论上有可能存在取消hook了,但是hook函数还要执行,所以应该可以再回调原函数了。 108 | //所以如果要绝对安全,那么hook和取消hook时暂停线程,检查函数调用栈是必须的。 109 | auto ori_open = (old_fopen)(getOriFunByHkFun((void *)(my_fopen))); 110 | if (!ori_open) { 111 | ori_open = (old_fopen)fopen; 112 | } 113 | fd = ori_open(pathname, mode); 114 | LE("ori: fopen %s , fd=%p", pathname ? pathname : "is null", fd); 115 | return fd; 116 | } 117 | 118 | 119 | //因为都是hook的同一个函数是互斥的,用于演示函数的用法 120 | void test_dump(){ 121 | LE("open=%p, callback=%p", open, onPreCallBack); 122 | LE("__open=%p, callback=%p", dlsym(RTLD_DEFAULT, "__open"), onPreCallBack); 123 | if (dump((dlsym(RTLD_DEFAULT, "__open")), onPreCallBack, NULL, "__open") != success) { 124 | LE("hook __open error"); 125 | } else { 126 | LE("hook success"); 127 | } 128 | 129 | int (*my__open)(const char*, int, int) = (int (*)(const char*, int, int))dlsym(RTLD_DEFAULT, "__open"); 130 | int fd = my__open("/system/lib/libc.so", O_RDONLY, 0); 131 | LE("__open /system/lib/libc.so, fd=%d", fd); 132 | } 133 | 134 | /* 135 | void test_justReplace(){ 136 | LE("fopen=%p, callback=%p", fopen, onPreCallBack); 137 | if (dump((void *)(fopen), onPreCallBack, NULL, "fopen") != success) { 138 | LE("hook fopen error"); 139 | } else { 140 | LE("hook success"); 141 | } 142 | 143 | FILE *pFile = fopen("/system/lib/libc.so", "re"); 144 | LE("fopen /system/lib/libc.so, fd=%p", pFile); 145 | }*/ 146 | 147 | void test_dump_just_ret(){ 148 | LE("open=%p, callback=%p", open, onPreCallBack); 149 | if (dumpRet((void *)(open), onPreCallBack, "open") != success) { 150 | LE("hook open error"); 151 | } 152 | 153 | int fd = open("/system/lib/libc.so", O_RDONLY); 154 | LE("open /system/lib/libc.so, fd=%d", fd); 155 | } 156 | 157 | void test_dump_with_ret(){ 158 | LE("open=%p, callback=%p", open, onPreCallBack); 159 | if (dump((void *)(open), onPreCallBack, onCallBack, "open") != success) { 160 | LE("hook open error"); 161 | } 162 | 163 | int fd = open("/system/lib/libc.so", O_RDONLY); 164 | LE("open /system/lib/libc.so, fd=%d", fd); 165 | } 166 | 167 | void test_justReplace(){ 168 | LE("fopen=%p, callback=%p", fopen, onPreCallBack); 169 | // const RetInfo info = dump_replace(dlsym(RTLD_DEFAULT, "__openat"), (void *) (my__open), NULL, 170 | // NULL, "__open"); 171 | //android高版本没有__open了,__openat也隐藏符号了(只有64位隐藏了) 172 | // const RetInfo info = dump_replace(dlsym(RTLD_DEFAULT, "__openat"), (void *) (my__openat), NULL, 173 | // NULL, "__openat"); 174 | 175 | const RetInfo info = dump_replace((void*)fopen, (void *) (my_fopen), NULL, 176 | NULL, "fopen"); 177 | if (info.status != success) { 178 | LE("hook fopen error=%d", info.status); 179 | } 180 | 181 | 182 | FILE *pFile = fopen("/system/lib/libc.so", "re"); 183 | LE("fopen /system/lib/libc.so, fd=%p", pFile); 184 | unHook(info.info); 185 | } 186 | 187 | 188 | JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){ 189 | LE("JNI_OnLoad"); 190 | 191 | // test_dump(); 192 | test_justReplace(); 193 | // test_dump_just_ret(); 194 | test_dump_with_ret(); 195 | 196 | // test_dump_with_ret(); 197 | // test_dump_ret(); 198 | // test_dump_just_ret(); 199 | // test_replace(); 200 | // test_justReplace(); 201 | // test_args(); 202 | 203 | //解除hook后再次hook 204 | // test_replace(); 205 | // test_justReplace(); 206 | // test_args(); 207 | 208 | // test__system_property_get(); 209 | 210 | 211 | return JNI_VERSION_1_4; 212 | } 213 | 214 | int main(){ 215 | 216 | return 0; 217 | } 218 | 219 | -------------------------------------------------------------------------------- /myihk/src/main/libs/arm64-v8a/libshk.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/libs/arm64-v8a/libshk.so -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/libdump.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/libdump.a -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/libdump_with_ret.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/libdump_with_ret.a -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/libreplace.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/libreplace.a -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/libshk.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/libshk.so -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump/__/__/asm/dump.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump/__/__/asm/dump.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump/__/fixPCOpcode.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump/__/fixPCOpcode.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump/__/fixPCOpcode.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/dump/__/fixPCOpcode.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../fixPCOpcode.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../fixPCOpcode.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../../../include\../include/mhk.h 5 | 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../fixPCOpcode.h: 7 | 8 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../../../include\../include/mhk.h: 9 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump/__/mhk.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump/__/mhk.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump/__/mhk.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/dump/__/mhk.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../mhk.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../../../include\mhk.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../fixPCOpcode.h 5 | 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../../../include\mhk.h: 7 | 8 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../fixPCOpcode.h: 9 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump/dump.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump/dump.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump/dump.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/dump/dump.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/dump.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../../../include\mhk.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../fixPCOpcode.h 5 | 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../../../include\mhk.h: 7 | 8 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump/../fixPCOpcode.h: 9 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/__/asm/dump_with_ret.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/__/asm/dump_with_ret.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/fixPCOpcode.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/fixPCOpcode.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/fixPCOpcode.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/fixPCOpcode.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../fixPCOpcode.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../fixPCOpcode.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\../include/mhk.h 5 | 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../fixPCOpcode.h: 7 | 8 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\../include/mhk.h: 9 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/mhk.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/mhk.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/mhk.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/__/mhk.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../mhk.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\mhk.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../fixPCOpcode.h 5 | 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\mhk.h: 7 | 8 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../fixPCOpcode.h: 9 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/dump.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\mhk.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../fixPCOpcode.h \ 5 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/lr.h 6 | 7 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\mhk.h: 8 | 9 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../fixPCOpcode.h: 10 | 11 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/lr.h: 12 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump_with_ret.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump_with_ret.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump_with_ret.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/dump_with_ret/dump_with_ret.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/dump_with_ret.cpp \ 3 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\map \ 4 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\vector \ 5 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/lr.h \ 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\mhk.h 7 | 8 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\map: 9 | 10 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\vector: 11 | 12 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/lr.h: 13 | 14 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/dump_with_ret/../../../include\mhk.h: 15 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/__/__/asm/replace.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/replace/__/__/asm/replace.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/__/fixPCOpcode.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/replace/__/fixPCOpcode.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/__/fixPCOpcode.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/replace/__/fixPCOpcode.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../fixPCOpcode.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../fixPCOpcode.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\../include/mhk.h 5 | 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../fixPCOpcode.h: 7 | 8 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\../include/mhk.h: 9 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/__/mhk.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/replace/__/mhk.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/__/mhk.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/replace/__/mhk.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../mhk.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\mhk.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../fixPCOpcode.h 5 | 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\mhk.h: 7 | 8 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../fixPCOpcode.h: 9 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/lr.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/replace/lr.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/lr.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/replace/lr.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/lr.cpp \ 3 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\map \ 4 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\vector \ 5 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/lr.h \ 6 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\mhk.h 7 | 8 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\map: 9 | 10 | D:/android/NDK/android-ndk-r16b/build//../sources/cxx-stl/gnu-libstdc++/4.9/include\vector: 11 | 12 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/lr.h: 13 | 14 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\mhk.h: 15 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/replace.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/replace/replace.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/replace/replace.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/replace/replace.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/replace.c \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\mhk.h \ 4 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../fixPCOpcode.h \ 5 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/lr.h 6 | 7 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../../../include\mhk.h: 8 | 9 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/../fixPCOpcode.h: 10 | 11 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/arm64/src/replace/lr.h: 12 | -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/shk/main.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuotong/Android_InlineHook/728eaca9d33d59a578f617c693264650387c97fd/myihk/src/main/obj/local/arm64-v8a/objs/shk/main.o -------------------------------------------------------------------------------- /myihk/src/main/obj/local/arm64-v8a/objs/shk/main.o.d: -------------------------------------------------------------------------------- 1 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/obj/local/arm64-v8a/objs/shk/main.o: \ 2 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/test/main.cpp \ 3 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/test/../include\mhk.h 4 | 5 | D:/code/android_code/hook/got_plt/MyInHk/myihk/src/main/jni/test/../include\mhk.h: 6 | -------------------------------------------------------------------------------- /myihk/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /myihk/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 | -------------------------------------------------------------------------------- /myihk/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |