日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 反射_Java代码审计基础之反射

發(fā)布時間:2024/8/5 c/c++ 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 反射_Java代码审计基础之反射 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

先來一段反射的概念:

在程序運行的時候動態(tài)裝載類,查看類的信息,生成對象,或操作生成對象。
類在運行的時候,可以得到該類的信息,并且可以動態(tài)的修改這些信息

反射類的首要操作 - 獲取類

獲取類有 三種 方法:

假設(shè)類名為 Cat

(1)直接根據(jù)類名獲取類

Class a = Cat.class;

(2)通過Class.forName 獲取類,需要打全指定類的路徑

Class a = Class.forName("org.xiaopan.test.Cat");

注意:

Class.forName 需要一個異常處理。不然編輯器無法通過。

(3)通過實例化的方式獲取類

Class a = (new Cat()).getClass();

反射構(gòu)造方法

吾有一類,曰:

class Cat{ //構(gòu)造方法,形參為空 public Cat(){ System.out.println("Cat->nullCat"); } //構(gòu)造方法,形參為 一個String類型 public Cat(String a){ System.out.println("Cat->aCat,a=" + a); } //私有構(gòu)造方法,形參為 一個String類型 和 一個Integer類型 private Cat(String a,Integer b){ System.out.println("Cat->abCat,a=" + a + "b=" + b.toString()); } //構(gòu)造方法,形參為 一個String數(shù)組類型 和 一個Map類型 public Cat(String[] aa,Map bb){ System.out.println("Cat->aabbCat"); System.out.println("aa=" + Arrays.toString(aa)); System.out.println("bb=" + bb); }}

無參構(gòu)造方法調(diào)用

try{ //獲取到類 Class a = Cat.class; //通過反射獲取到指定類下的構(gòu)造方法 //要獲取的構(gòu)造方法為: //public Cat() //由于該構(gòu)造方法無參數(shù),所以我們傳入一個 null 即可,也可以不傳 Constructor constructor1 = a.getConstructor(null); //實例化類 constructor1.newInstance(null);}catch (Exception e){ System.out.println(e);}

輸出:

注意:

getConstructor 需要加一個異常處理。

一個參數(shù)的構(gòu)造方法調(diào)用

try{ //獲取到類 Class a = Cat.class; //通過反射獲取到指定類下的構(gòu)造方法 //要獲取的構(gòu)造方法為: //public Cat(String a) //由于該構(gòu)造方法有一 String類型 參數(shù) //在進(jìn)行 getConstructor 反射時,就需要指定傳參類型為 String.class Constructor constructor1 = a.getConstructor(String.class); //在實例化時,進(jìn)行傳參 constructor1.newInstance("testvalue");}catch (Exception e){ System.out.println(e);}

輸出:

多個參數(shù)的私有構(gòu)造方法調(diào)用

注意,這里調(diào)用的構(gòu)造方法是私有的哦~

try{ //獲取到類 Class a = Class.forName("org.xiaopan.test.Cat"); //通過反射獲取到指定類下的構(gòu)造方法 //要獲取的 私有 構(gòu)造方法為: //private Cat(String a,Integer b) // //由于是 私有 方法,獲取私有方法的函數(shù)為 getDeclaredConstructor //由于有兩個參數(shù),所以需要在 getDeclaredConstructor 傳入對應(yīng)的參數(shù)類型 Constructor c = a.getDeclaredConstructor(String.class, Integer.class); //設(shè)置強制反射 c.setAccessible(true); //構(gòu)造函數(shù)實例化,并傳參 //這里有個注意點,看下文的注意 c.newInstance(new Object[]{"abcd",123456});}catch (Exception e){ System.out.println(e);}

輸出:

注意:

參考了大佬的文章(參考文章在本文末尾 Referer 中),文章說 jdk1.4和 jdk1.5 處理調(diào)用的方法有區(qū)別

jdk1.4中,數(shù)組每個元素對應(yīng)一個參數(shù)

jdk1.5中,整個數(shù)組是一個參數(shù),用一個對象包起來

所以我們調(diào)用的傳參的時候,需要使用這種格式:

c.newInstance(new Object[]{"abcd",123456});//即new Object[]{"abcd",123456} 的格式,用一個對象包裹起來

形參為數(shù)組和Map類型的構(gòu)造方法調(diào)用

字符串?dāng)?shù)組

創(chuàng)建格式:

String[] a = {"abc", "def"};

Map:

java中的map,可以理解為“可自定義鍵值的數(shù)組”

形參為數(shù)組和Map類型的構(gòu)造方法調(diào)用:

try{ //獲取類 Class a = (new Cat()).getClass(); //調(diào)用的構(gòu)造方法為: //public Cat(String[] aa,Map bb) //照常打 xxx.class 即可。java 萬物皆對象 Constructor c = a.getConstructor(String[].class, Map.class); //創(chuàng)建一個map Map m = new HashMap(); m.put("a_key","a_value"); //實例化構(gòu)造函數(shù),注意要用 Object包裹的形式 //new String[]{} 是當(dāng)場初始化字符串?dāng)?shù)組,當(dāng)場賦值 c.newInstance(new Object[]{new String[]{"a","b","c"}, m});}catch (Exception e){ System.out.println(e);}

輸出:

反射方法

簡介:

反射方法和上文的反射構(gòu)造方法差不多,如果是私有的話也是要設(shè)置強行調(diào)用,并且獲取方法的函數(shù)為 getDeclaredxxxx

吾有一類:

class Cat{ public void a(){ System.out.println("a invoke"); } public String[] b(String[] b){ return b; } public static void c(){ System.out.println("cccccc"); }}

反射無參數(shù)方法

try{ //獲取類 Class a = Class.forName("org.xiaopan.test.Cat"); //先實例化,后面調(diào)用方法的時候需要使用實例化好的類 //注意,實例化之后返回的類型就是對于的類,做好類型轉(zhuǎn)換 Cat cat =(Cat) a.newInstance(); //調(diào)用的方法為: //public void a() // //獲取方法,需要指定要獲取的方法名 Method m = a.getMethod("a", null); //調(diào)用方法,調(diào)用方法時,用 上一步代碼中獲取到的方法進(jìn)行 invoke 調(diào)用操作 //而invoke方法中,第一個參數(shù)是實例化好的類 //第二個參數(shù)就是需要傳入的參數(shù) m.invoke(cat,null);}catch (Exception e){ System.out.println(e);}

輸出:

反射有參數(shù)有返回值方法

try{ //獲取類 Class a = Class.forName("org.xiaopan.test.Cat"); //先實例化,后面調(diào)用方法的時候需要使用實例化好的類 //注意,實例化之后返回的類型就是對于的類,做好類型轉(zhuǎn)換 Cat cat =(Cat) a.newInstance(); //調(diào)用的方法為: //public String[] b(String[] b) // //獲取方法,需要指定要獲取的方法名 Method m = a.getMethod("b",String[].class); //調(diào)用方法,調(diào)用方法時,用 上一步代碼中獲取到的方法進(jìn)行 invoke 調(diào)用操作 //調(diào)用時,如果參數(shù)是字符串?dāng)?shù)組,或者兩個以上的參數(shù) //最好使用 new Object[]{} 的形式傳入 //兼容性好 //由于有返回值,我們在調(diào)用的時候也需要進(jìn)行接收 //接受類型就看調(diào)用的類返回的類型了 String[] strs = (String[]) m.invoke(cat, new Object[]{new String[]{"str1","str2","str3"}}); //打印數(shù)組: //for each打印數(shù)組,先指定抽出來的元素類型 //然后以冒號 : 分隔,左邊是抽出元素變量名,右邊是原數(shù)組 for (String str:strs){ System.out.println(str); }}catch (Exception e){ System.out.println(e);}

輸出:

反射靜態(tài)方法

由于靜態(tài)方法不需要實例化類,所以在 getMethod 的時候,直接傳個 null 即可。也不需要 newInstance 類了。

try{ //獲取類 Class a = Class.forName("org.xiaopan.test.Cat"); //調(diào)用的方法為: //public static void c() // //獲取方法 Method m = a.getMethod("c"); //由于是靜態(tài)方法。直接調(diào)用,類對象中傳入null即可 m.invoke(null);}catch (Exception e){ System.out.println(e);}

輸出:

反射屬性

反射屬性也大同小異

吾有一類:

class Cat{ public String name = "maomao"; //公共 String類型 屬性 public static Boolean sex = true; //公共 靜態(tài) String類型 屬性 private Integer age = 10; //私有 Integer類型 屬性}

反射公共屬性

try{ //獲取類 Class a = Class.forName("org.xiaopan.test.Cat"); //先實例化,后面獲取屬性的時候需要使用實例化好的類 Cat cat = (Cat) a.newInstance(); //屬性: //public String name = "maomao"; // //獲取屬性 Field m = a.getField("name"); //獲取屬性值 //需要傳入實例化類作為對象 String name = (String) m.get(cat); System.out.println(name);}catch (Exception e){ System.out.println(e);}

輸出:

反射公共靜態(tài)屬性

靜態(tài)屬性也一樣,不需要實例化即可調(diào)用:

try{ //獲取類 Class a = Class.forName("org.xiaopan.test.Cat"); //屬性: //public static Boolean sex = true; // //獲取屬性 Field m = a.getField("sex"); //獲取屬性值,靜態(tài)屬性不需要實例化類,直接傳入null作為類對象即可 Boolean b = (Boolean) m.get(null); System.out.println(b); //設(shè)置屬性值 m.set(null,false); b = (Boolean) m.get(null); System.out.println(b);}catch (Exception e){ System.out.println(e);}

輸出:

反射私有屬性

私有屬性也一樣,需要暴力反射

try{ //獲取類 Class a = Class.forName("org.xiaopan.test.Cat"); //先實例化,后面獲取屬性的時候需要使用實例化好的類 Cat cat = (Cat) a.newInstance(); //屬性: //private Integer age = 10; // //獲取私有屬性 Field m = a.getDeclaredField("age"); //設(shè)置強制反射 m.setAccessible(true); //獲取屬性值 Integer age = (Integer) m.get(cat); //注意輸出的時候要將非String類型 toString 哦,規(guī)范一點 System.out.println(age.toString());}catch (Exception e){ System.out.println(e);}

輸出:

引用包錯誤的報錯:

用IDEA寫代碼的時候,可以會遇到奇怪報錯,如:

代碼本來就沒問題,但還是報錯了:

這個時候可以看看代碼最上面,看看IDEA是不是自動引入了錯誤的包:

發(fā)現(xiàn)有引用錯誤的包,將其刪掉即可,然后再重新在 Method上進(jìn)行修復(fù):

Runtime.getRuntime.exec 反射

了解 Runtime.getRuntime.exec

Runtime.getRuntime.exec 是Java中執(zhí)行系統(tǒng)命令的方法

簡單使用如下:

byte[] a = new byte[1024];Process cmd = Runtime.getRuntime().exec("whoami");InputStream input = cmd.getInputStream();input.read(a);String res = new String(a);System.out.println(res);

我們來一一分析下,重點就兩大塊:Process 和 InputStream

Process cmd = Runtime.getRuntime().exec(“whoami”)

首先先看看 Runtime.getRuntime().exec 是什么東西,返回值類型是什么樣的:

在手冊上查看描述:

可知 exec 函數(shù)就是執(zhí)行系統(tǒng)命令用的

在去看看源碼做二次確認(rèn)

返回類型是 Process 類型,所以我們調(diào)用的時候用 Process 類型接收返回值

Process類提供進(jìn)程輸入、輸出等進(jìn)程方法。粗淺的說就是一個進(jìn)程類

通過文檔可以得知,我調(diào)用的這個exec方法需要一個String類型的參數(shù),即要執(zhí)行的系統(tǒng)命令

InputStream input = cmd.getInputStream()

其中:

InputStream ? ?輸入流,即數(shù)據(jù)流入,讀入數(shù)據(jù)

OutputStream 輸出流,即數(shù)據(jù)輸出,寫入數(shù)據(jù)

該代碼讀取上一步 Process 類型的數(shù)據(jù)流

input.read(a);

在上一步調(diào)用getInputStream后,可執(zhí)行 read 函數(shù)。

將當(dāng)前的數(shù)據(jù)流讀取出來,寫入到一個 byte[]類型的變量里。

String res = new String(a);

將byte類型轉(zhuǎn)換成字符串。以便后面打印輸出

這就是一個簡單的 Java 命令執(zhí)行并回顯結(jié)果。

我們可以看到主要調(diào)用了 Runtime.getRuntime().exec

那么我們要如何通過反射的方式進(jìn)行調(diào)用呢?

反射調(diào)用 Runtime.getRuntime().exec

第一種方式,通過強行反射私有構(gòu)造方法,用 Runtime 實例化進(jìn)行反射

這里有一個小坑,Runtime的構(gòu)造函數(shù)是私有的:

所以我們要強制反射私有構(gòu)造方法,而且不能直接 newInstance Class:

錯誤寫法:

直接用Class來進(jìn)行實例化

Class runtime = Class.forName("java.lang.Runtime");runtime.newInstance();

會報錯:

java.lang.IllegalAccessException: Class org.xiaopan.test.Main can not access a member of class java.lang.Runtime with modifiers “private”

正確寫法:

先強制反射Runtime的構(gòu)造方法,再實例化構(gòu)造方法。

Class runtime = Class.forName("java.lang.Runtime");Constructor c = runtime.getDeclaredConstructor();c.setAccessible(true);c.newInstance();

反射調(diào)用Runtime.gettime.exec

byte[] a = new byte[1024];try{ //獲取Runtime類 Class runtime = Class.forName("java.lang.Runtime"); //獲取Runtime類構(gòu)造方法 Constructor c_runtime = runtime.getDeclaredConstructor(); //設(shè)置強制反射 c_runtime.setAccessible(true); //Runtime類的構(gòu)造方法 實例化 //由于 Runtime類構(gòu)造方法返回類型為 Runtime類,所以需要使用 Runtime 類型變量進(jìn)行接收 Runtime r = (Runtime) c_runtime.newInstance(); //獲取 Runtime類的方法 exec Method m = runtime.getMethod("exec", String.class); //調(diào)用 exec 方法,傳入對象為 Runtime類的構(gòu)造方法實例化 //由于 exec 方法返回的是 Process 類型數(shù)據(jù),所以需要使用 Process 類型變量進(jìn)行接收 Process p = (Process) m.invoke(r,"whoami"); //讀入數(shù)據(jù)流,讀入到 byte[] 類型的變量中 p.getInputStream().read(a); System.out.println(new String(a));}catch (Exception e){ System.out.println(e);}

成功輸出:

第二種方式,不進(jìn)行 Runtime實例化,直接通過getRuntime進(jìn)行反射

注意點:

發(fā)現(xiàn)盲點:在本節(jié)一開頭,調(diào)用系統(tǒng)命令函數(shù) exec 的形式如下:

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

我們?nèi)ピ创a翻翻 getRuntime()是個什么函數(shù)

我們可以發(fā)現(xiàn),getRuntime就是為了返回 Runtime類 實例的,感覺應(yīng)該是一個 單例模式

我們遵守源碼的規(guī)則,直接調(diào)用 getRuntime,拿到 Runtime類實例

注意點:

由于 getRuntime方法 返回的是 Runtime類實例,所以反射的時候需要顯示類型轉(zhuǎn)換。

代碼如下:

byte[] a = new byte[1024];try{ //獲取 Runtime 類 Class runtime = Class.forName("java.lang.Runtime"); //獲取getRuntime方法 Method m = runtime.getMethod("getRuntime"); //調(diào)用getRuntime方法,并用 Runtime類 類型進(jìn)行接收,顯式轉(zhuǎn)換成 Runtime類 //調(diào)用的時候,在上文查看源碼時,發(fā)現(xiàn)是不需要傳入?yún)?shù)的 //不需傳入?yún)?shù),我們直接傳一個 null 進(jìn)去即可 Runtime r = (Runtime) m.invoke(null); //由于上一個代碼中調(diào)用 getRuntime 方法,返回了 Runtime類 //我們直接就可以調(diào)用底下的 exec 方法了 Process p = r.exec("ifconfig"); //數(shù)據(jù)輸入流,讀入數(shù)據(jù) InputStream res = p.getInputStream(); res.read(a); System.out.println(new String(a));}catch (Exception e){ System.out.println(e);}

成功輸出:

Referer:

java手冊:

https://www.oracle.com/cn/java/technologies/java-se-api-doc.html

大佬文章:

https://blog.csdn.net/ju_362204801/article/details/90578678

精彩推薦

總結(jié)

以上是生活随笔為你收集整理的c++ 反射_Java代码审计基础之反射的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。