本篇共分为 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
跟进去发现是调用 两个参数的 ZipFile,继续跟
继续跟会发现最后调用了三个参数的 ZipFile 函数,在其中可以发现调用了一个 jni 的 open 函数,ZipFile 所在的类是 package java.util.zip,所以我们需要找到其对应的 Native 代码
在在线源码网站中搜索一番找到了下面这段代码,从文件名可以确定这就是我们要找的地方了,这里面有两个函数比较重要,一个是 ZIP_Get_From_Catch 另一个是 JVM_Open
先看 JVM_Open,跟进去后发现调用了一个名为 open 的函数,说实话因为是在线源码,没有办法直接看这个 open 到底是啥,但在和群里大佬探讨的时候,大佬斩钉截铁的告诉我,这个 open 就是 libc 的 open !事已至此,hook 不到 bask.apk 的原因只有一个!那就是 ZIP_Get_From_Catch !
如何验证我们的猜想呢,因为 ZIP_Get_From_Catch 并不是一个导出函数,所以验证起来手段就少了许多,我选择了一个对我来讲比较简单,并且非常粗暴的方法,那就是在 art 源码里加 log,并且还发现了之前分析的一个问题,那就是 native 的文件找错了,它的真正路径是 libcore/ojluni/src/main/native/ZipFile.c
刷机后重新启动 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
于是乎这里我们可以做的选择就比较有限了,hook ZipFile_open 这个导出的 jni 函数貌似是可行的,但事情真的会如此顺利么,这里我有尝试使用 xhook 和 shadowhook 去 hook 这个 ZipFile_open 函数,但不好意思,全部翻车,xhook 完全 hook 不到(不排除是我姿势不对,毕竟没怎么用过),shadowhook 则比较诡异,只能 hook 到一次,这里我还问了我们公司的大佬,只能说这个框架确实是多少有问题的
一个 jni 函数又是走缓存又是不给 hook 的,我反手就是一个 diy inlinehook,倒要看看它还能不能继续这么傲娇,话不多说,继续参考网上各路大神的 inlinehook 帖子和项目,写代码嘛,主打的就是一个抄,肉丝大佬的代码更是得大抄特抄
首先是 so 解析部分,想要 hook 一个函数首先要拿到它在内存中的地址,本来这里准备直接照抄肉丝老师的代码的,但没想到肉丝老师的代码无法正确解析 libopenjdk.so 这个库(痛苦面具直接),最后经过几天的学习与分析,最终定位问题所在是符号表的大小计算有问题,肉丝大佬的代码中,直接以字符串表头的地址减符号表头的地址得到的大小作为整个符号表的大小,但这样其实是有问题的,有啥问题我也不知道,但我知道的是像他那样计算在访问字符串的时候会越界,GPT 说正确的判断符号表的大小的方式是从符号表头遍历到最后 st_name 为 0 时作为符号表的结束
但不幸的是我使用 010 editor 中查看 libopenjdk.so 符号表的结尾并不是 0,而是 00 00 02 00 这种诡异的数据,不过通过观察发现一个正常的 sym.st_info 的值只为 0x12 0x11 0x22,如果不是这三个就结束了,这里就先这样判断吧(我太难了...)
这里给出可以识别到 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 重定向没有问题,成功改签
本次研习历时一个月有余,本以为是简单复现,却不曾想在其中经历了各种意外的波折,尽管事情并没有像最初预期的那样顺利进行,但都已成为我宝贵的学习经验。前人的方法不总是全面的,还需要我们后来者继续补充,逆向之路,道阻且长,笔者借以此文抛砖引玉,希望今后可以看到更多的技术贴,大家一起交流学习
[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)
{
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);
}
}
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();
}
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)
{
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);
}
}
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();
}
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;
String signature_str =
"3082037130820259a003020102020419f0a927300d06092a864886f70d01010b05003068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c753020170d3138303632393037323931365a180f32303733303430313037323931365a3068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c7530820122300d06092a864886f70d01010105000382010f003082010a0282010100a55431f01fb453e65d7e070bc82e606c11e9bf77831367701e4d7c79a44c014afa2be320caade2e75f8d9160ecaa6e5a39ca63d8ee5ddaffe54f6da0d1f7ea24efa9591681fa39561780c2bef75ec72096e121524da2f9c84d9455593639e63ca41cdbf7a349e0e26cf5f27564825fa524eb3efdbac5ec62f851053cc833537182e6d24dffaaf50274e6062650d527d76856e188d144116731689881a05db10d8bb159bbef9cfd314b205c785e51d4a34e0db54fa89b7ddb837559338f1f58e38df78f7e5acceeaf94546c78d1b8eea3a25e095fc1c959e77860962b3e980e31b63c3089e3541e27cea1631c3b2c59bcfd4c7384123c778c599473a3a319b2270203010001a321301f301d0603551d0e04160414fc7d539fc8aea2e08ade9cd07c47f43621f3b209300d06092a864886f70d01010b05000382010100088fe8de887969eb896e5d9c31aead82bc348faff1917fb224018a38f6d0126e0a9af191bf84ca84cf530cbe2ba0a4993059ae89ce2a05266a8192b044b4a8e18e510a8c6b7e022bebe5482b09a7b80f47661adf9f53fd65b69cf3acb2efc69b89bac3e90eabf1e7ed719b0efd38159cb5f3fea51ee62307ca5f09cbb85660323a41597438aba3999d3626fcbfa628d5510a435c78a82482d1447c3cff3ea19a7ae87d347b7e5e7b0237029cd2e5e57baa907bde58cb5483ef54dcee05fabaadb1a46c88113d85333c6979d846490d3e8def5aa4c3d94d2fc6497bea36901e6a18e1000db8da1f4bb31421138fbf2cb3a22d0458ef28e7167458278a79bf67ef"
;
public
hook(PackageManager base, String packageName) {
this
.mPackageName = packageName;
this
.mBase = base;
}
@Override
public
PackageInfo getPackageInfo(String packageName,
int
flags)
throws
PackageManager.NameNotFoundException {
if
(!mPackageName.equals(packageName)) {
return
this
.mBase.getPackageInfo(packageName, flags);
}
if
(flags != PackageManager.GET_SIGNATURES) {
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;
}
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();
}
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 {
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;
String signature_str =
"3082037130820259a003020102020419f0a927300d06092a864886f70d01010b05003068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c753020170d3138303632393037323931365a180f32303733303430313037323931365a3068310b300906035504061302434e310f300d0603550408130646754a69616e310f300d0603550407130646755a686f753111300f060355040a13084c69616e596f6e673111300f060355040b13084c69616e596f6e673111300f060355040313084c6f756973204c7530820122300d06092a864886f70d01010105000382010f003082010a0282010100a55431f01fb453e65d7e070bc82e606c11e9bf77831367701e4d7c79a44c014afa2be320caade2e75f8d9160ecaa6e5a39ca63d8ee5ddaffe54f6da0d1f7ea24efa9591681fa39561780c2bef75ec72096e121524da2f9c84d9455593639e63ca41cdbf7a349e0e26cf5f27564825fa524eb3efdbac5ec62f851053cc833537182e6d24dffaaf50274e6062650d527d76856e188d144116731689881a05db10d8bb159bbef9cfd314b205c785e51d4a34e0db54fa89b7ddb837559338f1f58e38df78f7e5acceeaf94546c78d1b8eea3a25e095fc1c959e77860962b3e980e31b63c3089e3541e27cea1631c3b2c59bcfd4c7384123c778c599473a3a319b2270203010001a321301f301d0603551d0e04160414fc7d539fc8aea2e08ade9cd07c47f43621f3b209300d06092a864886f70d01010b05000382010100088fe8de887969eb896e5d9c31aead82bc348faff1917fb224018a38f6d0126e0a9af191bf84ca84cf530cbe2ba0a4993059ae89ce2a05266a8192b044b4a8e18e510a8c6b7e022bebe5482b09a7b80f47661adf9f53fd65b69cf3acb2efc69b89bac3e90eabf1e7ed719b0efd38159cb5f3fea51ee62307ca5f09cbb85660323a41597438aba3999d3626fcbfa628d5510a435c78a82482d1447c3cff3ea19a7ae87d347b7e5e7b0237029cd2e5e57baa907bde58cb5483ef54dcee05fabaadb1a46c88113d85333c6979d846490d3e8def5aa4c3d94d2fc6497bea36901e6a18e1000db8da1f4bb31421138fbf2cb3a22d0458ef28e7167458278a79bf67ef"
;
public
hook(PackageManager base, String packageName) {
this
.mPackageName = packageName;
this
.mBase = base;
}
@Override
public
PackageInfo getPackageInfo(String packageName,
int
flags)
throws
PackageManager.NameNotFoundException {
if
(!mPackageName.equals(packageName)) {
return
this
.mBase.getPackageInfo(packageName, flags);
}
if
(flags != PackageManager.GET_SIGNATURES) {
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;
}
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();
}
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 {
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
被简单的简单编辑
,原因: