Day2-javasec-Reflection-sun.misc.Unsafe

java反射机制

0x01 获取Class对象

方法:

  • 类名.class
  • classLoader.loadClass
  • Class.forName()

🅰️注意

获取数组类型的对象

Class<?> doubleArray = Class.forName("[D");//相当于double[].class
Class<?> cStringArray = Class.forName("[[Ljava.lang.String;");// 相当于String[][].class

获取内部类

com.dem0.test$Hello

0x02 反射Runtime

普通执行

Runtime.getRuntime().exec("whoami")

反射执行

Class runtimeClass = Class.forName("java.lang.Runtime");//反射拿到class
Constructor constr = runtimeClass.getDeclaredConstructor();//获取构造方法
constr.setAccessible(true);//将构造方法的属性设置未public
Obejct runtimeIns = constr.newInstance();//创建新示例
Method runtimeMethod = runtimeClass.getMethod("exec",String.class);//反射获取方法
Process process = (Process) runtimeMethod.invoke(runtimeIns,cmd);//反射调用方法

0x03 反射调用类方法

获取所有类方法

Method methods = cla.getDeclaredMethods()

获取当前类指定的成员方法

Method method = clazz.getDeclaredMethod("方法名", 参数类型如String.class,多个参数用","号隔开);

🚡 getMethod和getDeClaredMethod区别:

第一个只能获取到public和父类方法

第二个所有方法都能获取

🈂️调用方法

method.invoke(方法实例对象, 方法参数值,多个参数值用","隔开);

第一个参数时实例化的对象,如果时static类型的可以直接传递null。

第二个参数, 有参数那么就必须严格的依次传入对应的参数类型

0x04 反射调用成员变量

成员变量: fields

获取所有成员变量

Field fields = clazz.getDclaredFields();

获取当前类指定的成员变量

 clazz.getDclaredField(“name”);

获取值

filed.get(Object)

修改

filed.set(Object,value)

field.setAccessible(true)

yyds!

sun.misc.Unsafe

底层API 提供关于内存、CAS、线程调度、类、对象

0x01 获取Unsafe对象

 public final class Unsafe {
 private Unsafe() {
    }

    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }

发现他的源码不难看出来,这个类不能被继承,而且通过getUnsafe必须时跟加载器才行。

// 反射获取Unsafe的theUnsafe成员变量
Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");

// 反射设置theUnsafe访问权限
theUnsafeField.setAccessible(true);

// 反射获取theUnsafe成员变量值
Unsafe unsafe = (Unsafe) theUnsafeField.get(null);

当然我们也可以反射拿到构造方法最后新建实例

Constructor constructor = Unsafe.class.getDeclaredConstructor();
constructor.setAccessible(true);//设置可以被访问
Unsafe unsafe1 = (Unsafe) constructor.newInstance();

0x02 NB方法-allocateInstance

假如我们现在有一个类,因为一些原因我们既不可以通过new和反射来新建实例。那么allocateInstance可以绕过这个限制。

UnSafeTest test = (UnSafeTest) unsafe1.allocateInstance(UnSafeTest.class);

这样我们就可以绕过RASP的一些限制

0x02 NB方法-defineClass

之前我学过可以通过defineClass0/1/2直接向JVM注册一个类。那么我们在ClassLoader被限制的情况下使用这个方法。

unsafe.defineClass(Test_class_name,test_class_byte,0,length)

🅰️ 或者调用传入类加载器和保护域

// 获取系统的类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();

// 创建默认的保护域
ProtectionDomain domain = new ProtectionDomain(
    new CodeSource(null, (Certificate[]) null), null, classLoader, null
);

// 使用Unsafe向JVM中注
Class helloWorldClass = unsafe1.defineClass(
    TEST_CLASS_NAME, TEST_CLASS_BYTES, 0, TEST_CLASS_BYTES.length, classLoader, domain
);

defineAnonymousClass方法还可以创建内部类

🏷 注意!

这个实例只在java8之前版本的,在java8中应该使用第二种方法。

Java 11开始Unsafe类已经把defineClass方法移除了(defineAnonymousClass方法还在)。但是可以使用Lookup.defineClass代替,但是只是间接调用Loader的define,所以没得玩了。

测试sun.misc.unsafe

image-20211229011503686

image-20211229011718838
fineAnonymousClass`方法还在)。但是可以使用Lookup.defineClass代替,但是只是间接调用Loader的define,所以没得玩了。

测试sun.misc.unsafe

image-20211229011503686

image-20211229011718838

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值