首页
社区
课程
招聘
[原创] Android 签名对抗攻略
发表于: 2023-7-28 23:09 14571

[原创] Android 签名对抗攻略

2023-7-28 23:09
14571

本篇共分为 PMS 和 IO 重定向两个主要部分,其中IO重定向部分实现了 InLine Hook

dex反编译smali、xml解析、生成资源序号文件与资源名称对应表

smali文件编译为应用,应用生成目录为反编译应用的 dist 目录中

查看目标应用是否签名,及使用的签名版本

查看目标应用是否对齐

制作对齐的应用

制作签名,会生成一个 demo.keystore 签名文件

使用生成的签名文件对目标应用进行签名

在 build.gradle(app) 中添加 signingConfigs 字段,另外注意 buildTypes 中 signingConfig 应分别为 signingConfigs.debug 和 signingConfigs.release

首先我们需要制作一个可以获取其他 app 签名的工具,这里直接写一个可以获取其他应用 signature 的 app,需要注意的就是权限配置

注意权限配置

然后我们还需要写一个目标 app 作为实验对象

PMS 是 PackageManagerSignature 的缩写,其原理是将目标解包后添加一个父类,在父类中重写 PackageManager 中的 getPackageManager

Java 层实现的核心代码如下

java/com/lxz/hookactivity.java

java/com/lxz/hookactivity.java

修改目标主启动类为 hookactivity,其实就是多了一层继承,中间修改了 PMS

使用反编译工具将刚刚用 java 实现的 PMS 反编译,并取出其中的 lxz 文件夹

再将 CheckSignature 中 刚刚添加的 psm 部分删掉,让其还原成一个可以检查 Signature 的应用,重新打包成 apk,再使用 apktool 将其解包

将 lxz 文件夹拷贝到 smali_classes3/com 目录下,并修改 smali_classes3\com\example\checksignatuer\MainActivity.smali 的父类

androidx.multidex.MultiDexApplication

com\babybus\app\App.smali

重新打包回 apk 文件,生成 signature.apk

使用 zipalign 对生成的文件对齐,需要制作 v2 的签名,不然 android 11 及以后安装会失败

接下来我们需要进行签名,但我们现在还没有签名文件,所以还得做个签名文件,密码123456,问题答案随便填,这样我们就获得了签名文件 demo.keystore

使用生成的签名文件对目标应用进行签名,此时安装并启动 app 会发现强制返回正确签名的 log

简单介绍下 io 重定向,编写一个自定义的文件打开函数来替代、修改标准的文件打开函数。在这个自定义函数中,可以实现 IO 重定向的逻辑,比如将文件的读写重定向到其他文件,说白了就是把 open 函数中的路径参数换成我们想要的路径

老套路还是先制作一个通过 base.apk 检查 signature 的 app,相较于之前我们只需要改下 getSignatuer 这个函数,另外最好新建一个 带 native 的工程会方便些

此时竟有些不知如何提笔接着写,因为笔者在这里踩了太多的坑,以至于距离上次写这篇笔记已过去一个月有余,虽然可以像上边一样直接放出答案,但还是决定把我遇到的几个坑复现给大家,心急的也可以直接跳过看最后的答案

IO 重定向这里我参考了网上的几个帖子和 github 上的项目,无一例外,所有的矛头都指向了 libc 中的这四个函数 open、open64、openat、openat64,大致的 hook 伪代码大概是下面这样样子,只要找个 hook 框架就可以直接起飞

但当我实际进行 hook 时却发现了一个非常致命的问题,我在 libc.so 的 open 可以 hook 到几乎所有被打开的文件,但唯独缺少最重要的目标文件 base.apk,一度我以为是我 hook 姿势的问题,甚至我还换了好几个 hook 框架,但大同小异,都无法 hook 到 base.apk,这里就卡了我好久,下面直接放分析思路

首先是找到读取 Zip 文件使用类为 ZipFile

image-20230727234951039

跟进去发现是调用 两个参数的 ZipFile,继续跟

image-20230727235235734

继续跟会发现最后调用了三个参数的 ZipFile 函数,在其中可以发现调用了一个 jni 的 open 函数,ZipFile 所在的类是 package java.util.zip,所以我们需要找到其对应的 Native 代码

image-20230727235347536

在在线源码网站中搜索一番找到了下面这段代码,从文件名可以确定这就是我们要找的地方了,这里面有两个函数比较重要,一个是 ZIP_Get_From_Catch 另一个是 JVM_Open

image-20230727235757098

先看 JVM_Open,跟进去后发现调用了一个名为 open 的函数,说实话因为是在线源码,没有办法直接看这个 open 到底是啥,但在和群里大佬探讨的时候,大佬斩钉截铁的告诉我,这个 open 就是 libc 的 open !事已至此,hook 不到 bask.apk 的原因只有一个!那就是 ZIP_Get_From_Catch !

image-20230728000430084

如何验证我们的猜想呢,因为 ZIP_Get_From_Catch 并不是一个导出函数,所以验证起来手段就少了许多,我选择了一个对我来讲比较简单,并且非常粗暴的方法,那就是在 art 源码里加 log,并且还发现了之前分析的一个问题,那就是 native 的文件找错了,它的真正路径是 libcore/ojluni/src/main/native/ZipFile.c

image-20230728215308391

刷机后重新启动 app 点击获取签名的按钮后,可以看到如下日志,很明显在还未获取签名时系统加载过一次 base.apk,而在我们点击获取签名时走的是 ZIP_Get_From_Catch 分支,这个地方我有尝试过将 hook 的时机提到 so init 的时机,但还是 hook 不到这个系统加载的这次打开,只能暂且认为系统加载这个 zip 的时候 app 还没有启动,并且这里还有一点其实卡了我挺久的问题,就是是否走 catch 的这种情况和ndk版本以及as版本似乎都有关系,目前发现的规律就是低版本ndk不会走catch,直接 hook open 就可以,高版本在创建项目时如果选择不带ndk的模板,会走jvm_open,不会走catch,如果选择带 ndk 的模板,就会像我遇到这种情况一样,原因暂时未知,只能说android 碎片化过于严重,防守方还是可以通过很多版本机制进行抵抗的,进攻方则需要不断找到新路线的关键 api

