在我是萌新的时候--2022年,遇到我无法逾越的强敌! 某加固校验! 在那时候 内心就埋下的仇恨的种子! 从那时开始 熟读百家文章,从基础做起,先开发,后逆向。
这里 通过 如果 我直接hook getPackageInfo() 使他返回我们包装的packageInfo 不就解决了?
但是 我想了解 整个过程。
平时逆向分析 都是 通过hook 关键函数 打印堆栈 不就知道流程?
说干就干
我们在安卓源码找到 PackageInfo 的构造函数 直接 用xposed hook就完事了
hook代码:
打印的堆栈:
从堆栈来讲 ,我 hook 上面任何一种方法 都可以 对 签名信息进行替换 达到去签名的效果
这里 是我们java层的理论基础!!
MT 去除签名校验--https://github.com/L-JINBIN/ApkSignatureKillerEx
关键代码:
这个代码的功能就是 使用反射 替换 CREATOR 变量 而体现出来的 就是 : hook createFromParcel 这个方法 从而替换了签名信息
而从上面我说所的基础 体现出来 确实存在 createFromParcel 这个方法。而且在距离 构造函数很近 真是感叹前辈 技术的精妙!
然后对 libc进行 open相关的函数进行hook
就很轻松的实现了 对文件的io重定向
还有高手? 对的
LSPatch 打包 也是 很强的!
https://github.com/LSPosed/LSPatch/blob/master/patch-loader/src/main/java/org/lsposed/lspatch/loader/SigBypass.java
关键代码 :
有木有发现相同的方式? 都是对 CREATOR 这个变量进行替换 达到 hook createFromParcel 这个方法目的 代码写的是相当优雅 反射替换 稳定性相当高!
然后对so层进行 io重定向
也是 对 libc.so的 hook open相关的函数 实现io重定向
去签名校验的流程 了解的很清楚。
我们破坏或者检测 这里面的任何流程 去签就失效了
对本地的apk的签名文件进行检测
这个方式对 mt的去签名方式 在不同的安卓系统里有不一样的效果,因为 io重定向 诡异的失效了
原因可以看这篇文章 : https://bbs.kanxue.com/thread-278195.htm
对于某些去签名方式 他们会对application 进行替换
这里我们可以获取 application 然后对application 进行一些判断
这里使用更深入的的方式 获取 Application 当然 还有更深入的方式 : 比如 反射 LoadedApk 获取唯一单例的Application 更为底层 但是考虑到 安卓版本的兼容性 这里就 这样 获取了
对application 进行一些简单的判断 当然 你可以继续深入!!!
这里就完成的对 apk入口的简单判断
在mt去签名的早期版本 是对 mPM 进行的替换
这里顺便写一个吧 顺便检测了
当然 在一定程度上 可以 检测 是否在虚拟环境 毕竟virtrualapp的老版本 也是 通过 反射hook 进行多开的
前面说的 都是对付老版本的方法
现在 分析 刚刚 我们 看到的去签名方式 , 针对性的分析 可以得到
我们 的目标 就是 检测 Creator 是否被替换
https://bbs.kanxue.com/thread-277402.htm#%E6%A3%80%E6%B5%8Bcreator%E6%98%AF%E5%90%A6%E8%A2%AB%E6%9B%BF%E6%8D%A2
这里 大佬珍惜 分享出 比较 classloader 的属性 来判断
但我测试发现 好像 lsp的去签名方式 检测不出来
没关系 ,我们继往圣之绝学,继续拓展
通过珍惜大佬的思路 判断的就是 CREATOR 是否被改变---- 那么 任何细微的差距都可
我在这演示一点 剩下的交给后来人吧 !
这里我们 就获取的CREATOR 的类名 如果不一样就被替换了
当然 如果被hook了呢?
一般去签名的软件是不会对 对app进行 大量的hook
如果这个被 hook 了 那我们 反射 获取其他属性
这样 lsp打包的apk就被我们 anti了
此外,我们继续深耕
我们是否可以在内存中对我们的代码进行检验呢?
答案是可以 我早在以前就发了一篇关于内存校验的帖子 ,但是那时候 的方式被大佬吐槽,确实 只能在debug版本才生效
那篇帖子地址:https://bbs.kanxue.com/thread-282315.htm
现在我继续 探究这种方式
从安卓源码classloader加载的方式 我们获取app自身加载的dex
对dex 进行检测
我在这个过程中也遇到很多的问题 当然 被解决啦!
这里的环境 为 : 安卓12 其他版本 我不保证兼容性哈!
第一个问题 就是 安卓的反射限制
这里抄的看雪论坛里一篇大佬的代码
通过 so加载 解除反射限制后
反射获取 dex 代码的位置
然后在jni中获取地址
在这个过程中 我获取的地址 是dexfile的地址 他的成员变量指向dex
所以 对获取指针+1 就是dex在内存中的地址了 (这个问题困惑了我一晚上!!!!!)
到这里 其实我做的并不完善 你可以 动态的对内存进行crc校验 而我这只获取了 dex的头文件的值
当然 你有其他其实妙想可以一起交流!
这里测试 np的最强过签名 FancyBpysss
还好 ! 确实是检测出来了 !(不然 研究这麽久 连一键去签名都没过 有点 没面子 哈哈哈)
然后观察有些去签名方式 修改的是AppComponentFactory 来进行初始化hook
那么我们来进行检测这个也可以的
这里只做简单的判断 未深入 (有代码的兄弟 可以在下面发出来 给大伙乐呵乐呵 )
剩下 svc的部分 珍惜大佬已经讲的太清楚了
https://bbs.kanxue.com/thread-278982.htm
熟读 珍惜大佬的文章 !!!如果你看完还是不太清楚 可以买大佬的网课 补补基础嘛。
svc部分的代码:
这里 就基本完成了 app的签名校验,欢迎大佬 分享新的角度 新的思路 一起进步!
这里懒得用自己实现的svc了
第一 io重定向 :
https://bbs.kanxue.com/thread-273160.htm
https://bbs.kanxue.com/thread-285339-1.htm
这里的理论基础 很好!熟读 即可实现 对open相关的svc hook
第二 Creator的检测:
由于hook的实现都是由 代理的方式 替换的,会留下很多的痕迹。
最好进行 入侵式hook (类似 xposed ) 就不会检测出来了
做好这些 基本就实现 比较完美的去签名
通过这些理论知识 我将 mt开源的去签名方式 进行 修改 实现的svc的hook
对 22年的360加固进行 测试
完成了 去签名 ! 也算是 对22年那时候的我一个满意的答复!
工具实现了svc 的hook 未对 Creator 进行隐藏 进行去签名 会卡一会儿 完成后 在 download 目录里。 工具无法上传,放在github里了:https://github.com/ywl20020421/-AndroidReverse/tree/main/%E7%AD%BE%E5%90%8D%E6%A0%A1%E9%AA%8C%E7%9B%B8%E5%85%B3
另外 附上 我编写的签名检验 app 未混淆 大家可以反编译 我希望大家能使用自己编写的去签名软件 过掉它 而不是 修改显示的ui。
最后 我还有问题想求教大佬们: 基于SECCOMP的SVC指令拦截,如何实现仿真? 如何对svc 指令hook的检测?
private
boolean doNormalSignCheck() {
String trueSignMD5 =
"7d1e7be834bb349eb0694c524353ba3c"
;
String nowSignMD5 =
""
;
try
{
PackageInfo packageInfo = getPackageManager().getPackageInfo(
getPackageName(),
PackageManager.GET_SIGNATURES);
Signature[] signs = packageInfo.signatures;
if
(signs != null && signs.length > 0) {
byte[] signature = signs[0].toByteArray();
String signBase64 = Base64.encodeToString(signature, Base64.DEFAULT).trim();
nowSignMD5 = md5(signBase64);
Log.d(TAG,
"doNormalSignCheck: "
+ nowSignMD5);
}
}
catch
(PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return
trueSignMD5.equals(nowSignMD5);
}
private
boolean doNormalSignCheck() {
String trueSignMD5 =
"7d1e7be834bb349eb0694c524353ba3c"
;
String nowSignMD5 =
""
;
try
{
PackageInfo packageInfo = getPackageManager().getPackageInfo(
getPackageName(),
PackageManager.GET_SIGNATURES);
Signature[] signs = packageInfo.signatures;
if
(signs != null && signs.length > 0) {
byte[] signature = signs[0].toByteArray();
String signBase64 = Base64.encodeToString(signature, Base64.DEFAULT).trim();
nowSignMD5 = md5(signBase64);
Log.d(TAG,
"doNormalSignCheck: "
+ nowSignMD5);
}
}
catch
(PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return
trueSignMD5.equals(nowSignMD5);
}
XposedHelpers.findAndHookConstructor(classLoader.loadClass(
"android.content.pm.PackageInfo"
),Parcel.
class
, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super
.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
dumpStackTrace();
super
.afterHookedMethod(param);
}
});
XposedHelpers.findAndHookConstructor(classLoader.loadClass(
"android.content.pm.PackageInfo"
),Parcel.
class
, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super
.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
dumpStackTrace();
super
.afterHookedMethod(param);
}
});
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageInfo
-
-
-
-
PackageInfo.java
-
-
-
-
29
-
-
-
-
<init>
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageInfo$
1
-
-
-
-
PackageInfo.java
-
-
-
-
519
-
-
-
-
createFromParcel
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageInfo$
1
-
-
-
-
PackageInfo.java
-
-
-
-
516
-
-
-
-
createFromParcel
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.IPackageManager$Stub$Proxy
-
-
-
-
IPackageManager.java
-
-
-
-
4901
-
-
-
-
getPackageInfo
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager
-
-
-
-
PackageManager.java
-
-
-
-
9207
-
-
-
-
getPackageInfoAsUserUncached
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager
-
-
-
-
PackageManager.java
-
-
-
-
113
-
-
-
-
access$
100
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager$
2
-
-
-
-
PackageManager.java
-
-
-
-
9220
-
-
-
-
recompute
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager$
2
-
-
-
-
PackageManager.java
-
-
-
-
9217
-
-
-
-
recompute
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.app.PropertyInvalidatedCache
-
-
-
-
PropertyInvalidatedCache.java
-
-
-
-
562
-
-
-
-
query
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager
-
-
-
-
PackageManager.java
-
-
-
-
9235
-
-
-
-
getPackageInfoAsUserCached
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.app.ApplicationPackageManager
-
-
-
-
ApplicationPackageManager.java
-
-
-
-
236
-
-
-
-
getPackageInfoAsUser
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.app.ApplicationPackageManager
-
-
-
-
ApplicationPackageManager.java
-
-
-
-
213
-
-
-
-
getPackageInfo
2025
-
02
-
19
11
:
46
:
25.629
22548
-
22548
风控 com.calvin.sigcheck I com.calvin.sigcheck.MainActivity
-
-
-
-
MainActivity.java
-
-
-
-
370
-
-
-
-
doNormalSignCheck
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageInfo
-
-
-
-
PackageInfo.java
-
-
-
-
29
-
-
-
-
<init>
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageInfo$
1
-
-
-
-
PackageInfo.java
-
-
-
-
519
-
-
-
-
createFromParcel
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageInfo$
1
-
-
-
-
PackageInfo.java
-
-
-
-
516
-
-
-
-
createFromParcel
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.IPackageManager$Stub$Proxy
-
-
-
-
IPackageManager.java
-
-
-
-
4901
-
-
-
-
getPackageInfo
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager
-
-
-
-
PackageManager.java
-
-
-
-
9207
-
-
-
-
getPackageInfoAsUserUncached
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager
-
-
-
-
PackageManager.java
-
-
-
-
113
-
-
-
-
access$
100
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager$
2
-
-
-
-
PackageManager.java
-
-
-
-
9220
-
-
-
-
recompute
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager$
2
-
-
-
-
PackageManager.java
-
-
-
-
9217
-
-
-
-
recompute
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.app.PropertyInvalidatedCache
-
-
-
-
PropertyInvalidatedCache.java
-
-
-
-
562
-
-
-
-
query
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.content.pm.PackageManager
-
-
-
-
PackageManager.java
-
-
-
-
9235
-
-
-
-
getPackageInfoAsUserCached
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.app.ApplicationPackageManager
-
-
-
-
ApplicationPackageManager.java
-
-
-
-
236
-
-
-
-
getPackageInfoAsUser
2025
-
02
-
19
11
:
46
:
25.628
22548
-
22548
风控 com.calvin.sigcheck I android.app.ApplicationPackageManager
-
-
-
-
ApplicationPackageManager.java
-
-
-
-
213
-
-
-
-
getPackageInfo
2025
-
02
-
19
11
:
46
:
25.629
22548
-
22548
风控 com.calvin.sigcheck I com.calvin.sigcheck.MainActivity
-
-
-
-
MainActivity.java
-
-
-
-
370
-
-
-
-
doNormalSignCheck
private static void killPM(String packageName, String signatureData) {
Signature fakeSignature
=
new Signature(Base64.decode(signatureData, Base64.DEFAULT));
Parcelable.Creator<PackageInfo> originalCreator
=
PackageInfo.CREATOR;
Parcelable.Creator<PackageInfo> creator
=
new Parcelable.Creator<PackageInfo>() {
@Override
public PackageInfo createFromParcel(Parcel source) {
PackageInfo packageInfo
=
originalCreator.createFromParcel(source);
if
(packageInfo.packageName.equals(packageName)) {
if
(packageInfo.signatures !
=
null && packageInfo.signatures.length >
0
) {
packageInfo.signatures[
0
]
=
fakeSignature;
}
if
(Build.VERSION.SDK_INT >
=
Build.VERSION_CODES.P) {
if
(packageInfo.signingInfo !
=
null) {
Signature[] signaturesArray
=
packageInfo.signingInfo.getApkContentsSigners();
if
(signaturesArray !
=
null && signaturesArray.length >
0
) {
signaturesArray[
0
]
=
fakeSignature;
}
}
}
}
return
packageInfo;
}
@Override
public PackageInfo[] newArray(
int
size) {
return
originalCreator.newArray(size);
}
};
try
{
findField(PackageInfo.
class
,
"CREATOR"
).
set
(null, creator);
} catch (Exception e) {
throw new RuntimeException(e);
}
if
(Build.VERSION.SDK_INT >
=
Build.VERSION_CODES.P) {
HiddenApiBypass.addHiddenApiExemptions(
"Landroid/os/Parcel;"
,
"Landroid/content/pm"
,
"Landroid/app"
);
}
try
{
Object
cache
=
findField(PackageManager.
class
,
"sPackageInfoCache"
).get(null);
/
/
noinspection ConstantConditions
cache.getClass().getMethod(
"clear"
).invoke(cache);
} catch (Throwable ignored) {
}
try
{
Map
<?, ?> mCreators
=
(
Map
<?, ?>) findField(Parcel.
class
,
"mCreators"
).get(null);
/
/
noinspection ConstantConditions
mCreators.clear();
} catch (Throwable ignored) {
}
try
{
Map
<?, ?> sPairedCreators
=
(
Map
<?, ?>) findField(Parcel.
class
,
"sPairedCreators"
).get(null);
/
/
noinspection ConstantConditions
sPairedCreators.clear();
} catch (Throwable ignored) {
}
}
private static void killPM(String packageName, String signatureData) {
Signature fakeSignature
=
new Signature(Base64.decode(signatureData, Base64.DEFAULT));
Parcelable.Creator<PackageInfo> originalCreator
=
PackageInfo.CREATOR;
Parcelable.Creator<PackageInfo> creator
=
new Parcelable.Creator<PackageInfo>() {
@Override
public PackageInfo createFromParcel(Parcel source) {
PackageInfo packageInfo
=
originalCreator.createFromParcel(source);
if
(packageInfo.packageName.equals(packageName)) {
if
(packageInfo.signatures !
=
null && packageInfo.signatures.length >
0
) {
packageInfo.signatures[
0
]
=
fakeSignature;
}
if
(Build.VERSION.SDK_INT >
=
Build.VERSION_CODES.P) {
if
(packageInfo.signingInfo !
=
null) {
Signature[] signaturesArray
=
packageInfo.signingInfo.getApkContentsSigners();
if
(signaturesArray !
=
null && signaturesArray.length >
0
) {
signaturesArray[
0
]
=
fakeSignature;
}
}
}
}
return
packageInfo;
}
@Override
public PackageInfo[] newArray(
int
size) {
return
originalCreator.newArray(size);
}
};
try
{
findField(PackageInfo.
class
,
"CREATOR"
).
set
(null, creator);
} catch (Exception e) {
throw new RuntimeException(e);
}
if
(Build.VERSION.SDK_INT >
=
Build.VERSION_CODES.P) {
HiddenApiBypass.addHiddenApiExemptions(
"Landroid/os/Parcel;"
,
"Landroid/content/pm"
,
"Landroid/app"
);
}
try
{
Object
cache
=
findField(PackageManager.
class
,
"sPackageInfoCache"
).get(null);
/
/
noinspection ConstantConditions
cache.getClass().getMethod(
"clear"
).invoke(cache);
} catch (Throwable ignored) {
}
try
{
Map
<?, ?> mCreators
=
(
Map
<?, ?>) findField(Parcel.
class
,
"mCreators"
).get(null);
/
/
noinspection ConstantConditions
mCreators.clear();
} catch (Throwable ignored) {
}
try
{
Map
<?, ?> sPairedCreators
=
(
Map
<?, ?>) findField(Parcel.
class
,
"sPairedCreators"
).get(null);
/
/
noinspection ConstantConditions
sPairedCreators.clear();
} catch (Throwable ignored) {
}
}
JNIEXPORT void JNICALL
Java_bin_mt_signature_KillerApplication_hookApkPath(JNIEnv
*
env, __attribute__((unused)) jclass clazz, jstring apkPath, jstring repPath) {
apkPath__
=
(
*
env)
-
>GetStringUTFChars(env, apkPath,
0
);
repPath__
=
(
*
env)
-
>GetStringUTFChars(env, repPath,
0
);
xhook_register(
".*\\.so$"
,
"openat64"
, openat64Impl, (void
*
*
) &old_openat64);
xhook_register(
".*\\.so$"
,
"openat"
, openatImpl, (void
*
*
) &old_openat);
xhook_register(
".*\\.so$"
,
"open64"
, open64Impl, (void
*
*
) &old_open64);
xhook_register(
".*\\.so$"
,
"open"
, openImpl, (void
*
*
) &old_open);
xhook_refresh(
0
);
}
JNIEXPORT void JNICALL
Java_bin_mt_signature_KillerApplication_hookApkPath(JNIEnv
*
env, __attribute__((unused)) jclass clazz, jstring apkPath, jstring repPath) {
apkPath__
=
(
*
env)
-
>GetStringUTFChars(env, apkPath,
0
);
repPath__
=
(
*
env)
-
>GetStringUTFChars(env, repPath,
0
);
xhook_register(
".*\\.so$"
,
"openat64"
, openat64Impl, (void
*
*
) &old_openat64);
xhook_register(
".*\\.so$"
,
"openat"
, openatImpl, (void
*
*
) &old_openat);
xhook_register(
".*\\.so$"
,
"open64"
, open64Impl, (void
*
*
) &old_open64);
xhook_register(
".*\\.so$"
,
"open"
, openImpl, (void
*
*
) &old_open);
xhook_refresh(
0
);
}
private static void proxyPackageInfoCreator(Context context) {
Parcelable.Creator<PackageInfo> originalCreator
=
PackageInfo.CREATOR;
Parcelable.Creator<PackageInfo> proxiedCreator
=
new Parcelable.Creator<>() {
@Override
public PackageInfo createFromParcel(Parcel source) {
PackageInfo packageInfo
=
originalCreator.createFromParcel(source);
replaceSignature(context, packageInfo);
return
packageInfo;
}
@Override
public PackageInfo[] newArray(
int
size) {
return
originalCreator.newArray(size);
}
};
XposedHelpers.setStaticObjectField(PackageInfo.
class
,
"CREATOR"
, proxiedCreator);
try
{
Map
<?, ?> mCreators
=
(
Map
<?, ?>) XposedHelpers.getStaticObjectField(Parcel.
class
,
"mCreators"
);
mCreators.clear();
} catch (NoSuchFieldError ignore) {
} catch (Throwable e) {
Log.w(TAG,
"fail to clear Parcel.mCreators"
, e);
}
try
{
Map
<?, ?> sPairedCreators
=
(
Map
<?, ?>) XposedHelpers.getStaticObjectField(Parcel.
class
,
"sPairedCreators"
);
sPairedCreators.clear();
} catch (NoSuchFieldError ignore) {
} catch (Throwable e) {
Log.w(TAG,
"fail to clear Parcel.sPairedCreators"
, e);
}
}
private static void proxyPackageInfoCreator(Context context) {
Parcelable.Creator<PackageInfo> originalCreator
=
PackageInfo.CREATOR;
Parcelable.Creator<PackageInfo> proxiedCreator
=
new Parcelable.Creator<>() {
@Override
public PackageInfo createFromParcel(Parcel source) {
PackageInfo packageInfo
=
originalCreator.createFromParcel(source);
replaceSignature(context, packageInfo);
return
packageInfo;
}
@Override
public PackageInfo[] newArray(
int
size) {
return
originalCreator.newArray(size);
}
};
XposedHelpers.setStaticObjectField(PackageInfo.
class
,
"CREATOR"
, proxiedCreator);
try
{
Map
<?, ?> mCreators
=
(
Map
<?, ?>) XposedHelpers.getStaticObjectField(Parcel.
class
,
"mCreators"
);
mCreators.clear();
} catch (NoSuchFieldError ignore) {
} catch (Throwable e) {
Log.w(TAG,
"fail to clear Parcel.mCreators"
, e);
}
try
{
Map
<?, ?> sPairedCreators
=
(
Map
<?, ?>) XposedHelpers.getStaticObjectField(Parcel.
class
,
"sPairedCreators"
);
sPairedCreators.clear();
} catch (NoSuchFieldError ignore) {
} catch (Throwable e) {
Log.w(TAG,
"fail to clear Parcel.sPairedCreators"
, e);
}
}
LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath, jstring cacheApkPath) {
auto sym_openat
=
SandHook::ElfImg(
"libc.so"
).getSymbAddress<void
*
>(
"__openat"
);
auto r
=
HookSymNoHandle(handler, sym_openat, __openat);
if
(!r) {
LOGE(
"Hook __openat fail"
);
return
;
}
lsplant::JUTFString str1(env, origApkPath);
lsplant::JUTFString str2(env, cacheApkPath);
apkPath
=
str1.get();
redirectPath
=
str2.get();
LOGD(
"apkPath %s"
, apkPath.c_str());
LOGD(
"redirectPath %s"
, redirectPath.c_str());
}
LSP_DEF_NATIVE_METHOD(void, SigBypass, enableOpenatHook, jstring origApkPath, jstring cacheApkPath) {
auto sym_openat
=
SandHook::ElfImg(
"libc.so"
).getSymbAddress<void
*
>(
"__openat"
);
auto r
=
HookSymNoHandle(handler, sym_openat, __openat);
if
(!r) {
LOGE(
"Hook __openat fail"
);
return
;
}
lsplant::JUTFString str1(env, origApkPath);
lsplant::JUTFString str2(env, cacheApkPath);
apkPath
=
str1.get();
redirectPath
=
str2.get();
LOGD(
"apkPath %s"
, apkPath.c_str());
LOGD(
"redirectPath %s"
, redirectPath.c_str());
}
private byte[] signatureFromAPK() {
try
(ZipFile zipFile
=
new ZipFile(getPackageResourcePath())) {
Enumeration<? extends ZipEntry> entries
=
zipFile.entries();
while
(entries.hasMoreElements()) {
ZipEntry entry
=
entries.nextElement();
if
(entry.getName().matches(
"(META-INF/.*)\\.(RSA|DSA|EC)"
)) {
InputStream
is
=
zipFile.getInputStream(entry);
CertificateFactory certFactory
=
CertificateFactory.getInstance(
"X509"
);
X509Certificate x509Cert
=
(X509Certificate) certFactory.generateCertificate(
is
);
return
x509Cert.getEncoded();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return
null;
}
private byte[] signatureFromAPK() {
try
(ZipFile zipFile
=
new ZipFile(getPackageResourcePath())) {
Enumeration<? extends ZipEntry> entries
=
zipFile.entries();
while
(entries.hasMoreElements()) {
ZipEntry entry
=
entries.nextElement();
if
(entry.getName().matches(
"(META-INF/.*)\\.(RSA|DSA|EC)"
)) {
InputStream
is
=
zipFile.getInputStream(entry);
CertificateFactory certFactory
=
CertificateFactory.getInstance(
"X509"
);
X509Certificate x509Cert
=
(X509Certificate) certFactory.generateCertificate(
is
);
return
x509Cert.getEncoded();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return
null;
}
public Application getmyApplication() {
Class<?> aaaaaaa
=
null;
try
{
aaaaaaa
=
Class.forName(
"android.app.ActivityThread"
);
Method currentActivityThreadMethod
=
aaaaaaa.getDeclaredMethod(
"currentActivityThread"
);
Object
activityThread
=
currentActivityThreadMethod.invoke(null);
Application application
=
(Application) getObjectField(activityThread,
"mInitialApplication"
);
Log.d(TAG,
"ActivityThread 获取 Application: "
+
application.getClass().getName());
return
application;
} catch (Exception e) {
Log.d(TAG,
"报错!: "
+
e.getMessage());
return
null;
}
}
public Application getmyApplication() {
Class<?> aaaaaaa
=
null;
try
{
aaaaaaa
=
Class.forName(
"android.app.ActivityThread"
);
Method currentActivityThreadMethod
=
aaaaaaa.getDeclaredMethod(
"currentActivityThread"
);
Object
activityThread
=
currentActivityThreadMethod.invoke(null);
Application application
=
(Application) getObjectField(activityThread,
"mInitialApplication"
);
Log.d(TAG,
"ActivityThread 获取 Application: "
+
application.getClass().getName());
return
application;
} catch (Exception e) {
Log.d(TAG,
"报错!: "
+
e.getMessage());
return
null;
}
}
private boolean checkApplication(){
Application nowApplication
=
getmyApplication();
String trueApplicationName
=
"com.calvin.sigcheck.MYapp"
;
String nowApplicationName
=
nowApplication.getClass().getName();
Log.d(TAG,
"checkApplication: "
+
trueApplicationName
+
" "
+
nowApplicationName);
return
trueApplicationName.equals(nowApplicationName);
}
private boolean checkApplication(){
Application nowApplication
=
getmyApplication();
String trueApplicationName
=
"com.calvin.sigcheck.MYapp"
;
String nowApplicationName
=
nowApplication.getClass().getName();
Log.d(TAG,
"checkApplication: "
+
trueApplicationName
+
" "
+
nowApplicationName);
return
trueApplicationName.equals(nowApplicationName);
}
private boolean checkPMProxy(){
String truePMName
=
"android.content.pm.IPackageManager$Stub$Proxy"
;
String nowPMName
=
"";
try
{
/
/
被代理的对象是 PackageManager.mPM
PackageManager packageManager
=
getPackageManager();
Field mPMField
=
packageManager.getClass().getDeclaredField(
"mPM"
);
mPMField.setAccessible(true);
Object
mPM
=
mPMField.get(packageManager);
/
/
取得类名
nowPMName
=
mPM.getClass().getName();
} catch (Exception e) {
e.printStackTrace();
}
/
/
类名改变说明被代理了
return
truePMName.equals(nowPMName);
}
private boolean checkPMProxy(){
String truePMName
=
"android.content.pm.IPackageManager$Stub$Proxy"
;
String nowPMName
=
"";
try
{
/
/
被代理的对象是 PackageManager.mPM
PackageManager packageManager
=
getPackageManager();
Field mPMField
=
packageManager.getClass().getDeclaredField(
"mPM"
);
mPMField.setAccessible(true);
Object
mPM
=
mPMField.get(packageManager);
/
/
取得类名
nowPMName
=
mPM.getClass().getName();
} catch (Exception e) {
e.printStackTrace();
}
/
/
类名改变说明被代理了
return
truePMName.equals(nowPMName);
}
private boolean checkCreator3(){
try
{
Field creatorField
=
PackageInfo.
class
.getField(
"CREATOR"
);
creatorField.setAccessible(true);
Object
creator
=
creatorField.get(null);
int
i
=
creator.hashCode();
Log.d(TAG,
"checkCreator3: hashcode :"
+
i);
if
(creator !
=
null) {
ClassLoader creatorClassloader
=
creator.getClass().getClassLoader();
ClassLoader sysClassloader
=
ClassLoader.getSystemClassLoader();
if
(creatorClassloader
=
=
null || sysClassloader
=
=
null) {
return
false;
}
/
/
系统的是bootclassloader
/
/
用户创建的都是pathclassloader
/
/
如果相等则认为系统的被替换
if
(sysClassloader.getClass().getName().
equals(creatorClassloader.getClass().getName())) {
return
false;
}
return
true;
}
} catch (Throwable e) {
Log.d(TAG,
"checkCreator3: "
+
e);
}
return
false;
}
private boolean checkCreator3(){
try
{
Field creatorField
=
PackageInfo.
class
.getField(
"CREATOR"
);
creatorField.setAccessible(true);
Object
creator
=
creatorField.get(null);
int
i
=
creator.hashCode();
Log.d(TAG,
"checkCreator3: hashcode :"
+
i);
if
(creator !
=
null) {
ClassLoader creatorClassloader
=
creator.getClass().getClassLoader();
ClassLoader sysClassloader
=
ClassLoader.getSystemClassLoader();
if
(creatorClassloader
=
=
null || sysClassloader
=
=
null) {
return
false;
}
/
/
系统的是bootclassloader
/
/
用户创建的都是pathclassloader
/
/
如果相等则认为系统的被替换
if
(sysClassloader.getClass().getName().
equals(creatorClassloader.getClass().getName())) {
return
false;
[注意]看雪招聘,专注安全领域的专业人才平台!
上传的附件: