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
b7fc15d3
Commit
b7fc15d3
authored
Feb 13, 2022
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code refactoring
parent
c09b4dab
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
142 additions
and
176 deletions
+142
-176
ClassLoaders.java
stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java
+103
-9
DelegateComponentFactory.java
...n/java/com/topjohnwu/magisk/DelegateComponentFactory.java
+5
-11
DelegateRootService.java
...c/main/java/com/topjohnwu/magisk/DelegateRootService.java
+3
-2
DownloadActivity.java
.../src/main/java/com/topjohnwu/magisk/DownloadActivity.java
+1
-1
DynLoad.java
stub/src/main/java/com/topjohnwu/magisk/DynLoad.java
+30
-153
No files found.
stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java
View file @
b7fc15d3
package
com
.
topjohnwu
.
magisk
;
package
com
.
topjohnwu
.
magisk
;
import
android.app.job.JobService
;
import
android.content.pm.ActivityInfo
;
import
android.content.pm.PackageInfo
;
import
android.content.pm.ServiceInfo
;
import
com.topjohnwu.magisk.dummy.DummyProvider
;
import
com.topjohnwu.magisk.dummy.DummyReceiver
;
import
com.topjohnwu.magisk.dummy.DummyService
;
import
com.topjohnwu.magisk.utils.DynamicClassLoader
;
import
com.topjohnwu.magisk.utils.DynamicClassLoader
;
import
java.io.File
;
import
java.io.File
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
io.michaelrocks.paranoid.Obfuscate
;
// 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)
class
InjectedClassLoader
extends
ClassLoader
{
@Obfuscate
class
AppClassLoader
extends
ClassLoader
{
final
Map
<
String
,
String
>
mapping
=
new
HashMap
<>();
Injected
ClassLoader
(
File
apk
)
{
App
ClassLoader
(
File
apk
)
{
super
(
new
DynamicClassLoader
(
apk
));
super
(
new
DynamicClassLoader
(
apk
));
}
}
@Override
@Override
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
String
clz
=
DynLoad
.
componentMap
.
get
(
name
);
String
clz
=
mapping
.
get
(
name
);
name
=
clz
!=
null
?
clz
:
name
;
name
=
clz
!=
null
?
clz
:
name
;
return
super
.
loadClass
(
name
,
resolve
);
return
super
.
loadClass
(
name
,
resolve
);
}
}
void
updateComponentMap
(
PackageInfo
stub
,
PackageInfo
app
)
{
{
var
src
=
stub
.
activities
;
var
dest
=
app
.
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
];
}
mapping
.
put
(
sa
.
name
,
da
.
name
);
mapping
.
put
(
sb
.
name
,
db
.
name
);
}
{
var
src
=
stub
.
services
;
var
dest
=
app
.
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
];
}
mapping
.
put
(
sa
.
name
,
da
.
name
);
mapping
.
put
(
sb
.
name
,
db
.
name
);
}
{
var
src
=
stub
.
receivers
;
var
dest
=
app
.
receivers
;
mapping
.
put
(
src
[
0
].
name
,
dest
[
0
].
name
);
}
{
var
src
=
stub
.
providers
;
var
dest
=
app
.
providers
;
mapping
.
put
(
src
[
0
].
name
,
dest
[
0
].
name
);
}
}
}
}
class
Redirect
ClassLoader
extends
ClassLoader
{
class
Stub
ClassLoader
extends
ClassLoader
{
private
final
Map
<
String
,
Class
<?>>
mapping
;
private
final
Map
<
String
,
Class
<?>>
mapping
=
new
HashMap
<>()
;
RedirectClassLoader
(
Map
<
String
,
Class
<?>>
m
)
{
StubClassLoader
(
PackageInfo
info
)
{
super
(
RedirectClassLoader
.
class
.
getClassLoader
());
super
(
StubClassLoader
.
class
.
getClassLoader
());
mapping
=
m
;
for
(
var
c
:
info
.
activities
)
{
mapping
.
put
(
c
.
name
,
DownloadActivity
.
class
);
}
for
(
var
c
:
info
.
services
)
{
mapping
.
put
(
c
.
name
,
DummyService
.
class
);
}
for
(
var
c
:
info
.
providers
)
{
mapping
.
put
(
c
.
name
,
DummyProvider
.
class
);
}
for
(
var
c
:
info
.
receivers
)
{
mapping
.
put
(
c
.
name
,
DummyReceiver
.
class
);
}
}
}
@Override
@Override
...
@@ -39,12 +130,15 @@ class RedirectClassLoader extends ClassLoader {
...
@@ -39,12 +130,15 @@ class RedirectClassLoader extends ClassLoader {
class
DelegateClassLoader
extends
ClassLoader
{
class
DelegateClassLoader
extends
ClassLoader
{
// The active classloader
static
ClassLoader
cl
=
DelegateClassLoader
.
class
.
getClassLoader
();
DelegateClassLoader
()
{
DelegateClassLoader
()
{
super
(
null
);
super
(
null
);
}
}
@Override
@Override
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
return
DynLoad
.
loader
.
loadClass
(
name
);
return
cl
.
loadClass
(
name
);
}
}
}
}
stub/src/main/java/com/topjohnwu/magisk/DelegateComponentFactory.java
View file @
b7fc15d3
...
@@ -9,7 +9,6 @@ import android.content.BroadcastReceiver;
...
@@ -9,7 +9,6 @@ import android.content.BroadcastReceiver;
import
android.content.ContentProvider
;
import
android.content.ContentProvider
;
import
android.content.Intent
;
import
android.content.Intent
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.ApplicationInfo
;
import
android.os.Process
;
import
com.topjohnwu.magisk.dummy.DummyProvider
;
import
com.topjohnwu.magisk.dummy.DummyProvider
;
import
com.topjohnwu.magisk.dummy.DummyReceiver
;
import
com.topjohnwu.magisk.dummy.DummyReceiver
;
...
@@ -26,11 +25,6 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -26,11 +25,6 @@ public class DelegateComponentFactory extends AppComponentFactory {
@Override
@Override
public
ClassLoader
instantiateClassLoader
(
ClassLoader
cl
,
ApplicationInfo
info
)
{
public
ClassLoader
instantiateClassLoader
(
ClassLoader
cl
,
ApplicationInfo
info
)
{
if
(
Process
.
myUid
()
==
0
)
{
// Do not do anything in root process
return
cl
;
}
DynLoad
.
loadApk
(
info
);
return
new
DelegateClassLoader
();
return
new
DelegateClassLoader
();
}
}
...
@@ -43,7 +37,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -43,7 +37,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
Activity
instantiateActivity
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
public
Activity
instantiateActivity
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateActivity
(
D
ynLoad
.
loader
,
className
,
intent
);
return
receiver
.
instantiateActivity
(
D
elegateClassLoader
.
cl
,
className
,
intent
);
return
create
(
className
,
DownloadActivity
.
class
);
return
create
(
className
,
DownloadActivity
.
class
);
}
}
...
@@ -51,7 +45,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -51,7 +45,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
BroadcastReceiver
instantiateReceiver
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
public
BroadcastReceiver
instantiateReceiver
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateReceiver
(
D
ynLoad
.
loader
,
className
,
intent
);
return
receiver
.
instantiateReceiver
(
D
elegateClassLoader
.
cl
,
className
,
intent
);
return
create
(
className
,
DummyReceiver
.
class
);
return
create
(
className
,
DummyReceiver
.
class
);
}
}
...
@@ -59,7 +53,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -59,7 +53,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
Service
instantiateService
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
public
Service
instantiateService
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateService
(
D
ynLoad
.
loader
,
className
,
intent
);
return
receiver
.
instantiateService
(
D
elegateClassLoader
.
cl
,
className
,
intent
);
return
create
(
className
,
DummyService
.
class
);
return
create
(
className
,
DummyService
.
class
);
}
}
...
@@ -67,7 +61,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -67,7 +61,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
ContentProvider
instantiateProvider
(
ClassLoader
cl
,
String
className
)
public
ContentProvider
instantiateProvider
(
ClassLoader
cl
,
String
className
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateProvider
(
D
ynLoad
.
loader
,
className
);
return
receiver
.
instantiateProvider
(
D
elegateClassLoader
.
cl
,
className
);
return
create
(
className
,
DummyProvider
.
class
);
return
create
(
className
,
DummyProvider
.
class
);
}
}
...
@@ -75,7 +69,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -75,7 +69,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
throws
IllegalAccessException
,
InstantiationException
{
throws
IllegalAccessException
,
InstantiationException
{
try
{
try
{
// noinspection unchecked
// noinspection unchecked
return
(
T
)
D
ynLoad
.
loader
.
loadClass
(
name
).
newInstance
();
return
(
T
)
D
elegateClassLoader
.
cl
.
loadClass
(
name
).
newInstance
();
}
catch
(
ClassNotFoundException
e
)
{
}
catch
(
ClassNotFoundException
e
)
{
return
fallback
.
newInstance
();
return
fallback
.
newInstance
();
}
}
...
...
stub/src/main/java/com/topjohnwu/magisk/DelegateRootService.java
View file @
b7fc15d3
...
@@ -20,7 +20,8 @@ public class DelegateRootService extends ContextWrapper {
...
@@ -20,7 +20,8 @@ public class DelegateRootService extends ContextWrapper {
@Override
@Override
protected
void
attachBaseContext
(
Context
base
)
{
protected
void
attachBaseContext
(
Context
base
)
{
if
(!
DynLoad
.
loadApk
(
base
))
ClassLoader
loader
=
DynLoad
.
loadApk
(
base
);
if
(
loader
==
null
)
return
;
return
;
try
{
try
{
...
@@ -29,7 +30,7 @@ public class DelegateRootService extends ContextWrapper {
...
@@ -29,7 +30,7 @@ public class DelegateRootService extends ContextWrapper {
File
apk
=
StubApk
.
current
(
base
);
File
apk
=
StubApk
.
current
(
base
);
PackageManager
pm
=
base
.
getPackageManager
();
PackageManager
pm
=
base
.
getPackageManager
();
PackageInfo
pkgInfo
=
pm
.
getPackageArchiveInfo
(
apk
.
getPath
(),
0
);
PackageInfo
pkgInfo
=
pm
.
getPackageArchiveInfo
(
apk
.
getPath
(),
0
);
DynLoad
.
loader
.
loadClass
(
pkgInfo
.
applicationInfo
.
className
)
loader
.
loadClass
(
pkgInfo
.
applicationInfo
.
className
)
.
getConstructor
(
Object
.
class
)
.
getConstructor
(
Object
.
class
)
.
newInstance
(
data
.
getObject
());
.
newInstance
(
data
.
getObject
());
...
...
stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java
View file @
b7fc15d3
...
@@ -49,7 +49,7 @@ public class DownloadActivity extends Activity {
...
@@ -49,7 +49,7 @@ public class DownloadActivity extends Activity {
@Override
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
super
.
onCreate
(
savedInstanceState
);
if
(
D
ynLoad
.
isDynLoader
()
)
{
if
(
D
elegateClassLoader
.
cl
instanceof
AppClassLoader
)
{
// For some reason activity is created before Application.attach(),
// For some reason activity is created before Application.attach(),
// relaunch the activity using the same intent
// relaunch the activity using the same intent
finishAffinity
();
finishAffinity
();
...
...
stub/src/main/java/com/topjohnwu/magisk/DynLoad.java
View file @
b7fc15d3
...
@@ -4,21 +4,13 @@ import static com.topjohnwu.magisk.BuildConfig.APPLICATION_ID;
...
@@ -4,21 +4,13 @@ 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.PackageInfo
;
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.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
;
...
@@ -28,7 +20,6 @@ import java.io.IOException;
...
@@ -28,7 +20,6 @@ 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.HashMap
;
import
java.util.Map
;
import
io.michaelrocks.paranoid.Obfuscate
;
import
io.michaelrocks.paranoid.Obfuscate
;
...
@@ -36,21 +27,12 @@ import io.michaelrocks.paranoid.Obfuscate;
...
@@ -36,21 +27,12 @@ import io.michaelrocks.paranoid.Obfuscate;
@SuppressWarnings
(
"ResultOfMethodCallIgnored"
)
@SuppressWarnings
(
"ResultOfMethodCallIgnored"
)
public
class
DynLoad
{
public
class
DynLoad
{
// The current active classloader
static
ClassLoader
loader
=
DynLoad
.
class
.
getClassLoader
();
static
Object
componentFactory
;
static
Object
componentFactory
;
static
Map
<
String
,
String
>
componentMap
=
new
HashMap
<>();
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
);
Map
<
String
,
String
>
map
=
new
HashMap
<>();
data
.
setClassToComponent
(
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
;
}
}
...
@@ -65,14 +47,10 @@ public class DynLoad {
...
@@ -65,14 +47,10 @@ public class DynLoad {
}
catch
(
Exception
ignored
)
{
/* Impossible */
}
}
catch
(
Exception
ignored
)
{
/* Impossible */
}
}
}
// Dynamically load APK from internal or external storage
// Dynamically load APK from internal, external storage, or previous app
static
void
loadApk
(
ApplicationInfo
info
)
{
static
AppClassLoader
loadApk
(
Context
context
)
{
if
(
loadedApk
)
File
apk
=
StubApk
.
current
(
context
);
return
;
File
update
=
StubApk
.
update
(
context
);
loadedApk
=
true
;
File
apk
=
StubApk
.
current
(
info
);
File
update
=
StubApk
.
update
(
info
);
if
(
update
.
exists
())
{
if
(
update
.
exists
())
{
// Rename from update
// Rename from update
...
@@ -80,20 +58,8 @@ public class DynLoad {
...
@@ -80,20 +58,8 @@ public class DynLoad {
}
}
// Copy from external for easier development
// Copy from external for easier development
if
(
BuildConfig
.
DEBUG
)
copy_from_ext:
{
if
(
BuildConfig
.
DEBUG
)
{
final
File
dir
;
File
external
=
new
File
(
context
.
getExternalFilesDir
(
null
),
"magisk.apk"
);
try
{
var
dirs
=
(
File
[])
Environment
.
class
.
getMethod
(
"buildExternalStorageAppFilesDirs"
,
String
.
class
)
.
invoke
(
null
,
info
.
packageName
);
if
(
dirs
==
null
)
break
copy_from_ext
;
dir
=
dirs
[
0
];
}
catch
(
ReflectiveOperationException
e
)
{
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
break
copy_from_ext
;
}
File
external
=
new
File
(
dir
,
"magisk.apk"
);
if
(
external
.
exists
())
{
if
(
external
.
exists
())
{
try
{
try
{
var
in
=
new
FileInputStream
(
external
);
var
in
=
new
FileInputStream
(
external
);
...
@@ -111,20 +77,11 @@ public class DynLoad {
...
@@ -111,20 +77,11 @@ public class DynLoad {
}
}
if
(
apk
.
exists
())
{
if
(
apk
.
exists
())
{
loader
=
new
Injected
ClassLoader
(
apk
);
return
new
App
ClassLoader
(
apk
);
}
}
}
// Dynamically load APK from internal, external storage, or previous app
static
boolean
loadApk
(
Context
context
)
{
// Trigger folder creation
context
.
getExternalFilesDir
(
null
);
loadApk
(
context
.
getApplicationInfo
());
// If no APK is loaded, attempt to copy from previous app
// If no APK is loaded, attempt to copy from previous app
if
(!
isDynLoader
()
&&
!
context
.
getPackageName
().
equals
(
APPLICATION_ID
))
{
if
(!
context
.
getPackageName
().
equals
(
APPLICATION_ID
))
{
File
apk
=
StubApk
.
current
(
context
);
try
{
try
{
var
info
=
context
.
getPackageManager
().
getApplicationInfo
(
APPLICATION_ID
,
0
);
var
info
=
context
.
getPackageManager
().
getApplicationInfo
(
APPLICATION_ID
,
0
);
var
src
=
new
FileInputStream
(
info
.
sourceDir
);
var
src
=
new
FileInputStream
(
info
.
sourceDir
);
...
@@ -132,7 +89,7 @@ public class DynLoad {
...
@@ -132,7 +89,7 @@ public class DynLoad {
try
(
src
;
out
)
{
try
(
src
;
out
)
{
APKInstall
.
transfer
(
src
,
out
);
APKInstall
.
transfer
(
src
,
out
);
}
}
loader
=
new
Injected
ClassLoader
(
apk
);
return
new
App
ClassLoader
(
apk
);
}
catch
(
PackageManager
.
NameNotFoundException
ignored
)
{
}
catch
(
PackageManager
.
NameNotFoundException
ignored
)
{
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
...
@@ -140,7 +97,7 @@ public class DynLoad {
...
@@ -140,7 +97,7 @@ public class DynLoad {
}
}
}
}
return
isDynLoader
()
;
return
null
;
}
}
// Dynamically load APK and create the Application instance from the loaded APK
// Dynamically load APK and create the Application instance from the loaded APK
...
@@ -161,32 +118,37 @@ public class DynLoad {
...
@@ -161,32 +118,37 @@ public class DynLoad {
throw
new
RuntimeException
(
e
);
throw
new
RuntimeException
(
e
);
}
}
if
(!
loadApk
(
context
))
{
loader
=
new
RedirectClassLoader
(
createInternalMap
(
info
));
return
null
;
}
File
apk
=
StubApk
.
current
(
context
);
File
apk
=
StubApk
.
current
(
context
);
PackageManager
pm
=
context
.
getPackageManager
();
try
{
final
var
cl
=
loadApk
(
context
);
var
pkgInfo
=
pm
.
getPackageArchiveInfo
(
apk
.
getPath
(),
flags
);
if
(
cl
!=
null
)
try
{
var
pkgInfo
=
context
.
getPackageManager
()
.
getPackageArchiveInfo
(
apk
.
getPath
(),
flags
);
cl
.
updateComponentMap
(
info
,
pkgInfo
);
var
appInfo
=
pkgInfo
.
applicationInfo
;
var
appInfo
=
pkgInfo
.
applicationInfo
;
updateComponentMap
(
info
,
pkgInfo
);
var
data
=
createApkData
();
var
map
=
data
.
getClassToComponent
();
// Create the inverse mapping (class to component name)
for
(
var
e
:
cl
.
mapping
.
entrySet
())
{
map
.
put
(
e
.
getValue
(),
e
.
getKey
());
}
// Create the receiver Application
// Create the receiver Application
var
data
=
createApkData
();
var
app
=
(
Application
)
cl
.
loadClass
(
appInfo
.
className
)
var
app
=
(
Application
)
loader
.
loadClass
(
appInfo
.
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
(
appInfo
.
appComponentFactory
).
newInstance
();
Object
factory
=
cl
.
loadClass
(
appInfo
.
appComponentFactory
).
newInstance
();
var
delegate
=
(
DelegateComponentFactory
)
componentFactory
;
var
delegate
=
(
DelegateComponentFactory
)
componentFactory
;
delegate
.
receiver
=
(
AppComponentFactory
)
factory
;
delegate
.
receiver
=
(
AppComponentFactory
)
factory
;
}
}
DelegateClassLoader
.
cl
=
cl
;
// Send real application to attachBaseContext
// Send real application to attachBaseContext
attachContext
(
app
,
context
);
attachContext
(
app
,
context
);
...
@@ -196,97 +158,12 @@ public class DynLoad {
...
@@ -196,97 +158,12 @@ public class DynLoad {
apk
.
delete
();
apk
.
delete
();
}
}
DelegateClassLoader
.
cl
=
new
StubClassLoader
(
info
);
return
null
;
return
null
;
}
}
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
;
}
// Replace LoadedApk mClassLoader
// Replace LoadedApk mClassLoader
@SuppressWarnings
(
"ConstantConditions"
)
private
static
void
replaceClassLoader
(
Context
context
)
{
private
static
void
replaceClassLoader
(
Context
context
)
{
// Get ContextImpl
// Get ContextImpl
while
(
context
instanceof
ContextWrapper
)
{
while
(
context
instanceof
ContextWrapper
)
{
...
...
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