image-20230728215335148

于是乎这里我们可以做的选择就比较有限了,hook ZipFile_open 这个导出的 jni 函数貌似是可行的,但事情真的会如此顺利么,这里我有尝试使用 xhook 和 shadowhook 去 hook 这个 ZipFile_open 函数,但不好意思,全部翻车,xhook 完全 hook 不到(不排除是我姿势不对,毕竟没怎么用过),shadowhook 则比较诡异,只能 hook 到一次,这里我还问了我们公司的大佬,只能说这个框架确实是多少有问题的

image-20230728010250190

一个 jni 函数又是走缓存又是不给 hook 的,我反手就是一个 diy inlinehook,倒要看看它还能不能继续这么傲娇,话不多说,继续参考网上各路大神的 inlinehook 帖子和项目,写代码嘛,主打的就是一个抄,肉丝大佬的代码更是得大抄特抄

首先是 so 解析部分,想要 hook 一个函数首先要拿到它在内存中的地址,本来这里准备直接照抄肉丝老师的代码的,但没想到肉丝老师的代码无法正确解析 libopenjdk.so 这个库(痛苦面具直接),最后经过几天的学习与分析,最终定位问题所在是符号表的大小计算有问题,肉丝大佬的代码中,直接以字符串表头的地址减符号表头的地址得到的大小作为整个符号表的大小,但这样其实是有问题的,有啥问题我也不知道,但我知道的是像他那样计算在访问字符串的时候会越界,GPT 说正确的判断符号表的大小的方式是从符号表头遍历到最后 st_name 为 0 时作为符号表的结束

image-20230728012233796

但不幸的是我使用 010 editor 中查看 libopenjdk.so 符号表的结尾并不是 0,而是 00 00 02 00 这种诡异的数据,不过通过观察发现一个正常的 sym.st_info 的值只为 0x12 0x11 0x22,如果不是这三个就结束了,这里就先这样判断吧(我太难了...)

image-20230728012758427

这里给出可以识别到 ZipFile_open 的代码(符号表的大小判断估计还是有问题的,所以找到就赶紧 break,如果想通用一点还是得多观察几个 lib,看看结尾的共同之处)

android 的 inline hook 写起来要比 x86 麻烦许多,主要有以下几点:

下面就是参考肉丝大佬代码写()的一个简陋版 inline hook 框架

到了这里就是 hook 的实现部分了,但这里也有一点问题,那就是在hook函数中如何取出栈帧,虽然可以用汇编取出最上层栈帧,但因为 arm 中没有 ebp 这种寄存器,所以在 inline_fun 这个函数给自己开辟了多少的栈帧空间就是个不固定未知数,所以这里我采取解析函数头部汇编指令的方式获取 inline_fun 给自己开辟的栈帧大小,再向前倒推一下 hook 模板中存放栈的偏移,最终获取被 hook 函数的参数

下面是 java 层的代码,重点就是在 hook 之前要把傀儡 app 释放到指定位置做为 io 重定向的目标

最后放一张效果图,虽然我们的 inline hook 十分简陋,但 IO 重定向没有问题,成功改签

image-20230728225506629

本次研习历时一个月有余,本以为是简单复现,却不曾想在其中经历了各种意外的波折,尽管事情并没有像最初预期的那样顺利进行,但都已成为我宝贵的学习经验。前人的方法不总是全面的,还需要我们后来者继续补充,逆向之路,道阻且长,笔者借以此文抛砖引玉,希望今后可以看到更多的技术贴,大家一起交流学习

[1] ApkSignatureKillerEx

https://github.com/L-JINBIN/ApkSignatureKillerEx

[2] 寻找so中符号的地址

https://bbs.kanxue.com/thread-270015.htm

[3] 重打包APK绕过签名校验

https://bbs.kanxue.com/thread-260859.htm

[4] 《安卓逆向这档事》六、校验的N次方-签名校验对抗、PM代{过}{滤}理、IO重定向

https://www.52pojie.cn/forum.php?mod=viewthread&tid=1731181&highlight=%C7%A9%C3%FB

