一个通用多功能的 Xposed
隐藏器,采用 Native
与 Java
结合来做到双向屏蔽检测,提供高度自由化为每个应用配置不同属性。它不仅仅局限于屏蔽 Xposed
检测,还提供更多更加高级的功能,如 maps
文件自定义屏蔽各种检测、完整的文件重定向功能、访问权限控制、JNI
方法监控、动态符号查找屏蔽 dlsym
等等,还可以提供给其它模块在进程内动态添加或修改配置。开源地址 https://github.com/sanfengAndroid/FakeXposed 目前问题还较多不够稳定,欢迎加群讨论
Java
调用 System.getenv()
、System.getenv(String)
源码如下
其最终调用两个函数 Libcore.os.environ()
、Libcore.os.getenv(String)
不同版本 Libcore.os
的实现对象类名不一样,但是区别很小,而 native
中访问到是 libc 导出变量 environ
、导出函数 getenv
,因此通过 Native Hook
拦截 getenv
函数即可拦截对应 Java System.getenv(String)
调用,而 System.getenv()
调用是直接使用 environ
变量,因此暂时采用Java Hook
替换该Map
对象,通常情况下应用是很少使用到 System.getenv
非系统环境变量的,一些软件检测才会使用,因此后续可能会直接修改 environ
变量中的值
Java
反射使用 SystemProperties.get
系列方法
调用 android_os_SystemProperties.cpp 中的方法
而它调用了 libc.so
中的 __system_property_find
,__system_property_read_callback
,在低版本中获取属性也使用到了 __system_property_get
方法,因此采用 Native Hook
以上这三个方法,这里也要注意不同版本在不同动态库中实现
根据代码位置猜测,或者直接在 maps
文件里面查找哪些已经加载的可疑的库,目前查找到系统有关的库包含如下几个
如果有遗漏的库可以调用 NativeHook.relinkLibrary()
重新重定位该库
查看 FakeXposed 说明文档
static volatile IPackageManager sPackageManager;
public static IPackageManager getPackageManager() {
if
(sPackageManager !
=
null) {
return
sPackageManager;
}
final IBinder b
=
ServiceManager.getService(
"package"
);
sPackageManager
=
IPackageManager.Stub.asInterface(b);
return
sPackageManager;
}
static volatile IPackageManager sPackageManager;
public static IPackageManager getPackageManager() {
if
(sPackageManager !
=
null) {
return
sPackageManager;
}
final IBinder b
=
ServiceManager.getService(
"package"
);
sPackageManager
=
IPackageManager.Stub.asInterface(b);
return
sPackageManager;
}
private static final Singleton<IActivityManager> IActivityManagerSingleton
=
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b
=
ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am
=
IActivityManager.Stub.asInterface(b);
return
am;
}
};
private static final Singleton<IActivityManager> IActivityManagerSingleton
=
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b
=
ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am
=
IActivityManager.Stub.asInterface(b);
return
am;
}
};
public static java.util.
Map
<String,String> getenv() {
SecurityManager sm
=
getSecurityManager();
if
(sm !
=
null) {
sm.checkPermission(new RuntimePermission(
"getenv.*"
));
}
return
ProcessEnvironment.getenv();
}
public static String getenv(String name) {
if
(name
=
=
null) {
throw new NullPointerException(
"name == null"
);
}
return
Libcore.os.getenv(name);
}
public static java.util.
Map
<String,String> getenv() {
SecurityManager sm
=
getSecurityManager();
if
(sm !
=
null) {
sm.checkPermission(new RuntimePermission(
"getenv.*"
));
}
return
ProcessEnvironment.getenv();
}
public static String getenv(String name) {
if
(name
=
=
null) {
throw new NullPointerException(
"name == null"
);
}
return
Libcore.os.getenv(name);
}
public final
class
Libcore {
private Libcore() { }
public static final Os rawOs
=
new Linux();
public static volatile Os os
=
new BlockGuardOs(rawOs);
...
}
public final
class
Linux implements Os {
Linux() { }
public native String getenv(String name);
public native String[] environ();
...
}
public final
class
Libcore {
private Libcore() { }
public static final Os rawOs
=
new Linux();
public static volatile Os os
=
new BlockGuardOs(rawOs);
...
}
public final
class
Linux implements Os {
Linux() { }
public native String getenv(String name);
public native String[] environ();
...
}
@NonNull
@SystemApi
public static String get(@NonNull String key, @Nullable String
def
) {
if
(TRACK_KEY_ACCESS) onKeyAccess(key);
return
native_get(key,
def
);
}
...
@FastNative
@UnsupportedAppUsage
(maxTargetSdk
=
Build.VERSION_CODES.P)
private static native String native_get(String key, String
def
);
@NonNull
@SystemApi
public static String get(@NonNull String key, @Nullable String
def
) {
if
(TRACK_KEY_ACCESS) onKeyAccess(key);
return
native_get(key,
def
);
}
...
@FastNative
@UnsupportedAppUsage
(maxTargetSdk
=
Build.VERSION_CODES.P)
private static native String native_get(String key, String
def
);
template<typename Functor>
void ReadProperty(const prop_info
*
prop, Functor&& functor)
{
auto thunk
=
[](void
*
cookie,
const char
*
/
*
name
*
/
,
const char
*
value,
uint32_t
/
*
serial
*
/
) {
std::forward<Functor>(
*
static_cast<Functor
*
>(cookie))(value);
};
__system_property_read_callback(prop, thunk, &functor);
LOG(FATAL) <<
"fast property access supported only on device"
;
}
template<typename Functor>
void ReadProperty(JNIEnv
*
env, jstring keyJ, Functor&& functor)
{
ScopedUtfChars key(env, keyJ);
if
(!key.c_str()) {
return
;
}
const prop_info
*
prop
=
__system_property_find(key.c_str());
if
(!prop) {
return
;
}
ReadProperty(prop, std::forward<Functor>(functor));
std::forward<Functor>(functor)(
android::base::GetProperty(key.c_str(), "").c_str());
}
jstring SystemProperties_getSS(JNIEnv
*
env, jclass clazz, jstring keyJ,
jstring defJ)
{
jstring ret
=
defJ;
ReadProperty(env, keyJ, [&](const char
*
value) {
if
(value[
0
]) {
ret
=
env
-
>NewStringUTF(value);
}
});
if
(ret
=
=
nullptr && !env
-
>ExceptionCheck()) {
ret
=
env
-
>NewStringUTF("");
/
/
Legacy behavior
}
return
ret;
}
int
register_android_os_SystemProperties(JNIEnv
*
env)
{
const JNINativeMethod method_table[]
=
{
{
"native_get"
,
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"
,
(void
*
) SystemProperties_getSS },
{
"native_get_int"
,
"(Ljava/lang/String;I)I"
,
(void
*
) SystemProperties_get_integral<jint> },
{
"native_get_long"
,
"(Ljava/lang/String;J)J"
,
(void
*
) SystemProperties_get_integral<jlong> },
{
"native_get_boolean"
,
"(Ljava/lang/String;Z)Z"
,
(void
*
) SystemProperties_get_boolean },
{
"native_find"
,
"(Ljava/lang/String;)J"
,
(void
*
) SystemProperties_find },
{
"native_get"
,
"(J)Ljava/lang/String;"
,
(void
*
) SystemProperties_getH },
{
"native_get_int"
,
"(JI)I"
,
(void
*
) SystemProperties_get_integralH<jint> },
{
"native_get_long"
,
"(JJ)J"
,
(void
*
) SystemProperties_get_integralH<jlong> },
{
"native_get_boolean"
,
"(JZ)Z"
,
(void
*
) SystemProperties_get_booleanH },
{
"native_set"
,
"(Ljava/lang/String;Ljava/lang/String;)V"
,
(void
*
) SystemProperties_set },
{
"native_add_change_callback"
,
"()V"
,
(void
*
) SystemProperties_add_change_callback },
{
"native_report_sysprop_change"
,
"()V"
,
(void
*
) SystemProperties_report_sysprop_change },
};
return
RegisterMethodsOrDie(env,
"android/os/SystemProperties"
,
method_table, NELEM(method_table));
}
template<typename Functor>
void ReadProperty(const prop_info
*
prop, Functor&& functor)
{
auto thunk
=
[](void
*
cookie,
const char
*
/
*
name
*
/
,
const char
*
value,
uint32_t
/
*
serial
*
/
) {
std::forward<Functor>(
*
static_cast<Functor
*
>(cookie))(value);
};
__system_property_read_callback(prop, thunk, &functor);
LOG(FATAL) <<
"fast property access supported only on device"
;
}
template<typename Functor>
void ReadProperty(JNIEnv
*
env, jstring keyJ, Functor&& functor)
{
ScopedUtfChars key(env, keyJ);
if
(!key.c_str()) {
return
;
}
const prop_info
*
prop
=
__system_property_find(key.c_str());
if
(!prop) {
return
;
}
ReadProperty(prop, std::forward<Functor>(functor));
std::forward<Functor>(functor)(
android::base::GetProperty(key.c_str(), "").c_str());
}
jstring SystemProperties_getSS(JNIEnv
*
env, jclass clazz, jstring keyJ,
jstring defJ)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-2-23 12:48
被北辰制作编辑
,原因: 添加问题说明