22import struct
33
44def loads (object ):
5+ """
6+ Deserializes Java primitive data and objects serialized by ObjectOutputStream
7+ """
58 f = StringIO .StringIO (object )
6- ba = f .read (4 )
7- (magic , version ) = struct .unpack (">HH" , ba )
8- print magic
9- if magic != 0xaced :
10- raise RuntimeError ("The stream is not java serialized object. Magic number failed." )
9+ marshaller = JavaObjectMarshaller (f )
10+ return marshaller .readObject ()
11+ # ba = f.read(4)
12+ # (magic, version) = struct.unpack(">HH", ba)
13+ # print magic
14+ # if magic != 0xaced:
15+ # raise RuntimeError("The stream is not java serialized object. Magic number failed.")
16+ #
17+ # print version
18+ #
19+ # print type(object), Magic
1120
12- print version
21+ class JavaObjectMarshaller :
1322
14- print type (object ), Magic
15-
23+ STREAM_MAGIC = 0xaced
24+ STREAM_VERSION = 0x05
25+
26+ TC_REFERENCE = 0x71
27+ TC_CLASSDESC = 0x72
28+ TC_OBJECT = 0x73
29+ TC_STRING = 0x74
30+ TC_ARRAY = 0x75
31+ TC_CLASS = 0x76
32+ TC_BLOCKDATA = 0x77
33+ TC_ENDBLOCKDATA = 0x78
34+ TC_RESET = 0x79
35+ TC_BLOCKDATALONG = 0x7A
36+ TC_EXCEPTION = 0x7B
37+ TC_LONGSTRING = 0x7C
38+ TC_PROXYCLASSDESC = 0x7D
39+ TC_ENUM = 0x7E
40+ TC_MAX = 0x7E
41+
42+ def __init__ (self , stream ):
43+ self .opmap = {
44+ self .TC_CLASSDESC : self .do_classdesc ,
45+ self .TC_OBJECT : self .do_object ,
46+ self .TC_STRING : self .do_string ,
47+ self .TC_CLASS : self .do_class ,
48+ self .TC_BLOCKDATA : self .do_blockdata ,
49+ self .TC_REFERENCE : self .do_reference
50+ }
51+ self .object_stream = stream
52+ self ._readStreamHeader ()
53+ self .finalValue = True
54+
55+ def _readStreamHeader (self ):
56+ (magic , version ) = self ._readStruct (">HH" , 4 )
57+ if magic != self .STREAM_MAGIC or version != self .STREAM_VERSION :
58+ raise IOError ("The stream is not java serialized object. Invalid stream header: %04X%04X" % (magic , version ))
59+
60+ def readObject (self ):
61+ (opid , ) = self ._readStruct (">B" , 1 )
62+ print "OpCode: 0x%X" % opid
63+ self .opmap .get (opid , self .do_default_stuff )()
64+ return self .finalValue
65+
66+ def _readStruct (self , unpack , length ):
67+ ba = self .object_stream .read (length )
68+ return struct .unpack (unpack , ba )
69+
70+ def _readString (self ):
71+ (length , ) = self ._readStruct (">H" , 2 )
72+ ba = self .object_stream .read (length )
73+ return ba
74+
75+ def do_classdesc (self ):
76+ # TC_CLASSDESC className serialVersionUID newHandle classDescInfo
77+ # classDescInfo:
78+ # classDescFlags fields classAnnotation superClassDesc
79+ # classDescFlags:
80+ # (byte) // Defined in Terminal Symbols and Constants
81+ # fields:
82+ # (short)<count> fieldDesc[count]
83+
84+ # fieldDesc:
85+ # primitiveDesc
86+ # objectDesc
87+ # primitiveDesc:
88+ # prim_typecode fieldName
89+ # objectDesc:
90+ # obj_typecode fieldName className1
91+ print "do_classdesc"
92+ ba = self ._readString ()
93+ print "Class name:" , ba
94+ (serialVersionUID , newHandle , classDescFlags ) = self ._readStruct (">LLB" , 4 + 4 + 1 )
95+ print "Serial: 0x%X newHanle: 0x%X. classDescFlags: 0x%X" % (serialVersionUID , newHandle , classDescFlags )
96+ (length , ) = self ._readStruct (">H" , 2 )
97+ print "Fields num: 0x%X" % length
98+
99+ for fieldId in range (length ):
100+ (type , ) = self ._readStruct (">B" , 1 )
101+ ba = self ._readString ()
102+ print "FieldType: 0x%X" % type , ba
103+ (opid , ) = self ._readStruct (">B" , 1 )
104+ print "OpCode: 0x%X" % opid
105+ res = self .opmap .get (opid , self .do_default_stuff )()
106+
107+ def do_blockdata (self ):
108+ # TC_BLOCKDATA (unsigned byte)<size> (byte)[size]
109+ print "[blockdata]"
110+ (length , ) = self ._readStruct (">B" , 1 )
111+ ba = self .object_stream .read (length )
112+ self .finalValue = ba
113+
114+ def do_class (self ):
115+ # TC_CLASS classDesc newHandle
116+ print "[class]"
117+
118+ def do_object (self ):
119+ # TC_OBJECT classDesc newHandle classdata[] // data for each class
120+ print "[object]"
121+ (opid , ) = self ._readStruct (">B" , 1 )
122+ print "OpCode: 0x%X" % opid
123+ res = self .opmap .get (opid , self .do_default_stuff )()
124+ self .finalValue = res
125+
126+ def do_string (self ):
127+ print "[string]"
128+ ba = self ._readString ()
129+ # (handle, ) = self._readStruct(">B", 1)
130+ return str (ba )
131+
132+ def do_reference (self ):
133+ (handle , reference ) = self ._readStruct (">HH" , 4 )
134+ pass
135+
136+ def do_default_stuff (self ):
137+ raise RuntimeError ("Unknown opcode" )
0 commit comments