java -jar apksigner.jar verify -v app-debug.apk
-------------------------
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1
java -jar apksigner.jar verify -v app-debug.apk
-------------------------
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1
zipalign -c -v 4 app-debug.apk
----------------
Verification succesful
zipalign -c -v 4 app-debug.apk
----------------
Verification succesful
zipalign -v 4 app-debug.apk zipalign.apk
zipalign -v 4 app-debug.apk zipalign.apk
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
java -jar apksigner.jar sign --ks demo.keystore --ks-key-alias demo.keystore --ks-pass pass:123456 --key-pass pass:123456 --out sign.apk app-debug.apk
java -jar apksigner.jar sign --ks demo.keystore --ks-key-alias demo.keystore --ks-pass pass:123456 --key-pass pass:123456 --out sign.apk app-debug.apk
signingConfigs {
    release {
        storeFile file('C:\\Users\\lxz\\Documents\\mytools\\sign\\demo.keystore.jks')
        storePassword '123456'
        keyAlias 'demo.keystore'
        keyPassword '123456'
    }
}
signingConfigs {
    release {
        storeFile file('C:\\Users\\lxz\\Documents\\mytools\\sign\\demo.keystore.jks')
        storePassword '123456'
        keyAlias 'demo.keystore'
        keyPassword '123456'
    }
}
package com.example.myapplication;
 
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.SigningInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.example.myapplication.databinding.ActivityMainBinding;
 
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 
public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
 
        TextView textView = findViewById(R.id.mytext);
         
        String str = getSignatuer(this,"com.example.myapplication4");
 
        Log.e("lxz" , "获取到目标签名:" + str);
 
    }
 
    private String getSignatuer(Context context, String packagename){
        try {
 
            PackageInfo info = context.getPackageManager().getPackageInfo(packagename, PackageManager.GET_SIGNATURES);
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                SigningInfo signingInfo = info.signingInfo;
            }else{
                Log.e("lxz","未获取到签名信息");
            }
            byte[] bytes = info.signatures[0].toByteArray();
            String str = bytesToHex(bytes);
            return str;
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
 
    // 将 byte[] 转换为 16 进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
 
    // 16 进制字符串转换为 byte[]
    public static byte[] hexToBytes(String hexString) {
        int length = hexString.length();
        if (length % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string length");
        }
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            String hex = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(hex, 16);
        }
        return bytes;
    }
 
}
package com.example.myapplication;
 
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.SigningInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.example.myapplication.databinding.ActivityMainBinding;
 
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 
public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
 
        TextView textView = findViewById(R.id.mytext);
         
        String str = getSignatuer(this,"com.example.myapplication4");
 
        Log.e("lxz" , "获取到目标签名:" + str);
 
    }
 
    private String getSignatuer(Context context, String packagename){
        try {
 
            PackageInfo info = context.getPackageManager().getPackageInfo(packagename, PackageManager.GET_SIGNATURES);
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                SigningInfo signingInfo = info.signingInfo;
            }else{
                Log.e("lxz","未获取到签名信息");
            }
            byte[] bytes = info.signatures[0].toByteArray();
            String str = bytesToHex(bytes);
            return str;
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
 
    // 将 byte[] 转换为 16 进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
 
    // 16 进制字符串转换为 byte[]
    public static byte[] hexToBytes(String hexString) {
        int length = hexString.length();
        if (length % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string length");
        }
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            String hex = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(hex, 16);
        }
        return bytes;
    }
 
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
    <uses-permission android:name="android.permission.GET_PACKAGE_NAME" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_INSTALLED_PACKAGES" />
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
    <uses-permission android:name="android.permission.GET_PACKAGE_NAME" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_INSTALLED_PACKAGES" />
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
</manifest>
package com.example.checksignatuer;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.SigningInfo;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        TextView textView = findViewById(R.id.mytext);
 
        String str = getSignatuer(this);
        if(checkSignatuer(str))
        {
            Log.d("lxz","签名正确");
            textView.setText("签名正确");
        }else{
            Log.d("lxz","签名错误");
            textView.setText("签名错误");
        }
    }
 
    private boolean checkSignatuer(String str)
    {
        // 这里的 signature_str 可以使用 GetSignature 获取
        String signature_str = "308202e4308201cc020101300d06092a864886f70d01010b050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b30090603550406130255533020170d3233303430363038313332325a180f32303533303332393038313332325a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a02820101009e80d9990b9622e00c04c4608d404c89ab3b5f28ea1ababfe2c9e4d172d3004c1a0c4494fb3359dc0071024738d942ae7b2db78a5f5898261ef1e49a353651facc6c7aca2a7d2ace9bfb158f63a2177a7c7d7dd18e0f57ca59dd56d325d14b6a697257f20e9f923363ac7724ac4e6c2600648fd81f8dc85db648a8d8e06947d15c8c89bbb469e86c685bb6165ec936264c8af54f04f86794887371c564d6340c838e4821dd3e72824dfcc0246efab42241324887de2fbe043113d4544e6e6c3c6b42a77ad8f50f91f8c43fc2e2cf4c3de689995326fedbfd8f86606ec9ffae1e5e30bc4f5296fd8d30ac0117cd66efba7292ea1377a56f9890fa9948ec9b57010203010001300d06092a864886f70d01010b05000382010100754cf3804666464192d206c9f76354b91e88d664fd553f0dceababf007d26eb208424fb92829dc029b0b291ccab55b642bdc0c8b9346089552970460918306262218bf6c776eb803019928568a53ed97a970003c570e20fd472170e0057203ed7ed8118fb944f984e78536b020f44558e518f46f70132216d4162d9363a2ccc62a53083b7e3a3df4b8da03bc7cd8b06b8d193b2b33aa20acc66c9f53cb0c2bd2eeb691285e8cc3eeb897c160ddf916f556a4606527e9e1b9d3856000193af4641dbc951660cf018621267486ac7b4b0d57c7e64e9880ce5ae4e70cc37cb72bdc5f2fef1b50004872844a23f8706b226349583316e3ed7770eb662bd3567ffb96";
 
        if(str.equals(signature_str))
        {
            return true;
        }else{
            return false;
        }
    }
 
    private String getSignatuer(Context context){
        try {
            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                SigningInfo signingInfo = info.signingInfo;
            }else{
                Log.e("lxz","未获取到签名信息");
            }
            byte[] bytes = info.signatures[0].toByteArray();
            String str = bytesToHex(bytes);
            return str;
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
 
    // 将 byte[] 转换为 16 进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
 
    // 将 16 进制字符串转换为 byte[]
    public static byte[] hexToBytes(String hexString) {
        int length = hexString.length();
        if (length % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string length");
        }
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            String hex = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(hex, 16);
        }
        return bytes;
    }
}
package com.example.checksignatuer;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.SigningInfo;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        TextView textView = findViewById(R.id.mytext);
 
        String str = getSignatuer(this);
        if(checkSignatuer(str))
        {
            Log.d("lxz","签名正确");
            textView.setText("签名正确");
        }else{
            Log.d("lxz","签名错误");
            textView.setText("签名错误");
        }
    }
 
    private boolean checkSignatuer(String str)
    {
        // 这里的 signature_str 可以使用 GetSignature 获取
        String signature_str = "308202e4308201cc020101300d06092a864886f70d01010b050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b30090603550406130255533020170d3233303430363038313332325a180f32303533303332393038313332325a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a02820101009e80d9990b9622e00c04c4608d404c89ab3b5f28ea1ababfe2c9e4d172d3004c1a0c4494fb3359dc0071024738d942ae7b2db78a5f5898261ef1e49a353651facc6c7aca2a7d2ace9bfb158f63a2177a7c7d7dd18e0f57ca59dd56d325d14b6a697257f20e9f923363ac7724ac4e6c2600648fd81f8dc85db648a8d8e06947d15c8c89bbb469e86c685bb6165ec936264c8af54f04f86794887371c564d6340c838e4821dd3e72824dfcc0246efab42241324887de2fbe043113d4544e6e6c3c6b42a77ad8f50f91f8c43fc2e2cf4c3de689995326fedbfd8f86606ec9ffae1e5e30bc4f5296fd8d30ac0117cd66efba7292ea1377a56f9890fa9948ec9b57010203010001300d06092a864886f70d01010b05000382010100754cf3804666464192d206c9f76354b91e88d664fd553f0dceababf007d26eb208424fb92829dc029b0b291ccab55b642bdc0c8b9346089552970460918306262218bf6c776eb803019928568a53ed97a970003c570e20fd472170e0057203ed7ed8118fb944f984e78536b020f44558e518f46f70132216d4162d9363a2ccc62a53083b7e3a3df4b8da03bc7cd8b06b8d193b2b33aa20acc66c9f53cb0c2bd2eeb691285e8cc3eeb897c160ddf916f556a4606527e9e1b9d3856000193af4641dbc951660cf018621267486ac7b4b0d57c7e64e9880ce5ae4e70cc37cb72bdc5f2fef1b50004872844a23f8706b226349583316e3ed7770eb662bd3567ffb96";
 
        if(str.equals(signature_str))
        {
            return true;
        }else{
            return false;
        }
    }
 
    private String getSignatuer(Context context){
        try {
            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                SigningInfo signingInfo = info.signingInfo;
            }else{
                Log.e("lxz","未获取到签名信息");
            }
            byte[] bytes = info.signatures[0].toByteArray();
            String str = bytesToHex(bytes);
            return str;
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
 
    // 将 byte[] 转换为 16 进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
 
    // 将 16 进制字符串转换为 byte[]
    public static byte[] hexToBytes(String hexString) {
        int length = hexString.length();
        if (length % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string length");
        }
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            String hex = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(hex, 16);
        }
        return bytes;
    }
}
package com.lxz;
 
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ChangedPackages;
import android.content.pm.FeatureInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
import android.content.pm.VersionedPackage;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.UserHandle;
import android.util.Log;
 
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
 
