1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import re
21 import itertools
22 import base64
23
24 from BinaryParser import Block
25 from BinaryParser import hex_dump
26 from BinaryParser import ParseException
27 from BinaryParser import memoize
46
47
48 node_dispatch_table = []
49 node_readable_tokens = []
53 """
54 This exception is to be thrown to indicate that a conditional
55 substitution evaluated to NULL, and the parent element should
56 be suppressed. This exception should be caught at the first
57 opportunity, and must not propagate far up the call chain.
58
59 Strategy:
60 AttributeNode catches this, .xml() --> ""
61 StartOpenElementNode catches this for each child, ensures
62 there's at least one useful value. Or, .xml() --> ""
63 """
66
69
70 - def __init__(self, buf, offset, chunk, parent):
74
76 return "BXmlNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
77 (self._buf, self.offset(), self._chunk, self._parent)
78
80 return "BXmlNode(offset=%s)" % (hex(self.offset()))
81
85
87 """
88 This method must be implemented and overridden for all BXmlNodes.
89 @return An integer specifying the length of this tag, not including
90 its children.
91 """
92 raise NotImplementedError("tag_length not implemented for %r") % \
93 (self)
94
97 """
98 @return A list containing all of the children BXmlNodes.
99 """
100 ret = []
101 ofs = self.tag_length()
102
103 if max_children:
104 gen = xrange(max_children)
105 else:
106 gen = itertools.count()
107
108 for _ in gen:
109
110
111 token = self.unpack_byte(ofs) & 0x0F
112 try:
113 HandlerNodeClass = node_dispatch_table[token]
114 child = HandlerNodeClass(self._buf, self.offset() + ofs,
115 self._chunk, self)
116 except IndexError:
117 raise ParseException("Unexpected token %02X at %s" % \
118 (token,
119 self.absolute_offset(0x0) + ofs))
120 ret.append(child)
121 ofs += child.length()
122 if token in end_tokens:
123 break
124 if child.find_end_of_stream():
125 break
126 return ret
127
128 @memoize
131
132 @memoize
134 """
135 @return An integer specifying the length of this tag and all
136 its children.
137 """
138 ret = self.tag_length()
139 for child in self.children():
140 ret += child.length()
141 return ret
142
143 @memoize
152
155 - def __init__(self, buf, offset, chunk, parent):
156 super(NameStringNode, self).__init__(buf, offset, chunk, parent)
157 self.declare_field("dword", "next_offset", 0x0)
158 self.declare_field("word", "hash")
159 self.declare_field("word", "string_length")
160 self.declare_field("wstring", "string", length=self.string_length())
161
163 return "NameStringNode(buf=%r, offset=%r, chunk=%r)" % \
164 (self._buf, self.offset(), self._chunk)
165
167 return "NameStringNode(offset=%s, length=%s, end=%s)" % \
168 (hex(self.offset()), hex(self.length()),
169 hex(self.offset() + self.length()))
170
172 return str(self._string())
173
175 return (self.string_length() * 2) + 8
176
180
183 - def __init__(self, buf, offset, chunk, parent):
184 super(TemplateNode, self).__init__(buf, offset, chunk, parent)
185 self.declare_field("dword", "next_offset", 0x0)
186 self.declare_field("dword", "template_id")
187 self.declare_field("guid", "guid", 0x04)
188 self.declare_field("dword", "data_length")
189
191 return "TemplateNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
192 (self._buf, self.offset(), self._chunk, self._parent)
193
195 return "TemplateNode(offset=%s, guid=%s, length=%s)" % \
196 (hex(self.offset()), self.guid(), hex(self.length()))
197
200
203
206 """
207 The binary XML node for the system token 0x00.
208
209 This is the "end of stream" token. It may never actually
210 be instantiated here.
211 """
212 - def __init__(self, buf, offset, chunk, parent):
214
216 return "EndOfStreamNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
217 (self._buf, self.offset(), self._chunk, self._parent)
218
220 return "EndOfStreamNode(offset=%s, length=%s, token=%s)" % \
221 (hex(self.offset()), hex(self.length()), 0x00)
222
224 return self.token() >> 4
225
228
231
234
237 """
238 The binary XML node for the system token 0x01.
239
240 This is the "open start element" token.
241 """
242 - def __init__(self, buf, offset, chunk, parent):
243 super(OpenStartElementNode, self).__init__(buf, offset, chunk, parent)
244 self.declare_field("byte", "token", 0x0)
245 self.declare_field("word", "unknown0")
246
247 self.declare_field("dword", "size")
248 self.declare_field("dword", "string_offset")
249 self._tag_length = 11
250 self._element_type = 0
251
252 if self.flags() & 0x04:
253 self._tag_length += 4
254
255 if self.string_offset() > self.offset() - self._chunk._offset:
256 new_string = self._chunk.add_string(self.string_offset(),
257 parent=self)
258 self._tag_length += new_string.length()
259
261 return "OpenStartElementNode(buf=%r, offset=%r, chunk=%r)" % \
262 (self._buf, self.offset(), self._chunk)
263
265 return "OpenStartElementNode(offset=%s, name=%s, length=%s, token=%s, end=%s, taglength=%s, endtag=%s)" % \
266 (hex(self.offset()), self.tag_name(),
267 hex(self.length()), hex(self.token()),
268 hex(self.offset() + self.length()),
269 hex(self.tag_length()),
270 hex(self.offset() + self.tag_length()))
271
272 @memoize
278
280 return self.token() >> 4
281
282 @memoize
285
287 return self._tag_length
288
290 return self.flags() & 0x0b == 0 and \
291 self.opcode() & 0x0F == 0x01
292
293 @memoize
297
300 """
301 The binary XML node for the system token 0x02.
302
303 This is the "close start element" token.
304 """
305 - def __init__(self, buf, offset, chunk, parent):
308
310 return "CloseStartElementNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
311 (self._buf, self.offset(), self._chunk, self._parent)
312
314 return "CloseStartElementNode(offset=%s, length=%s, token=%s)" % \
315 (hex(self.offset()), hex(self.length()), hex(self.token()))
316
318 return self.token() >> 4
319
322
325
328
330 return self.flags() & 0x0F == 0 and \
331 self.opcode() & 0x0F == 0x02
332
335 """
336 The binary XML node for the system token 0x03.
337 """
338 - def __init__(self, buf, offset, chunk, parent):
341
343 return "CloseEmptyElementNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
344 (self._buf, self.offset(), self._chunk, self._parent)
345
347 return "CloseEmptyElementNode(offset=%s, length=%s, token=%s)" % \
348 (hex(self.offset()), hex(self.length()), hex(0x03))
349
351 return self.token() >> 4
352
355
358
361
364 """
365 The binary XML node for the system token 0x04.
366
367 This is the "close element" token.
368 """
369 - def __init__(self, buf, offset, chunk, parent):
372
374 return "CloseElementNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
375 (self._buf, self.offset(), self._chunk, self._parent)
376
378 return "CloseElementNode(offset=%s, length=%s, token=%s)" % \
379 (hex(self.offset()), hex(self.length()), hex(self.token()))
380
382 return self.token() >> 4
383
386
389
392
394 return self.flags() & 0x0F == 0 and \
395 self.opcode() & 0x0F == 0x04
396
399 """
400 @return A VariantType subclass instance found in the given
401 buffer and offset.
402 """
403 types = {
404 0x00: NullTypeNode,
405 0x01: WstringTypeNode,
406 0x02: StringTypeNode,
407 0x03: SignedByteTypeNode,
408 0x04: UnsignedByteTypeNode,
409 0x05: SignedWordTypeNode,
410 0x06: UnsignedWordTypeNode,
411 0x07: SignedDwordTypeNode,
412 0x08: UnsignedDwordTypeNode,
413 0x09: SignedQwordTypeNode,
414 0x0A: UnsignedQwordTypeNode,
415 0x0B: FloatTypeNode,
416 0x0C: DoubleTypeNode,
417 0x0D: BooleanTypeNode,
418 0x0E: BinaryTypeNode,
419 0x0F: GuidTypeNode,
420 0x10: SizeTypeNode,
421 0x11: FiletimeTypeNode,
422 0x12: SystemtimeTypeNode,
423 0x13: SIDTypeNode,
424 0x14: Hex32TypeNode,
425 0x15: Hex64TypeNode,
426 0x21: BXmlTypeNode,
427 0x81: WstringArrayTypeNode,
428 }
429 try:
430 TypeClass = types[type_]
431 except IndexError:
432 raise NotImplementedError("Type %s not implemented" % (type_))
433 return TypeClass(buf, offset, chunk, parent, length=length)
434
437 """
438 The binary XML node for the system token 0x05.
439
440 This is the "value" token.
441 """
442 - def __init__(self, buf, offset, chunk, parent):
446
448 return "ValueNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
449 (self._buf, self.offset(), self._chunk, self._parent)
450
452 return "ValueNode(offset=%s, length=%s, token=%s, value=%s)" % \
453 (hex(self.offset()), hex(self.length()),
454 hex(self.token()), self.value().string())
455
457 return self.token() >> 4
458
461
464
470
474
477 """
478 The binary XML node for the system token 0x06.
479
480 This is the "attribute" token.
481 """
482 - def __init__(self, buf, offset, chunk, parent):
483 super(AttributeNode, self).__init__(buf, offset, chunk, parent)
484 self.declare_field("byte", "token", 0x0)
485 self.declare_field("dword", "string_offset")
486
487 self._name_string_length = 0
488 if self.string_offset() > self.offset() - self._chunk._offset:
489 new_string = self._chunk.add_string(self.string_offset(),
490 parent=self)
491 self._name_string_length += new_string.length()
492
494 return "AttributeNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
495 (self._buf, self.offset(), self._chunk, self._parent)
496
501
503 return self.token() >> 4
504
506 """
507 @return A NameNode instance that contains the attribute name.
508 """
509 return self._chunk.strings()[self.string_offset()]
510
512 """
513 @return A BXmlNode instance that is one of (ValueNode,
514 ConditionalSubstitutionNode, NormalSubstitutionNode).
515 """
516 return self.children()[0]
517
519 return 5 + self._name_string_length
520
522 return self.flags() & 0x0B == 0 and \
523 self.opcode() & 0x0F == 0x06
524
525 @memoize
528
531 """
532 The binary XML node for the system token 0x07.
533
534 This is the "CDATA section" system token.
535 """
536 - def __init__(self, buf, offset, chunk, parent):
541
543 return "CDataSectionNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
544 (self._buf, self.offset(), self._chunk, self._parent)
545
547 return "CDataSectionNode(offset=%s, length=%s, token=%s)" % \
548 (hex(self.offset()), hex(self.length()), 0x07)
549
551 return self.token() >> 4
552
554 return 0x3 + self.string_length()
555
558
561
565
568 """
569 The binary XML node for the system token 0x09.
570
571 This is an entity reference node. That is, something that represents
572 a non-XML character, eg. & --> &.
573
574 TODO(wb): this is untested.
575 """
576 - def __init__(self, buf, offset, chunk, parent):
586
587
589 return "EntityReferenceNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
590 (self._buf, self.offset(), self._chunk, self._parent)
591
593 return "EntityReferenceNode(offset=%s, length=%s, token=%s)" % \
594 (hex(self.offset()), hex(self.length()), hex(0x09))
595
597 return "&%s;" % \
598 (self._chunk.strings()[self.string_offset()].string())
599
601 return self.token() >> 4
602
604 return self._tag_length
605
609
612 """
613 The binary XML node for the system token 0x0A.
614
615 TODO(wb): untested.
616 """
617 - def __init__(self, buf, offset, chunk, parent):
627
629 return "ProcessingInstructionTargetNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
630 (self._buf, self.offset(), self._chunk, self._parent)
631
633 return "ProcessingInstructionTargetNode(offset=%s, length=%s, token=%s)" % \
634 (hex(self.offset()), hex(self.length()), hex(0x0A))
635
637 return "<?%s" % \
638 (self._chunk.strings()[self.string_offset()].string())
639
641 return self.token() >> 4
642
644 return self._tag_length
645
649
652 """
653 The binary XML node for the system token 0x0B.
654
655 TODO(wb): untested.
656 """
657 - def __init__(self, buf, offset, chunk, parent):
667
669 return "ProcessingInstructionDataNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
670 (self._buf, self.offset(), self._chunk, self._parent)
671
673 return "ProcessingInstructionDataNode(offset=%s, length=%s, token=%s)" % \
674 (hex(self.offset()), hex(self.length()), hex(0x0B))
675
677 return self.token() >> 4
678
680 if self.string_length() > 0:
681 return " %s?>" % (self._string)
682 else:
683 return "?>"
684
686 return self._tag_length
687
691
694 """
695 The binary XML node for the system token 0x0C.
696 """
697 - def __init__(self, buf, offset, chunk, parent):
698 super(TemplateInstanceNode, self).__init__(buf, offset, chunk, parent)
699 self.declare_field("byte", "token", 0x0)
700 self.declare_field("byte", "unknown0")
701 self.declare_field("dword", "template_id")
702 self.declare_field("dword", "template_offset")
703
704 self._data_length = 0
705
706 if self.is_resident_template():
707 new_template = self._chunk.add_template(self.template_offset(),
708 parent=self)
709 self._data_length += new_template.length()
710
712 return "TemplateInstanceNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
713 (self._buf, self.offset(), self._chunk, self._parent)
714
716 return "TemplateInstanceNode(offset=%s, length=%s, token=%s)" % \
717 (hex(self.offset()), hex(self.length()), hex(0x0C))
718
720 return self.token() >> 4
721
723 return self.template_offset() > self.offset() - self._chunk._offset
724
727
730
732 return self._chunk.templates()[self.template_offset()]
733
736
737 @memoize
740
743 """
744 The binary XML node for the system token 0x0D.
745
746 This is a "normal substitution" token.
747 """
748 - def __init__(self, buf, offset, chunk, parent):
754
756 return "NormalSubstitutionNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
757 (self._buf, self.offset(), self._chunk, self._parent)
758
760 return "NormalSubstitutionNode(offset=%s, length=%s, token=%s, index=%d, type=%d)" % \
761 (hex(self.offset()), hex(self.length()), hex(self.token()),
762 self.index(), self.type())
763
765 return self.token() >> 4
766
769
772
775
779
782 """
783 The binary XML node for the system token 0x0E.
784 """
785 - def __init__(self, buf, offset, chunk, parent):
791
793 return "ConditionalSubstitutionNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
794 (self._buf, self.offset(), self._chunk, self._parent)
795
797 return "ConditionalSubstitutionNode(offset=%s, length=%s, token=%s)" % \
798 (hex(self.offset()), hex(self.length()), hex(0x0E))
799
803
805 return self.token() >> 4
806
809
812
815
819
822 """
823 The binary XML node for the system token 0x0F.
824
825 This is the "start of stream" token.
826 """
827 - def __init__(self, buf, offset, chunk, parent):
832
834 return "StreamStartNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
835 (self._buf, self.offset(), self._chunk, self._parent)
836
838 return "StreamStartNode(offset=%s, length=%s, token=%s)" % \
839 (hex(self.offset()), hex(self.length()), hex(self.token()))
840
846
848 return self.token() >> 4
849
852
855
858
861 """
862 The binary XML node for the Root node.
863 """
864 - def __init__(self, buf, offset, chunk, parent):
866
868 return "RootNode(buf=%r, offset=%r, chunk=%r, parent=%r)" % \
869 (self._buf, self.offset(), self._chunk, self._parent)
870
872 return "RootNode(offset=%s, length=%s)" % \
873 (hex(self.offset()), hex(self.length()))
874
877
878 @memoize
884
886 """
887 @return The length of the tag of this element, and the children.
888 This does not take into account the substitutions that may be
889 at the end of this element.
890 """
891 children_length = 0
892
893 for child in self.children():
894 children_length += child.length()
895
896 return self.tag_length() + children_length
897
903
904 @memoize
906 """
907 Get the list of elements that are the
908 the substitutions for this root node.
909 Each element is one of:
910 str
911 int
912 float
913 RootNode
914 @rtype: list
915 """
916 sub_decl = []
917 sub_def = []
918 ofs = self.tag_and_children_length()
919 sub_count = self.unpack_dword(ofs)
920 ofs += 4
921 for _ in xrange(sub_count):
922 size = self.unpack_word(ofs)
923 type_ = self.unpack_byte(ofs + 0x2)
924 sub_decl.append((size, type_))
925 ofs += 4
926 for (size, type_) in sub_decl:
927
928 if type_ == 0x0:
929 value = None
930 sub_def.append(value)
931
932 elif type_ == 0x1:
933 s = self.unpack_wstring(ofs, size / 2).rstrip("\x00")
934 value = s.replace("<", ">").replace(">", "<")
935 sub_def.append(value)
936
937 elif type_ == 0x2:
938 s = self.unpack_string(ofs, size)
939 value = s.decode("utf8").rstrip("\x00")
940 value = value.replace("<", ">")
941 value = value.replace(">", "<")
942 sub_def.append(value)
943
944 elif type_ == 0x3:
945 sub_def.append(self.unpack_int8(ofs))
946
947 elif type_ == 0x4:
948 sub_def.append(self.unpack_byte(ofs))
949
950 elif type_ == 0x5:
951 sub_def.append(self.unpack_int16(ofs))
952
953 elif type_ == 0x6:
954 sub_def.append(self.unpack_word(ofs))
955
956 elif type_ == 0x7:
957 sub_def.append(self.unpack_int32(ofs))
958
959 elif type_ == 0x8:
960 sub_def.append(self.unpack_dword(ofs))
961
962 elif type_ == 0x9:
963 sub_def.append(self.unpack_int64(ofs))
964
965 elif type_ == 0xA:
966 sub_def.append(self.unpack_qword(ofs))
967
968 elif type_ == 0xB:
969 sub_def.append(self.unpack_float(ofs))
970
971 elif type_ == 0xC:
972 sub_def.append(self.unpack_double(ofs))
973
974 elif type_ == 0xD:
975 sub_def.append(str(self.unpack_word(ofs) > 1))
976
977 elif type_ == 0xE:
978 sub_def.append(base64.b64encode(self.unpack_binary(ofs, size)))
979
980 elif type_ == 0xF:
981 sub_def.append(self.unpack_guid(ofs))
982
983 elif type_ == 0x10:
984 if size == 0x4:
985 sub_def.append(self.unpack_dword(ofs))
986 elif size == 0x8:
987 sub_def.append(self.unpack_qword(ofs))
988 else:
989 raise "Unexpected size for SizeTypeNode: %s" % hex(size)
990
991 elif type_ == 0x11:
992 sub_def.append(self.unpack_filetime(ofs))
993
994 elif type_ == 0x12:
995 sub_def.append(self.unpack_systemtime(ofs))
996
997 elif type_ == 0x13:
998 version = self.unpack_byte(ofs)
999 num_elements = self.unpack_byte(ofs + 1)
1000 id_high = self.unpack_dword_be(ofs)
1001 id_low = self.unpack_word_be(ofs)
1002 value = "S-%d-%d" % (version, (id_high << 16) ^ id_low)
1003 for i in xrange(num_elements):
1004 val = self.unpack_dword(ofs + 8 + (4 * i))
1005 value += "-%d" % val
1006 sub_def.append(value)
1007
1008 elif type_ == 0x14:
1009 value = "0x"
1010 for c in self.unpack_binary(ofs, size)[::-1]:
1011 value += "%02x" % ord(c)
1012 sub_def.append(value)
1013
1014 elif type_ == 0x15:
1015 value = "0x"
1016 for c in self.unpack_binary(ofs, size)[::-1]:
1017 value += "%02x" % ord(c)
1018 sub_def.append(value)
1019
1020 elif type_ == 0x21:
1021 sub_def.append(RootNode(self._buf, self.offset() + ofs,
1022 self._chunk, self))
1023
1024 elif type_ == 0x81:
1025 bin = self.unpack_binary(ofs, size)
1026 acc = []
1027 while len(bin) > 0:
1028 match = re.search("((?:[^\x00].)+)", bin)
1029 if match:
1030 frag = match.group()
1031 acc.append("<string>")
1032 acc.append(frag.decode("utf16"))
1033 acc.append("</string>\n")
1034 bin = bin[len(frag) + 2:]
1035 if len(bin) == 0:
1036 break
1037 frag = re.search("(\x00*)", bin).group()
1038 if len(frag) % 2 == 0:
1039 for _ in xrange(len(frag) // 2):
1040 acc.append("<string></string>\n")
1041 else:
1042 raise "Error parsing uneven substring of NULLs"
1043 bin = bin[len(frag):]
1044 sub_def.append("".join(acc))
1045 else:
1046 raise "Unexpected type encountered: %s" % hex(type_)
1047 ofs += size
1048 return sub_def
1049
1050 @memoize
1052 """
1053 @return A list of VariantTypeNode subclass instances that
1054 contain the substitutions for this root node.
1055 """
1056 sub_decl = []
1057 sub_def = []
1058 ofs = self.tag_and_children_length()
1059 sub_count = self.unpack_dword(ofs)
1060 ofs += 4
1061 for _ in xrange(sub_count):
1062 size = self.unpack_word(ofs)
1063 type_ = self.unpack_byte(ofs + 0x2)
1064 sub_decl.append((size, type_))
1065 ofs += 4
1066 for (size, type_) in sub_decl:
1067 val = get_variant_value(self._buf, self.offset() + ofs,
1068 self._chunk, self, type_, length=size)
1069 if abs(size - val.length()) > 4:
1070
1071
1072
1073
1074
1075
1076 raise ParseException("Invalid substitution value size")
1077 sub_def.append(val)
1078 ofs += size
1079 return sub_def
1080
1081 @memoize
1092
1095 """
1096
1097 """
1098 - def __init__(self, buf, offset, chunk, parent, length=None):
1101
1103 return "%s(buf=%r, offset=%s, chunk=%r)" % \
1104 (self.__class__.__name__, self._buf, hex(self.offset()),
1105 self._chunk)
1106
1108 return "%s(offset=%s, length=%s, string=%s)" % \
1109 (self.__class__.__name__, hex(self.offset()),
1110 hex(self.length()), self.string())
1111
1113 raise NotImplementedError("tag_length not implemented for %r" % \
1114 (self))
1115
1118
1121
1123 raise NotImplementedError("string not implemented for %r" % \
1124 (self))
1125
1128 """
1129 Variant type 0x00.
1130 """
1131 - def __init__(self, buf, offset, chunk, parent, length=None):
1135
1137 return "NullTypeNode"
1138
1141
1143 return self._length or 0
1144
1146 return self._length or 0
1147
1150
1153
1156 """
1157 Variant ttype 0x01.
1158 """
1159 - def __init__(self, buf, offset, chunk, parent, length=None):
1160 super(WstringTypeNode, self).__init__(buf, offset, chunk,
1161 parent, length=length)
1162 if self._length is None:
1163 self.declare_field("word", "string_length", 0x0)
1164 self.declare_field("wstring", "_string",
1165 length=(self.string_length()))
1166 else:
1167 self.declare_field("wstring", "_string", 0x0,
1168 length=(self._length / 2))
1169
1171 if self._length is None:
1172 return (2 + (self.string_length() * 2))
1173 return self._length
1174
1176 return self._string().rstrip("\x00")
1177
1180 """
1181 Variant type 0x02.
1182 """
1183 - def __init__(self, buf, offset, chunk, parent, length=None):
1184 super(StringTypeNode, self).__init__(buf, offset, chunk,
1185 parent, length=length)
1186 if self._length is None:
1187 self.declare_field("word", "string_length", 0x0)
1188 self.declare_field("string", "_string",
1189 length=(self.string_length()))
1190 else:
1191 self.declare_field("string", "_string", 0x0, length=self._length)
1192
1194 if self._length is None:
1195 return (2 + (self.string_length()))
1196 return self._length
1197
1199 return self._string().rstrip("\x00")
1200
1203 """
1204 Variant type 0x03.
1205 """
1206 - def __init__(self, buf, offset, chunk, parent, length=None):
1210
1213
1215 return str(self.byte())
1216
1219 """
1220 Variant type 0x04.
1221 """
1222 - def __init__(self, buf, offset, chunk, parent, length=None):
1227
1230
1232 return str(self.byte())
1233
1236 """
1237 Variant type 0x05.
1238 """
1239 - def __init__(self, buf, offset, chunk, parent, length=None):
1243
1246
1248 return str(self.word())
1249
1252 """
1253 Variant type 0x06.
1254 """
1255 - def __init__(self, buf, offset, chunk, parent, length=None):
1260
1263
1265 return str(self.word())
1266
1269 """
1270 Variant type 0x07.
1271 """
1272 - def __init__(self, buf, offset, chunk, parent, length=None):
1276
1279
1281 return str(self.dword())
1282
1285 """
1286 Variant type 0x08.
1287 """
1288 - def __init__(self, buf, offset, chunk, parent, length=None):
1293
1296
1298 return str(self.dword())
1299
1302 """
1303 Variant type 0x09.
1304 """
1305 - def __init__(self, buf, offset, chunk, parent, length=None):
1309
1312
1314 return str(self.qword())
1315
1318 """
1319 Variant type 0x0A.
1320 """
1321 - def __init__(self, buf, offset, chunk, parent, length=None):
1326
1329
1331 return str(self.qword())
1332
1335 """
1336 Variant type 0x0B.
1337 """
1338 - def __init__(self, buf, offset, chunk, parent, length=None):
1342
1345
1347 return str(self.float())
1348
1351 """
1352 Variant type 0x0C.
1353 """
1354 - def __init__(self, buf, offset, chunk, parent, length=None):
1358
1361
1363 return str(self.double())
1364
1367 """
1368 Variant type 0x0D.
1369 """
1370 - def __init__(self, buf, offset, chunk, parent, length=None):
1374
1377
1379 if self.int32 > 0:
1380 return "True"
1381 return "False"
1382
1385 """
1386 Variant type 0x0E.
1387
1388 String/XML representation is Base64 encoded.
1389 """
1390 - def __init__(self, buf, offset, chunk, parent, length=None):
1391 super(BinaryTypeNode, self).__init__(buf, offset, chunk,
1392 parent, length=length)
1393 if self._length is None:
1394 self.declare_field("dword", "size", 0x0)
1395 self.declare_field("binary", "binary", length=self.size())
1396 else:
1397 self.declare_field("binary", "binary", 0x0, length=self._length)
1398
1400 if self._length is None:
1401 return (4 + self.size())
1402 return self._length
1403
1405 return base64.b64encode(self.binary())
1406
1409 """
1410 Variant type 0x0F.
1411 """
1412 - def __init__(self, buf, offset, chunk, parent, length=None):
1416
1419
1421 return "{%s}" % (self.guid())
1422
1425 """
1426 Variant type 0x10.
1427
1428 Note: Assuming sizeof(size_t) == 0x8.
1429 """
1430 - def __init__(self, buf, offset, chunk, parent, length=None):
1431 super(SizeTypeNode, self).__init__(buf, offset, chunk,
1432 parent, length=length)
1433 if self._length == 0x4:
1434 self.declare_field("dword", "num", 0x0)
1435 elif self._length == 0x8:
1436 self.declare_field("qword", "num", 0x0)
1437 else:
1438 self.declare_field("qword", "num", 0x0)
1439
1441 if self._length is None:
1442 return 8
1443 return self._length
1444
1446 return str(self.num())
1447
1450 """
1451 Variant type 0x11.
1452 """
1453 - def __init__(self, buf, offset, chunk, parent, length=None):
1457
1459 return self.filetime().isoformat("T") + "Z"
1460
1463
1466 """
1467 Variant type 0x12.
1468 """
1469 - def __init__(self, buf, offset, chunk, parent, length=None):
1473
1476
1478 return self.systemtime().isoformat("T") + "Z"
1479
1482 """
1483 Variant type 0x13.
1484 """
1485 - def __init__(self, buf, offset, chunk, parent, length=None):
1486 super(SIDTypeNode, self).__init__(buf, offset, chunk,
1487 parent, length=length)
1488 self.declare_field("byte", "version", 0x0)
1489 self.declare_field("byte", "num_elements")
1490 self.declare_field("dword_be", "id_high")
1491 self.declare_field("word_be", "id_low")
1492
1493 @memoize
1499
1500 @memoize
1502 ret = "S-%d-%d" % \
1503 (self.version(), (self.id_high() << 16) ^ self.id_low())
1504 for elem in self.elements():
1505 ret += "-%d" % (elem)
1506 return ret
1507
1509 return 8 + 4 * self.num_elements()
1510
1513
1516 """
1517 Variant type 0x14.
1518 """
1519 - def __init__(self, buf, offset, chunk, parent, length=None):
1523
1526
1528 ret = "0x"
1529 for c in self.hex()[::-1]:
1530 ret += "%02x" % (ord(c))
1531 return ret
1532
1535 """
1536 Variant type 0x15.
1537 """
1538 - def __init__(self, buf, offset, chunk, parent, length=None):
1542
1545
1547 ret = "0x"
1548 for c in self.hex()[::-1]:
1549 ret += "%02x" % (ord(c))
1550 return ret
1551
1554 """
1555 Variant type 0x21.
1556 """
1557 - def __init__(self, buf, offset, chunk, parent, length=None):
1561
1563 return self._length or self._root.length()
1564
1566 return str(self._root)
1567
1570
1573 """
1574 Variant ttype 0x81.
1575 """
1576 - def __init__(self, buf, offset, chunk, parent, length=None):
1577 super(WstringArrayTypeNode, self).__init__(buf, offset, chunk,
1578 parent, length=length)
1579 if self._length is None:
1580 self.declare_field("word", "binary_length", 0x0)
1581 self.declare_field("binary", "binary",
1582 length=(self.binary_length()))
1583 else:
1584 self.declare_field("binary", "binary", 0x0,
1585 length=(self._length))
1586
1588 if self._length is None:
1589 return (2 + self.binary_length())
1590 return self._length
1591
1593 bin = self.binary()
1594 acc = []
1595 while len(bin) > 0:
1596 match = re.search("((?:[^\x00].)+)", bin)
1597 if match:
1598 frag = match.group()
1599 acc.append("<string>")
1600 acc.append(frag.decode("utf16"))
1601 acc.append("</string>\n")
1602 bin = bin[len(frag) + 2:]
1603 if len(bin) == 0:
1604 break
1605 frag = re.search("(\x00*)", bin).group()
1606 if len(frag) % 2 == 0:
1607 for _ in xrange(len(frag) // 2):
1608 acc.append("<string></string>\n")
1609 else:
1610 raise "Error parsing uneven substring of NULLs"
1611 bin = bin[len(frag):]
1612 return "".join(acc)
1613
1614
1615 node_dispatch_table = [
1616 EndOfStreamNode,
1617 OpenStartElementNode,
1618 CloseStartElementNode,
1619 CloseEmptyElementNode,
1620 CloseElementNode,
1621 ValueNode,
1622 AttributeNode,
1623 CDataSectionNode,
1624 None,
1625 EntityReferenceNode,
1626 ProcessingInstructionTargetNode,
1627 ProcessingInstructionDataNode,
1628 TemplateInstanceNode,
1629 NormalSubstitutionNode,
1630 ConditionalSubstitutionNode,
1631 StreamStartNode,
1632 ]
1633
1634 node_readable_tokens = [
1635 "End of Stream",
1636 "Open Start Element",
1637 "Close Start Element",
1638 "Close Empty Element",
1639 "Close Element",
1640 "Value",
1641 "Attribute",
1642 "unknown",
1643 "unknown",
1644 "unknown",
1645 "unknown",
1646 "unknown",
1647 "TemplateInstanceNode",
1648 "Normal Substitution",
1649 "Conditional Substitution",
1650 "Start of Stream",
1651 ]
1652