Java中的Unsafe在安全领域的一些应用总结和复现

本文介绍了Java中的Unsafe类在安全领域的应用,包括内存级别修改值、创建对象、创建VM Anonymous Class,以及如何利用这些特性绕过防御措施,如关闭RASP、实现webshell、创建内存马等。同时探讨了相关风险,如文件落地可能被监控以及内存马的隐蔽性。
摘要由CSDN通过智能技术生成

Python微信订餐小程序课程视频

https://edu.csdn.net/course/detail/36074

Python实战量化交易理财系统

https://edu.csdn.net/course/detail/35475
目录* 0 前言

0 前言

unsafe里面有很多好用的方法,比如allocateInstance可以直接创建实例对象,defineAnonymousClass可以创建一个VM匿名类(VM Anonymous Class),以及直接从内存级别修改对象的值。

1 基本使用

首先是获取Unsafe对象,一般使用反射获取Unsafe,否则会被Java安全机制拦截,代码如下

public static Unsafe getUnsafe() throws Exception{
        Class aClass = Class.forName("sun.misc.Unsafe");
        Constructor declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        Unsafe unsafe= (Unsafe) declaredConstructor.newInstance();
        return unsafe;
    }

1.1 内存级别修改值

这里首先要提到的是,在jvm中,对实例的Field进行了有规律的存储,具体可见JVM相关知识,而通过一个偏移量可以从内存中找到相应的Field值。在Unsafe中获取偏移量的方法是staticFieldOffset(Field var1)和objectFieldOffset(Field var1)这两个方法,输入一个Field对象后,会返回该Field在其相应的类中的内存偏移量是多少。通过获得的偏移量可进一步调用putInt、putLong、putObject等方法对实例的field进行修改。

例如:

package com.bitterz.unsafe;

import sun.misc.Unsafe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class UnsafeTest {
    private int a = 1;
    private String string = "whoami";
    public UnsafeTest(){}

    public void test(){    }

    public static void main(String[] args) throws Exception {
        Unsafe unsafe = getUnsafe();
        UnsafeTest unsafeTest = new UnsafeTest();
        
        // 修改int
        Field f = Class.forName("com.bitterz.unsafe.UnsafeTest").getDeclaredField("a");
        long l = unsafe.objectFieldOffset(f);
        unsafe.putInt(unsafeTest, l, 9999);
        System.out.println(unsafeTest.a);

        // 修改string
        Field f2 = Class.forName("com.bitterz.unsafe.UnsafeTest").getDeclaredField("string");
        long l2 = unsafe.objectFieldOffset(f2);
        unsafe.putObject(unsafeTest, l2, "bitterz");
        System.out.println(unsafeTest.string);
    }

    public static Unsafe getUnsafe() throws Exception{
        Class aClass = Class.forName("sun.misc.Unsafe");
        Constructor declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        Unsafe unsafe= (Unsafe) declaredConstructor.newInstance();
        return unsafe;
    }
}


其输出结果为

但对final和static修饰的field这种修改方法无效。另外还可以通过偏移量使用getInt()、getObject()等方法获取实例的field值,这种方法也可以作为反射被限制时的一种绕过。

1.2 创建对象

Unsafe中有个allocateInstance方法,可以无视构造方法,直接利用类对象构建实例,这种方法往往能够减少反射创建实例时可能遇到的各种阻碍,比如类的依赖关系。

比如前面创建Unsafe时使用了反射,不能直接进行创建,那么可以使用unsafe进行创建(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值