import java.util.List;
 
public class hook extends PackageManager {
    private PackageManager mBase;
    private String mPackageName;
 
    // 此处的签名使用 GetSignature 获取原包的签名信息
    String signature_str = "3082037130820259a003020102020419f0a927300d06092a864886f70d01010b05003068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c753020170d3138303632393037323931365a180f32303733303430313037323931365a3068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c7530820122300d06092a864886f70d01010105000382010f003082010a0282010100a55431f01fb453e65d7e070bc82e606c11e9bf77831367701e4d7c79a44c014afa2be320caade2e75f8d9160ecaa6e5a39ca63d8ee5ddaffe54f6da0d1f7ea24efa9591681fa39561780c2bef75ec72096e121524da2f9c84d9455593639e63ca41cdbf7a349e0e26cf5f27564825fa524eb3efdbac5ec62f851053cc833537182e6d24dffaaf50274e6062650d527d76856e188d144116731689881a05db10d8bb159bbef9cfd314b205c785e51d4a34e0db54fa89b7ddb837559338f1f58e38df78f7e5acceeaf94546c78d1b8eea3a25e095fc1c959e77860962b3e980e31b63c3089e3541e27cea1631c3b2c59bcfd4c7384123c778c599473a3a319b2270203010001a321301f301d0603551d0e04160414fc7d539fc8aea2e08ade9cd07c47f43621f3b209300d06092a864886f70d01010b05000382010100088fe8de887969eb896e5d9c31aead82bc348faff1917fb224018a38f6d0126e0a9af191bf84ca84cf530cbe2ba0a4993059ae89ce2a05266a8192b044b4a8e18e510a8c6b7e022bebe5482b09a7b80f47661adf9f53fd65b69cf3acb2efc69b89bac3e90eabf1e7ed719b0efd38159cb5f3fea51ee62307ca5f09cbb85660323a41597438aba3999d3626fcbfa628d5510a435c78a82482d1447c3cff3ea19a7ae87d347b7e5e7b0237029cd2e5e57baa907bde58cb5483ef54dcee05fabaadb1a46c88113d85333c6979d846490d3e8def5aa4c3d94d2fc6497bea36901e6a18e1000db8da1f4bb31421138fbf2cb3a22d0458ef28e7167458278a79bf67ef";
 
    public hook(PackageManager base, String packageName) {
        this.mPackageName = packageName;
        this.mBase = base;
    }
 
    @Override // android.content.pm.PackageManager
    public PackageInfo getPackageInfo(String packageName, int flags) throws PackageManager.NameNotFoundException {
 
        if (!mPackageName.equals(packageName)) {
            // 不是自己在检查 PackageInfo 信息,返回真实信息
            return this.mBase.getPackageInfo(packageName, flags);
        }
        if (flags != PackageManager.GET_SIGNATURES) {
            // 检查的不是 signature, 返回真实信息
            return this.mBase.getPackageInfo(packageName, flags);
        }
 
        PackageInfo pkgInfo = new PackageInfo();
        byte bytes[] = hexToBytes(signature_str);
        pkgInfo.signatures = new Signature[]{new Signature(bytes)};
        Log.e("lxz","强制返回正确签名");
        return pkgInfo;
    }
 
