• 『Java安全』Unsafe类


    前言

    jdk版本基于8u111

    简介

    https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/misc/Unsafe.java

    Unsafe类提供一些低级、不安全的操作,调用前必须确保安全。使用Unsafe可以进行类定义、类实例化、修改内存等操作。

    在这里插入图片描述

    警告

    Unsafe抛出的任何错误都是jvm级别,会导致JVM崩溃的错误,而不是普通异常

    在这里插入图片描述

    unsafe类的获取

    Unsafe的自动实例化在自身的静态代码块

    在这里插入图片描述
    仅拥有一个private构造器,getter有严格验证:只允许根加载器调用该方法

    在这里插入图片描述
    因此可以考虑反射获取,常规两种方式:调构造器或者调getter

            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            Unsafe unsafe1 = (Unsafe) f.get(null);
    
            Constructor constructor = Unsafe.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            Unsafe unsafe2 = (Unsafe) constructor.newInstance();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    常用方法

    不调用构造器实例化类

    Unsafe.allocateInstance(Class cls)方法提供绕过任意构造器实例化的功能
    在这里插入图片描述

    		Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            Unsafe unsafe1 = (Unsafe) f.get(null);
    
            TestAllocateInst testAllocateInst = (TestAllocateInst) unsafe1.allocateInstance(TestAllocateInst.class);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    package unsafeTest;
    
    public class TestAllocateInst {
    
        public TestAllocateInst() {
            System.out.println("Constructor");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行并未触发构造器

    在这里插入图片描述

    defineClass定义类

    绕过安全检查直接向jvm注册类

    在这里插入图片描述
    传入六个参数:类名、字节码、字节码起始、字节码长度、加载器、保护域

    package unsafeTest;
    
    import sun.misc.Unsafe;
    import java.io.File;
    import java.io.FileInputStream;
    import java.lang.reflect.Field;
    import java.security.CodeSource;
    import java.security.ProtectionDomain;
    import java.security.cert.Certificate;
    
    public class TestDefine {
        public static void main(String[] args) throws Exception{
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            Unsafe unsafe = (Unsafe) f.get(null);
            
            FileInputStream fis = new FileInputStream(new File("src//main//java//unsafeTest//TestAllocateInst.class"));
            byte[] bytes = new byte[fis.available()];
            fis.read(bytes);
    
            ClassLoader clazzLoader = ClassLoader.getSystemClassLoader();
            ProtectionDomain domain = new ProtectionDomain(
                    new CodeSource(null, (Certificate[]) null), null, clazzLoader, null
            );
            
            Class clazz = unsafe.defineClass("TestAllocateInst", bytes, 0, bytes.length, clazzLoader, domain);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    抛出任意错误

    在这里插入图片描述
    在这里插入图片描述

    获取内存信息

    在这里插入图片描述

    参考

    https://javasec.org/javase/Unsafe

    欢迎关注我的CSDN博客 :@Ho1aAs
    版权属于:Ho1aAs
    本文链接:https://ho1aas.blog.csdn.net/article/details/126928128
    版权声明:本文为原创,转载时须注明出处及本声明

  • 相关阅读:
    Map集合保存数据库
    mysql的分组group by
    Vue3.2插槽全家桶
    记首次参加网络安全比赛(初赛-知识竞赛,决赛-CTF夺旗赛-解题模式)
    地图之战争迷雾/地图算法/自动导航(一)
    授人以渔 - 如何自行查询任意 SAP UI5 控件属性的文档和技术实现细节试读版
    随想录一刷Day37——贪心算法
    深入浅出 OkHttp 源码解析及应用实践
    CMake技术总结
    2023CSP-S初赛复习整理
  • 原文地址:https://blog.csdn.net/Xxy605/article/details/126928128