返回列表 发新帖

对于替换CREATOR和代理PMS去签,可以直接比较class对象地址

[复制链接]

15

主题

42

回帖

997

积分

高中生

Rank: 4

金币
211
好评
10
信誉
100
发表于 2025-12-8 14:09:55 | 显示全部楼层 | 阅读模式  来自 湖北
本帖最后由 LivedForward 于 2025-12-8 17:33 编辑

检测基于:
在同一个JVM中,对于一个特定的类加载器,一个类(.class文件)在其生命周期内,只会生成一个 Class 对象。

先看一下android.jar里面的android.os.Parcelable这个公共接口类和
android.content.pm.PackageInfo类里面的这段代码:
public static final Parcelable.Creator<PackageInfo> CREATOR = new Parcelable.Creator<PackageInfo>() {
        public PackageInfo createFromParcel(Parcel parcel) {
            return new PackageInfo(parcel);
        }

        public PackageInfo[] newArray(int i) {
            return new PackageInfo;
        }
    };









所以CREATOR这个静态字段存储的是一个Parcelable.Creator<PackageInfo>
接口的匿名实现类的实例对象,为PackageInfo$1类型。

匿名内部类在编译时会被编译成一个独立的类文件,命名格式为:
你执行实例化new Parcelable.Creator<PackageInfo>
代码所在的类名+$数字.class  // 数字从 1 开始


  Class packageInfoClass = Class.forName("android.content.pm.PackageInfo");
  Field creatorField = packageInfoClass.getDeclaredField("CREATOR");
  creatorField.setAccessible(true);
  Object creatorObject = creatorField.get(null);
  Class creatorObjectClass = creatorObject.getClass();
  
  
creatorObjectClass是android.content.pm.PackageInfo$1这个class文件所
对应的class对象。
重点:一份class文件只对应内存里面的一个class对象,一个class对象里面
里面所包含的类名包括public和非public修饰的,我们可以创建无数个类名
所对应的对象。也就是说你通过java方法获取的class对象的地址
其实指向的是同一个地址:
Class packageInfoClass1 = Class.forName("android.content.pm.PackageInfo");
Class packageInfoClass2 = android.content.pm.PackageInfo.class;

packageInfoClass1和packageInfoClass2地址一致。


回到这里:
public class PackageInfo implements Parcelable {
    public static final Parcelable.Creator<PackageInfo> CREATOR = new Parcelable.Creator<PackageInfo>() {
        public PackageInfo createFromParcel(Parcel parcel) {
            return new PackageInfo(parcel);
        }

        public PackageInfo[] newArray(int i) {
            return new PackageInfo;
        }
    };


*****

}

匿名内部类在编译时会被编译成一个独立的类文件,命名格式为:
你执行实例化new Parcelable.Creator<PackageInfo>
代码所在的类名+$数字.class  // 数字从 1 开始


因为这段代码:
public static final Parcelable.Creator<PackageInfo> CREATOR = new Parcelable.Creator<PackageInfo>() {
        public PackageInfo createFromParcel(Parcel parcel) {
            return new PackageInfo(parcel);
        }

        public PackageInfo[] newArray(int i) {
            return new PackageInfo
;
        }
    };
        
重点:
是在android.content.pm.PackageInfo类里面实例化的Parcelable.Creator内部接口类,
所以是android.content.pm.PackageInfo$1.class文件。


我们Class packageInfoClassJava = Class.forName("android.content.pm.PackageInfo$1");
获取到的是android.jar里面的android.content.pm.PackageInfo$1所对应的class对象。


哪再看一下替换CREATOR静态字段所实例化的Parcelable.Creator内部接口类在哪个类里面执行
的:




肯定不是在android.content.pm.PackageInfo类里面执行的,所以被编译后所生成的class文件是:
YourJavaClassName$1,这样我们再通过Class.forName("YourJavaClassName");所获取到的class
对象就与android.content.pm.PackageInfo$1.class所对应的class对象不是同一个class对象了,
所以直接判断class对象地址是否相等即可:


  Class packageInfoClass = Class.forName("android.content.pm.PackageInfo");
  Field creatorField = packageInfoClass.getDeclaredField("CREATOR");
  creatorField.setAccessible(true);
  Object creatorObject = creatorField.get(null);
  Class creatorObjectClass = creatorObject.getClass();
  // CREATOR静态字段里的Object对应的class文件对象
  
  Class packageInfo$1Class = Class.forName("android.content.pm.PackageInfo$1");
  // 期望的CREATOR静态字段里的Object对应的class文件对象
  
  if(creatorObjectClass == packageInfo$1Class){
  // 未被篡改
  
  }else{
  // 被篡改
  
  }


同理,检测PMS是否被Proxy一样。


最后:
在JNI中,我们通过FindClass获取的类引用和通过GetObjectClass获取的类引用可能不同,
即使它们代表同一个类。这是因为JNI的类引用是本地引用,
所以,我们通常不能在JNI里直接比较两个jclass的地址。


SafeCheck发布了2.0.1新版本,感兴趣可以一试:
SafeCheck


感谢大家的支持和关注,请评论指正错误之处。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

65

主题

1808

回帖

5805

积分

硕士生

Nirithy

Rank: 6Rank: 6

金币
1064
好评
7
信誉
87

MT论坛新人MT论坛帅哥考神MT论坛最佳新人

QQ
发表于 2025-12-8 14:15:55 来自手机  | 显示全部楼层  来自 河北
劫持类加载器
回复

使用道具 举报

19

主题

1872

回帖

1万

积分

博士生

Rank: 7Rank: 7Rank: 7

金币
4944
好评
24
信誉
133

考神

发表于 2025-12-12 08:30:03 来自手机  | 显示全部楼层  来自 福建
链接失效了么,白屏啥也没有
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表