    // 将 byte[] 转换为 16 进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
 
    // 将 16 进制字符串转换为 byte[]
    public static byte[] hexToBytes(String hexString) {
        int length = hexString.length();
        if (length % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string length");
        }
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            String hex = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(hex, 16);
        }
        return bytes;
    }
 
    @Override
    public PackageInfo getPackageInfo(@NonNull VersionedPackage versionedPackage, int flags) throws NameNotFoundException {
        // 这里好像也可以返回 PackageInfo,但我没做处理
        return this.mBase.getPackageInfo(versionedPackage, flags);
    }
    @Override
    public List<PackageInfo> getInstalledPackages(int flags) {
        return this.mBase.getInstalledPackages(flags);
    }
    @Override
    public String[] currentToCanonicalPackageNames(String[] names) {
        return this.mBase.currentToCanonicalPackageNames(names);
    }
    @Override
    public String[] canonicalToCurrentPackageNames(String[] names) {
        return this.mBase.canonicalToCurrentPackageNames(names);
    }
    @Override
    public Intent getLaunchIntentForPackage(String packageName) {
        return this.mBase.getLaunchIntentForPackage(packageName);
    }
    @Override
    public Intent getLeanbackLaunchIntentForPackage(String packageName) {
        return this.mBase.getLeanbackLaunchIntentForPackage(packageName);
    }
    @Override
    public int[] getPackageGids(String packageName) throws PackageManager.NameNotFoundException {
        return this.mBase.getPackageGids(packageName);
    }
    @Override
    public int[] getPackageGids(@NonNull String packageName, int flags) throws NameNotFoundException {
        return new int[0];
    }
    @Override
    public int getPackageUid(@NonNull String packageName, int flags) throws NameNotFoundException {
        return 0;
    }
    @Override
    public PermissionInfo getPermissionInfo(String name, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getPermissionInfo(name, flags);
    }
    @Override
    public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.queryPermissionsByGroup(group, flags);
    }
    @Override
    public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getPermissionGroupInfo(name, flags);
    }
    @Override
    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
        return this.mBase.getAllPermissionGroups(flags);
    }
    @Override
    public ApplicationInfo getApplicationInfo(String packageName, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getApplicationInfo(packageName, flags);
    }
    @Override
    public ActivityInfo getActivityInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityInfo(component, flags);
    }
    @Override
    public ActivityInfo getReceiverInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getReceiverInfo(component, flags);
    }
    @Override
    public ServiceInfo getServiceInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getServiceInfo(component, flags);
    }
    @Override
    public ProviderInfo getProviderInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getProviderInfo(component, flags);
    }
    @Override
    public List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) {
        return this.mBase.getPackagesHoldingPermissions(permissions, flags);
    }
    @Override
    public int checkPermission(String permName, String pkgName) {
        return this.mBase.checkPermission(permName, pkgName);
    }
    @Override
    public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
        return this.mBase.isPermissionRevokedByPolicy(permName, pkgName);
    }
    @Override
    public boolean addPermission(PermissionInfo info) {
        return this.mBase.addPermission(info);
    }
    @Override
    public boolean addPermissionAsync(PermissionInfo info) {
        return this.mBase.addPermissionAsync(info);
    }
    @Override
    public void removePermission(String name) {
        this.mBase.removePermission(name);
    }
    @Override
    public int checkSignatures(String pkg1, String pkg2) {
        return this.mBase.checkSignatures(pkg1, pkg2);
    }
    @Override
    public int checkSignatures(int uid1, int uid2) {
        return this.mBase.checkSignatures(uid1, uid2);
    }
    @Override
    public String[] getPackagesForUid(int uid) {
        return this.mBase.getPackagesForUid(uid);
    }
    @Override
    public String getNameForUid(int uid) {
        return this.mBase.getNameForUid(uid);
    }
    @Override
    public List<ApplicationInfo> getInstalledApplications(int flags) {
        return this.mBase.getInstalledApplications(flags);
    }
    @Override
    public boolean isInstantApp() {
        return false;
    }
    @Override
    public boolean isInstantApp(@NonNull String packageName) {
        return false;
    }
    @Override
    public int getInstantAppCookieMaxBytes() {
        return 0;
    }
    @NonNull
    @Override
    public byte[] getInstantAppCookie() {
        return new byte[0];
    }
    @Override
    public void clearInstantAppCookie() {
 
    }
    @Override
    public void updateInstantAppCookie(@Nullable byte[] cookie) {
 
    }
    @Override
    public String[] getSystemSharedLibraryNames() {
        return this.mBase.getSystemSharedLibraryNames();
    }
    @NonNull
    @Override
    public List<SharedLibraryInfo> getSharedLibraries(int flags) {
        return null;
    }
 
    @Nullable
    @Override
    public ChangedPackages getChangedPackages(int sequenceNumber) {
        return null;
    }
    @Override
    public FeatureInfo[] getSystemAvailableFeatures() {
        return this.mBase.getSystemAvailableFeatures();
    }
    @Override
    public boolean hasSystemFeature(String name) {
        return this.mBase.hasSystemFeature(name);
    }
 
    @Override
    public boolean hasSystemFeature(@NonNull String featureName, int version) {
        return false;
    }
    @Override
    public ResolveInfo resolveActivity(Intent intent, int flags) {
        return this.mBase.resolveActivity(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
        return this.mBase.queryIntentActivities(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller, Intent[] specifics, Intent intent, int flags) {
        return this.mBase.queryIntentActivityOptions(caller, specifics, intent, flags);
    }
    @Override
    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
        return this.mBase.queryBroadcastReceivers(intent, flags);
    }
    @Override
    public ResolveInfo resolveService(Intent intent, int flags) {
        return this.mBase.resolveService(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
        return this.mBase.queryIntentServices(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
        return this.mBase.queryIntentContentProviders(intent, flags);
    }
    @Override
    public ProviderInfo resolveContentProvider(String name, int flags) {
        return this.mBase.resolveContentProvider(name, flags);
    }
    @Override
    public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
        return this.mBase.queryContentProviders(processName, uid, flags);
    }
    @Override
    public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getInstrumentationInfo(className, flags);
    }
    @Override
    public List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) {
        return this.mBase.queryInstrumentation(targetPackage, flags);
    }
    @Override
    public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) {
        return this.mBase.getDrawable(packageName, resid, appInfo);
    }
    @Override
    public Drawable getActivityIcon(ComponentName activityName) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityIcon(activityName);
    }
    @Override
    public Drawable getActivityIcon(Intent intent) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityIcon(intent);
    }
    @Override
    public Drawable getActivityBanner(ComponentName activityName) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityBanner(activityName);
    }
    @Override
    public Drawable getActivityBanner(Intent intent) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityBanner(intent);
    }
    @Override
    public Drawable getDefaultActivityIcon() {
        return this.mBase.getDefaultActivityIcon();
    }
    @Override
    public Drawable getApplicationIcon(ApplicationInfo info) {
        return this.mBase.getApplicationIcon(info);
    }
    @Override
    public Drawable getApplicationIcon(String packageName) throws PackageManager.NameNotFoundException {
        return this.mBase.getApplicationIcon(packageName);
    }
    @Override
    public Drawable getApplicationBanner(ApplicationInfo info) {
        return this.mBase.getApplicationBanner(info);
    }
    @Override
    public Drawable getApplicationBanner(String packageName) throws PackageManager.NameNotFoundException {
        return this.mBase.getApplicationBanner(packageName);
    }
    @Override
    public Drawable getActivityLogo(ComponentName activityName) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityLogo(activityName);
    }
    @Override
    public Drawable getActivityLogo(Intent intent) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityLogo(intent);
    }
    @Override
    public Drawable getApplicationLogo(ApplicationInfo info) {
        return this.mBase.getApplicationLogo(info);
    }
    @Override
    public Drawable getApplicationLogo(String packageName) throws PackageManager.NameNotFoundException {
        return this.mBase.getApplicationLogo(packageName);
    }
    @Override
    public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
        return this.mBase.getUserBadgedIcon(icon, user);
    }
    @Override
    public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user, Rect badgeLocation, int badgeDensity) {
        return this.mBase.getUserBadgedDrawableForDensity(drawable, user, badgeLocation, badgeDensity);
    }
    @Override
    public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
        return this.mBase.getUserBadgedLabel(label, user);
    }
    @Override
    public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) {
        return this.mBase.getText(packageName, resid, appInfo);
    }
    @Override
    public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) {
        return this.mBase.getXml(packageName, resid, appInfo);
    }
    @Override
    public CharSequence getApplicationLabel(ApplicationInfo info) {
        return this.mBase.getApplicationLabel(info);
    }
    @Override
    public Resources getResourcesForActivity(ComponentName activityName) throws PackageManager.NameNotFoundException {
        return this.mBase.getResourcesForActivity(activityName);
    }
    @Override
    public Resources getResourcesForApplication(ApplicationInfo app) throws PackageManager.NameNotFoundException {
        return this.mBase.getResourcesForApplication(app);
    }
    @Override
    public Resources getResourcesForApplication(String appPackageName) throws PackageManager.NameNotFoundException {
        return this.mBase.getResourcesForApplication(appPackageName);
    }
    @Override
    public void verifyPendingInstall(int id, int verificationCode) {
        this.mBase.verifyPendingInstall(id, verificationCode);
    }
    @Override
    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay) {
        this.mBase.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay);
    }
    @Override
    public void setInstallerPackageName(String targetPackage, String installerPackageName) {
        this.mBase.setInstallerPackageName(targetPackage, installerPackageName);
    }
    @Override
    public String getInstallerPackageName(String packageName) {
        return this.mBase.getInstallerPackageName(packageName);
    }
    @Override
    public void addPackageToPreferred(String packageName) {
        this.mBase.addPackageToPreferred(packageName);
    }
    @Override
    public void removePackageFromPreferred(String packageName) {
        this.mBase.removePackageFromPreferred(packageName);
    }
    @Override
    public List<PackageInfo> getPreferredPackages(int flags) {
        return this.mBase.getPreferredPackages(flags);
    }
    @Override
    public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
        this.mBase.addPreferredActivity(filter, match, set, activity);
    }
    @Override
    public void clearPackagePreferredActivities(String packageName) {
        this.mBase.clearPackagePreferredActivities(packageName);
    }
    @Override
    public int getPreferredActivities(List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) {
        return this.mBase.getPreferredActivities(outFilters, outActivities, packageName);
    }
    @Override
    public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
        this.mBase.setComponentEnabledSetting(componentName, newState, flags);
    }
    @Override
    public int getComponentEnabledSetting(ComponentName componentName) {
        return this.mBase.getComponentEnabledSetting(componentName);
    }
    @Override
    public void setApplicationEnabledSetting(String packageName, int newState, int flags) {
        this.mBase.setApplicationEnabledSetting(packageName, newState, flags);
    }
    @Override
    public int getApplicationEnabledSetting(String packageName) {
        return this.mBase.getApplicationEnabledSetting(packageName);
    }
    @Override
    public boolean isSafeMode() {
        return this.mBase.isSafeMode();
    }
    @Override
    public void setApplicationCategoryHint(@NonNull String packageName, int categoryHint) {
 
    }
    @Override
    public PackageInstaller getPackageInstaller() {
        return this.mBase.getPackageInstaller();
    }
    @Override
    public boolean canRequestPackageInstalls() {
        return false;
    }
}
package com.lxz;
 
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ChangedPackages;
import android.content.pm.FeatureInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
import android.content.pm.VersionedPackage;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.UserHandle;
import android.util.Log;
 
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
 
