Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
S
SandHook
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
SandHook
Commits
3615f339
Commit
3615f339
authored
Feb 12, 2019
by
swift_gan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
done compat for xposed
parent
8e0774b6
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
713 additions
and
295 deletions
+713
-295
build.gradle
app/build.gradle
+1
-0
MyApp.java
app/src/main/java/com/swift/sandhook/MyApp.java
+26
-0
SandHook.java
hooklib/src/main/java/com/swift/sandhook/SandHook.java
+13
-0
HookWrapper.java
...src/main/java/com/swift/sandhook/wrapper/HookWrapper.java
+6
-8
build.gradle
xposedcompat/build.gradle
+2
-1
ProcessUtils.java
...in/java/com/swift/sandhook/xposedcompat/ProcessUtils.java
+64
-0
XposedCompat.java
...in/java/com/swift/sandhook/xposedcompat/XposedCompat.java
+9
-0
DexLog.java
...ava/com/swift/sandhook/xposedcompat/methodgen/DexLog.java
+38
-0
DexMakerUtils.java
.../swift/sandhook/xposedcompat/methodgen/DexMakerUtils.java
+2
-0
DynamicBridge.java
.../swift/sandhook/xposedcompat/methodgen/DynamicBridge.java
+113
-0
FileUtils.java
.../com/swift/sandhook/xposedcompat/methodgen/FileUtils.java
+77
-0
HookerDexMaker.java
...swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java
+4
-2
ProcessUtils.java
...m/swift/sandhook/xposedcompat/methodgen/ProcessUtils.java
+82
-0
IXposedHookInitPackageResources.java
.../robv/android/xposed/IXposedHookInitPackageResources.java
+1
-1
SELinuxHelper.java
...t/src/main/java/de/robv/android/xposed/SELinuxHelper.java
+7
-7
XSharedPreferences.java
.../main/java/de/robv/android/xposed/XSharedPreferences.java
+1
-4
XposedBridge.java
...at/src/main/java/de/robv/android/xposed/XposedBridge.java
+3
-11
XposedInit.java
...mpat/src/main/java/de/robv/android/xposed/XposedInit.java
+246
-246
XC_InitPackageResources.java
...obv/android/xposed/callbacks/XC_InitPackageResources.java
+2
-2
XC_LayoutInflated.java
...a/de/robv/android/xposed/callbacks/XC_LayoutInflated.java
+6
-6
XC_LoadPackage.java
...java/de/robv/android/xposed/callbacks/XC_LoadPackage.java
+8
-5
BinderService.java
...n/java/de/robv/android/xposed/services/BinderService.java
+2
-2
No files found.
app/build.gradle
View file @
3615f339
...
...
@@ -27,4 +27,5 @@ dependencies {
androidTestImplementation
'com.android.support.test:runner:1.0.2'
androidTestImplementation
'com.android.support.test.espresso:espresso-core:3.0.2'
implementation
project
(
':hooklib'
)
implementation
project
(
':xposedcompat'
)
}
app/src/main/java/com/swift/sandhook/MyApp.java
View file @
3615f339
package
com
.
swift
.
sandhook
;
import
android.app.Activity
;
import
android.app.Application
;
import
android.util.Log
;
import
com.swift.sandhook.testHookers.ActivityHooker
;
import
com.swift.sandhook.testHookers.CtrHook
;
...
...
@@ -9,13 +11,17 @@ import com.swift.sandhook.testHookers.JniHooker;
import
com.swift.sandhook.testHookers.LogHooker
;
import
com.swift.sandhook.testHookers.ObjectHooker
;
import
com.swift.sandhook.wrapper.HookErrorException
;
import
com.swift.sandhook.xposedcompat.XposedCompat
;
import
dalvik.system.DexClassLoader
;
import
de.robv.android.xposed.XC_MethodHook
;
import
de.robv.android.xposed.XposedHelpers
;
public
class
MyApp
extends
Application
{
@Override
public
void
onCreate
()
{
super
.
onCreate
();
try
{
SandHook
.
addHookClass
(
JniHooker
.
class
,
CtrHook
.
class
,
...
...
@@ -27,6 +33,26 @@ public class MyApp extends Application {
e
.
printStackTrace
();
}
//setup for xposed
XposedCompat
.
cacheDir
=
getCacheDir
();
XposedCompat
.
context
=
this
;
XposedCompat
.
classLoader
=
getClassLoader
();
XposedCompat
.
isFirstApplication
=
true
;
XposedHelpers
.
findAndHookMethod
(
Activity
.
class
,
"onResume"
,
new
XC_MethodHook
()
{
@Override
protected
void
beforeHookedMethod
(
MethodHookParam
param
)
throws
Throwable
{
super
.
beforeHookedMethod
(
param
);
Log
.
e
(
"XposedCompat"
,
"beforeHookedMethod: "
+
param
.
method
.
getName
());
}
@Override
protected
void
afterHookedMethod
(
MethodHookParam
param
)
throws
Throwable
{
super
.
afterHookedMethod
(
param
);
Log
.
e
(
"XposedCompat"
,
"afterHookedMethod: "
+
param
.
method
.
getName
());
}
});
try
{
ClassLoader
classLoader
=
getClassLoader
();
DexClassLoader
dexClassLoader
=
new
DexClassLoader
(
"/sdcard/hookers-debug.apk"
,
...
...
hooklib/src/main/java/com/swift/sandhook/SandHook.java
View file @
3615f339
...
...
@@ -10,9 +10,13 @@ import java.lang.reflect.Field;
import
java.lang.reflect.Member
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
public
class
SandHook
{
static
Map
<
Member
,
HookWrapper
.
HookEntity
>
globalHookEntityMap
=
new
ConcurrentHashMap
<>();
public
static
Class
artMethodClass
;
public
static
Field
nativePeerField
;
...
...
@@ -55,6 +59,15 @@ public class SandHook {
HookWrapper
.
addHookClass
(
classLoader
,
hookWrapperClass
);
}
public
static
void
hook
(
HookWrapper
.
HookEntity
entity
)
throws
HookErrorException
{
if
(
entity
.
target
!=
null
&&
entity
.
hook
!=
null
)
{
if
(!
SandHook
.
hook
(
entity
.
target
,
entity
.
hook
,
entity
.
backup
))
{
throw
new
HookErrorException
(
"hook method <"
+
entity
.
target
.
getName
()
+
"> error in native!"
);
}
globalHookEntityMap
.
put
(
entity
.
target
,
entity
);
}
}
public
static
boolean
hook
(
Member
target
,
Method
hook
,
Method
backup
)
{
if
(
target
==
null
||
hook
==
null
)
return
false
;
...
...
hooklib/src/main/java/com/swift/sandhook/wrapper/HookWrapper.java
View file @
3615f339
...
...
@@ -21,8 +21,6 @@ import java.util.concurrent.ConcurrentHashMap;
public
class
HookWrapper
{
static
Map
<
Member
,
HookEntity
>
globalHookEntityMap
=
new
ConcurrentHashMap
<>();
public
static
void
addHookClass
(
Class
<?>...
classes
)
throws
HookErrorException
{
addHookClass
(
null
,
classes
);
}
...
...
@@ -40,12 +38,7 @@ public class HookWrapper {
Map
<
Member
,
HookEntity
>
hookEntityMap
=
getHookMethods
(
classLoader
,
targetHookClass
,
clazz
);
fillBackupMethod
(
classLoader
,
clazz
,
hookEntityMap
);
for
(
HookEntity
entity:
hookEntityMap
.
values
())
{
if
(
entity
.
target
!=
null
&&
entity
.
hook
!=
null
)
{
if
(!
SandHook
.
hook
(
entity
.
target
,
entity
.
hook
,
entity
.
backup
))
{
throw
new
HookErrorException
(
"hook method <"
+
entity
.
target
.
getName
()
+
"> error in native!"
);
}
globalHookEntityMap
.
put
(
entity
.
target
,
entity
);
}
SandHook
.
hook
(
entity
);
}
}
...
...
@@ -285,6 +278,11 @@ public class HookWrapper {
this
.
target
=
target
;
}
public
HookEntity
(
Member
target
,
Method
hook
,
Method
backup
)
{
this
.
target
=
target
;
this
.
hook
=
hook
;
this
.
backup
=
backup
;
}
public
boolean
isCtor
()
{
return
target
instanceof
Constructor
;
...
...
xposedcompat/build.gradle
View file @
3615f339
...
...
@@ -25,6 +25,7 @@ android {
}
dependencies
{
implementation
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
]
)
implementation
fileTree
(
include:
[
'*.jar'
],
dir:
'libs'
)
implementation
'com.linkedin.dexmaker:dexmaker:2.21.0'
compileOnly
project
(
':hooklib'
)
}
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/ProcessUtils.java
0 → 100644
View file @
3615f339
package
com
.
swift
.
sandhook
.
xposedcompat
;
import
android.app.ActivityManager
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.pm.PackageManager
;
import
android.content.pm.ResolveInfo
;
import
android.text.TextUtils
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* Created by swift_gan on 2017/11/23.
*/
public
class
ProcessUtils
{
private
static
volatile
String
processName
=
null
;
public
static
String
getProcessName
(
Context
context
)
{
if
(!
TextUtils
.
isEmpty
(
processName
))
return
processName
;
processName
=
doGetProcessName
(
context
);
return
processName
;
}
private
static
String
doGetProcessName
(
Context
context
)
{
ActivityManager
am
=
(
ActivityManager
)
context
.
getSystemService
(
Context
.
ACTIVITY_SERVICE
);
List
<
ActivityManager
.
RunningAppProcessInfo
>
runningApps
=
am
.
getRunningAppProcesses
();
if
(
runningApps
==
null
)
{
return
null
;
}
for
(
ActivityManager
.
RunningAppProcessInfo
proInfo
:
runningApps
)
{
if
(
proInfo
.
pid
==
android
.
os
.
Process
.
myPid
())
{
if
(
proInfo
.
processName
!=
null
)
{
return
proInfo
.
processName
;
}
}
}
return
context
.
getPackageName
();
}
public
static
boolean
isMainProcess
(
Context
context
)
{
String
processName
=
getProcessName
(
context
);
String
pkgName
=
context
.
getPackageName
();
if
(!
TextUtils
.
isEmpty
(
processName
)
&&
!
TextUtils
.
equals
(
processName
,
pkgName
))
{
return
false
;
}
else
{
return
true
;
}
}
public
static
List
<
ResolveInfo
>
findActivitiesForPackage
(
Context
context
,
String
packageName
)
{
final
PackageManager
packageManager
=
context
.
getPackageManager
();
final
Intent
mainIntent
=
new
Intent
(
Intent
.
ACTION_MAIN
,
null
);
mainIntent
.
addCategory
(
Intent
.
CATEGORY_LAUNCHER
);
mainIntent
.
setPackage
(
packageName
);
final
List
<
ResolveInfo
>
apps
=
packageManager
.
queryIntentActivities
(
mainIntent
,
0
);
return
apps
!=
null
?
apps
:
new
ArrayList
<
ResolveInfo
>();
}
}
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java
View file @
3615f339
package
com
.
swift
.
sandhook
.
xposedcompat
;
import
android.content.Context
;
import
android.content.pm.ApplicationInfo
;
import
java.io.File
;
public
class
XposedCompat
{
public
static
File
cacheDir
;
public
static
Context
context
;
public
static
ClassLoader
classLoader
;
public
static
boolean
isFirstApplication
;
}
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/DexLog.java
0 → 100644
View file @
3615f339
package
com
.
swift
.
sandhook
.
xposedcompat
.
methodgen
;
import
android.util.Log
;
import
com.swift.sandhook.xposedcompat.BuildConfig
;
public
class
DexLog
{
public
static
final
String
TAG
=
"SandXposed-dexmaker"
;
public
static
int
v
(
String
s
)
{
return
Log
.
v
(
TAG
,
s
);
}
public
static
int
i
(
String
s
)
{
return
Log
.
i
(
TAG
,
s
);
}
public
static
int
d
(
String
s
)
{
if
(
BuildConfig
.
DEBUG
)
{
return
Log
.
d
(
TAG
,
s
);
}
return
0
;
}
public
static
int
w
(
String
s
)
{
return
Log
.
w
(
TAG
,
s
);
}
public
static
int
e
(
String
s
)
{
return
Log
.
e
(
TAG
,
s
);
}
public
static
int
e
(
String
s
,
Throwable
t
)
{
return
Log
.
e
(
TAG
,
s
,
t
);
}
}
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/DexMakerUtils.java
View file @
3615f339
...
...
@@ -225,6 +225,7 @@ public class DexMakerUtils {
if
(
addInstMethod
==
null
)
{
try
{
addInstMethod
=
Code
.
class
.
getDeclaredMethod
(
"addInstruction"
,
Insn
.
class
);
addInstMethod
.
setAccessible
(
true
);
}
catch
(
NoSuchMethodException
e
)
{
e
.
printStackTrace
();
}
...
...
@@ -240,6 +241,7 @@ public class DexMakerUtils {
if
(
specMethod
==
null
)
{
try
{
specMethod
=
Local
.
class
.
getDeclaredMethod
(
"spec"
);
specMethod
.
setAccessible
(
true
);
}
catch
(
NoSuchMethodException
e
)
{
e
.
printStackTrace
();
}
...
...
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/DynamicBridge.java
0 → 100644
View file @
3615f339
package
com
.
swift
.
sandhook
.
xposedcompat
.
methodgen
;
import
com.swift.sandhook.xposedcompat.XposedCompat
;
import
java.io.File
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Member
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.HashMap
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
de.robv.android.xposed.XposedBridge
;
public
final
class
DynamicBridge
{
private
static
final
HashMap
<
Member
,
Method
>
hookedInfo
=
new
HashMap
<>();
private
static
final
HookerDexMaker
dexMaker
=
new
HookerDexMaker
();
private
static
final
AtomicBoolean
dexPathInited
=
new
AtomicBoolean
(
false
);
private
static
File
dexDir
;
private
static
File
dexOptDir
;
public
static
void
onForkPost
()
{
dexPathInited
.
set
(
false
);
}
public
static
synchronized
void
hookMethod
(
Member
hookMethod
,
XposedBridge
.
AdditionalHookInfo
additionalHookInfo
)
{
if
(!
checkMember
(
hookMethod
))
{
return
;
}
if
(
hookedInfo
.
containsKey
(
hookMethod
))
{
DexLog
.
w
(
"already hook method:"
+
hookMethod
.
toString
());
return
;
}
DexLog
.
d
(
"start to generate class for: "
+
hookMethod
);
try
{
// using file based DexClassLoader
if
(
dexPathInited
.
compareAndSet
(
false
,
true
))
{
// delete previous compiled dex to prevent potential crashing
// TODO find a way to reuse them in consideration of performance
try
{
// we always choose to use device encrypted storage data on android N and later
// in case some app is installing hooks before phone is unlocked
String
fixedAppDataDir
=
XposedCompat
.
cacheDir
.
getAbsolutePath
();
dexDir
=
new
File
(
fixedAppDataDir
,
"/sandxposed/"
);
dexOptDir
=
new
File
(
dexDir
,
"oat"
);
dexDir
.
mkdirs
();
try
{
FileUtils
.
delete
(
dexOptDir
);
}
catch
(
Throwable
throwable
)
{
}
}
catch
(
Throwable
throwable
)
{
DexLog
.
e
(
"error when init dex path"
,
throwable
);
}
}
dexMaker
.
start
(
hookMethod
,
additionalHookInfo
,
hookMethod
.
getDeclaringClass
().
getClassLoader
(),
dexDir
==
null
?
null
:
dexDir
.
getAbsolutePath
());
hookedInfo
.
put
(
hookMethod
,
dexMaker
.
getCallBackupMethod
());
}
catch
(
Exception
e
)
{
DexLog
.
e
(
"error occur when generating dex. dexDir="
+
dexDir
,
e
);
}
}
private
static
boolean
checkMember
(
Member
member
)
{
if
(
member
instanceof
Method
)
{
return
true
;
}
else
if
(
member
instanceof
Constructor
<?>)
{
return
true
;
}
else
if
(
member
.
getDeclaringClass
().
isInterface
())
{
DexLog
.
e
(
"Cannot hook interfaces: "
+
member
.
toString
());
return
false
;
}
else
if
(
Modifier
.
isAbstract
(
member
.
getModifiers
()))
{
DexLog
.
e
(
"Cannot hook abstract methods: "
+
member
.
toString
());
return
false
;
}
else
{
DexLog
.
e
(
"Only methods and constructors can be hooked: "
+
member
.
toString
());
return
false
;
}
}
public
static
Object
invokeOriginalMethod
(
Member
method
,
Object
thisObject
,
Object
[]
args
)
throws
InvocationTargetException
,
IllegalAccessException
{
Method
callBackup
=
hookedInfo
.
get
(
method
);
if
(
callBackup
==
null
)
{
throw
new
IllegalStateException
(
"method not hooked, cannot call original method."
);
}
if
(!
Modifier
.
isStatic
(
callBackup
.
getModifiers
()))
{
throw
new
IllegalStateException
(
"original method is not static, something must be wrong!"
);
}
callBackup
.
setAccessible
(
true
);
if
(
args
==
null
)
{
args
=
new
Object
[
0
];
}
final
int
argsSize
=
args
.
length
;
if
(
Modifier
.
isStatic
(
method
.
getModifiers
()))
{
return
callBackup
.
invoke
(
null
,
args
);
}
else
{
Object
[]
newArgs
=
new
Object
[
argsSize
+
1
];
newArgs
[
0
]
=
thisObject
;
for
(
int
i
=
1
;
i
<
newArgs
.
length
;
i
++)
{
newArgs
[
i
]
=
args
[
i
-
1
];
}
return
callBackup
.
invoke
(
null
,
newArgs
);
}
}
}
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/FileUtils.java
0 → 100644
View file @
3615f339
package
com
.
swift
.
sandhook
.
xposedcompat
.
methodgen
;
import
android.os.Build
;
import
android.text.TextUtils
;
import
java.io.BufferedReader
;
import
java.io.BufferedWriter
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.FileWriter
;
import
java.io.IOException
;
public
class
FileUtils
{
public
static
final
boolean
IS_USING_PROTECTED_STORAGE
=
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
N
;
/**
* Delete a file or a directory and its children.
*
* @param file The directory to delete.
* @throws IOException Exception when problem occurs during deleting the directory.
*/
public
static
void
delete
(
File
file
)
throws
IOException
{
for
(
File
childFile
:
file
.
listFiles
())
{
if
(
childFile
.
isDirectory
())
{
delete
(
childFile
);
}
else
{
if
(!
childFile
.
delete
())
{
throw
new
IOException
();
}
}
}
if
(!
file
.
delete
())
{
throw
new
IOException
();
}
}
public
static
String
readLine
(
File
file
)
{
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
FileReader
(
file
)))
{
return
reader
.
readLine
();
}
catch
(
Throwable
throwable
)
{
return
""
;
}
}
public
static
void
writeLine
(
File
file
,
String
line
)
{
try
{
file
.
createNewFile
();
}
catch
(
IOException
ex
)
{
}
try
(
BufferedWriter
writer
=
new
BufferedWriter
(
new
FileWriter
(
file
)))
{
writer
.
write
(
line
);
writer
.
flush
();
}
catch
(
Throwable
throwable
)
{
DexLog
.
e
(
"error writing line to file "
+
file
+
": "
+
throwable
.
getMessage
());
}
}
public
static
String
getPackageName
(
String
dataDir
)
{
if
(
TextUtils
.
isEmpty
(
dataDir
))
{
DexLog
.
e
(
"getPackageName using empty dataDir"
);
return
""
;
}
int
lastIndex
=
dataDir
.
lastIndexOf
(
"/"
);
if
(
lastIndex
<
0
)
{
return
dataDir
;
}
return
dataDir
.
substring
(
lastIndex
+
1
);
}
public
static
String
getDataPathPrefix
()
{
return
IS_USING_PROTECTED_STORAGE
?
"/data/user_de/0/"
:
"/data/data/"
;
}
}
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java
View file @
3615f339
...
...
@@ -11,6 +11,8 @@ import com.android.dx.Label;
import
com.android.dx.Local
;
import
com.android.dx.MethodId
;
import
com.android.dx.TypeId
;
import
com.swift.sandhook.SandHook
;
import
com.swift.sandhook.wrapper.HookWrapper
;
import
java.io.File
;
import
java.lang.reflect.Constructor
;
...
...
@@ -37,7 +39,7 @@ public class HookerDexMaker {
public
static
final
String
METHOD_NAME_SETUP
=
"setup"
;
public
static
final
TypeId
<
Object
[]>
objArrayTypeId
=
TypeId
.
get
(
Object
[].
class
);
private
static
final
String
CLASS_DESC_PREFIX
=
"L"
;
private
static
final
String
CLASS_NAME_PREFIX
=
"
E
dHooker"
;
private
static
final
String
CLASS_NAME_PREFIX
=
"
San
dHooker"
;
private
static
final
String
FIELD_NAME_HOOK_INFO
=
"additionalHookInfo"
;
private
static
final
String
FIELD_NAME_METHOD
=
"method"
;
private
static
final
String
PARAMS_FIELD_NAME_METHOD
=
"method"
;
...
...
@@ -203,7 +205,7 @@ public class HookerDexMaker {
mHookMethod
=
mHookClass
.
getMethod
(
METHOD_NAME_HOOK
,
mActualParameterTypes
);
mBackupMethod
=
mHookClass
.
getMethod
(
METHOD_NAME_BACKUP
,
mActualParameterTypes
);
mCallBackupMethod
=
mHookClass
.
getMethod
(
METHOD_NAME_CALL_BACKUP
,
mActualParameterTypes
);
//HookMain.backupAndHook(mMember, mHookMethod, mBackupMethod
);
SandHook
.
hook
(
new
HookWrapper
.
HookEntity
(
mMember
,
mHookMethod
,
mBackupMethod
)
);
}
public
Method
getHookMethod
()
{
...
...
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/ProcessUtils.java
0 → 100644
View file @
3615f339
package
com
.
swift
.
sandhook
.
xposedcompat
.
methodgen
;
import
android.os.Process
;
import
android.text.TextUtils
;
//import com.elderdrivers.riru.xposed.Main;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.InputStreamReader
;
public
class
ProcessUtils
{
public
static
String
getCurrentProcessName
()
{
String
prettyName
=
null
;
//Main.sAppProcessName;
if
(!
TextUtils
.
isEmpty
(
prettyName
))
{
return
prettyName
;
}
return
getProcessName
(
Process
.
myPid
());
}
/**
* a common solution from https://stackoverflow.com/a/21389402
* <p>
* use {@link com.elderdrivers.riru.xposed.Main#sAppProcessName} to get current process name
*/
public
static
String
getProcessName
(
int
pid
)
{
BufferedReader
cmdlineReader
=
null
;
try
{
cmdlineReader
=
new
BufferedReader
(
new
InputStreamReader
(
new
FileInputStream
(
"/proc/"
+
pid
+
"/cmdline"
),
"iso-8859-1"
));
int
c
;
StringBuilder
processName
=
new
StringBuilder
();
while
((
c
=
cmdlineReader
.
read
())
>
0
)
{
processName
.
append
((
char
)
c
);
}
return
processName
.
toString
();
}
catch
(
Throwable
throwable
)
{
DexLog
.
w
(
"getProcessName: "
+
throwable
.
getMessage
());
}
finally
{
try
{
if
(
cmdlineReader
!=
null
)
{
cmdlineReader
.
close
();
}
}
catch
(
Throwable
throwable
)
{
DexLog
.
e
(
"getProcessName: "
+
throwable
.
getMessage
());
}
}
return
""
;
}
public
static
boolean
isLastPidAlive
(
File
lastPidFile
)
{
String
lastPidInfo
=
FileUtils
.
readLine
(
lastPidFile
);
try
{
String
[]
split
=
lastPidInfo
.
split
(
":"
,
2
);
return
checkProcessAlive
(
Integer
.
parseInt
(
split
[
0
]),
split
[
1
]);
}
catch
(
Throwable
throwable
)
{
DexLog
.
w
(
"error when check last pid "
+
lastPidFile
+
": "
+
throwable
.
getMessage
());
return
false
;
}
}
public
static
void
saveLastPidInfo
(
File
lastPidFile
,
int
pid
,
String
processName
)
{
try
{
if
(!
lastPidFile
.
exists
())
{
lastPidFile
.
getParentFile
().
mkdirs
();
lastPidFile
.
createNewFile
();
}
}
catch
(
Throwable
throwable
)
{
}
FileUtils
.
writeLine
(
lastPidFile
,
pid
+
":"
+
processName
);
}
public
static
boolean
checkProcessAlive
(
int
pid
,
String
processName
)
{
String
existsPrcName
=
getProcessName
(
pid
);
DexLog
.
w
(
"checking pid alive: "
+
pid
+
", "
+
processName
+
", processName="
+
existsPrcName
);
return
existsPrcName
.
equals
(
processName
);
}
}
xposedcompat/src/main/java/de/robv/android/xposed/IXposedHookInitPackageResources.java
View file @
3615f339
package
de
.
robv
.
android
.
xposed
;
import
android.content.res.XResources
;
//
import android.content.res.XResources;
import
de.robv.android.xposed.callbacks.XC_InitPackageResources
;
import
de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam
;
...
...
xposedcompat/src/main/java/de/robv/android/xposed/SELinuxHelper.java
View file @
3615f339
package
de
.
robv
.
android
.
xposed
;
import
android.os.SELinux
;
//
import android.os.SELinux;
import
de.robv.android.xposed.services.BaseService
;
import
de.robv.android.xposed.services.DirectAccessService
;
...
...
@@ -25,18 +25,18 @@ public final class SELinuxHelper {
*
* @return A boolean indicating whether SELinux is enforcing.
*/
public
static
boolean
isSELinuxEnforced
()
{
return
sIsSELinuxEnabled
&&
SELinux
.
isSELinuxEnforced
();
}
//
public static boolean isSELinuxEnforced() {
//
return sIsSELinuxEnabled && SELinux.isSELinuxEnforced();
//
}
/**
* Gets the security context of the current process.
*
* @return A String representing the security context of the current process.
*/
public
static
String
getContext
()
{
return
sIsSELinuxEnabled
?
SELinux
.
getContext
()
:
null
;
}
//
public static String getContext() {
//
return sIsSELinuxEnabled ? SELinux.getContext() : null;
//
}
/**
* Retrieve the service to be used when accessing files in {@code /data/data/*}.
...
...
xposedcompat/src/main/java/de/robv/android/xposed/XSharedPreferences.java
View file @
3615f339
...
...
@@ -7,7 +7,6 @@ import android.os.Environment;
import
android.preference.PreferenceManager
;
import
android.util.Log
;
import
com.android.internal.util.XmlUtils
;
import
org.xmlpull.v1.XmlPullParserException
;
...
...
@@ -121,14 +120,12 @@ public final class XSharedPreferences implements SharedPreferences {
try
{
result
=
SELinuxHelper
.
getAppDataFileService
().
getFileInputStream
(
mFilename
,
mFileSize
,
mLastModified
);
if
(
result
.
stream
!=
null
)
{
map
=
XmlUtils
.
readMapXml
(
result
.
stream
);
//
map = XmlUtils.readMapXml(result.stream);
result
.
stream
.
close
();
}
else
{
// The file is unchanged, keep the current values
map
=
mMap
;
}
}
catch
(
XmlPullParserException
e
)
{
Log
.
w
(
TAG
,
"getSharedPreferences"
,
e
);
}
catch
(
FileNotFoundException
ignored
)
{
// SharedPreferencesImpl has a canRead() check, so it doesn't log anything in case the file doesn't exist
}
catch
(
IOException
e
)
{
...
...
xposedcompat/src/main/java/de/robv/android/xposed/XposedBridge.java
View file @
3615f339
...
...
@@ -4,6 +4,8 @@ import android.annotation.SuppressLint;
import
android.util.Log
;
import
com.swift.sandhook.xposedcompat.methodgen.DynamicBridge
;
import
java.io.File
;
import
java.io.IOException
;
import
java.lang.reflect.AccessibleObject
;
...
...
@@ -151,7 +153,6 @@ public final class XposedBridge {
* @see #hookAllConstructors
*/
public
static
XC_MethodHook
.
Unhook
hookMethod
(
Member
hookMethod
,
XC_MethodHook
callback
)
{
hookMethod
=
MethodHookUtils
.
preCheck
(
hookMethod
);
if
(!(
hookMethod
instanceof
Method
)
&&
!(
hookMethod
instanceof
Constructor
<?>))
{
throw
new
IllegalArgumentException
(
"Only methods and constructors can be hooked: "
+
hookMethod
.
toString
());
}
else
if
(
hookMethod
.
getDeclaringClass
().
isInterface
())
{
...
...
@@ -196,16 +197,7 @@ public final class XposedBridge {
}
AdditionalHookInfo
additionalInfo
=
new
AdditionalHookInfo
(
callbacks
,
parameterTypes
,
returnType
);
MethodInfo
methodInfo
=
new
MethodInfo
(
hookMethod
);
declaringClass
=
methodInfo
.
getClassForSure
();
Member
reflectMethod
=
(
Member
)
HookMain
.
findMethod
(
declaringClass
,
methodInfo
.
methodName
,
methodInfo
.
methodSig
);
if
(
reflectMethod
==
null
)
{
Log
.
e
(
TAG
,
"method not found: name="
+
methodInfo
.
methodName
+
", sig="
+
methodInfo
.
methodSig
);
reflectMethod
=
hookMethod
;
}
hookMethodNative
(
reflectMethod
,
declaringClass
,
slot
,
additionalInfo
);
hookMethodNative
(
hookMethod
,
declaringClass
,
slot
,
additionalInfo
);
}
return
callback
.
new
Unhook
(
hookMethod
);
...
...
xposedcompat/src/main/java/de/robv/android/xposed/XposedInit.java
View file @
3615f339
package
de
.
robv
.
android
.
xposed
;
import
android.annotation.SuppressLint
;
import
android.app.AndroidAppHelper
;
import
android.os.Build
;
import
android.text.TextUtils
;
import
android.util.Log
;
import
com.android.internal.os.ZygoteInit
;
import
com.elderdrivers.riru.xposed.BuildConfig
;
import
com.elderdrivers.riru.xposed.entry.Router
;
import
com.elderdrivers.riru.xposed.util.Utils
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.util.HashSet
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipFile
;
import
dalvik.system.DexFile
;
import
dalvik.system.PathClassLoader
;
import
de.robv.android.xposed.services.BaseService
;
import
static
com
.
elderdrivers
.
riru
.
xposed
.
entry
.
hooker
.
XposedBlackListHooker
.
BLACK_LIST_PACKAGE_NAME
;
import
static
de
.
robv
.
android
.
xposed
.
XposedHelpers
.
closeSilently
;
import
static
de
.
robv
.
android
.
xposed
.
XposedHelpers
.
findClass
;
import
static
de
.
robv
.
android
.
xposed
.
XposedHelpers
.
findFieldIfExists
;
import
static
de
.
robv
.
android
.
xposed
.
XposedHelpers
.
setStaticBooleanField
;
import
static
de
.
robv
.
android
.
xposed
.
XposedHelpers
.
setStaticLongField
;
//
import android.annotation.SuppressLint;
//
import android.app.AndroidAppHelper;
//
import android.os.Build;
//
import android.text.TextUtils;
//
import android.util.Log;
//
//
import com.android.internal.os.ZygoteInit;
//
import com.elderdrivers.riru.xposed.BuildConfig;
//
import com.elderdrivers.riru.xposed.entry.Router;
//
import com.elderdrivers.riru.xposed.util.Utils;
//
//
import java.io.BufferedReader;
//
import java.io.File;
//
import java.io.IOException;
//
import java.io.InputStream;
//
import java.io.InputStreamReader;
//
import java.util.HashSet;
//
import java.util.concurrent.atomic.AtomicBoolean;
//
import java.util.zip.ZipEntry;
//
import java.util.zip.ZipFile;
//
//
import dalvik.system.DexFile;
//
import dalvik.system.PathClassLoader;
//
import de.robv.android.xposed.services.BaseService;
//
//
import static com.elderdrivers.riru.xposed.entry.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
//
import static de.robv.android.xposed.XposedHelpers.closeSilently;
//
import static de.robv.android.xposed.XposedHelpers.findClass;
//
import static de.robv.android.xposed.XposedHelpers.findFieldIfExists;
//
import static de.robv.android.xposed.XposedHelpers.setStaticBooleanField;
//
import static de.robv.android.xposed.XposedHelpers.setStaticLongField;
public
final
class
XposedInit
{
private
static
final
String
TAG
=
XposedBridge
.
TAG
;
private
static
boolean
startsSystemServer
=
false
;
private
static
final
String
startClassName
=
""
;
// ed: no support for tool process anymore
public
static
final
String
INSTALLER_PACKAGE_NAME
=
"com.solohsu.android.edxp.manager"
;
public
static
final
String
INSTALLER_LEGACY_PACKAGE_NAME
=
"de.robv.android.xposed.installer"
;
@SuppressLint
(
"SdCardPath"
)
public
static
final
String
INSTALLER_DATA_BASE_DIR
=
Build
.
VERSION
.
SDK_INT
>=
24
?
"/data/user_de/0/"
+
INSTALLER_PACKAGE_NAME
+
"/"
:
"/data/data/"
+
INSTALLER_PACKAGE_NAME
+
"/"
;
private
static
final
String
INSTANT_RUN_CLASS
=
"com.android.tools.fd.runtime.BootstrapApplication"
;
// TODO not supported yet
private
static
boolean
disableResources
=
true
;
private
static
final
String
[]
XRESOURCES_CONFLICTING_PACKAGES
=
{
"com.sygic.aura"
};
private
XposedInit
()
{
}
private
static
volatile
AtomicBoolean
bootstrapHooked
=
new
AtomicBoolean
(
false
);
/**
* Hook some methods which we want to create an easier interface for developers.
*/
/*package*/
public
static
void
initForZygote
(
boolean
isSystem
)
throws
Throwable
{
if
(!
bootstrapHooked
.
compareAndSet
(
false
,
true
))
{
return
;
}
startsSystemServer
=
isSystem
;
Router
.
startBootstrapHook
(
isSystem
);
// MIUI
if
(
findFieldIfExists
(
ZygoteInit
.
class
,
"BOOT_START_TIME"
)
!=
null
)
{
setStaticLongField
(
ZygoteInit
.
class
,
"BOOT_START_TIME"
,
XposedBridge
.
BOOT_START_TIME
);
}
// Samsung
if
(
Build
.
VERSION
.
SDK_INT
>=
24
)
{
Class
<?>
zygote
=
findClass
(
"com.android.internal.os.Zygote"
,
null
);
try
{
setStaticBooleanField
(
zygote
,
"isEnhancedZygoteASLREnabled"
,
false
);
}
catch
(
NoSuchFieldError
ignored
)
{
}
}
}
/*package*/
static
void
hookResources
()
throws
Throwable
{
// ed: not for now
}
private
static
boolean
needsToCloseFilesForFork
()
{
// ed: we always start to do our work after forking finishes
return
false
;
}
/**
* Try to load all modules defined in <code>INSTALLER_DATA_BASE_DIR/conf/modules.list</code>
*/
private
static
volatile
AtomicBoolean
modulesLoaded
=
new
AtomicBoolean
(
false
);
public
static
void
loadModules
()
throws
IOException
{
if
(!
modulesLoaded
.
compareAndSet
(
false
,
true
))
{
return
;
}
final
String
filename
=
INSTALLER_DATA_BASE_DIR
+
"conf/modules.list"
;
BaseService
service
=
SELinuxHelper
.
getAppDataFileService
();
if
(!
service
.
checkFileExists
(
filename
))
{
Log
.
e
(
TAG
,
"Cannot load any modules because "
+
filename
+
" was not found"
);
return
;
}
ClassLoader
topClassLoader
=
XposedBridge
.
BOOTCLASSLOADER
;
ClassLoader
parent
;
while
((
parent
=
topClassLoader
.
getParent
())
!=
null
)
{
topClassLoader
=
parent
;
}
InputStream
stream
=
service
.
getFileInputStream
(
filename
);
BufferedReader
apks
=
new
BufferedReader
(
new
InputStreamReader
(
stream
));
String
apk
;
while
((
apk
=
apks
.
readLine
())
!=
null
)
{
loadModule
(
apk
,
topClassLoader
);
}
apks
.
close
();
}
/**
* Load a module from an APK by calling the init(String) method for all classes defined
* in <code>assets/xposed_init</code>.
*/
private
static
void
loadModule
(
String
apk
,
ClassLoader
topClassLoader
)
{
if
(
BuildConfig
.
DEBUG
)
Log
.
i
(
TAG
,
"Loading modules from "
+
apk
);
if
(!
TextUtils
.
isEmpty
(
apk
)
&&
apk
.
contains
(
BLACK_LIST_PACKAGE_NAME
))
{
if
(
BuildConfig
.
DEBUG
)
Log
.
i
(
TAG
,
"We are going to take over black list's job..."
);
return
;
}
if
(!
new
File
(
apk
).
exists
())
{
Log
.
e
(
TAG
,
" File does not exist"
);
return
;
}
DexFile
dexFile
;
try
{
dexFile
=
new
DexFile
(
apk
);
}
catch
(
IOException
e
)
{
Log
.
e
(
TAG
,
" Cannot load module"
,
e
);
return
;
}
if
(
dexFile
.
loadClass
(
INSTANT_RUN_CLASS
,
topClassLoader
)
!=
null
)
{
Log
.
e
(
TAG
,
" Cannot load module, please disable \"Instant Run\" in Android Studio."
);
closeSilently
(
dexFile
);
return
;
}
if
(
dexFile
.
loadClass
(
XposedBridge
.
class
.
getName
(),
topClassLoader
)
!=
null
)
{
Log
.
e
(
TAG
,
" Cannot load module:"
);
Log
.
e
(
TAG
,
" The Xposed API classes are compiled into the module's APK."
);
Log
.
e
(
TAG
,
" This may cause strange issues and must be fixed by the module developer."
);
Log
.
e
(
TAG
,
" For details, see: http://api.xposed.info/using.html"
);
closeSilently
(
dexFile
);
return
;
}
closeSilently
(
dexFile
);
ZipFile
zipFile
=
null
;
InputStream
is
;
try
{
zipFile
=
new
ZipFile
(
apk
);
ZipEntry
zipEntry
=
zipFile
.
getEntry
(
"assets/xposed_init"
);
if
(
zipEntry
==
null
)
{
Log
.
e
(
TAG
,
" assets/xposed_init not found in the APK"
);
closeSilently
(
zipFile
);
return
;
}
is
=
zipFile
.
getInputStream
(
zipEntry
);
}
catch
(
IOException
e
)
{
Log
.
e
(
TAG
,
" Cannot read assets/xposed_init in the APK"
,
e
);
closeSilently
(
zipFile
);
return
;
}
ClassLoader
mcl
=
new
PathClassLoader
(
apk
,
XposedInit
.
class
.
getClassLoader
());
BufferedReader
moduleClassesReader
=
new
BufferedReader
(
new
InputStreamReader
(
is
));
try
{
String
moduleClassName
;
while
((
moduleClassName
=
moduleClassesReader
.
readLine
())
!=
null
)
{
moduleClassName
=
moduleClassName
.
trim
();
if
(
moduleClassName
.
isEmpty
()
||
moduleClassName
.
startsWith
(
"#"
))
continue
;
try
{
if
(
BuildConfig
.
DEBUG
)
Log
.
i
(
TAG
,
" Loading class "
+
moduleClassName
);
Class
<?>
moduleClass
=
mcl
.
loadClass
(
moduleClassName
);
if
(!
IXposedMod
.
class
.
isAssignableFrom
(
moduleClass
))
{
Log
.
e
(
TAG
,
" This class doesn't implement any sub-interface of IXposedMod, skipping it"
);
continue
;
}
else
if
(
disableResources
&&
IXposedHookInitPackageResources
.
class
.
isAssignableFrom
(
moduleClass
))
{
Log
.
e
(
TAG
,
" This class requires resource-related hooks (which are disabled), skipping it."
);
continue
;
}
final
Object
moduleInstance
=
moduleClass
.
newInstance
();
if
(
XposedBridge
.
isZygote
)
{
if
(
moduleInstance
instanceof
IXposedHookZygoteInit
)
{
IXposedHookZygoteInit
.
StartupParam
param
=
new
IXposedHookZygoteInit
.
StartupParam
();
param
.
modulePath
=
apk
;
param
.
startsSystemServer
=
startsSystemServer
;
((
IXposedHookZygoteInit
)
moduleInstance
).
initZygote
(
param
);
}
if
(
moduleInstance
instanceof
IXposedHookLoadPackage
)
XposedBridge
.
hookLoadPackage
(
new
IXposedHookLoadPackage
.
Wrapper
((
IXposedHookLoadPackage
)
moduleInstance
));
if
(
moduleInstance
instanceof
IXposedHookInitPackageResources
)
XposedBridge
.
hookInitPackageResources
(
new
IXposedHookInitPackageResources
.
Wrapper
((
IXposedHookInitPackageResources
)
moduleInstance
));
}
else
{
if
(
moduleInstance
instanceof
IXposedHookCmdInit
)
{
IXposedHookCmdInit
.
StartupParam
param
=
new
IXposedHookCmdInit
.
StartupParam
();
param
.
modulePath
=
apk
;
param
.
startClassName
=
startClassName
;
((
IXposedHookCmdInit
)
moduleInstance
).
initCmdApp
(
param
);
}
}
}
catch
(
Throwable
t
)
{
Log
.
e
(
TAG
,
" Failed to load class "
+
moduleClassName
,
t
);
}
}
}
catch
(
IOException
e
)
{
Log
.
e
(
TAG
,
" Failed to load module from "
+
apk
,
e
);
}
finally
{
closeSilently
(
is
);
closeSilently
(
zipFile
);
}
}
public
final
static
HashSet
<
String
>
loadedPackagesInProcess
=
new
HashSet
<>(
1
);
public
static
void
logD
(
String
prefix
)
{
Utils
.
logD
(
String
.
format
(
"%s: pkg=%s, prc=%s"
,
prefix
,
AndroidAppHelper
.
currentPackageName
(),
AndroidAppHelper
.
currentProcessName
()));
}
public
static
void
logE
(
String
prefix
,
Throwable
throwable
)
{
Utils
.
logE
(
String
.
format
(
"%s: pkg=%s, prc=%s"
,
prefix
,
AndroidAppHelper
.
currentPackageName
(),
AndroidAppHelper
.
currentProcessName
()),
throwable
);
}
//
private static final String TAG = XposedBridge.TAG;
//
private static boolean startsSystemServer = false;
//
private static final String startClassName = ""; // ed: no support for tool process anymore
//
//
public static final String INSTALLER_PACKAGE_NAME = "com.solohsu.android.edxp.manager";
//
public static final String INSTALLER_LEGACY_PACKAGE_NAME = "de.robv.android.xposed.installer";
//
@SuppressLint("SdCardPath")
//
public static final String INSTALLER_DATA_BASE_DIR = Build.VERSION.SDK_INT >= 24
//
? "/data/user_de/0/" + INSTALLER_PACKAGE_NAME + "/"
//
: "/data/data/" + INSTALLER_PACKAGE_NAME + "/";
//
private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication";
//
// TODO not supported yet
//
private static boolean disableResources = true;
//
private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"};
//
//
private XposedInit() {
//
}
//
//
private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false);
//
//
/**
//
* Hook some methods which we want to create an easier interface for developers.
//
*/
//
/*package*/
//
public static void initForZygote(boolean isSystem) throws Throwable {
//
if (!bootstrapHooked.compareAndSet(false, true)) {
//
return;
//
}
//
startsSystemServer = isSystem;
//
Router.startBootstrapHook(isSystem);
//
// MIUI
//
if (findFieldIfExists(ZygoteInit.class, "BOOT_START_TIME") != null) {
//
setStaticLongField(ZygoteInit.class, "BOOT_START_TIME", XposedBridge.BOOT_START_TIME);
//
}
//
//
// Samsung
//
if (Build.VERSION.SDK_INT >= 24) {
//
Class<?> zygote = findClass("com.android.internal.os.Zygote", null);
//
try {
//
setStaticBooleanField(zygote, "isEnhancedZygoteASLREnabled", false);
//
} catch (NoSuchFieldError ignored) {
//
}
//
}
//
}
//
//
/*package*/
//
static void hookResources() throws Throwable {
//
// ed: not for now
//
}
//
//
private static boolean needsToCloseFilesForFork() {
//
// ed: we always start to do our work after forking finishes
//
return false;
//
}
//
//
/**
//
* Try to load all modules defined in <code>INSTALLER_DATA_BASE_DIR/conf/modules.list</code>
//
*/
//
private static volatile AtomicBoolean modulesLoaded = new AtomicBoolean(false);
//
//
public static void loadModules() throws IOException {
//
if (!modulesLoaded.compareAndSet(false, true)) {
//
return;
//
}
//
final String filename = INSTALLER_DATA_BASE_DIR + "conf/modules.list";
//
BaseService service = SELinuxHelper.getAppDataFileService();
//
if (!service.checkFileExists(filename)) {
//
Log.e(TAG, "Cannot load any modules because " + filename + " was not found");
//
return;
//
}
//
//
ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER;
//
ClassLoader parent;
//
while ((parent = topClassLoader.getParent()) != null) {
//
topClassLoader = parent;
//
}
//
//
InputStream stream = service.getFileInputStream(filename);
//
BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
//
String apk;
//
while ((apk = apks.readLine()) != null) {
//
loadModule(apk, topClassLoader);
//
}
//
apks.close();
//
}
//
//
//
/**
//
* Load a module from an APK by calling the init(String) method for all classes defined
//
* in <code>assets/xposed_init</code>.
//
*/
//
private static void loadModule(String apk, ClassLoader topClassLoader) {
//
if (BuildConfig.DEBUG)
//
Log.i(TAG, "Loading modules from " + apk);
//
//
if (!TextUtils.isEmpty(apk) && apk.contains(BLACK_LIST_PACKAGE_NAME)) {
//
if (BuildConfig.DEBUG)
//
Log.i(TAG, "We are going to take over black list's job...");
//
return;
//
}
//
//
if (!new File(apk).exists()) {
//
Log.e(TAG, " File does not exist");
//
return;
//
}
//
//
DexFile dexFile;
//
try {
//
dexFile = new DexFile(apk);
//
} catch (IOException e) {
//
Log.e(TAG, " Cannot load module", e);
//
return;
//
}
//
//
if (dexFile.loadClass(INSTANT_RUN_CLASS, topClassLoader) != null) {
//
Log.e(TAG, " Cannot load module, please disable \"Instant Run\" in Android Studio.");
//
closeSilently(dexFile);
//
return;
//
}
//
//
if (dexFile.loadClass(XposedBridge.class.getName(), topClassLoader) != null) {
//
Log.e(TAG, " Cannot load module:");
//
Log.e(TAG, " The Xposed API classes are compiled into the module's APK.");
//
Log.e(TAG, " This may cause strange issues and must be fixed by the module developer.");
//
Log.e(TAG, " For details, see: http://api.xposed.info/using.html");
//
closeSilently(dexFile);
//
return;
//
}
//
//
closeSilently(dexFile);
//
//
ZipFile zipFile = null;
//
InputStream is;
//
try {
//
zipFile = new ZipFile(apk);
//
ZipEntry zipEntry = zipFile.getEntry("assets/xposed_init");
//
if (zipEntry == null) {
//
Log.e(TAG, " assets/xposed_init not found in the APK");
//
closeSilently(zipFile);
//
return;
//
}
//
is = zipFile.getInputStream(zipEntry);
//
} catch (IOException e) {
//
Log.e(TAG, " Cannot read assets/xposed_init in the APK", e);
//
closeSilently(zipFile);
//
return;
//
}
//
//
ClassLoader mcl = new PathClassLoader(apk, XposedInit.class.getClassLoader());
//
BufferedReader moduleClassesReader = new BufferedReader(new InputStreamReader(is));
//
try {
//
String moduleClassName;
//
while ((moduleClassName = moduleClassesReader.readLine()) != null) {
//
moduleClassName = moduleClassName.trim();
//
if (moduleClassName.isEmpty() || moduleClassName.startsWith("#"))
//
continue;
//
//
try {
//
if (BuildConfig.DEBUG)
//
Log.i(TAG, " Loading class " + moduleClassName);
//
Class<?> moduleClass = mcl.loadClass(moduleClassName);
//
//
if (!IXposedMod.class.isAssignableFrom(moduleClass)) {
//
Log.e(TAG, " This class doesn't implement any sub-interface of IXposedMod, skipping it");
//
continue;
//
} else if (disableResources && IXposedHookInitPackageResources.class.isAssignableFrom(moduleClass)) {
//
Log.e(TAG, " This class requires resource-related hooks (which are disabled), skipping it.");
//
continue;
//
}
//
//
final Object moduleInstance = moduleClass.newInstance();
//
if (XposedBridge.isZygote) {
//
if (moduleInstance instanceof IXposedHookZygoteInit) {
//
IXposedHookZygoteInit.StartupParam param = new IXposedHookZygoteInit.StartupParam();
//
param.modulePath = apk;
//
param.startsSystemServer = startsSystemServer;
//
((IXposedHookZygoteInit) moduleInstance).initZygote(param);
//
}
//
//
if (moduleInstance instanceof IXposedHookLoadPackage)
//
XposedBridge.hookLoadPackage(new IXposedHookLoadPackage.Wrapper((IXposedHookLoadPackage) moduleInstance));
//
//
if (moduleInstance instanceof IXposedHookInitPackageResources)
//
XposedBridge.hookInitPackageResources(new IXposedHookInitPackageResources.Wrapper((IXposedHookInitPackageResources) moduleInstance));
//
} else {
//
if (moduleInstance instanceof IXposedHookCmdInit) {
//
IXposedHookCmdInit.StartupParam param = new IXposedHookCmdInit.StartupParam();
//
param.modulePath = apk;
//
param.startClassName = startClassName;
//
((IXposedHookCmdInit) moduleInstance).initCmdApp(param);
//
}
//
}
//
} catch (Throwable t) {
//
Log.e(TAG, " Failed to load class " + moduleClassName, t);
//
}
//
}
//
} catch (IOException e) {
//
Log.e(TAG, " Failed to load module from " + apk, e);
//
} finally {
//
closeSilently(is);
//
closeSilently(zipFile);
//
}
//
}
//
//
public final static HashSet<String> loadedPackagesInProcess = new HashSet<>(1);
//
//
public static void logD(String prefix) {
//
Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(),
//
AndroidAppHelper.currentProcessName()));
//
}
//
//
public static void logE(String prefix, Throwable throwable) {
//
Utils.logE(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(),
//
AndroidAppHelper.currentProcessName()), throwable);
//
}
}
xposedcompat/src/main/java/de/robv/android/xposed/callbacks/XC_InitPackageResources.java
View file @
3615f339
package
de
.
robv
.
android
.
xposed
.
callbacks
;
import
android.content.res.XResources
;
//
import android.content.res.XResources;
import
de.robv.android.xposed.IXposedHookInitPackageResources
;
import
de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet
;
...
...
@@ -45,7 +45,7 @@ public abstract class XC_InitPackageResources extends XCallback implements IXpos
* Reference to the resources that can be used for calls to
* {@link XResources#setReplacement(String, String, String, Object)}.
*/
public
XResources
res
;
//
public XResources res;
}
/** @hide */
...
...
xposedcompat/src/main/java/de/robv/android/xposed/callbacks/XC_LayoutInflated.java
View file @
3615f339
package
de
.
robv
.
android
.
xposed
.
callbacks
;
import
android.content.res.XResources
;
import
android.content.res.XResources.ResourceNames
;
//
import android.content.res.XResources;
//
import android.content.res.XResources.ResourceNames;
import
android.view.View
;
import
de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet
;
...
...
@@ -41,13 +41,13 @@ public abstract class XC_LayoutInflated extends XCallback {
public
View
view
;
/** Container with the ID and name of the underlying resource. */
public
ResourceNames
resNames
;
//
public ResourceNames resNames;
/** Directory from which the layout was actually loaded (e.g. "layout-sw600dp"). */
public
String
variant
;
//
public String variant;
/** Resources containing the layout. */
public
XResources
res
;
//
public XResources res;
}
/** @hide */
...
...
@@ -92,7 +92,7 @@ public abstract class XC_LayoutInflated extends XCallback {
@Override
public
void
unhook
()
{
XResources
.
unhookLayout
(
resDir
,
id
,
XC_LayoutInflated
.
this
);
//
XResources.unhookLayout(resDir, id, XC_LayoutInflated.this);
}
}
...
...
xposedcompat/src/main/java/de/robv/android/xposed/callbacks/XC_LoadPackage.java
View file @
3615f339
...
...
@@ -2,6 +2,9 @@ package de.robv.android.xposed.callbacks;
import
android.content.pm.ApplicationInfo
;
import
com.swift.sandhook.xposedcompat.ProcessUtils
;
import
com.swift.sandhook.xposedcompat.XposedCompat
;
import
de.robv.android.xposed.IXposedHookLoadPackage
;
import
de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet
;
...
...
@@ -39,19 +42,19 @@ public abstract class XC_LoadPackage extends XCallback implements IXposedHookLoa
}
/** The name of the package being loaded. */
public
String
packageName
;
public
String
packageName
=
XposedCompat
.
context
.
getPackageName
()
;
/** The process in which the package is executed. */
public
String
processName
;
public
String
processName
=
ProcessUtils
.
getProcessName
(
XposedCompat
.
context
)
;
/** The ClassLoader used for this package. */
public
ClassLoader
classLoader
;
public
ClassLoader
classLoader
=
XposedCompat
.
classLoader
;
/** More information about the application being loaded. */
public
ApplicationInfo
appInfo
;
public
ApplicationInfo
appInfo
=
XposedCompat
.
context
.
getApplicationInfo
()
;
/** Set to {@code true} if this is the first (and main) application for this process. */
public
boolean
isFirstApplication
;
public
boolean
isFirstApplication
=
XposedCompat
.
isFirstApplication
;
}
/** @hide */
...
...
xposedcompat/src/main/java/de/robv/android/xposed/services/BinderService.java
View file @
3615f339
...
...
@@ -3,7 +3,7 @@ package de.robv.android.xposed.services;
import
android.os.IBinder
;
import
android.os.Parcel
;
import
android.os.RemoteException
;
import
android.os.ServiceManager
;
//
import android.os.ServiceManager;
import
java.io.IOException
;
...
...
@@ -158,7 +158,7 @@ public final class BinderService extends BaseService {
private
final
IBinder
mRemote
;
private
BinderService
(
int
target
)
{
IBinder
binder
=
ServiceManager
.
getService
(
SERVICE_NAMES
[
target
]);
IBinder
binder
=
null
;
//
ServiceManager.getService(SERVICE_NAMES[target]);
if
(
binder
==
null
)
throw
new
IllegalStateException
(
"Service "
+
SERVICE_NAMES
[
target
]
+
" does not exist"
);
this
.
mRemote
=
binder
;
...
...
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