├── .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 |
6 |
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 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
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