久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      實例詳解Java反序列化之反射機制

      本篇文章給大家?guī)砹岁P(guān)于java的相關(guān)知識,其中主要介紹了java反射機制的相關(guān)問題,動態(tài)獲取程序信息以及動態(tài)調(diào)用對象的功能稱為Java語言的反射機制,希望對大家有幫助。

      實例詳解Java反序列化之反射機制

      推薦學(xué)習(xí):《java教程》

      每次聽到大佬在講或者看論壇等一些方式學(xué)java反序列化漏洞時,都會有一個詞叫做反射機制,大佬順勢借著這個詞,就給你造出一個payload,對于剛學(xué)java反序列化的我們,可能有點會懵圈,反正我是懵了,所以就趕緊學(xué)了一波,不然和大佬差距越來越大。所以這篇文章主要講述java反射機制

      Java反射機制

      Java的反射(reflection)機制是指在程序的運行狀態(tài)中,可以構(gòu)造任意一個類的對象,可以了解任意一個對象所屬的類,可以了解任意一個類的成員變量和方法,可以調(diào)用任意一個對象的屬性和方法。這種動態(tài)獲取程序信息以及動態(tài)調(diào)用對象的功能稱為Java語言的反射機制。反射被視為動態(tài)語言的關(guān)鍵。

      我不太擅長文字表達,還是上圖操作把

      不用反射機制的例子

      //定義一個animals接口interface animals {     public abstract void print();}//定義類來實現(xiàn)animals接口的抽象方法class Dog implements animals {     public void print() {         System.out.println("Dog");     }}class Cat implements animals {     public void print() {         System.out.println("Cat");     }}// 構(gòu)造一個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類尋找對應(yīng)的類來實現(xiàn)接口         animals a=zoo.getInstance("Cat");         if(a!=null)             a.print();     }}

      這時候添加動物,只需要

      • 添加類
      • 修改zoo
      • 修改main函數(shù)的動物類

      把上面修改為反射機制

      //定義一個animals接口interface animals {     public abstract void print();}//定義類來實現(xiàn)animals接口的抽象方法class Dog implements animals {     public void print() {         System.out.println("Dog");     }}class Cat implements animals {     public void print() {         System.out.println("Cat");     }}// 構(gòu)造一個zoo類// 之后如果我們在添加其他的實例的時候只需要修改zoo類class zoo {      public static animals getInstance(String className) {         animals a = null;         try {             //借助Class.forName尋找類名,并用newInstance實例化類似于new             a = (animals) Class.forName(className).newInstance();         } catch (Exception e) {             e.printStackTrace();         }         return a;     }}public class reflection {     public static void main(String[] args) {         //借助zoo類尋找對應(yīng)的類來實現(xiàn)接口(classname為當(dāng)前包名加類名)         animals a = zoo.getInstance("com.cc1.Dog");         if (a != null)             a.print();     }}

      這時候添加動物只需要

      • 添加類
      • 修改main函數(shù)的動物類

      省了一步,傳入類名可控,發(fā)現(xiàn)好像是存在的類都可以調(diào)

      反射機制方法

      我們用的最多的可能是

      • forName(調(diào)用類)
      • getMethod(調(diào)用類下方法)
      • invoke(執(zhí)行)
      • newInstance(實例化對象)
      Class.forName(className).getMethod(methodName).invoke(Class.forName(className).newInstance());

      下面我們用反射機制來彈出計算機(calc)或者記事本(notepad)

      由于彈出計算機有點多這次我就彈記事本把,總而言之,能彈出來就很美妙

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

      實例詳解Java反序列化之反射機制
      我們看下getRuntime函數(shù)
      實例詳解Java反序列化之反射機制
      得知,該函數(shù)是Runtime類獲取對象的方式,個人感覺是每用一次就調(diào)一次比較麻煩,為了不調(diào)用一次建立一個對象所以封裝成了函數(shù)

      類對象獲取方式

      • Class.forName(類名獲?。?/li>
      • zoo.class(已經(jīng)加載過的類)
      • obj.class(實例)
        實例詳解Java反序列化之反射機制

      類初始化

      修改zoo類,增加初始塊、靜態(tài)初始塊、和構(gòu)造函數(shù)

      class zoo {     //初始塊     {         System.out.println("1  " + this.getClass());     }      //靜態(tài)初始塊     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實例化類似于new             a = (animals) Class.forName(className).newInstance();         } catch (Exception e) {             e.printStackTrace();         }         return a;     }}

      類初始化執(zhí)行順序:靜態(tài)初始塊
      實例詳解Java反序列化之反射機制
      類實例化執(zhí)行順序:靜態(tài)初始塊 – > 初始塊 – > 構(gòu)造函數(shù)
      實例詳解Java反序列化之反射機制
      由此得知,類初始化和類實例化不一樣

      接下來增加zoo1類繼承zoo類

      class zoo1 extends zoo{     //初始塊     {         System.out.println("11  " + this.getClass());     }      //靜態(tài)初始塊     static {         System.out.println("12  " + zoo.class);     }      public zoo1() {         System.out.println("13  " + this.getClass());     }}

      子類初始化順序:父類靜態(tài)初始化塊 – > 子類靜態(tài)初始化塊
      實例詳解Java反序列化之反射機制
      子類實例化順序:父類靜態(tài)初始化塊 – > 子類靜態(tài)初始化塊 – > 父類初始化塊 – > 父類構(gòu)造函數(shù) – > 子類初始化塊 – >子類構(gòu)造函數(shù)
      實例詳解Java反序列化之反射機制
      以上可以得知,當(dāng)使用Class.forName時,且類靜態(tài)初始化塊可控,可以執(zhí)行任意代碼

      調(diào)用內(nèi)部類

      Class.forName(“java.lang.Runtime”)來獲取類(java.lang.Runtime是Runtime類的完整路徑)

      getMethod

      getMethod 的作用是通過反射獲取類的某個特定的公有方法。
      java支持類重載,但不能僅通過一個函數(shù)名確定一個函數(shù),所以在調(diào)用getMethod時,需要傳給它方法的參數(shù)類型列表
      Class.forName(“java.lang.Runtime”).getMethod(“exec”, String.class)

      invoke

      靜態(tài)和動態(tài)方法的區(qū)別
      實例詳解Java反序列化之反射機制

      invoke方法在getMethod類下,作用時傳遞參數(shù),執(zhí)行方法
      public Object invoke(Object obj, Object… args)
      第一個參數(shù)是getMethod獲取的方法的類對象(如果方法是靜態(tài)方法則傳類)
      獲取exec函數(shù)的類對象
      Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”))
      由于getRuntime是靜態(tài)方法,所以傳類
      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");

      實例詳解Java反序列化之反射機制

      指定構(gòu)造方法生成實例

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

      getConsturctor(函數(shù)可以選定指定接口格式的構(gòu)造函數(shù)(由于構(gòu)造函數(shù)也可以根據(jù)參數(shù)來進行重載)
      選定后我們可以通過newInstance(),并傳入構(gòu)造函數(shù)的參數(shù)執(zhí)行構(gòu)造函數(shù)

      ProcessBuilder類有兩個構(gòu)造函數(shù)

      • public ProcessBuilder(String… command)(String…變長的字符串?dāng)?shù)組String[].class)
      • public ProcessBuilder(List command)

      分別使用構(gòu)造方法

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

      執(zhí)行完構(gòu)造方法實例后,在進行強制轉(zhuǎn)化使用start函數(shù)即可

      ( (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”)));
      實例詳解Java反序列化之反射機制
      這里可能有人會好奇我寫的里那的另一個構(gòu)造函數(shù),String…command這個傳參為什么用new String[][]{{“notepad”}},不應(yīng)該是new String[]{“notepad”},現(xiàn)在用應(yīng)該的

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

      在這行打斷點調(diào)試
      實例詳解Java反序列化之反射機制
      我們傳的是一個字符串?dāng)?shù)組到了實例化的時候變成了一個字符串,再看看另一個構(gòu)造函數(shù)(List)

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

      依舊還是這行打斷點

      實例詳解Java反序列化之反射機制
      由此可知,List傳入時會被當(dāng)作Object的第一項,而String[]會被當(dāng)做Object,所以多加一層[]{}

      執(zhí)行私有方法

      通過函數(shù)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");

      推薦學(xué)習(xí):《java視頻教程》

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號