<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    sun.misc.Unsafe

    sun.misc.Unsafe是Java底層API(僅限Java內部使用,反射可調用)提供的一個神奇的Java類,Unsafe提供了非常底層的內存、CAS、線程調度、類、對象等操作、Unsafe正如它的名字一樣它提供的幾乎所有的方法都是不安全的,本節只講解如何使用Unsafe定義Java類、創建類實例。

    如何獲取Unsafe對象

    Unsafe是Java內部API,外部是禁止調用的,在編譯Java類時如果檢測到引用了Unsafe類也會有禁止使用的警告:Unsafe是內部專用 API, 可能會在未來發行版中刪除

    sun.misc.Unsafe代碼片段:

    import sun.reflect.CallerSensitive;
    import sun.reflect.Reflection;
    
    public final class Unsafe {
    
        private static final Unsafe theUnsafe;
    
        static {
            theUnsafe = new Unsafe();
            省去其他代碼......
        }
    
        private Unsafe() {
        }
    
        @CallerSensitive
        public static Unsafe getUnsafe() {
            Class var0 = Reflection.getCallerClass();
            if (var0.getClassLoader() != null) {
                throw new SecurityException("Unsafe");
            } else {
                return theUnsafe;
            }
        }
    
        省去其他代碼......
    }
    

    由上代碼片段可以看到,Unsafe類是一個不能被繼承的類且不能直接通過new的方式創建Unsafe類實例,如果通過getUnsafe方法獲取Unsafe實例還會檢查類加載器,默認只允許Bootstrap Classloader調用。

    既然無法直接通過Unsafe.getUnsafe()的方式調用,那么可以使用反射的方式去獲取Unsafe類實例。

    反射獲取Unsafe類實例代碼片段:

    // 反射獲取Unsafe的theUnsafe成員變量
    Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
    
    // 反射設置theUnsafe訪問權限
    theUnsafeField.setAccessible(true);
    
    // 反射獲取theUnsafe成員變量值
    Unsafe unsafe = (Unsafe) theUnsafeField.get(null);
    

    當然我們也可以用反射創建Unsafe類實例的方式去獲取Unsafe對象:

    // 獲取Unsafe無參構造方法
    Constructor constructor = Unsafe.class.getDeclaredConstructor();
    
    // 修改構造方法訪問權限
    constructor.setAccessible(true);
    
    // 反射創建Unsafe類實例,等價于 Unsafe unsafe1 = new Unsafe();
    Unsafe unsafe1 = (Unsafe) constructor.newInstance();
    

    獲取到了Unsafe對象我們就可以調用內部的方法了。

    allocateInstance無視構造方法創建類實例

    假設我們有一個叫com.anbai.sec.unsafe.UnSafeTest的類,因為某種原因我們不能直接通過反射的方式去創建UnSafeTest類實例,那么這個時候使用UnsafeallocateInstance方法就可以繞過這個限制了。

    UnSafeTest代碼片段:

    public class UnSafeTest {
    
       private UnSafeTest() {
          // 假設RASP在這個構造方法中插入了Hook代碼,我們可以利用Unsafe來創建類實例
          System.out.println("init...");
       }
    
    }
    

    使用Unsafe創建UnSafeTest對象:

    // 使用Unsafe創建UnSafeTest類實例
    UnSafeTest test = (UnSafeTest) unsafe1.allocateInstance(UnSafeTest.class);
    

    Google的GSON庫在JSON反序列化的時候就使用這個方式來創建類實例,在滲透測試中也會經常遇到這樣的限制,比如RASP限制了java.io.FileInputStream類的構造方法導致我們無法讀文件或者限制了UNIXProcess/ProcessImpl類的構造方法導致我們無法執行本地命令等。

    defineClass直接調用JVM創建類對象

    ClassLoader章節我們講了通過ClassLoader類的defineClass0/1/2方法我們可以直接向JVM中注冊一個類,如果ClassLoader被限制的情況下我們還可以使用UnsafedefineClass方法來實現同樣的功能。

    Unsafe提供了一個通過傳入類名、類字節碼的方式就可以定義類的defineClass方法:

    public native Class defineClass(String var1, byte[] var2, int var3, int var4);

    public native Class<?> defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);

    使用Unsafe創建TestHelloWorld對象:

    // 使用Unsafe向JVM中注冊com.anbai.sec.classloader.TestHelloWorld類
    Class helloWorldClass = unsafe1.defineClass(TEST_CLASS_NAME, TEST_CLASS_BYTES, 0, TEST_CLASS_BYTES.length);
    

    或調用需要傳入類加載器和保護域的方法:

    // 獲取系統的類加載器
    ClassLoader classLoader = ClassLoader.getSystemClassLoader();
    
    // 創建默認的保護域
    ProtectionDomain domain = new ProtectionDomain(
        new CodeSource(null, (Certificate[]) null), null, classLoader, null
    );
    
    // 使用Unsafe向JVM中注冊com.anbai.sec.classloader.TestHelloWorld類
    Class helloWorldClass = unsafe1.defineClass(
        TEST_CLASS_NAME, TEST_CLASS_BYTES, 0, TEST_CLASS_BYTES.length, classLoader, domain
    );
    

    Unsafe還可以通過defineAnonymousClass方法創建內部類,這里不再多做測試。

    注意:

    這個實例僅適用于Java 8以前的版本如果在Java 8中應該使用應該調用需要傳類加載器和保護域的那個方法。Java 11開始Unsafe類已經把defineClass方法移除了(defineAnonymousClass方法還在),雖然可以使用java.lang.invoke.MethodHandles.Lookup.defineClass來代替,但是MethodHandles只是間接的調用了ClassLoaderdefineClass,所以一切也就回到了ClassLoader

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类