import java.util.List;
 
public class hook extends PackageManager {
    private PackageManager mBase;
    private String mPackageName;
 
    // 此处的签名使用 GetSignature 获取原包的签名信息
    String signature_str = "3082037130820259a003020102020419f0a927300d06092a864886f70d01010b05003068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c753020170d3138303632393037323931365a180f32303733303430313037323931365a3068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c7530820122300d06092a864886f70d01010105000382010f003082010a0282010100a55431f01fb453e65d7e070bc82e606c11e9bf77831367701e4d7c79a44c014afa2be320caade2e75f8d9160ecaa6e5a39ca63d8ee5ddaffe54f6da0d1f7ea24efa9591681fa39561780c2bef75ec72096e121524da2f9c84d9455593639e63ca41cdbf7a349e0e26cf5f27564825fa524eb3efdbac5ec62f851053cc833537182e6d24dffaaf50274e6062650d527d76856e188d144116731689881a05db10d8bb159bbef9cfd314b205c785e51d4a34e0db54fa89b7ddb837559338f1f58e38df78f7e5acceeaf94546c78d1b8eea3a25e095fc1c959e77860962b3e980e31b63c3089e3541e27cea1631c3b2c59bcfd4c7384123c778c599473a3a319b2270203010001a321301f301d0603551d0e04160414fc7d539fc8aea2e08ade9cd07c47f43621f3b209300d06092a864886f70d01010b05000382010100088fe8de887969eb896e5d9c31aead82bc348faff1917fb224018a38f6d0126e0a9af191bf84ca84cf530cbe2ba0a4993059ae89ce2a05266a8192b044b4a8e18e510a8c6b7e022bebe5482b09a7b80f47661adf9f53fd65b69cf3acb2efc69b89bac3e90eabf1e7ed719b0efd38159cb5f3fea51ee62307ca5f09cbb85660323a41597438aba3999d3626fcbfa628d5510a435c78a82482d1447c3cff3ea19a7ae87d347b7e5e7b0237029cd2e5e57baa907bde58cb5483ef54dcee05fabaadb1a46c88113d85333c6979d846490d3e8def5aa4c3d94d2fc6497bea36901e6a18e1000db8da1f4bb31421138fbf2cb3a22d0458ef28e7167458278a79bf67ef";
 
