Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
c09b4dab
Commit
c09b4dab
authored
Feb 13, 2022
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Generate class mapping at runtime
parent
a4aa4a91
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
200 additions
and
126 deletions
+200
-126
Codegen.kt
buildSrc/src/main/java/Codegen.kt
+34
-83
ClassLoaders.java
stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java
+9
-3
DelegateComponentFactory.java
...n/java/com/topjohnwu/magisk/DelegateComponentFactory.java
+16
-7
DownloadActivity.java
.../src/main/java/com/topjohnwu/magisk/DownloadActivity.java
+8
-0
DynLoad.java
stub/src/main/java/com/topjohnwu/magisk/DynLoad.java
+121
-7
DummyService.java
...rc/main/java/com/topjohnwu/magisk/dummy/DummyService.java
+12
-0
Mapping.java
stub/template/Mapping.java
+0
-26
No files found.
buildSrc/src/main/java/Codegen.kt
View file @
c09b4dab
...
@@ -74,13 +74,6 @@ fun genKeyData(keysDir: File, outSrc: File) {
...
@@ -74,13 +74,6 @@ fun genKeyData(keysDir: File, outSrc: File) {
}
}
fun
genStubManifest
(
srcDir
:
File
,
outDir
:
File
):
String
{
fun
genStubManifest
(
srcDir
:
File
,
outDir
:
File
):
String
{
class
Component
(
val
real
:
String
,
val
stub
:
String
,
val
xml
:
String
,
val
genClass
:
Boolean
=
false
)
outDir
.
deleteRecursively
()
outDir
.
deleteRecursively
()
val
mainPkgDir
=
File
(
outDir
,
"com/topjohnwu/magisk"
)
val
mainPkgDir
=
File
(
outDir
,
"com/topjohnwu/magisk"
)
...
@@ -88,25 +81,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
...
@@ -88,25 +81,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
fun
String
.
ind
(
level
:
Int
)
=
replaceIndentByMargin
(
" "
.
repeat
(
level
))
fun
String
.
ind
(
level
:
Int
)
=
replaceIndentByMargin
(
" "
.
repeat
(
level
))
val
cmpList
=
mutableListOf
<
Component
>()
val
cmpList
=
mutableListOf
<
String
>()
cmpList
.
add
(
Component
(
cmpList
.
add
(
"androidx.core.app.CoreComponentFactory"
,
"DelegateComponentFactory"
,
""
,
true
))
cmpList
.
add
(
Component
(
"com.topjohnwu.magisk.core.App"
,
"DelegateApplication"
,
""
,
true
))
cmpList
.
add
(
Component
(
"com.topjohnwu.magisk.core.Provider"
,
"dummy.DummyProvider"
,
"""
"""
|<provider
|<provider
| android:name="%s"
| android:name="%s"
...
@@ -114,11 +91,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
...
@@ -114,11 +91,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
| android:directBootAware="true"
| android:directBootAware="true"
| android:exported="false"
| android:exported="false"
| android:grantUriPermissions="true" />"""
.
ind
(
2
)
| android:grantUriPermissions="true" />"""
.
ind
(
2
)
)
)
)
cmpList
.
add
(
Component
(
cmpList
.
add
(
"com.topjohnwu.magisk.core.Receiver"
,
"dummy.DummyReceiver"
,
"""
"""
|<receiver
|<receiver
| android:name="%s"
| android:name="%s"
...
@@ -135,11 +110,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
...
@@ -135,11 +110,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
| <data android:scheme="package" />
| <data android:scheme="package" />
| </intent-filter>
| </intent-filter>
|</receiver>"""
.
ind
(
2
)
|</receiver>"""
.
ind
(
2
)
)
)
)
cmpList
.
add
(
Component
(
cmpList
.
add
(
"com.topjohnwu.magisk.ui.MainActivity"
,
"DownloadActivity"
,
"""
"""
|<activity
|<activity
| android:name="%s"
| android:name="%s"
...
@@ -149,11 +122,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
...
@@ -149,11 +122,9 @@ fun genStubManifest(srcDir: File, outDir: File): String {
| <category android:name="android.intent.category.LAUNCHER" />
| <category android:name="android.intent.category.LAUNCHER" />
| </intent-filter>
| </intent-filter>
|</activity>"""
.
ind
(
2
)
|</activity>"""
.
ind
(
2
)
)
)
)
cmpList
.
add
(
Component
(
cmpList
.
add
(
"com.topjohnwu.magisk.ui.surequest.SuRequestActivity"
,
""
,
"""
"""
|<activity
|<activity
| android:name="%s"
| android:name="%s"
...
@@ -167,26 +138,22 @@ fun genStubManifest(srcDir: File, outDir: File): String {
...
@@ -167,26 +138,22 @@ fun genStubManifest(srcDir: File, outDir: File): String {
| <category android:name="android.intent.category.DEFAULT"/>
| <category android:name="android.intent.category.DEFAULT"/>
| </intent-filter>
| </intent-filter>
|</activity>"""
.
ind
(
2
)
|</activity>"""
.
ind
(
2
)
)
)
)
cmpList
.
add
(
Component
(
cmpList
.
add
(
"com.topjohnwu.magisk.core.download.DownloadService"
,
""
,
"""
"""
|<service
|<service
| android:name="%s"
| android:name="%s"
| android:exported="false" />"""
.
trimIndent
().
ind
(
2
)
| android:exported="false" />"""
.
ind
(
2
)
)
)
)
cmpList
.
add
(
Component
(
cmpList
.
add
(
"com.topjohnwu.magisk.core.JobService"
,
""
,
"""
"""
|<service
|<service
| android:name="%s"
| android:name="%s"
| android:exported="false"
| android:exported="false"
| android:permission="android.permission.BIND_JOB_SERVICE" />"""
.
ind
(
2
)
| android:permission="android.permission.BIND_JOB_SERVICE" />"""
.
ind
(
2
)
)
)
)
val
names
=
mutableListOf
<
String
>()
val
names
=
mutableListOf
<
String
>()
names
.
addAll
(
c1
)
names
.
addAll
(
c1
)
...
@@ -194,33 +161,38 @@ fun genStubManifest(srcDir: File, outDir: File): String {
...
@@ -194,33 +161,38 @@ fun genStubManifest(srcDir: File, outDir: File): String {
names
.
addAll
(
c3
.
subList
(
0
,
10
))
names
.
addAll
(
c3
.
subList
(
0
,
10
))
names
.
shuffle
(
RANDOM
)
names
.
shuffle
(
RANDOM
)
val
pkgNames
=
names
.
subList
(
0
,
50
)
val
pkgNames
=
names
// Distinct by lower case to support case insensitive file systems
// Distinct by lower case to support case insensitive file systems
.
distinctBy
{
it
.
toLowerCase
(
Locale
.
ROOT
)
}
.
distinctBy
{
it
.
toLowerCase
(
Locale
.
ROOT
)
}
// Old Android does not support capitalized package names
// Old Android does not support capitalized package names
// Check Android 7.0.0 PackageParser#buildClassName
// Check Android 7.0.0 PackageParser#buildClassName
.
map
{
it
.
decapitalize
(
Locale
.
ROOT
)
}
.
map
{
it
.
decapitalize
(
Locale
.
ROOT
)
}
var
idx
=
0
fun
isJavaKeyword
(
name
:
String
)
=
when
(
name
)
{
fun
isJavaKeyword
(
name
:
String
)
=
when
(
name
)
{
"do"
,
"if"
,
"for"
,
"int"
,
"new"
,
"try"
->
true
"do"
,
"if"
,
"for"
,
"int"
,
"new"
,
"try"
->
true
else
->
false
else
->
false
}
}
fun
genCmpName
()
:
String
{
val
cmps
=
mutableListOf
<
String
>()
var
pkgName
:
String
val
usedNames
=
mutableListOf
<
String
>()
fun
genCmpName
():
String
{
var
pkgName
:
String
do
{
do
{
pkgName
=
pkgNames
[
idx
++]
pkgName
=
pkgNames
.
random
(
kRANDOM
)
}
while
(
isJavaKeyword
(
pkgName
))
}
while
(
isJavaKeyword
(
pkgName
))
var
clzName
:
String
var
clzName
:
String
do
{
do
{
clzName
=
names
.
random
(
kRANDOM
)
clzName
=
names
.
random
(
kRANDOM
)
}
while
(
isJavaKeyword
(
clzName
))
}
while
(
isJavaKeyword
(
clzName
))
return
"${pkgName}.${clzName}"
val
cmp
=
"${pkgName}.${clzName}"
usedNames
.
add
(
cmp
)
return
cmp
}
}
fun
genClass
(
clzName
:
String
,
type
:
String
)
{
fun
genClass
(
type
:
String
)
{
val
clzName
=
genCmpName
()
val
(
pkg
,
name
)
=
clzName
.
split
(
'.'
)
val
(
pkg
,
name
)
=
clzName
.
split
(
'.'
)
val
pkgDir
=
File
(
outDir
,
pkg
)
val
pkgDir
=
File
(
outDir
,
pkg
)
pkgDir
.
mkdir
()
pkgDir
.
mkdir
()
...
@@ -230,41 +202,20 @@ fun genStubManifest(srcDir: File, outDir: File): String {
...
@@ -230,41 +202,20 @@ fun genStubManifest(srcDir: File, outDir: File): String {
}
}
}
}
val
cmps
=
mutableListOf
<
String
>()
// Generate 2 non redirect-able classes
val
usedNames
=
mutableListOf
<
String
>(
)
genClass
(
"DelegateComponentFactory"
)
val
maps
=
StringBuilder
(
)
genClass
(
"DelegateApplication"
)
for
(
gen
in
cmpList
)
{
for
(
gen
in
cmpList
)
{
val
name
=
genCmpName
()
val
name
=
genCmpName
()
usedNames
.
add
(
name
)
cmps
.
add
(
gen
.
format
(
name
))
maps
.
append
(
"|map.put(\"$name\", \"${gen.real}\");"
.
ind
(
2
))
maps
.
append
(
'\n'
)
if
(
gen
.
stub
.
isNotEmpty
())
{
if
(
gen
.
stub
!=
"DelegateComponentFactory"
)
{
maps
.
append
(
"|internalMap.put(\"$name\", com.topjohnwu.magisk.${gen.stub}.class);"
.
ind
(
2
))
maps
.
append
(
'\n'
)
}
if
(
gen
.
genClass
)
{
genClass
(
name
,
gen
.
stub
)
}
}
if
(
gen
.
xml
.
isNotEmpty
())
{
cmps
.
add
(
gen
.
xml
.
format
(
name
))
}
}
}
// Shuffle the order of the components
// Shuffle the order of the components
cmps
.
shuffle
(
RANDOM
)
cmps
.
shuffle
(
RANDOM
)
val
xml
=
File
(
srcDir
,
"AndroidManifest.xml"
).
readText
()
val
genXml
=
xml
.
format
(
usedNames
[
0
],
usedNames
[
1
],
cmps
.
joinToString
(
"\n\n"
))
// Write mapping information to code
val
xml
=
File
(
srcDir
,
"AndroidManifest.xml"
).
readText
()
val
mapping
=
File
(
srcDir
,
"Mapping.java"
).
readText
().
format
(
maps
)
return
xml
.
format
(
usedNames
[
0
],
usedNames
[
1
],
cmps
.
joinToString
(
"\n\n"
))
PrintStream
(
File
(
mainPkgDir
,
"Mapping.java"
)).
use
{
it
.
print
(
mapping
)
}
return
genXml
}
}
fun
genEncryptedResources
(
res
:
InputStream
,
outDir
:
File
)
{
fun
genEncryptedResources
(
res
:
InputStream
,
outDir
:
File
)
{
...
...
stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java
View file @
c09b4dab
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk;
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk;
import
com.topjohnwu.magisk.utils.DynamicClassLoader
;
import
com.topjohnwu.magisk.utils.DynamicClassLoader
;
import
java.io.File
;
import
java.io.File
;
import
java.util.Map
;
// Wrap the actual classloader as we only want to resolve classname
// Wrap the actual classloader as we only want to resolve classname
// mapping when loading from platform (via LoadedApk.mClassLoader)
// mapping when loading from platform (via LoadedApk.mClassLoader)
...
@@ -14,19 +15,24 @@ class InjectedClassLoader extends ClassLoader {
...
@@ -14,19 +15,24 @@ class InjectedClassLoader extends ClassLoader {
@Override
@Override
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
return
super
.
loadClass
(
Mapping
.
get
(
name
),
resolve
);
String
clz
=
DynLoad
.
componentMap
.
get
(
name
);
name
=
clz
!=
null
?
clz
:
name
;
return
super
.
loadClass
(
name
,
resolve
);
}
}
}
}
class
RedirectClassLoader
extends
ClassLoader
{
class
RedirectClassLoader
extends
ClassLoader
{
RedirectClassLoader
()
{
private
final
Map
<
String
,
Class
<?>>
mapping
;
RedirectClassLoader
(
Map
<
String
,
Class
<?>>
m
)
{
super
(
RedirectClassLoader
.
class
.
getClassLoader
());
super
(
RedirectClassLoader
.
class
.
getClassLoader
());
mapping
=
m
;
}
}
@Override
@Override
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
Class
<?>
clz
=
Mapping
.
internalMap
.
get
(
name
);
Class
<?>
clz
=
mapping
.
get
(
name
);
return
clz
==
null
?
super
.
loadClass
(
name
,
resolve
)
:
clz
;
return
clz
==
null
?
super
.
loadClass
(
name
,
resolve
)
:
clz
;
}
}
}
}
...
...
stub/src/main/java/com/topjohnwu/magisk/DelegateComponentFactory.java
View file @
c09b4dab
...
@@ -11,6 +11,10 @@ import android.content.Intent;
...
@@ -11,6 +11,10 @@ import android.content.Intent;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.ApplicationInfo
;
import
android.os.Process
;
import
android.os.Process
;
import
com.topjohnwu.magisk.dummy.DummyProvider
;
import
com.topjohnwu.magisk.dummy.DummyReceiver
;
import
com.topjohnwu.magisk.dummy.DummyService
;
@SuppressLint
(
"NewApi"
)
@SuppressLint
(
"NewApi"
)
public
class
DelegateComponentFactory
extends
AppComponentFactory
{
public
class
DelegateComponentFactory
extends
AppComponentFactory
{
...
@@ -40,7 +44,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -40,7 +44,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateActivity
(
DynLoad
.
loader
,
className
,
intent
);
return
receiver
.
instantiateActivity
(
DynLoad
.
loader
,
className
,
intent
);
return
create
(
className
);
return
create
(
className
,
DownloadActivity
.
class
);
}
}
@Override
@Override
...
@@ -48,7 +52,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -48,7 +52,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateReceiver
(
DynLoad
.
loader
,
className
,
intent
);
return
receiver
.
instantiateReceiver
(
DynLoad
.
loader
,
className
,
intent
);
return
create
(
className
);
return
create
(
className
,
DummyReceiver
.
class
);
}
}
@Override
@Override
...
@@ -56,7 +60,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -56,7 +60,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateService
(
DynLoad
.
loader
,
className
,
intent
);
return
receiver
.
instantiateService
(
DynLoad
.
loader
,
className
,
intent
);
return
create
(
className
);
return
create
(
className
,
DummyService
.
class
);
}
}
@Override
@Override
...
@@ -64,12 +68,17 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -64,12 +68,17 @@ public class DelegateComponentFactory extends AppComponentFactory {
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateProvider
(
DynLoad
.
loader
,
className
);
return
receiver
.
instantiateProvider
(
DynLoad
.
loader
,
className
);
return
create
(
className
);
return
create
(
className
,
DummyProvider
.
class
);
}
}
private
<
T
>
T
create
(
String
name
)
private
<
T
>
T
create
(
String
name
,
Class
<
T
>
fallback
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
IllegalAccessException
,
InstantiationException
{
return
(
T
)
DynLoad
.
loader
.
loadClass
(
name
).
newInstance
();
try
{
// noinspection unchecked
return
(
T
)
DynLoad
.
loader
.
loadClass
(
name
).
newInstance
();
}
catch
(
ClassNotFoundException
e
)
{
return
fallback
.
newInstance
();
}
}
}
}
}
stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java
View file @
c09b4dab
...
@@ -49,6 +49,14 @@ public class DownloadActivity extends Activity {
...
@@ -49,6 +49,14 @@ public class DownloadActivity extends Activity {
@Override
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
super
.
onCreate
(
savedInstanceState
);
if
(
DynLoad
.
isDynLoader
())
{
// For some reason activity is created before Application.attach(),
// relaunch the activity using the same intent
finishAffinity
();
startActivity
(
getIntent
());
return
;
}
themed
=
new
ContextThemeWrapper
(
this
,
android
.
R
.
style
.
Theme_DeviceDefault
);
themed
=
new
ContextThemeWrapper
(
this
,
android
.
R
.
style
.
Theme_DeviceDefault
);
// Only download and dynamic load full APK if hidden
// Only download and dynamic load full APK if hidden
...
...
stub/src/main/java/com/topjohnwu/magisk/DynLoad.java
View file @
c09b4dab
...
@@ -4,14 +4,21 @@ import static com.topjohnwu.magisk.BuildConfig.APPLICATION_ID;
...
@@ -4,14 +4,21 @@ import static com.topjohnwu.magisk.BuildConfig.APPLICATION_ID;
import
android.app.AppComponentFactory
;
import
android.app.AppComponentFactory
;
import
android.app.Application
;
import
android.app.Application
;
import
android.app.job.JobService
;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.ContextWrapper
;
import
android.content.ContextWrapper
;
import
android.content.pm.ActivityInfo
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.PackageInfo
;
import
android.content.pm.PackageManager
;
import
android.content.pm.PackageManager
;
import
android.content.pm.ServiceInfo
;
import
android.os.Build
;
import
android.os.Build
;
import
android.os.Environment
;
import
android.os.Environment
;
import
android.util.Log
;
import
android.util.Log
;
import
com.topjohnwu.magisk.dummy.DummyProvider
;
import
com.topjohnwu.magisk.dummy.DummyReceiver
;
import
com.topjohnwu.magisk.dummy.DummyService
;
import
com.topjohnwu.magisk.utils.APKInstall
;
import
com.topjohnwu.magisk.utils.APKInstall
;
import
java.io.File
;
import
java.io.File
;
...
@@ -20,6 +27,8 @@ import java.io.FileOutputStream;
...
@@ -20,6 +27,8 @@ import java.io.FileOutputStream;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
import
java.util.HashMap
;
import
java.util.Map
;
import
io.michaelrocks.paranoid.Obfuscate
;
import
io.michaelrocks.paranoid.Obfuscate
;
...
@@ -28,15 +37,20 @@ import io.michaelrocks.paranoid.Obfuscate;
...
@@ -28,15 +37,20 @@ import io.michaelrocks.paranoid.Obfuscate;
public
class
DynLoad
{
public
class
DynLoad
{
// The current active classloader
// The current active classloader
static
ClassLoader
loader
=
new
Redirec
tClassLoader
();
static
ClassLoader
loader
=
DynLoad
.
class
.
ge
tClassLoader
();
static
Object
componentFactory
;
static
Object
componentFactory
;
static
Map
<
String
,
String
>
componentMap
=
new
HashMap
<>();
private
static
boolean
loadedApk
=
false
;
private
static
boolean
loadedApk
=
false
;
static
StubApk
.
Data
createApkData
()
{
static
StubApk
.
Data
createApkData
()
{
var
data
=
new
StubApk
.
Data
();
var
data
=
new
StubApk
.
Data
();
data
.
setVersion
(
BuildConfig
.
STUB_VERSION
);
data
.
setVersion
(
BuildConfig
.
STUB_VERSION
);
data
.
setClassToComponent
(
Mapping
.
inverseMap
);
Map
<
String
,
String
>
map
=
new
HashMap
<>();
for
(
var
e
:
componentMap
.
entrySet
())
{
map
.
put
(
e
.
getValue
(),
e
.
getKey
());
}
data
.
setClassToComponent
(
map
);
data
.
setRootService
(
DelegateRootService
.
class
);
data
.
setRootService
(
DelegateRootService
.
class
);
return
data
;
return
data
;
}
}
...
@@ -135,23 +149,40 @@ public class DynLoad {
...
@@ -135,23 +149,40 @@ public class DynLoad {
if
(
Build
.
VERSION
.
SDK_INT
<
29
)
if
(
Build
.
VERSION
.
SDK_INT
<
29
)
replaceClassLoader
(
context
);
replaceClassLoader
(
context
);
if
(!
loadApk
(
context
))
int
flags
=
PackageManager
.
GET_ACTIVITIES
|
PackageManager
.
GET_SERVICES
|
PackageManager
.
GET_PROVIDERS
|
PackageManager
.
GET_RECEIVERS
;
final
PackageInfo
info
;
try
{
info
=
context
.
getPackageManager
()
.
getPackageInfo
(
context
.
getPackageName
(),
flags
);
}
catch
(
PackageManager
.
NameNotFoundException
e
)
{
// Impossible
throw
new
RuntimeException
(
e
);
}
if
(!
loadApk
(
context
))
{
loader
=
new
RedirectClassLoader
(
createInternalMap
(
info
));
return
null
;
return
null
;
}
File
apk
=
StubApk
.
current
(
context
);
File
apk
=
StubApk
.
current
(
context
);
PackageManager
pm
=
context
.
getPackageManager
();
PackageManager
pm
=
context
.
getPackageManager
();
try
{
try
{
var
info
=
pm
.
getPackageArchiveInfo
(
apk
.
getPath
(),
0
).
applicationInfo
;
var
pkgInfo
=
pm
.
getPackageArchiveInfo
(
apk
.
getPath
(),
flags
);
var
appInfo
=
pkgInfo
.
applicationInfo
;
updateComponentMap
(
info
,
pkgInfo
);
// Create the receiver Application
// Create the receiver Application
var
data
=
createApkData
();
var
data
=
createApkData
();
var
app
=
(
Application
)
loader
.
loadClass
(
i
nfo
.
className
)
var
app
=
(
Application
)
loader
.
loadClass
(
appI
nfo
.
className
)
.
getConstructor
(
Object
.
class
)
.
getConstructor
(
Object
.
class
)
.
newInstance
(
data
.
getObject
());
.
newInstance
(
data
.
getObject
());
// Create the receiver component factory
// Create the receiver component factory
if
(
Build
.
VERSION
.
SDK_INT
>=
28
&&
componentFactory
!=
null
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
28
&&
componentFactory
!=
null
)
{
Object
factory
=
loader
.
loadClass
(
i
nfo
.
appComponentFactory
).
newInstance
();
Object
factory
=
loader
.
loadClass
(
appI
nfo
.
appComponentFactory
).
newInstance
();
var
delegate
=
(
DelegateComponentFactory
)
componentFactory
;
var
delegate
=
(
DelegateComponentFactory
)
componentFactory
;
delegate
.
receiver
=
(
AppComponentFactory
)
factory
;
delegate
.
receiver
=
(
AppComponentFactory
)
factory
;
}
}
...
@@ -168,7 +199,90 @@ public class DynLoad {
...
@@ -168,7 +199,90 @@ public class DynLoad {
return
null
;
return
null
;
}
}
private
static
boolean
isDynLoader
()
{
private
static
Map
<
String
,
Class
<?>>
createInternalMap
(
PackageInfo
info
)
{
Map
<
String
,
Class
<?>>
map
=
new
HashMap
<>();
for
(
var
c
:
info
.
activities
)
{
map
.
put
(
c
.
name
,
DownloadActivity
.
class
);
}
for
(
var
c
:
info
.
services
)
{
map
.
put
(
c
.
name
,
DummyService
.
class
);
}
for
(
var
c
:
info
.
providers
)
{
map
.
put
(
c
.
name
,
DummyProvider
.
class
);
}
for
(
var
c
:
info
.
receivers
)
{
map
.
put
(
c
.
name
,
DummyReceiver
.
class
);
}
return
map
;
}
private
static
void
updateComponentMap
(
PackageInfo
from
,
PackageInfo
to
)
{
{
var
src
=
from
.
activities
;
var
dest
=
to
.
activities
;
final
ActivityInfo
sa
;
final
ActivityInfo
da
;
final
ActivityInfo
sb
;
final
ActivityInfo
db
;
if
(
src
[
0
].
exported
)
{
sa
=
src
[
0
];
sb
=
src
[
1
];
}
else
{
sa
=
src
[
1
];
sb
=
src
[
0
];
}
if
(
dest
[
0
].
exported
)
{
da
=
dest
[
0
];
db
=
dest
[
1
];
}
else
{
da
=
dest
[
1
];
db
=
dest
[
0
];
}
componentMap
.
put
(
sa
.
name
,
da
.
name
);
componentMap
.
put
(
sb
.
name
,
db
.
name
);
}
{
var
src
=
from
.
services
;
var
dest
=
to
.
services
;
final
ServiceInfo
sa
;
final
ServiceInfo
da
;
final
ServiceInfo
sb
;
final
ServiceInfo
db
;
if
(
JobService
.
PERMISSION_BIND
.
equals
(
src
[
0
].
permission
))
{
sa
=
src
[
0
];
sb
=
src
[
1
];
}
else
{
sa
=
src
[
1
];
sb
=
src
[
0
];
}
if
(
JobService
.
PERMISSION_BIND
.
equals
(
dest
[
0
].
permission
))
{
da
=
dest
[
0
];
db
=
dest
[
1
];
}
else
{
da
=
dest
[
1
];
db
=
dest
[
0
];
}
componentMap
.
put
(
sa
.
name
,
da
.
name
);
componentMap
.
put
(
sb
.
name
,
db
.
name
);
}
{
var
src
=
from
.
receivers
;
var
dest
=
to
.
receivers
;
componentMap
.
put
(
src
[
0
].
name
,
dest
[
0
].
name
);
}
{
var
src
=
from
.
providers
;
var
dest
=
to
.
providers
;
componentMap
.
put
(
src
[
0
].
name
,
dest
[
0
].
name
);
}
}
static
boolean
isDynLoader
()
{
return
loader
instanceof
InjectedClassLoader
;
return
loader
instanceof
InjectedClassLoader
;
}
}
...
...
stub/src/main/java/com/topjohnwu/magisk/dummy/DummyService.java
0 → 100644
View file @
c09b4dab
package
com
.
topjohnwu
.
magisk
.
dummy
;
import
android.app.Service
;
import
android.content.Intent
;
import
android.os.IBinder
;
public
class
DummyService
extends
Service
{
@Override
public
IBinder
onBind
(
Intent
intent
)
{
return
null
;
}
}
stub/template/Mapping.java
deleted
100644 → 0
View file @
a4aa4a91
package
com
.
topjohnwu
.
magisk
;
import
java.util.HashMap
;
import
java.util.Map
;
import
io.michaelrocks.paranoid.Obfuscate
;
@Obfuscate
public
class
Mapping
{
private
static
final
Map
<
String
,
String
>
map
=
new
HashMap
<>();
public
static
final
Map
<
String
,
Class
<?>>
internalMap
=
new
HashMap
<>();
public
static
final
Map
<
String
,
String
>
inverseMap
=
new
HashMap
<>();
static
{
%
s
for
(
Map
.
Entry
<
String
,
String
>
e
:
map
.
entrySet
())
{
inverseMap
.
put
(
e
.
getValue
(),
e
.
getKey
());
}
}
public
static
String
get
(
String
name
)
{
String
n
=
map
.
get
(
name
);
return
n
!=
null
?
n
:
name
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment