目录

  • 前言
  • Java反射机制
  • 反射机制方法
  • 指定构造方法生成实例
  • 执行私有方法
  • 总结

前言

每次听到大佬在讲或者看论坛等一些方式学java反序列化漏洞时,都会有一个词叫做反射机制,大佬顺势借着这个词,就给你造出一个payload,对于刚学java反序列化的我们,可能有点会懵圈,反正我是懵了,所以就赶紧学了一波,不然和大佬差距越来越大。所以这篇文章主要讲述java反射机制

Java反射机制

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

我不太擅长文字表达,还是上图操作把

不用反射机制的例子


//定义一个animals接口
interface animals {public abstract void print();
}
//定义类来实现animals接口的抽象方法
class Dog implements animals {public void print() {System.out.println("Dog");}
}class Cat implements animals {public void print() {System.out.println("Cat");}
}// 构造一个zoo类
// 之后如果我们在添加其他的实例的时候只需要修改zoo类
class zoo {public static animals getInstance(String animalsName) {animals a = null;if ("Dog".equals(animalsName)) {a = new Dog();}if ("Cat".equals(animalsName)) {a = new Cat();}return a;}
}public class reflection {public static void main(String[] args) {//借助zoo类寻找对应的类来实现接口animals a=zoo.getInstance("Cat");if(a!=null)a.print();}
}

这时候添加动物,只需要

  • 添加类
  • 修改zoo
  • 修改main函数的动物类

把上面修改为反射机制

//定义一个animals接口
interface animals {public abstract void print();
}//定义类来实现animals接口的抽象方法
class Dog implements animals {public void print() {System.out.println("Dog");}
}class Cat implements animals {public void print() {System.out.println("Cat");}
}// 构造一个zoo类
// 之后如果我们在添加其他的实例的时候只需要修改zoo类
class zoo {public static animals getInstance(String className) {animals a = null;try {//借助Class.forName寻找类名,并用newInstance实例化类似于newa = (animals) Class.forName(className).newInstance();} catch (Exception e) {e.printStackTrace();}return a;}
}public class reflection {public static void main(String[] args) {//借助zoo类寻找对应的类来实现接口(classname为当前包名加类名)animals a = zoo.getInstance("com.cc1.Dog");if (a != null)a.print();}
}

这时候添加动物只需要

  • 添加类
  • 修改main函数的动物类

省了一步,传入类名可控,发现好像是存在的类都可以调

反射机制方法

我们用的最多的可能是

  • forName(调用类)
  • getMethod(调用类下方法)
  • invoke(执行)
  • newInstance(实例化对象)

Class.forName(className).getMethod(methodName).invoke(Class.forName(className).newInstance());

下面我们用反射机制来弹出计算机(calc)或者记事本(notepad)

由于弹出计算机有点多这次我就弹记事本把,总而言之,能弹出来就很美妙

Runtime.getRuntime().exec("notepad");


我们看下getRuntime函数

得知,该函数是Runtime类获取对象的方式,个人感觉是每用一次就调一次比较麻烦,为了不调用一次建立一个对象所以封装成了函数

类对象获取方式

  • Class.forName(类名获取)
  • zoo.class(已经加载过的类)
  • obj.class(实例)

类初始化

修改zoo类,增加初始块、静态初始块、和构造函数


class zoo {//初始块{System.out.println("1  " + this.getClass());}//静态初始块static {System.out.println("2  " + zoo.class);}public zoo() {System.out.println("3  " + this.getClass());}public static animals getInstance(String className) {animals a = null;try {//借助Class.forName寻找类名,并用newInstance实例化类似于newa = (animals) Class.forName(className).newInstance();} catch (Exception e) {e.printStackTrace();}return a;}
}

类初始化执行顺序:静态初始块

类实例化执行顺序:静态初始块 - > 初始块 - > 构造函数

由此得知,类初始化和类实例化不一样

接下来增加zoo1类继承zoo类


class zoo1 extends zoo{//初始块{System.out.println("11  " + this.getClass());}//静态初始块static {System.out.println("12  " + zoo.class);}public zoo1() {System.out.println("13  " + this.getClass());}
}

子类初始化顺序:父类静态初始化块 - > 子类静态初始化块

子类实例化顺序:父类静态初始化块 - > 子类静态初始化块 - > 父类初始化块 - > 父类构造函数 - > 子类初始化块 - >子类构造函数

以上可以得知,当使用Class.forName时,且类静态初始化块可控,可以执行任意代码

调用内部类

Class.forName(“java.lang.Runtime”)来获取类(java.lang.Runtime是Runtime类的完整路径)

getMethod

getMethod 的作用是通过反射获取类的某个特定的公有方法。
java支持类重载,但不能仅通过一个函数名确定一个函数,所以在调用getMethod时,需要传给它方法的参数类型列表
Class.forName(“java.lang.Runtime”).getMethod(“exec”, String.class)

invoke

静态和动态方法的区别

invoke方法在getMethod类下,作用时传递参数,执行方法
public Object invoke(Object obj, Object… args)
第一个参数是getMethod获取的方法的类对象(如果方法是静态方法则传类)
获取exec函数的类对象
Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”))
由于getRuntime是静态方法,所以传类
invoke(Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”)),“calc.exe”)

最后我们合并一下


Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")), "notepad");

指定构造方法生成实例


String str="notepad";
ProcessBuilder pb = new ProcessBuilder(str);
pb.start();

getConsturctor(函数可以选定指定接口格式的构造函数(由于构造函数也可以根据参数来进行重载)
选定后我们可以通过newInstance(),并传入构造函数的参数执行构造函数

ProcessBuilder类有两个构造函数

  • public ProcessBuilder(String… command)(String…变长的字符串数组String[].class)
  • public ProcessBuilder(List command)

分别使用构造方法

  • Class.forName(“java.lang.ProcessBuilder”).getConstructor(String[].class).newInstance(new String[][]{{“notepad”}})
  • Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))

