首页
社区
课程
招聘
141
[原创]安卓签名校验-探讨
发表于: 2025-2-19 19:52 36876

[原创]安卓签名校验-探讨

2025-2-19 19:52
36876

在我是萌新的时候--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) { // 检查 signs 是否为空
            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) { // 检查 signs 是否为空
            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;

[注意]看雪招聘,专注安全领域的专业人才平台!

上传的附件:
收藏
免费 141
支持
分享
赞赏记录
参与人
雪币
留言
时间
mb_mzboxhri
谢谢你的细致分析,受益匪浅!
7分钟前
轻快笑着行
感谢你分享这么好的资源!
1天前
git_29583Bumchou
谢谢你的细致分析,受益匪浅!
1天前
Crack999
为你点赞!
2天前
看这是什么
你的帖子非常有用,感谢分享!
4天前
qqizai
期待更多优质内容的分享,论坛有你更精彩!
5天前
小向i小葵
感谢你的积极参与,期待更多精彩内容!
6天前
qqyspgj
+1
你的分享对大家帮助很大,非常感谢!
6天前
JaniQuiz
+1
你的分享对大家帮助很大,非常感谢!
2025-3-25 10:15
mb_hlgwcshl
感谢你的贡献,论坛因你而更加精彩!
2025-3-24 15:32
git_32619Wcisang
为你点赞!
2025-3-21 01:48
mb_hsscwjpz
感谢你的贡献,论坛因你而更加精彩!
2025-3-20 17:05
jygzyc
感谢你分享这么好的资源!
2025-3-20 11:03
sudaxx
非常支持你的观点!
2025-3-20 09:12
cppasm
感谢你的积极参与,期待更多精彩内容!
2025-3-19 15:43
Emtanling
为你点赞!
2025-3-19 15:17
mb_llhsilzj
为你点赞!
2025-3-19 14:39
mb_mbblqtaj
这个讨论对我很有帮助,谢谢!
2025-3-19 10:22
王麻子本人
+1
非常支持你的观点!
2025-3-17 17:59
UltraTC
感谢你的积极参与,期待更多精彩内容!
2025-3-17 10:24
yhock
感谢你的积极参与,期待更多精彩内容!
2025-3-17 09:40
mb_qecctkwn
感谢你的贡献,论坛因你而更加精彩!
2025-3-16 18:45
mb_xtmbgeth
你的帖子非常有用,感谢分享!
2025-3-16 17:46
龙飞雪
非常支持你的观点!
2025-3-15 09:01
PoisonousCat
谢谢你的细致分析,受益匪浅!
2025-3-15 00:30
mb_paxfeknx
期待更多优质内容的分享,论坛有你更精彩!
2025-3-14 16:54
git_18216java02014
你的帖子非常有用,感谢分享!
2025-3-13 20:52
Cillo
谢谢你的细致分析,受益匪浅!
2025-3-12 19:18
这个讨论对我很有帮助,谢谢!
2025-3-10 09:33
青头潜鸭
期待更多优质内容的分享,论坛有你更精彩!
2025-3-8 20:13
wx_ㅤ_683
感谢你分享这么好的资源!
2025-3-8 09:27
码小芹
感谢你的贡献,论坛因你而更加精彩!
2025-3-7 14:56
Javaer
感谢你的积极参与,期待更多精彩内容!
2025-3-7 00:07
mb_itwfugbn
感谢你分享这么好的资源!
2025-3-6 20:48
V1n3entS0ng
你的分享对大家帮助很大,非常感谢!
2025-3-6 19:40
carrys
感谢你的贡献,论坛因你而更加精彩!
2025-3-6 16:32
无事不觉
为你点赞!
2025-3-5 22:37
mb_fvplkqtf
非常支持你的观点!
2025-3-5 20:35
上网鱼
这个讨论对我很有帮助,谢谢!
2025-3-5 19:13
mb_nrdkziep
感谢你的积极参与,期待更多精彩内容!
2025-3-5 16:11
cubeeeee
感谢你的贡献,论坛因你而更加精彩!
2025-3-5 11:09
wx_春风十里
+1
感谢你分享这么好的资源!
2025-3-5 07:05
小黑瞳
这个讨论对我很有帮助,谢谢!
2025-3-4 21:19
0371
谢谢你的细致分析,受益匪浅!
2025-3-4 16:37
Amun
感谢你的积极参与,期待更多精彩内容!
2025-3-4 15:46
pop_m
+1
感谢你分享这么好的资源!
2025-3-4 15:31
AunCss
为你点赞!
2025-3-4 15:06
gamehack
感谢你的贡献,论坛因你而更加精彩!
2025-3-4 13:12
yichen115
感谢你的积极参与,期待更多精彩内容!
2025-3-4 12:39
马来
你的帖子非常有用,感谢分享!
2025-3-3 20:44
黄小黑
感谢你的积极参与,期待更多精彩内容!
2025-3-3 19:19
Ssssone
为你点赞!
2025-3-3 15:40
Editor
+1
感谢你分享这么好的资源!
2025-3-3 14:16
foenfeow
这个讨论对我很有帮助,谢谢!
2025-3-3 11:13
老小白
为你点赞!
2025-3-3 11:12
mb_nwflotoa
感谢你的贡献,论坛因你而更加精彩!
2025-3-2 03:35
风兮木晓
感谢你的贡献,论坛因你而更加精彩!
2025-3-1 22:21
Lupinus
感谢你的贡献,论坛因你而更加精彩!
2025-3-1 14:31
android菜鸡
你的帖子非常有用,感谢分享!
2025-3-1 10:08
KiHanahare
感谢你的贡献,论坛因你而更加精彩!
2025-3-1 02:48
泠潋
你的分享对大家帮助很大,非常感谢!
2025-3-1 01:05
GoKu123
感谢你的贡献,论坛因你而更加精彩!
2025-2-28 16:19
Lnju
感谢你的贡献,论坛因你而更加精彩!
2025-2-28 15:46
constant
谢谢你的细致分析,受益匪浅!
2025-2-28 10:56
mb_undccabr
为你点赞!
2025-2-28 08:59
mb_hdptcgkk
为你点赞!
2025-2-27 18:53
Ive_406746
非常支持你的观点!
2025-2-27 17:24
菱志漪
为你点赞!
2025-2-27 17:14
mb_mcubivlt
非常支持你的观点!
2025-2-27 13:53
mb_mddfhmcj
这个讨论对我很有帮助,谢谢!
2025-2-27 13:18
pannifushe
你的分享对大家帮助很大,非常感谢!
2025-2-27 01:29
xiaowaaa
你的帖子非常有用,感谢分享!
2025-2-26 22:40
马先越
非常支持你的观点!
2025-2-26 19:48
javaobject
这个讨论对我很有帮助,谢谢!
2025-2-26 18:34
星落噜啦啦
感谢你的积极参与,期待更多精彩内容!
2025-2-26 17:26
梧桐生
期待更多优质内容的分享,论坛有你更精彩!
2025-2-26 15:21
想要
感谢你的贡献,论坛因你而更加精彩!
2025-2-26 13:14
wogao
+1
谢谢你的细致分析,受益匪浅!
2025-2-26 12:45
来福灵
感谢你的积极参与,期待更多精彩内容!
2025-2-26 11:50
gladly
为你点赞!
2025-2-26 10:41
ptr1234565
为你点赞!
2025-2-26 10:29
LXIN_520
这个讨论对我很有帮助,谢谢!
2025-2-26 01:25
mb_sorbkdcr
谢谢你的细致分析,受益匪浅!
2025-2-25 22:03
x_req
期待更多优质内容的分享,论坛有你更精彩!
2025-2-25 21:25
mb_fozshfmz
为你点赞!
2025-2-25 21:04
MsScotch
请注意发帖规范,保持良好的讨论环境!
2025-2-25 20:15
NopsSan
感谢你的贡献,论坛因你而更加精彩!
2025-2-25 18:36
落花为谁
感谢你分享这么好的资源!
2025-2-25 17:16
一个大橙子
期待更多优质内容的分享,论坛有你更精彩!
2025-2-25 16:20
liufengwenyu
感谢你的贡献,论坛因你而更加精彩!
2025-2-25 15:37
Forgo7ten
感谢你的贡献,论坛因你而更加精彩!
2025-2-25 11:29
养只猫不好么
为你点赞!
2025-2-24 21:28
blue_sky
感谢你的积极参与,期待更多精彩内容!
2025-2-24 20:58
MMD_DYOR
感谢你分享这么好的资源!
2025-2-24 16:17
wx_Dispa1r
为你点赞!
2025-2-24 15:48
taeyeon_ss
为你点赞!
2025-2-24 13:34
看不见的bug
+1
期待更多优质内容的分享,论坛有你更精彩!
2025-2-24 13:32
mb_fgcxqivc
期待更多优质内容的分享,论坛有你更精彩!
2025-2-24 11:09
mb_kdyaokdn
感谢你的贡献,论坛因你而更加精彩!
2025-2-24 09:29
git_99394jiangyei
这个讨论对我很有帮助,谢谢!
2025-2-24 09:15
mb_fzolvnwv
你的帖子非常有用,感谢分享!
2025-2-23 20:10
NPC2000
谢谢你的细致分析,受益匪浅!
2025-2-23 18:07
mb_vrexoteh
非常支持你的观点!
2025-2-22 20:58
哆啦噩梦
期待更多优质内容的分享,论坛有你更精彩!
2025-2-22 15:28
逆向小玖
谢谢你的细致分析,受益匪浅!
2025-2-22 13:19
wx_嗨
为你点赞!
2025-2-22 12:07
软件君子
非常支持你的观点!
2025-2-21 19:55
tfflowers
+1
感谢你的积极参与,期待更多精彩内容!
2025-2-21 15:20
mb_ooliergk
非常支持你的观点!
2025-2-21 13:33
顽劣
感谢你的贡献,论坛因你而更加精彩!
2025-2-21 11:38
KingSelyF
为你点赞!
2025-2-21 11:32
mb_ifqtwleh
谢谢你的细致分析,受益匪浅!
2025-2-21 10:49
mb_wyefudor
你的帖子非常有用,感谢分享!
2025-2-20 22:05
wwwst
感谢你的贡献,论坛因你而更加精彩!
2025-2-20 19:54
mb_eeigcyob
非常支持你的观点!
2025-2-20 19:53
juice4fun
感谢你的贡献,论坛因你而更加精彩!
2025-2-20 14:01
sayutizxc
你的帖子非常有用,感谢分享!
2025-2-20 14:00
U3D_Modder
非常支持你的观点!
2025-2-20 11:58
LLeaves
为你点赞!
2025-2-20 11:56
泰国老大
为你点赞!
2025-2-20 11:49
wx_funcrever
感谢你的贡献,论坛因你而更加精彩!
2025-2-20 11:40
kxcg1
为你点赞!
2025-2-20 11:15
.KK
非常支持你的观点!
2025-2-20 10:38
pexillove
非常支持你的观点!
2025-2-20 10:35
七星舞月
非常支持你的观点!
2025-2-20 09:55
ChuXinﻬ.
为你点赞!
2025-2-20 09:55
mb_nymhrhcn
感谢你的积极参与,期待更多精彩内容!
2025-2-20 09:52
cydian
你的分享对大家帮助很大,非常感谢!
2025-2-20 09:47
Shangwendada
谢谢你的细致分析,受益匪浅!
2025-2-20 09:33
mb_bppcorlj
为你点赞!
2025-2-20 09:20
你瞒我瞒
感谢你分享这么好的资源!
2025-2-20 09:10
vVv一
感谢你分享这么好的资源!
2025-2-20 04:20
mb_mmiqbqma
非常支持你的观点!
2025-2-19 23:00
doduhuang
为你点赞!
2025-2-19 22:33
mb_qqnashwi
这个讨论对我很有帮助,谢谢!
2025-2-19 22:27
sinker_
你的分享对大家帮助很大,非常感谢!
2025-2-19 22:24
mb_oowzftna
谢谢你的细致分析,受益匪浅!
2025-2-19 20:32
令狐双
你的分享对大家帮助很大,非常感谢!
2025-2-19 20:23
ngiokweng
期待更多优质内容的分享,论坛有你更精彩!
2025-2-19 20:13
mingyuexc
+1
谢谢你的细致分析,受益匪浅!
2025-2-19 20:13
huangyalei
非常支持你的观点!
2025-2-19 20:03
最新回复 (92)
雪    币: 2085
活跃值: (1895)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谢谢你的细致分析,受益匪浅!
2025-2-19 20:15
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
感谢分享,向大佬学习
2025-2-19 22:03
0
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
thanks
2025-2-19 23:10
0
雪    币: 4232
活跃值: (4044)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
thanks
2025-2-20 08:05
0
雪    币: 11150
活跃值: (1880)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
6
帖子写得不错,谢谢楼主分享!
2025-2-20 09:31
0
雪    币: 2115
活跃值: (1767)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
666
2025-2-20 09:53
0
雪    币: 235
活跃值: (660)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
太6了
2025-2-20 09:58
0
雪    币: 1990
活跃值: (2328)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
过来瞧瞧
2025-2-20 11:51
0
雪    币: 1496
活跃值: (2283)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
10
牛逼
2025-2-20 12:41
0
雪    币: 2469
活跃值: (2305)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
谢谢楼主分享!
2025-2-20 12:56
0
雪    币: 1930
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
看看
2025-2-20 18:20
0
雪    币: 2116
活跃值: (4462)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
13
学习
2025-2-20 20:11
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
学习一下,非常全面
2025-2-21 07:46
0
雪    币: 5086
活跃值: (3114)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
学习学习。。。
2025-2-21 09:31
0
雪    币: 96
活跃值: (2750)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
看看
2025-2-21 10:59
0
雪    币: 78
活跃值: (2248)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
看看
2025-2-21 14:45
0
雪    币: 27
活跃值: (1390)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
看看
2025-2-21 16:57
0
雪    币: 7103
活跃值: (3373)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
看看 学学
2025-2-21 17:02
0
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
学习了
2025-2-21 17:11
0
雪    币: 384
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21
最新版的加固校验 楼主有研究吗 是readlink和dex内存校验? svc应该过不了
2025-2-22 13:15
0
雪    币: 0
活跃值: (549)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
nice
2025-2-22 13:19
0
雪    币: 30
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
学习大佬的好东西。
2025-2-22 14:21
0
雪    币: 2806
活跃值: (3335)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
24
软件君子 最新版的加固校验 楼主有研究吗 是readlink和dex内存校验? svc应该过不了
应该 是 svc hook的检测对抗
2025-2-22 15:07
0
雪    币: 2485
活跃值: (3525)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
25
学习了
2025-2-22 16:04
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册