├── .gitignore
├── .idea
├── .gitignore
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── kotlinc.xml
├── misc.xml
└── vcs.xml
├── README.md
├── assets
└── ezAndroid.apk
├── build.gradle.kts
├── classes-rewritten.dex
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src
└── main
├── kotlin
└── site
│ └── gaoyucan
│ ├── Main.kt
│ ├── dexpatch
│ └── instruction
│ │ ├── DexPatchArrayPayload.kt
│ │ ├── DexPatchInstruction.kt
│ │ ├── DexPatchInstruction10t.kt
│ │ ├── DexPatchInstruction10x.kt
│ │ ├── DexPatchInstruction11n.kt
│ │ ├── DexPatchInstruction11x.kt
│ │ ├── DexPatchInstruction12x.kt
│ │ ├── DexPatchInstruction20bc.kt
│ │ ├── DexPatchInstruction20t.kt
│ │ ├── DexPatchInstruction21c.kt
│ │ ├── DexPatchInstruction21ih.kt
│ │ ├── DexPatchInstruction21lh.kt
│ │ ├── DexPatchInstruction21s.kt
│ │ ├── DexPatchInstruction21t.kt
│ │ ├── DexPatchInstruction22b.kt
│ │ ├── DexPatchInstruction22c.kt
│ │ ├── DexPatchInstruction22cs.kt
│ │ ├── DexPatchInstruction22s.kt
│ │ ├── DexPatchInstruction22t.kt
│ │ ├── DexPatchInstruction22x.kt
│ │ ├── DexPatchInstruction23x.kt
│ │ ├── DexPatchInstruction30t.kt
│ │ ├── DexPatchInstruction31c.kt
│ │ ├── DexPatchInstruction31i.kt
│ │ ├── DexPatchInstruction31t.kt
│ │ ├── DexPatchInstruction32x.kt
│ │ ├── DexPatchInstruction35c.kt
│ │ ├── DexPatchInstruction35mi.kt
│ │ ├── DexPatchInstruction35ms.kt
│ │ ├── DexPatchInstruction3rc.kt
│ │ ├── DexPatchInstruction3rmi.kt
│ │ ├── DexPatchInstruction3rms.kt
│ │ ├── DexPatchInstruction45cc.kt
│ │ ├── DexPatchInstruction4rcc.kt
│ │ ├── DexPatchInstruction51l.kt
│ │ ├── DexPatchPackedSwitchPayload.kt
│ │ └── DexPatchSparseSwitchPayload.kt
│ └── ext
│ └── ByteArrayExt.kt
└── resources
├── assets
├── 0OooOO
├── O0ooOO
├── OOoo0O
├── OOooO0
├── oo0Ooo
└── ooO0oo
└── classes.dex
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 | !**/src/main/**/build/
5 | !**/src/test/**/build/
6 |
7 | ### IntelliJ IDEA ###
8 | .idea/modules.xml
9 | .idea/jarRepositories.xml
10 | .idea/compiler.xml
11 | .idea/libraries/
12 | *.iws
13 | *.iml
14 | *.ipr
15 | out/
16 | !**/src/main/**/out/
17 | !**/src/test/**/out/
18 |
19 | ### Eclipse ###
20 | .apt_generated
21 | .classpath
22 | .factorypath
23 | .project
24 | .settings
25 | .springBeans
26 | .sts4-cache
27 | bin/
28 | !**/src/main/**/bin/
29 | !**/src/test/**/bin/
30 |
31 | ### NetBeans ###
32 | /nbproject/private/
33 | /nbbuild/
34 | /dist/
35 | /nbdist/
36 | /.nb-gradle/
37 |
38 | ### VS Code ###
39 | .vscode/
40 |
41 | ### Mac OS ###
42 | .DS_Store
43 |
44 | *.i64
45 | *.idb
46 | *.cache
47 | *.jadx
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DexPatcher
2 | 2023 年 羊城杯 [ezAndroid](./assets/ezAndroid.apk) dex VMP 恢复工具
3 |
4 | 恢复效果:
5 | 
6 | 
7 |
8 |
--------------------------------------------------------------------------------
/assets/ezAndroid.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/assets/ezAndroid.apk
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm") version "1.9.20"
3 | application
4 | }
5 |
6 | group = "site.gaoyucan"
7 | version = "1.0-SNAPSHOT"
8 |
9 | repositories {
10 | mavenCentral()
11 | }
12 |
13 | dependencies {
14 | implementation("org.smali:dexlib2:2.5.2")
15 | implementation("com.google.guava:guava:32.1.3-jre")
16 | testImplementation(kotlin("test"))
17 | }
18 |
19 | tasks.test {
20 | useJUnitPlatform()
21 | }
22 |
23 | kotlin {
24 | jvmToolchain(8)
25 | }
26 |
27 | application {
28 | mainClass.set("MainKt")
29 | }
--------------------------------------------------------------------------------
/classes-rewritten.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/classes-rewritten.dex
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | kotlin.code.style=official
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | mavenCentral()
4 | gradlePluginPortal()
5 | }
6 | }
7 |
8 | plugins {
9 | id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
10 | }
11 |
12 | rootProject.name = "DexPatcher"
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/Main.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan
2 |
3 | import com.google.common.collect.ImmutableList
4 | import com.google.common.collect.ImmutableSet
5 | import com.google.common.io.LittleEndianDataInputStream
6 | import org.jf.dexlib2.AccessFlags
7 | import org.jf.dexlib2.DexFileFactory
8 | import org.jf.dexlib2.Opcode
9 | import org.jf.dexlib2.Opcodes
10 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
11 | import org.jf.dexlib2.formatter.DexFormatter
12 | import org.jf.dexlib2.iface.Method
13 | import org.jf.dexlib2.iface.instruction.Instruction
14 | import org.jf.dexlib2.immutable.ImmutableAnnotation
15 | import org.jf.dexlib2.immutable.ImmutableMethod
16 | import org.jf.dexlib2.immutable.ImmutableMethodImplementation
17 | import org.jf.dexlib2.immutable.ImmutableMethodParameter
18 | import org.jf.dexlib2.immutable.instruction.ImmutableInstruction10t
19 | import org.jf.dexlib2.immutable.instruction.ImmutableInstruction10x
20 | import org.jf.dexlib2.rewriter.DexRewriter
21 | import org.jf.dexlib2.rewriter.MethodRewriter
22 | import org.jf.dexlib2.rewriter.Rewriter
23 | import org.jf.dexlib2.rewriter.RewriterModule
24 | import org.jf.dexlib2.rewriter.Rewriters
25 | import site.gaoyucan.dexpatch.instruction.DexPatchInstruction
26 | import site.gaoyucan.ext.readSmallUint
27 | import site.gaoyucan.ext.readUshort
28 | import java.io.InputStream
29 |
30 |
31 | class Main {
32 | companion object {
33 | val methods = mapOf(
34 | "Lcom/example/ezandroid/S;->onCreate(Landroid/os/Bundle;)V" to "assets/0OooOO",
35 | "Lcom/example/ezandroid/S2;->onCreate(Landroid/os/Bundle;)V" to "assets/O0ooOO",
36 | "Lcom/example/ezandroid/MU;->GMS(Ljava/lang/String;)Ljava/lang/String;" to "assets/oo0Ooo",
37 | "Lcom/example/ezandroid/C;->cf(Ljava/lang/String;I)Z" to "assets/ooO0oo",
38 | "Lcom/example/ezandroid/S$1;->onClick(Landroid/view/View;)V" to "assets/OOoo0O",
39 | "Lcom/example/ezandroid/S2$1;->onClick(Landroid/view/View;)V" to "assets/OOooO0",
40 | )
41 |
42 |
43 | @OptIn(ExperimentalStdlibApi::class)
44 | @JvmStatic
45 | fun main(args: Array) {
46 | val dexFileAsStream = openResource("classes.dex")
47 | val dexFile = DexBackedDexFile.fromInputStream(Opcodes.getDefault(), dexFileAsStream)
48 | val opcodeArr = Opcode.entries.map {
49 | it.apiToValueMap[dexFile.opcodes.api]?.toInt() to it
50 | }.toMap()
51 | DexRewriter(object : RewriterModule() {
52 | override fun getMethodRewriter(rewriters: Rewriters): Rewriter {
53 | return object : MethodRewriter(rewriters) {
54 | override fun rewrite(method: Method): Method {
55 | val methodDescriptor = DexFormatter.INSTANCE.getMethodDescriptor(method)
56 | if (methodDescriptor in methods.keys) {
57 | println("Rewriting $methodDescriptor : native method: ${method.accessFlags and AccessFlags.NATIVE.value != 0}")
58 | val rawMethod = LittleEndianDataInputStream(openResource(methods[methodDescriptor]!!))
59 | val regCount = rawMethod.readUnsignedShort()
60 | val codeSegSize = rawMethod.readUnsignedShort() * 2
61 | val _argCount = rawMethod.readUnsignedShort() // drop this
62 | val instructions = mutableListOf()
63 | var i = 0
64 | while (i < codeSegSize) {
65 | var op = rawMethod.readUnsignedByte()
66 | // TODO: 这里存在问题,按理说该放后面,但是这里我确定几个 Payload 和 Nop 都没动,所以先这样吧
67 | if (op == 0x00) { // maybe Payload
68 | op = rawMethod.readUnsignedByte() shl 8
69 | }
70 | if (op == 0x00) { // 提前处理 NOP
71 | instructions.add(ImmutableInstruction10x(Opcode.NOP))
72 | i += 2
73 | continue
74 | }
75 | // 获取原始(真实) opcode
76 | if (op !in opcodesMap.keys) { // 验证是否已经找到对应的修改后的opcode
77 | throw IllegalStateException("Unknown opcode: ${op.toUShort().toHexString()}")
78 | }
79 | op = opcodesMap[op]!!
80 | val opcode = opcodeArr[op]!!
81 | // 获取指令长度
82 | val insSize = opcode.format.size
83 | if (insSize == -1) {
84 | var insSizeVar: Int
85 | var rawCount: ByteArray
86 | if (opcode == Opcode.PACKED_SWITCH_PAYLOAD) {
87 | rawCount = ByteArray(2) // elementCount
88 | rawMethod.read(rawCount, 0, 2)
89 | insSizeVar = 8 + rawCount.readUshort(0) * 4
90 |
91 | } else if (opcode == Opcode.SPARSE_SWITCH_PAYLOAD) {
92 | rawCount = ByteArray(2) // elementCount
93 | rawMethod.read(rawCount, 0, 2)
94 | insSizeVar = 4 + rawCount.readUshort(0) * 8
95 | } else {
96 | rawCount = ByteArray(6) // elementWidth
97 | rawMethod.read(rawCount, 0, 6)
98 | val localElementWidth = rawCount.readUshort(0)
99 | insSizeVar = if (localElementWidth == 0) {
100 | 8
101 | } else {
102 | ((rawCount.readSmallUint(2) * localElementWidth + 1) / 2) * 2 + 8
103 | }
104 | }
105 | val rawInstruction = ByteArray(insSizeVar)
106 | // offset=2 跳过 opcode,补上 rawCount
107 | rawCount.copyInto(rawInstruction, 2, 0, rawCount.size)
108 | // offset=2+rawCount.size 跳过 opcode,rawCount,补上剩余的数据
109 | rawMethod.read(
110 | rawInstruction,
111 | 2 + rawCount.size,
112 | insSizeVar - 2 - rawCount.size
113 | )
114 | val instruction =
115 | DexPatchInstruction.buildInstruction(opcode, rawInstruction, dexFile)
116 | instructions.add(instruction)
117 | i += insSizeVar
118 | } else {
119 | // 创建指令
120 | val rawInstruction = ByteArray(insSize)
121 | // offset=1 跳过 opcode
122 | rawMethod.read(rawInstruction, 1, insSize - 1)
123 | val instruction =
124 | DexPatchInstruction.buildInstruction(opcode, rawInstruction, dexFile)
125 | instructions.add(instruction)
126 | i += insSize
127 | }
128 | }
129 | // 构造 methodImplementation, parameters, annotations
130 | val methodImplementation = ImmutableMethodImplementation(
131 | regCount,
132 | instructions,
133 | emptyList(),
134 | emptyList(),
135 | )
136 | val parameters = method.parameters.stream().map { ImmutableMethodParameter.of(it) }
137 | .collect(ImmutableList.toImmutableList())
138 | val annotations = method.annotations.stream().map { ImmutableAnnotation.of(it) }
139 | .collect(ImmutableSet.toImmutableSet())
140 | // 构造新的 method
141 | return ImmutableMethod(
142 | method.definingClass,
143 | method.name,
144 | parameters,
145 | method.returnType,
146 | method.accessFlags xor AccessFlags.NATIVE.value,
147 | annotations,
148 | ImmutableSet.of(),
149 | methodImplementation
150 | )
151 | }
152 | return super.rewrite(method)
153 | }
154 | }
155 | }
156 | }).dexFileRewriter.rewrite(dexFile).let {
157 | DexFileFactory.writeDexFile("classes-rewritten.dex", it)
158 | }
159 |
160 | }
161 |
162 | val opcodesMap = mapOf(
163 | 0x6f to 0x6f,
164 | 0x1a to 0x6e,
165 | 0x26 to 0x0c,
166 | 0x54 to 0x71,
167 | 0x22 to 0x54,
168 | 0x71 to 0x1a,
169 | 0x0e to 0x22,
170 | 0x0c to 0x70,
171 | 0x70 to 0x0e,
172 | 0x12 to 0x12,
173 | 0x5b to 0x5b,
174 | 0x39 to 0x39,
175 | 0x0a to 0x0a,
176 | 0x13 to 0x13,
177 | 0xdf to 0x33,
178 | 0x23 to 0x23,
179 | 0x4d to 0x4d,
180 | 0x28 to 0x28,
181 | 0x38 to 0x38,
182 | 0x33 to 0x26,
183 | 0x35 to 0x35,
184 | 0x48 to 0xdf,
185 | 0x6e to 0x48,
186 | 0x32 to 0x32,
187 | 0x0f to 0x0f,
188 | 0xd8 to 0xd8,
189 | 0x300 to 0x300,
190 | 0x0d to 0x0d,
191 | 0x11 to 0x11,
192 | 0x14 to 0x14,
193 | 0x1f to 0x1f
194 | )
195 |
196 | private fun openResource(name: String): InputStream {
197 | return Main::class.java.classLoader.getResourceAsStream(name)!!
198 | }
199 | }
200 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchArrayPayload.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.util.FixedSizeList
6 | import org.jf.dexlib2.iface.instruction.formats.ArrayPayload
7 | import org.jf.util.ExceptionWithContext
8 | import site.gaoyucan.ext.*
9 |
10 | class DexPatchArrayPayload(rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
11 | DexPatchInstruction(Opcode.ARRAY_PAYLOAD, rawInstruction, dexFile), ArrayPayload {
12 | private val elementWidth: Int
13 | val elementCount: Int
14 |
15 | init {
16 | val localElementWidth = rawInstruction.readUshort(ELEMENT_WIDTH_OFFSET)
17 | if (localElementWidth == 0) {
18 | elementWidth = 1
19 | elementCount = 0
20 | } else {
21 | elementWidth = localElementWidth
22 | elementCount = rawInstruction.readSmallUint(ELEMENT_COUNT_OFFSET)
23 | if (elementWidth.toLong() * elementCount > Int.MAX_VALUE) {
24 | throw ExceptionWithContext("Invalid array-payload instruction: element width*count overflows")
25 | }
26 | }
27 | }
28 |
29 | override fun getElementWidth(): Int {
30 | return elementWidth
31 | }
32 |
33 | override fun getArrayElements(): MutableList {
34 |
35 | abstract class ReturnedList : FixedSizeList() {
36 | override val size: Int
37 | get() = elementCount
38 | }
39 |
40 | if (elementCount == 0) {
41 | return mutableListOf()
42 | }
43 | return when (elementWidth) {
44 | 1 -> object : ReturnedList() {
45 | override fun readItem(offset: Int): Number {
46 | return rawInstruction[ELEMENTS_OFFSET + offset]
47 | }
48 | }
49 | 2 -> object : ReturnedList() {
50 | override fun readItem(offset: Int): Number {
51 | return rawInstruction.readShort(ELEMENTS_OFFSET + offset * 2)
52 | }
53 | }
54 | 4 -> object : ReturnedList() {
55 | override fun readItem(offset: Int): Number {
56 | return rawInstruction.readInt(ELEMENTS_OFFSET + offset * 4)
57 | }
58 | }
59 | 8 -> object : ReturnedList() {
60 | override fun readItem(offset: Int): Number {
61 | return rawInstruction.readLong(ELEMENTS_OFFSET + offset * 8)
62 | }
63 | }
64 | else -> throw ExceptionWithContext("Invalid element width: %d", elementWidth)
65 | }
66 | }
67 |
68 | override fun getCodeUnits(): Int {
69 | return 4 + (elementWidth * elementCount + 1) / 2
70 | }
71 |
72 | companion object {
73 | private const val ELEMENT_WIDTH_OFFSET = 2
74 | private const val ELEMENT_COUNT_OFFSET = 4
75 | private const val ELEMENTS_OFFSET = 8
76 | }
77 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Format
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.Instruction
7 |
8 | abstract class DexPatchInstruction(
9 | private val opcode: Opcode,
10 | val rawInstruction: ByteArray,
11 | val dexFile: DexBackedDexFile
12 | ) :
13 | Instruction {
14 | override fun getCodeUnits() = opcode.format.size / 2
15 | override fun getOpcode() = opcode
16 |
17 | companion object {
18 | fun buildInstruction(opcode: Opcode, raw: ByteArray, dexFile: DexBackedDexFile): DexPatchInstruction {
19 | return when (opcode.format) {
20 | Format.Format10t -> DexPatchInstruction10t(opcode, raw, dexFile)
21 | Format.Format10x -> DexPatchInstruction10x(opcode, raw, dexFile)
22 | Format.Format11n -> DexPatchInstruction11n(opcode, raw, dexFile)
23 | Format.Format11x -> DexPatchInstruction11x(opcode, raw, dexFile)
24 | Format.Format12x -> DexPatchInstruction12x(opcode, raw, dexFile)
25 | Format.Format20bc -> DexPatchInstruction20bc(opcode, raw, dexFile)
26 | Format.Format20t -> DexPatchInstruction20t(opcode, raw, dexFile)
27 | Format.Format21c -> DexPatchInstruction21c(opcode, raw, dexFile)
28 | Format.Format21ih -> DexPatchInstruction21ih(opcode, raw, dexFile)
29 | Format.Format21lh -> DexPatchInstruction21lh(opcode, raw, dexFile)
30 | Format.Format21s -> DexPatchInstruction21s(opcode, raw, dexFile)
31 | Format.Format21t -> DexPatchInstruction21t(opcode, raw, dexFile)
32 | Format.Format22b -> DexPatchInstruction22b(opcode, raw, dexFile)
33 | Format.Format22c -> DexPatchInstruction22c(opcode, raw, dexFile)
34 | Format.Format22cs -> DexPatchInstruction22cs(opcode, raw, dexFile)
35 | Format.Format22s -> DexPatchInstruction22s(opcode, raw, dexFile)
36 | Format.Format22t -> DexPatchInstruction22t(opcode, raw, dexFile)
37 | Format.Format22x -> DexPatchInstruction22x(opcode, raw, dexFile)
38 | Format.Format23x -> DexPatchInstruction23x(opcode, raw, dexFile)
39 | Format.Format30t -> DexPatchInstruction30t(opcode, raw, dexFile)
40 | Format.Format31c -> DexPatchInstruction31c(opcode, raw, dexFile)
41 | Format.Format31i -> DexPatchInstruction31i(opcode, raw, dexFile)
42 | Format.Format31t -> DexPatchInstruction31t(opcode, raw, dexFile)
43 | Format.Format32x -> DexPatchInstruction32x(opcode, raw, dexFile)
44 | Format.Format35c -> DexPatchInstruction35c(opcode, raw, dexFile)
45 | Format.Format35mi -> DexPatchInstruction35mi(opcode, raw, dexFile)
46 | Format.Format35ms -> DexPatchInstruction35ms(opcode, raw, dexFile)
47 | Format.Format3rc -> DexPatchInstruction3rc(opcode, raw, dexFile)
48 | Format.Format3rmi -> DexPatchInstruction3rmi(opcode, raw, dexFile)
49 | Format.Format3rms -> DexPatchInstruction3rms(opcode, raw, dexFile)
50 | Format.Format45cc -> DexPatchInstruction45cc(opcode, raw, dexFile)
51 | Format.Format4rcc -> DexPatchInstruction4rcc(opcode, raw, dexFile)
52 | Format.Format51l -> DexPatchInstruction51l(opcode, raw, dexFile)
53 | Format.ArrayPayload -> DexPatchArrayPayload(raw, dexFile)
54 | Format.PackedSwitchPayload -> DexPatchPackedSwitchPayload(raw, dexFile)
55 | Format.SparseSwitchPayload -> DexPatchSparseSwitchPayload(raw, dexFile)
56 | else -> throw IllegalArgumentException("Unsupported opcode format: ${opcode.format}")
57 | }
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction10t.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction10t
6 |
7 | class DexPatchInstruction10t(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
8 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction10t {
9 |
10 |
11 | override fun getCodeOffset(): Int {
12 | return rawInstruction[1].toInt()
13 | }
14 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction10x.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction10x
6 |
7 | class DexPatchInstruction10x(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
8 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction10x {
9 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction11n.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction11n
6 | import org.jf.util.NibbleUtils
7 |
8 | class DexPatchInstruction11n(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction11n {
10 |
11 | override fun getRegisterA(): Int {
12 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
13 | }
14 |
15 | override fun getWideLiteral(): Long {
16 | return NibbleUtils.extractHighSignedNibble(rawInstruction[1].toInt()).toLong()
17 | }
18 |
19 | override fun getNarrowLiteral(): Int {
20 | return wideLiteral.toInt()
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction11x.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction11x
6 |
7 | class DexPatchInstruction11x(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
8 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction11x {
9 | override fun getRegisterA(): Int {
10 | return rawInstruction[1].toInt()
11 | }
12 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction12x.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction12x
6 | import org.jf.util.NibbleUtils
7 |
8 | class DexPatchInstruction12x(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction12x {
10 |
11 | override fun getRegisterA(): Int {
12 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
13 | }
14 |
15 | override fun getRegisterB(): Int {
16 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction20bc.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.ReferenceType
6 | import org.jf.dexlib2.ReferenceType.InvalidReferenceTypeException
7 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
8 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
9 | import org.jf.dexlib2.iface.instruction.formats.Instruction20bc
10 | import org.jf.dexlib2.iface.reference.Reference
11 | import org.jf.dexlib2.iface.reference.Reference.InvalidReferenceException
12 | import site.gaoyucan.ext.readUshort
13 |
14 | class DexPatchInstruction20bc(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
15 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction20bc {
16 |
17 | override fun getVerificationError(): Int {
18 | return rawInstruction[1].toUByte().toInt() and 0x3f
19 | }
20 |
21 | override fun getReference(): Reference {
22 | val referenceIndex = rawInstruction.readUshort(2)
23 | return try {
24 | val referenceType = getReferenceType()
25 | DexBackedReference.makeReference(dexFile, referenceType, referenceIndex)
26 | } catch (ex: InvalidReferenceTypeException) {
27 | Reference {
28 | throw InvalidReferenceException("${ex.referenceType}${referenceIndex}", ex)
29 | }
30 | }
31 | }
32 |
33 | override fun getReferenceType(): Int {
34 | val referenceType = (rawInstruction[1].toUByte().toInt() ushr 6) + 1
35 | ReferenceType.validateReferenceType(referenceType)
36 | return referenceType
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction20t.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction;
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile;
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction20t
7 | import site.gaoyucan.ext.readUshort
8 |
9 | class DexPatchInstruction20t(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction20t {
11 |
12 | override fun getCodeOffset(): Int {
13 | return rawInstruction.readUshort(2)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction21c.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
7 | import org.jf.dexlib2.iface.instruction.formats.Instruction21c
8 | import org.jf.dexlib2.iface.reference.Reference
9 | import site.gaoyucan.ext.readUshort
10 |
11 | class DexPatchInstruction21c(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
12 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction21c {
13 | override fun getRegisterA(): Int {
14 | return rawInstruction[1].toUByte().toInt()
15 | }
16 |
17 | override fun getReference(): Reference {
18 | val referenceIndex = rawInstruction.readUshort(2)
19 | return DexBackedReference.makeReference(dexFile, referenceType, referenceIndex)
20 | }
21 |
22 | override fun getReferenceType(): Int {
23 | return opcode.referenceType
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction21ih.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction21ih
7 | import site.gaoyucan.ext.readShort
8 |
9 | class DexPatchInstruction21ih(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction21ih {
11 | override fun getRegisterA(): Int {
12 | return rawInstruction[1].toUByte().toInt()
13 | }
14 |
15 | override fun getHatLiteral(): Short {
16 | return rawInstruction.readShort(2)
17 | }
18 |
19 | override fun getWideLiteral(): Long {
20 | return narrowLiteral.toLong()
21 | }
22 |
23 | override fun getNarrowLiteral(): Int {
24 | return hatLiteral.toInt() shl 16
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction21lh.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction21lh
7 | import site.gaoyucan.ext.readShort
8 |
9 | class DexPatchInstruction21lh(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction21lh {
11 | override fun getRegisterA(): Int {
12 | return rawInstruction[1].toUByte().toInt()
13 | }
14 |
15 | override fun getWideLiteral(): Long {
16 | return hatLiteral.toLong() shl 48;
17 | }
18 |
19 | override fun getHatLiteral(): Short {
20 | return rawInstruction.readShort(2)
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction21s.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction21s
6 | import site.gaoyucan.ext.readShort
7 |
8 | class DexPatchInstruction21s(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction21s
10 | {
11 | override fun getRegisterA(): Int {
12 | return rawInstruction[1].toUByte().toInt()
13 | }
14 |
15 | override fun getWideLiteral(): Long {
16 | return narrowLiteral.toLong()
17 | }
18 |
19 | override fun getNarrowLiteral(): Int {
20 | return rawInstruction.readShort(2).toInt()
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction21t.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction21t
7 | import site.gaoyucan.ext.readShort
8 |
9 | class DexPatchInstruction21t(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction21t {
11 | override fun getRegisterA(): Int {
12 | return rawInstruction[1].toUByte().toInt()
13 | }
14 |
15 | override fun getCodeOffset(): Int {
16 | return rawInstruction.readShort(2).toInt()
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction22b.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction22b
6 |
7 | class DexPatchInstruction22b(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
8 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction22b {
9 | override fun getRegisterA(): Int {
10 | return rawInstruction[1].toUByte().toInt()
11 | }
12 |
13 | override fun getRegisterB(): Int {
14 | return rawInstruction[2].toUByte().toInt()
15 | }
16 |
17 | override fun getWideLiteral(): Long {
18 | return narrowLiteral.toLong()
19 | }
20 |
21 | override fun getNarrowLiteral(): Int {
22 | return rawInstruction[3].toInt()
23 | }
24 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction22c.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
7 | import org.jf.dexlib2.iface.instruction.formats.Instruction22c
8 | import org.jf.dexlib2.iface.reference.Reference
9 | import org.jf.util.NibbleUtils
10 | import site.gaoyucan.ext.readUshort
11 |
12 | class DexPatchInstruction22c(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
13 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction22c {
14 | override fun getRegisterA(): Int {
15 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
16 | }
17 |
18 | override fun getRegisterB(): Int {
19 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
20 | }
21 |
22 | override fun getReference(): Reference {
23 | val referenceIndex = rawInstruction.readUshort(2)
24 | return DexBackedReference.makeReference(dexFile, referenceType, referenceIndex)
25 | }
26 |
27 | override fun getReferenceType(): Int {
28 | return opcode.referenceType
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction22cs.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction22cs
7 | import org.jf.util.NibbleUtils
8 | import site.gaoyucan.ext.readUshort
9 |
10 | class DexPatchInstruction22cs(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
11 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction22cs {
12 | override fun getRegisterA(): Int {
13 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
14 | }
15 |
16 | override fun getRegisterB(): Int {
17 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
18 | }
19 |
20 | override fun getFieldOffset(): Int {
21 | return rawInstruction.readUshort(2)
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction22s.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction22s
7 | import org.jf.util.NibbleUtils
8 | import site.gaoyucan.ext.readShort
9 |
10 | class DexPatchInstruction22s(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
11 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction22s {
12 | override fun getRegisterA(): Int {
13 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
14 | }
15 |
16 | override fun getRegisterB(): Int {
17 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
18 | }
19 |
20 | override fun getWideLiteral(): Long {
21 | return narrowLiteral.toLong()
22 | }
23 |
24 | override fun getNarrowLiteral(): Int {
25 | return rawInstruction.readShort(2).toInt()
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction22t.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction22t
7 | import org.jf.util.NibbleUtils
8 | import site.gaoyucan.ext.readShort
9 |
10 | class DexPatchInstruction22t(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
11 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction22t {
12 | override fun getRegisterA(): Int {
13 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
14 | }
15 |
16 | override fun getRegisterB(): Int {
17 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
18 | }
19 |
20 | override fun getCodeOffset(): Int {
21 | return rawInstruction.readShort(2).toInt()
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction22x.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction22x
7 | import site.gaoyucan.ext.readUshort
8 |
9 | class DexPatchInstruction22x(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction22x {
11 | override fun getRegisterA(): Int {
12 | return rawInstruction[1].toUByte().toInt()
13 | }
14 |
15 | override fun getRegisterB(): Int {
16 | return rawInstruction.readUshort(2)
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction23x.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction23x
6 |
7 | class DexPatchInstruction23x(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
8 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction23x {
9 | override fun getRegisterA(): Int {
10 | return rawInstruction[1].toUByte().toInt()
11 | }
12 |
13 | override fun getRegisterB(): Int {
14 | return rawInstruction[2].toUByte().toInt()
15 | }
16 |
17 | override fun getRegisterC(): Int {
18 | return rawInstruction[3].toUByte().toInt()
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction30t.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import com.google.common.io.LittleEndianDataInputStream
4 | import org.jf.dexlib2.Opcode
5 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction30t
7 | import site.gaoyucan.ext.readInt
8 |
9 | class DexPatchInstruction30t(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction30t {
11 | override fun getCodeOffset(): Int {
12 | return rawInstruction.readInt(2)
13 | }
14 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction31c.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction31c
7 | import org.jf.dexlib2.iface.reference.Reference
8 | import org.jf.util.ExceptionWithContext
9 | import site.gaoyucan.ext.readSmallUint
10 |
11 | class DexPatchInstruction31c(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
12 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction31c {
13 | override fun getRegisterA(): Int {
14 | return rawInstruction[1].toUByte().toInt()
15 | }
16 |
17 | override fun getReference(): Reference {
18 | return DexBackedReference.makeReference(dexFile, referenceType, rawInstruction.readSmallUint(2))
19 | }
20 |
21 | override fun getReferenceType(): Int {
22 | return opcode.referenceType
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction31i.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction31i
6 | import site.gaoyucan.ext.readInt
7 |
8 | class DexPatchInstruction31i(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction31i {
10 | override fun getRegisterA(): Int {
11 | return rawInstruction[1].toUByte().toInt()
12 | }
13 |
14 | override fun getWideLiteral(): Long {
15 | return narrowLiteral.toLong()
16 | }
17 |
18 | override fun getNarrowLiteral(): Int {
19 | return rawInstruction.readInt(2)
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction31t.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction31t
6 | import site.gaoyucan.ext.readInt
7 |
8 | class DexPatchInstruction31t(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction31t {
10 | override fun getRegisterA(): Int {
11 | return rawInstruction[1].toUByte().toInt()
12 | }
13 |
14 | override fun getCodeOffset(): Int {
15 | return rawInstruction.readInt(2)
16 | }
17 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction32x.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction32x
6 | import site.gaoyucan.ext.readUshort
7 |
8 | class DexPatchInstruction32x(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction32x {
10 | override fun getRegisterA(): Int {
11 | return rawInstruction.readUshort(2)
12 | }
13 |
14 | override fun getRegisterB(): Int {
15 | return rawInstruction.readUshort(4)
16 | }
17 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction35c.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction35c
7 | import org.jf.dexlib2.iface.reference.Reference
8 | import org.jf.util.NibbleUtils
9 | import site.gaoyucan.ext.readUshort
10 |
11 | class DexPatchInstruction35c(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
12 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction35c {
13 | override fun getRegisterCount(): Int {
14 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
15 | }
16 |
17 | override fun getRegisterC(): Int {
18 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[4].toInt())
19 | }
20 |
21 | override fun getRegisterD(): Int {
22 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[4].toInt())
23 | }
24 |
25 | override fun getRegisterE(): Int {
26 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[5].toInt())
27 | }
28 |
29 | override fun getRegisterF(): Int {
30 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[5].toInt())
31 | }
32 |
33 | override fun getRegisterG(): Int {
34 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
35 | }
36 |
37 | override fun getReference(): Reference {
38 | return DexBackedReference.makeReference(dexFile, referenceType, rawInstruction.readUshort(2))
39 | }
40 |
41 | override fun getReferenceType(): Int {
42 | return opcode.referenceType
43 | }
44 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction35mi.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction35mi
6 | import org.jf.util.NibbleUtils
7 | import site.gaoyucan.ext.readUshort
8 |
9 | class DexPatchInstruction35mi(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction35mi {
11 | override fun getRegisterCount(): Int {
12 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
13 | }
14 |
15 | override fun getRegisterC(): Int {
16 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[4].toInt())
17 | }
18 |
19 | override fun getRegisterD(): Int {
20 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[4].toInt())
21 | }
22 |
23 | override fun getRegisterE(): Int {
24 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[5].toInt())
25 | }
26 |
27 | override fun getRegisterF(): Int {
28 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[5].toInt())
29 | }
30 |
31 | override fun getRegisterG(): Int {
32 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
33 | }
34 |
35 | override fun getInlineIndex(): Int {
36 | return rawInstruction.readUshort(2)
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction35ms.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction35ms
6 | import org.jf.util.NibbleUtils
7 | import site.gaoyucan.ext.readUshort
8 |
9 | class DexPatchInstruction35ms(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
10 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction35ms {
11 |
12 | override fun getRegisterCount(): Int {
13 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
14 | }
15 |
16 | override fun getRegisterC(): Int {
17 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[4].toInt())
18 | }
19 |
20 | override fun getRegisterD(): Int {
21 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[4].toInt())
22 | }
23 |
24 | override fun getRegisterE(): Int {
25 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[5].toInt())
26 | }
27 |
28 | override fun getRegisterF(): Int {
29 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[5].toInt())
30 | }
31 |
32 | override fun getRegisterG(): Int {
33 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
34 | }
35 |
36 | override fun getVtableIndex(): Int {
37 | return rawInstruction.readUshort(2)
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction3rc.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction3rc
7 | import org.jf.dexlib2.iface.reference.Reference
8 | import site.gaoyucan.ext.readUshort
9 |
10 | class DexPatchInstruction3rc(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
11 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction3rc {
12 | override fun getRegisterCount(): Int {
13 | return rawInstruction[1].toUByte().toInt()
14 | }
15 |
16 | override fun getStartRegister(): Int {
17 | return rawInstruction.readUshort(4)
18 | }
19 |
20 | override fun getReference(): Reference {
21 | return DexBackedReference.makeReference(dexFile, referenceType, rawInstruction.readUshort(2))
22 | }
23 |
24 | override fun getReferenceType(): Int {
25 | return opcode.referenceType
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction3rmi.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction3rmi
6 | import site.gaoyucan.ext.readUshort
7 |
8 | class DexPatchInstruction3rmi(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction3rmi {
10 | override fun getRegisterCount(): Int {
11 | return rawInstruction[1].toUByte().toInt()
12 | }
13 |
14 | override fun getStartRegister(): Int {
15 | return rawInstruction.readUshort(4)
16 | }
17 |
18 | override fun getInlineIndex(): Int {
19 | return rawInstruction.readUshort(2)
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction3rms.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction3rms
6 | import site.gaoyucan.ext.readUshort
7 |
8 | class DexPatchInstruction3rms(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction3rms {
10 | override fun getRegisterCount(): Int {
11 | return rawInstruction[1].toUByte().toInt()
12 | }
13 |
14 | override fun getStartRegister(): Int {
15 | return rawInstruction.readUshort(4)
16 | }
17 |
18 | override fun getVtableIndex(): Int {
19 | return rawInstruction.readUshort(2)
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction45cc.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction45cc
7 | import org.jf.dexlib2.iface.reference.Reference
8 | import org.jf.util.NibbleUtils
9 | import site.gaoyucan.ext.readUshort
10 |
11 | class DexPatchInstruction45cc(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
12 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction45cc {
13 | override fun getRegisterCount(): Int {
14 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[1].toInt())
15 | }
16 |
17 | override fun getRegisterC(): Int {
18 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[4].toInt())
19 | }
20 |
21 | override fun getRegisterD(): Int {
22 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[4].toInt())
23 | }
24 |
25 | override fun getRegisterE(): Int {
26 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[5].toInt())
27 | }
28 |
29 | override fun getRegisterF(): Int {
30 | return NibbleUtils.extractHighUnsignedNibble(rawInstruction[5].toInt())
31 | }
32 |
33 | override fun getRegisterG(): Int {
34 | return NibbleUtils.extractLowUnsignedNibble(rawInstruction[1].toInt())
35 | }
36 |
37 | override fun getReference(): Reference {
38 | return DexBackedReference.makeReference(dexFile, referenceType, rawInstruction.readUshort(2))
39 | }
40 |
41 | override fun getReferenceType(): Int {
42 | return opcode.referenceType
43 | }
44 |
45 | override fun getReference2(): Reference {
46 | return DexBackedReference.makeReference(dexFile, referenceType2, rawInstruction.readUshort(6))
47 | }
48 |
49 | override fun getReferenceType2(): Int {
50 | return opcode.referenceType2
51 | }
52 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction4rcc.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.reference.DexBackedReference
6 | import org.jf.dexlib2.iface.instruction.formats.Instruction4rcc
7 | import org.jf.dexlib2.iface.reference.Reference
8 | import site.gaoyucan.ext.readUshort
9 |
10 | class DexPatchInstruction4rcc(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
11 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction4rcc {
12 | override fun getRegisterCount(): Int {
13 | return rawInstruction[1].toUByte().toInt()
14 | }
15 |
16 | override fun getStartRegister(): Int {
17 | return rawInstruction.readUshort(4)
18 | }
19 |
20 | override fun getReference(): Reference {
21 | return DexBackedReference.makeReference(dexFile, referenceType, rawInstruction.readUshort(2))
22 | }
23 |
24 | override fun getReferenceType(): Int {
25 | return opcode.referenceType
26 | }
27 |
28 | override fun getReference2(): Reference {
29 | return DexBackedReference.makeReference(dexFile, referenceType2, rawInstruction.readUshort(6))
30 | }
31 |
32 | override fun getReferenceType2(): Int {
33 | return opcode.referenceType
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchInstruction51l.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.iface.instruction.formats.Instruction51l
6 | import site.gaoyucan.ext.readLong
7 |
8 | class DexPatchInstruction51l(opcode: Opcode, rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
9 | DexPatchInstruction(opcode, rawInstruction, dexFile), Instruction51l {
10 | override fun getRegisterA(): Int {
11 | return rawInstruction[1].toUByte().toInt()
12 | }
13 |
14 | override fun getWideLiteral(): Long {
15 | return rawInstruction.readLong(2)
16 | }
17 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchPackedSwitchPayload.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.util.FixedSizeList
6 | import org.jf.dexlib2.iface.instruction.SwitchElement
7 | import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload
8 | import site.gaoyucan.ext.readInt
9 | import site.gaoyucan.ext.readUshort
10 |
11 | class DexPatchPackedSwitchPayload(rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
12 | DexPatchInstruction(Opcode.PACKED_SWITCH_PAYLOAD, rawInstruction, dexFile), PackedSwitchPayload {
13 |
14 | val elementCount: Int
15 |
16 | init {
17 | elementCount = rawInstruction.readUshort(ELEMENT_COUNT_OFFSET)
18 | }
19 |
20 | override fun getSwitchElements(): MutableList {
21 | val firstKey = rawInstruction.readInt(FIRST_KEY_OFFSET)
22 | return object : FixedSizeList() {
23 | override val size: Int
24 | get() = elementCount
25 |
26 | override fun readItem(offset: Int): SwitchElement {
27 | return object : SwitchElement {
28 | override fun getOffset(): Int {
29 | return rawInstruction.readInt(TARGETS_OFFSET + offset * 4)
30 | }
31 |
32 | override fun getKey(): Int {
33 | return firstKey + offset
34 | }
35 | }
36 | }
37 | }
38 | }
39 |
40 | override fun getCodeUnits(): Int {
41 | return 4 + elementCount * 2
42 | }
43 |
44 | companion object {
45 | private const val ELEMENT_COUNT_OFFSET = 2
46 | private const val FIRST_KEY_OFFSET = 4
47 | private const val TARGETS_OFFSET = 8
48 | }
49 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/dexpatch/instruction/DexPatchSparseSwitchPayload.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.dexpatch.instruction
2 |
3 | import org.jf.dexlib2.Opcode
4 | import org.jf.dexlib2.dexbacked.DexBackedDexFile
5 | import org.jf.dexlib2.dexbacked.util.FixedSizeList
6 | import org.jf.dexlib2.iface.instruction.SwitchElement
7 | import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload
8 | import site.gaoyucan.ext.readInt
9 | import site.gaoyucan.ext.readUshort
10 |
11 | class DexPatchSparseSwitchPayload(rawInstruction: ByteArray, dexFile: DexBackedDexFile) :
12 | DexPatchInstruction(Opcode.PACKED_SWITCH_PAYLOAD, rawInstruction, dexFile), SparseSwitchPayload {
13 | val elementCount: Int
14 |
15 | init {
16 | elementCount = rawInstruction.readUshort(ELEMENT_COUNT_OFFSET)
17 | }
18 |
19 | override fun getSwitchElements(): MutableList {
20 | return object : FixedSizeList() {
21 | override val size: Int
22 | get() = elementCount
23 |
24 | override fun readItem(offset: Int): SwitchElement {
25 | return object : SwitchElement {
26 | override fun getOffset(): Int {
27 | return rawInstruction.readInt(KEYS_OFFSET + elementCount * 4 + offset * 4)
28 | }
29 |
30 | override fun getKey(): Int {
31 | return rawInstruction.readInt(KEYS_OFFSET + offset * 4)
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
38 | override fun getCodeUnits(): Int {
39 | return 2 + elementCount * 4
40 | }
41 |
42 | companion object {
43 |
44 | private const val ELEMENT_COUNT_OFFSET = 2
45 | private const val KEYS_OFFSET = 4
46 | }
47 | }
--------------------------------------------------------------------------------
/src/main/kotlin/site/gaoyucan/ext/ByteArrayExt.kt:
--------------------------------------------------------------------------------
1 | package site.gaoyucan.ext
2 |
3 | import org.jf.util.ExceptionWithContext
4 |
5 |
6 | fun ByteArray.readUshort(offset: Int): Int {
7 | return (this[offset].toInt() and 0xff) or ((this[offset + 1].toInt() and 0xff) shl 8)
8 | }
9 |
10 | fun ByteArray.readSmallUint(offset: Int): Int {
11 | val result = readInt(offset)
12 | if (result < 0) {
13 | throw ExceptionWithContext("Encountered small uint that is out of range at offset 0x%x", offset)
14 | }
15 | return result
16 | }
17 |
18 | fun ByteArray.readShort(offset: Int): Short {
19 | return ((this[offset].toInt() and 0xff) or (this[offset + 1].toInt() shl 8)).toShort()
20 | }
21 |
22 | fun ByteArray.readInt(offset: Int): Int {
23 | return this[offset].toInt() and 0xff or
24 | ((this[offset + 1].toInt() and 0xff) shl 8) or
25 | ((this[offset + 2].toInt() and 0xff) shl 16) or
26 | (this[offset + 3].toInt() shl 24)
27 | }
28 |
29 | fun ByteArray.readLong(offset: Int): Long {
30 | return (this[offset].toLong() and 0xffL) or
31 | ((this[offset + 1].toLong() and 0xffL) shl 8) or
32 | ((this[offset + 2].toLong() and 0xffL) shl 16) or
33 | ((this[offset + 3].toLong() and 0xffL) shl 24) or
34 | ((this[offset + 4].toLong() and 0xffL) shl 32) or
35 | ((this[offset + 5].toLong() and 0xffL) shl 40) or
36 | ((this[offset + 6].toLong() and 0xffL) shl 48) or
37 | (this[offset + 7].toLong() shl 56)
38 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/0OooOO:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/src/main/resources/assets/0OooOO
--------------------------------------------------------------------------------
/src/main/resources/assets/O0ooOO:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/src/main/resources/assets/O0ooOO
--------------------------------------------------------------------------------
/src/main/resources/assets/OOoo0O:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/src/main/resources/assets/OOoo0O
--------------------------------------------------------------------------------
/src/main/resources/assets/OOooO0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/src/main/resources/assets/OOooO0
--------------------------------------------------------------------------------
/src/main/resources/assets/oo0Ooo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/src/main/resources/assets/oo0Ooo
--------------------------------------------------------------------------------
/src/main/resources/assets/ooO0oo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/src/main/resources/assets/ooO0oo
--------------------------------------------------------------------------------
/src/main/resources/classes.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GaoYuCan/DexPatcher/822c52681bab3c8d5d9097c40091481e9774d877/src/main/resources/classes.dex
--------------------------------------------------------------------------------