执行完构造方法实例后,在进行强制转化使用start函数即可

( (ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))).start();

实际中,肯定用不了,哪有这么好的事,还是接着反射把

Class.forName(“java.lang.ProcessBuilder”).getMethod(“start”).invoke(clazz.getConstructor(List.class).newInstance(Arrays.asList(“notepad”)));

这里可能有人会好奇我写的里那的另一个构造函数,String…command这个传参为什么用new String[][]{{“notepad”}},不应该是new String[]{“notepad”},现在用应该的

((ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(String[].class).newInstance(new String[]{“notepad”})).start();

在这行打断点调试

我们传的是一个字符串数组到了实例化的时候变成了一个字符串,再看看另一个构造函数(List)

( (ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))).start();

依旧还是这行打断点


由此可知,List传入时会被当作Object的第一项,而String[]会被当做Object,所以多加一层[]{}

执行私有方法

通过函数getDeclaredConstructor获取私有方法,再利用setAccessible(true)打破私有方法限制


Class cls = Class.forName("java.lang.Runtime");
Constructor m = cls.getDeclaredConstructor();
m.setAccessible(true);
cls.getMethod("exec", String.class).invoke(m.newInstance(), "notepad");

总结

这里也是通过反射机制调用任意类,大致让我这个门外汉也明白了反射,看到这里的你们想比应该也明白了,如果有什么疑问,我们可以一起交流学习,也请大佬多多指点

大家可以关注菜鸡的公众号,有什么好想法也可以让我学习一下,有什么问题可以一块解决,由于二维码违规,下面是base64编码的文字

5b6u5L+h5YWs5LyX5Y+34oCc5a6J5YWo5re35a2Q4oCd77yM5Y+v5Lul55So5b6u5L+h5pCc5LiA5pCc77yM5q2j5Zyo5a6M5ZaE5LitLi4uLi4u

Java反序列化之反射机制相关推荐

  1. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  2. JAVA基础--JAVA中的反射机制详解

    JAVA反射机制     JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能 ...

  3. java 有哪些反射机制_Java 的反射机制你了解多少?

    不知道多少次听说过了Java反射机制的使用,比如:Spring 框架如何实例化IoC容器中的Bean,编码过程中如何动态的清理对象中的字段信息等等.工作中只是听说.看同事们编码实践,但是自己却只是概念 ...

  4. java代码安全检测机制_全面解析:java中的反射机制,内含代码验证解析

    什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功 ...

  5. 根据实例详解Java中的反射机制

    概念: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java ...

  6. JAVA Reflection(反射机制)续

    接上一篇文章  JAVA Reflection(反射机制) 动态数组 java.lang.reflect.Array static Object set(Object array, int index ...

  7. JAVA Reflection(反射机制)

    Java 反射机制 反射机制简介 反射机制应用示例 简单的Ioc实现 代理模式 Java动态代理 简单的Aop实现 "程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言" ...

  8. Java语言基础-反射机制、正则表达式

    反射机制 反射机制是在运行状态中,对于任意一个类,都能知道这个类(class文件)的所有属性和方法. 对于任意一个对象,都能调用它的任意一个方法和属性. 这种动态获取信息以及动态调用对象的方法的功能称 ...

  9. formdata 接受参数中带有class 对象_浅析JAVA中的反射机制及对Servlet的优化

    今天来聊聊java中的反射机制,工作以后发现很多东西动不动就要使用反射或者动态代理,如果不能很好的理解反射,那么对于动态代理等一些重要的设计模式就会有种不够通透的感觉. 所谓的反射,就是在运行状态中, ...

最新文章

  1. LeetCode刷题-6
  2. sudo及其配置文件sudoers
  3. 第四范式恭祝大家新春快乐!
  4. BZOJ2705 [SDOI2012]Longge的问题 欧拉函数
  5. 【TensorFlow-windows】TensorBoard可视化
  6. Windows CE 6.0中断处理过程(转载)
  7. Spring RESTful错误处理
  8. mysql密码高级_mysql高级操作
  9. 认清一个人,看这四点就够了
  10. socket抓包_64、抓包分析tcp与udp
  11. Linux Shell编程 - 正则表达式
  12. FISCO BCOS 控制台 部署合约 调用 查看已部署合约的地址
  13. Win7系统下解决VB6.0鼠标滚轮支持
  14. 设计模式 (十四) Cglib动态代理模式
  15. 计算机系统硬件基本组成
  16. VScode:禁止VScode自动升级
  17. 《东周列国志》第十回 楚熊通僭号称王 郑祭足被胁立庶
  18. Apostrophe not preceded错误
  19. ThinkPHP门面源码解析
  20. 数据库插入微信表情错误

热门文章

  1. No gradients provided for any variable, check your graph for ops that do not support gradients
  2. 【历史上的今天】4 月 30 日:信息论之父出生;万维网对所有人免费开放;图灵奖算法先驱诞生
  3. 离散数学 --- 图论基础 --- 无向图的连通性和有向图的连通性
  4. 北京中科红旗软件技术有限公司
  5. 自主创新进展制造世界主要轴承制作强国
  6. 原创_Android Jetpack Compose 最全上手指南,互联网寒冬公司倒闭后
  7. CFA【异常检测:Embedding_based】
  8. python模型训练 warm_start_随机森林入门攻略(内含R、Python代码)
  9. 马化腾:我和太太也是QQ认识的
  10. vscode调试nodejs不要太爽啊