java安全学习-第二天(反射补充)
0x01、前言
第一天的文章中有个小点写错了,小标题”如何执行类的私有方法”有误,应该改成”如何在类的构造函数是私有类型的情况下进行调用”
还有,方法和函数本质上一个东西,本人对这块叫法比较随意
今天补充一些内容
1、
如果一个类没有无参构造方法
如果一个类并非单例模式(不含getxxx的静态方法)
那该怎样成功的调用这个类呢?
2、类中的私有方法有办法利用吗?
构造方法(构造函数)—->无参构造方法/有参构造方法
接下来开始探索
0x02、开始
第一种情况的应对
我们需要了解一个新的知识点
getConstructor函数
这个函数是用来获得目标类具体构造方法的
而获得构造方法后,我们用第一天将过的知识点class.newInstance()来执行构造方法
我来举一个例子🌰
import java.lang.reflect.*;public class rat{public static void main(String[] args) throws Exception {try{Class clazz = Class.forName("java.lang.ProcessBuilder");Constructor name[] = clazz.getConstructors();for (int i = 0; i < name.length; ++i) {System.out.println(name[i]);}}catch (Exception e){e.printStackTrace();}}}

可以看到,目标ProcessBuilder中有两个含参构造方法
那我们又该如何用这个方法去执行命令呢?
exp:
import java.lang.reflect.*;import java.util.Arrays;import java.util.List;import java.io.IOException;public class rat{public static void main(String[] args) throws Exception {try{Class clazz = Class.forName("java.lang.ProcessBuilder");String[] cmd = new String[] {"open", "-a", "Calculator"};clazz.getMethod("start").invoke(clazz.getConstructor(List.class).newInstance(Arrays.asList(cmd)));}catch (Exception e){e.printStackTrace();}}}

估计你们会有些疑惑。start是哪来的?为什么要用List.class
start方法是ProcessBuilder中执行命令的一种方法
而我们这里,默认初始化时是使用List的参数(也就是第一种有参构造函数),所以用到了List.class
毕竟要把构造函数运行后才算真正调用了一个类
先给ProcessBuilder附上初始化的值——>再由start创建一个新进程执行命令
第二种情况的应对
我们以Runtime类举例
在第一天中,我们是使用了单例模式下静态方法的特性,才能成功调用私有属性的方法exec
那我们是否可以不用第一天的方法呢?
答案是肯定的
我们先来了解获取方法的区别,这里引用p牛的文章
getMethod 系列方法获取的是当前类中所有公共方法,包括从父类继承的方法
getDeclaredMethod 系列方法获取的是当前类中“声明”的方法,是实在写在这个类里的,包括私有的方法,但从父类里继承来的就不包含了
同理,getConstructor和getDeclaredConstructor也是如此
一个是获取public类构造方法,一个是获取所有的构造方法(包括私有)
Exp:
import java.lang.reflect.*;public class siyou{public static void main(String[] args) throws Exception {try{Class clazz = Class.forName("java.lang.Runtime");String cmd = "open"+" "+"-a"+" "+"Calculator";Constructor cmds = clazz.getDeclaredConstructor(); //获取私有构造方法cmds.setAccessible(true); //设置作用域使私有函数能执行clazz.getMethod("exec",String.class).invoke(cmds.newInstance(),cmd); //私有构造方法初始化变为Runtime class}catch (Exception e){e.printStackTrace();}}}
关于setAccessible,这个,我认为只要记住就行了,它的作用是修改作用域,能让你的私有函数(构造方法)执行
0x03、小结
第一天的知识点理顺后,感觉作用还是蛮大的,能更快的理解第二天的知识点
最后,以花爷的话结尾
“Web,有手就行”