    public hook(PackageManager base, String packageName) {
        this.mPackageName = packageName;
        this.mBase = base;
    }
 
    @Override // android.content.pm.PackageManager
    public PackageInfo getPackageInfo(String packageName, int flags) throws PackageManager.NameNotFoundException {
 
        if (!mPackageName.equals(packageName)) {
            // 不是自己在检查 PackageInfo 信息,返回真实信息
            return this.mBase.getPackageInfo(packageName, flags);
        }
        if (flags != PackageManager.GET_SIGNATURES) {
            // 检查的不是 signature, 返回真实信息
            return this.mBase.getPackageInfo(packageName, flags);
        }
 
        PackageInfo pkgInfo = new PackageInfo();
        byte bytes[] = hexToBytes(signature_str);
        pkgInfo.signatures = new Signature[]{new Signature(bytes)};
        Log.e("lxz","强制返回正确签名");
        return pkgInfo;
    }
 
    // 将 byte[] 转换为 16 进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
 
    // 将 16 进制字符串转换为 byte[]
    public static byte[] hexToBytes(String hexString) {
        int length = hexString.length();
        if (length % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex string length");
        }
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            String hex = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(hex, 16);
        }
        return bytes;
    }
 
    @Override
    public PackageInfo getPackageInfo(@NonNull VersionedPackage versionedPackage, int flags) throws NameNotFoundException {
        // 这里好像也可以返回 PackageInfo,但我没做处理
        return this.mBase.getPackageInfo(versionedPackage, flags);
    }
    @Override
    public List<PackageInfo> getInstalledPackages(int flags) {
        return this.mBase.getInstalledPackages(flags);
    }
    @Override
    public String[] currentToCanonicalPackageNames(String[] names) {
        return this.mBase.currentToCanonicalPackageNames(names);
    }
    @Override
    public String[] canonicalToCurrentPackageNames(String[] names) {
        return this.mBase.canonicalToCurrentPackageNames(names);
    }
    @Override
    public Intent getLaunchIntentForPackage(String packageName) {
        return this.mBase.getLaunchIntentForPackage(packageName);
    }
    @Override
    public Intent getLeanbackLaunchIntentForPackage(String packageName) {
        return this.mBase.getLeanbackLaunchIntentForPackage(packageName);
    }
    @Override
    public int[] getPackageGids(String packageName) throws PackageManager.NameNotFoundException {
        return this.mBase.getPackageGids(packageName);
    }
    @Override
    public int[] getPackageGids(@NonNull String packageName, int flags) throws NameNotFoundException {
        return new int[0];
    }
    @Override
    public int getPackageUid(@NonNull String packageName, int flags) throws NameNotFoundException {
        return 0;
    }
    @Override
    public PermissionInfo getPermissionInfo(String name, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getPermissionInfo(name, flags);
    }
    @Override
    public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.queryPermissionsByGroup(group, flags);
    }
    @Override
    public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getPermissionGroupInfo(name, flags);
    }
    @Override
    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
        return this.mBase.getAllPermissionGroups(flags);
    }
    @Override
    public ApplicationInfo getApplicationInfo(String packageName, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getApplicationInfo(packageName, flags);
    }
    @Override
    public ActivityInfo getActivityInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityInfo(component, flags);
    }
    @Override
    public ActivityInfo getReceiverInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getReceiverInfo(component, flags);
    }
    @Override
    public ServiceInfo getServiceInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getServiceInfo(component, flags);
    }
    @Override
    public ProviderInfo getProviderInfo(ComponentName component, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getProviderInfo(component, flags);
    }
    @Override
    public List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) {
        return this.mBase.getPackagesHoldingPermissions(permissions, flags);
    }
    @Override
    public int checkPermission(String permName, String pkgName) {
        return this.mBase.checkPermission(permName, pkgName);
    }
    @Override
    public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
        return this.mBase.isPermissionRevokedByPolicy(permName, pkgName);
    }
    @Override
    public boolean addPermission(PermissionInfo info) {
        return this.mBase.addPermission(info);
    }
    @Override
    public boolean addPermissionAsync(PermissionInfo info) {
        return this.mBase.addPermissionAsync(info);
    }
    @Override
    public void removePermission(String name) {
        this.mBase.removePermission(name);
    }
    @Override
    public int checkSignatures(String pkg1, String pkg2) {
        return this.mBase.checkSignatures(pkg1, pkg2);
    }
    @Override
    public int checkSignatures(int uid1, int uid2) {
        return this.mBase.checkSignatures(uid1, uid2);
    }
    @Override
    public String[] getPackagesForUid(int uid) {
        return this.mBase.getPackagesForUid(uid);
    }
    @Override
    public String getNameForUid(int uid) {
        return this.mBase.getNameForUid(uid);
    }
    @Override
    public List<ApplicationInfo> getInstalledApplications(int flags) {
        return this.mBase.getInstalledApplications(flags);
    }
    @Override
    public boolean isInstantApp() {
        return false;
    }
    @Override
    public boolean isInstantApp(@NonNull String packageName) {
        return false;
    }
    @Override
    public int getInstantAppCookieMaxBytes() {
        return 0;
    }
    @NonNull
    @Override
    public byte[] getInstantAppCookie() {
        return new byte[0];
    }
    @Override
    public void clearInstantAppCookie() {
 
    }
    @Override
    public void updateInstantAppCookie(@Nullable byte[] cookie) {
 
    }
    @Override
    public String[] getSystemSharedLibraryNames() {
        return this.mBase.getSystemSharedLibraryNames();
    }
    @NonNull
    @Override
    public List<SharedLibraryInfo> getSharedLibraries(int flags) {
        return null;
    }
 
    @Nullable
    @Override
    public ChangedPackages getChangedPackages(int sequenceNumber) {
        return null;
    }
    @Override
    public FeatureInfo[] getSystemAvailableFeatures() {
        return this.mBase.getSystemAvailableFeatures();
    }
    @Override
    public boolean hasSystemFeature(String name) {
        return this.mBase.hasSystemFeature(name);
    }
 
    @Override
    public boolean hasSystemFeature(@NonNull String featureName, int version) {
        return false;
    }
    @Override
    public ResolveInfo resolveActivity(Intent intent, int flags) {
        return this.mBase.resolveActivity(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
        return this.mBase.queryIntentActivities(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller, Intent[] specifics, Intent intent, int flags) {
        return this.mBase.queryIntentActivityOptions(caller, specifics, intent, flags);
    }
    @Override
    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
        return this.mBase.queryBroadcastReceivers(intent, flags);
    }
    @Override
    public ResolveInfo resolveService(Intent intent, int flags) {
        return this.mBase.resolveService(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
        return this.mBase.queryIntentServices(intent, flags);
    }
    @Override
    public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
        return this.mBase.queryIntentContentProviders(intent, flags);
    }
    @Override
    public ProviderInfo resolveContentProvider(String name, int flags) {
        return this.mBase.resolveContentProvider(name, flags);
    }
    @Override
    public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
        return this.mBase.queryContentProviders(processName, uid, flags);
    }
    @Override
    public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) throws PackageManager.NameNotFoundException {
        return this.mBase.getInstrumentationInfo(className, flags);
    }
    @Override
    public List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) {
        return this.mBase.queryInstrumentation(targetPackage, flags);
    }
    @Override
    public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) {
        return this.mBase.getDrawable(packageName, resid, appInfo);
    }
    @Override
    public Drawable getActivityIcon(ComponentName activityName) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityIcon(activityName);
    }
    @Override
    public Drawable getActivityIcon(Intent intent) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityIcon(intent);
    }
    @Override
    public Drawable getActivityBanner(ComponentName activityName) throws PackageManager.NameNotFoundException {
        return this.mBase.getActivityBanner(activityName);
    }
    @Override
    public Drawable getActivityBanner(Intent intent) throws PackageManager.NameNotFoundException {

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-1-12 22:25 被简单的简单编辑 ,原因:
收藏
免费 9
支持
分享
最新回复 (6)
雪    币: 1539
活跃值: (1618)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
可以的,不过看着你好像有点眼熟 NP的几个去签是你写的吗
2023-7-29 00:15
0
雪    币: 9057
活跃值: (1615)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
3
能过翻切小说的签名吗?嘿嘿,试试
2023-7-29 09:21
0
雪    币: 3527
活跃值: (3908)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
先收藏了,谢谢分享。
2023-7-29 09:22
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
大佬,我遇到的问题主要是在U3D游戏里,如果hook open后重定向路径(用的还是原包模式),游戏会报错:Not enough storage space to install required resources,任何一款u3d都会,没检测随意反编译回编译。比如这款pl.idreams.Dino  https://apkpure.com/cn/crazy-dino-park-iiii/pl.idreams.Dino
2023-7-30 00:38
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
为啥读取base.apk中的文件数据时,读取的数据均为0呢?
3天前
0
雪    币: 183
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢大佬的分享
2天前
0
游客
登录 | 注册 方可回帖
返回
//