1
2 '''
3 Convert WireShark PDML files into Peach XML files.
4
5 Currently does a fairly good job of converting PDML files to Peach XML files
6 including the ability to find sizeof relations by looking for fields that look
7 like a length and matching them up to other fields in the focument.
8
9 Todo:
10
11 - Support parsing out multiple packets
12 - Support parsing out multiple proto's in a packet
13 - Look at proto's earlier then indicated one to pull out
14 transport and transport info (host, ip, etc)
15 - Generate the Tests/Test/Run sections
16 - Create multiple Data elements from multiple packets
17
18 @author: Michael Eddington
19 @version: $Id: Peach.Engine.peachshark-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $
20 '''
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 import sys, struct, re
50 from Ft.Xml import Parse
51
53 sys.stderr.write("debug: %s\n" % str)
54
55
56
57
58
59
60
61
62
63
65
67 self._currentPos = 0
68 self._regexIp = re.compile("^\d+\.\d+\.\d+\.\d+$")
69 self._regexFlagBit1 = re.compile("^(\.*)(\d+)(\.*)")
70 self._relations = {}
71 self._findStack = []
72 self._templates = []
73
74 - def inStr(self, str, values):
75 str = str.lower()
76 for value in values:
77 if str.find(value) > -1:
78
79 return True
80
81
82 return False
83
84
86
87
88
89
90
91
92
93 if node in self._findStack:
94 return None
95 self._findStack.append(node)
96
97 size = self.findSizeGetSize(sizeNode)
98
99
100 sibling = sizeNode.nextSibling
101 while sibling != None:
102 checkSize = int(sibling.getAttributeNS(None, 'size'))
103
104 if checkSize == size:
105 return sibling
106
107 sibling = sibling.nextSibling
108
109
110 for child in node.childNodes:
111 if child != sizeNode:
112 checkSize = int(child.getAttributeNS(None, 'size'))
113 if checkSize == size:
114 return child
115
116 ret = self.findSizeRelation(sizeNode, child)
117 if ret != None:
118 return ret
119
120
121 sibling = node.nextSibling
122 while sibling != None:
123 checkSize = int(sibling.getAttributeNS(None, 'size'))
124
125 if checkSize == size:
126 return sibling
127
128 ret = self.findSizeRelation(sizeNode, sibling)
129 if ret != None:
130 return ret
131
132 sibling = sibling.nextSibling
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 return None
151
153 '''
154 Find nodes that could be sizes or lengths.
155 '''
156
157 if nodes == None:
158 return []
159
160 findValues = ["length", "size"]
161 sizeNodes = []
162
163 for node in nodes:
164 if node == None:
165 continue
166
167 name = node.getAttributeNS(None, 'name')
168 show = node.getAttributeNS(None, 'show')
169 showName = node.getAttributeNS(None, 'showname')
170
171 if self.inStr(show, findValues) or self.inStr(showName, findValues) or self.inStr(name, findValues):
172
173 sizeNodes.append(node)
174
175 for n in self.findSizes(node.childNodes):
176 sizeNodes.append(n)
177
178 return sizeNodes
179
181 '''
182 Take a size/length node and figure out it's value.
183 '''
184
185 ret = None
186 if node.hasAttributeNS(None, 'show') and len(node.getAttributeNS(None, 'show')) > 0:
187 try:
188 return int(node.getAttributeNS(None, 'show'))
189 except:
190 pass
191
192 if node.hasAttributeNS(None, 'value') and len(node.getAttributeNS(None, 'value')) > 0:
193 try:
194 return int(node.getAttributeNS(None, 'value'), 16)
195 except:
196 pass
197
198 try:
199 return int(re.compile(r"(\d+)").search(node.getAttributeNS(None, 'show')).group(1))
200
201 except:
202 pass
203
204 debug(str("Failed on %s:%s" % (node.getAttributeNS(None, 'name'), node.nodeName)))
205 debug(str("Show: " + node.getAttributeNS(None, 'show')))
206 debug(str("Value: "+ node.getAttributeNS(None, 'value')))
207 raise Exception("OMG!!")
208
209
211 '''
212 Check if parent - me + prior siblings == size
213 '''
214
215 parentSize = int(node.parentNode.getAttributeNS(None, 'size'))
216 sizeUptoMe = int(node.getAttributeNS(None, 'size'))
217 size = self.findSizeGetSize(node)
218
219
220
221
222 if parentSize == size:
223 return True
224
225 return False
226
228 '''
229 Find and resolve size relations.
230 '''
231
232 debug("Finding relations: " + nodes[0].nodeName)
233 if nodes[0].nodeName == 'proto':
234 parentNode = nodes[0]
235 else:
236 parentNode = nodes[0].parentNode
237
238 for node in self.findSizes(nodes):
239
240
241 if self.findSizeRelationCheckSelf(node):
242 debug("findSizeRelations: Found relation to parent: %s and %s" % (node.getAttributeNS(None, 'name'), node.parentNode.getAttributeNS(None, 'name')))
243 self._relations[node] = node.parentNode
244
245 else:
246 ret = self.findSizeRelation(node, parentNode)
247 if ret != None:
248 debug("findSizeRelations: Found relation: %s and %s" % (node.getAttributeNS(None, 'name'), ret.getAttributeNS(None, 'name')))
249 self._relations[node] = ret
250
251
252 - def removeTextNodes(self, node):
253
254 for child in node.childNodes:
255 if child.nodeName == '#text':
256 node.removeChild(child)
257 else:
258 self.removeTextNodes(child)
259
261
262 if strInput == None or len(strInput) == 0:
263 strInput = default
264
265 if strInput == None or len(strInput) == 0:
266 return ''
267
268
269
270
271 out = ''
272 for char in strInput:
273 c = ord(char)
274 if ((c >= 97 and c <= 122) or
275 (c >= 65 and c <= 90 ) or
276 (c >= 48 and c <= 57 ) or
277 c == 32 or c == 44 or c == 46):
278 out += char
279 else:
280 out += "&#%d;" % c
281
282 return out
283
285 '''
286 Check for name and show attributes. Figureout a possible name
287 for this node.
288 '''
289
290 if node.hasAttributeNS(None, 'name'):
291 name = node.getAttributeNS(None, 'name')
292
293 if len(name.strip()) < 1:
294 return None
295
296
297
298
299
300
301
302 return name.replace(' ', '_').replace('.', '_')
303
304 return None
305
306 - def peachNode(self, node, tabCount, size, parent):
307
308 if node.nodeName == '#text':
309 return '', 0, 0
310
311 tabs = '\t' * tabCount
312 name = node.getAttributeNS(None, 'name')
313 show = node.getAttributeNS(None, 'show')
314 showName = node.getAttributeNS(None, 'showname')
315 size = int(node.getAttributeNS(None, 'size'))
316 pos = int(node.getAttributeNS(None, 'pos'))
317 ret = ''
318 nodeName = self.getNodeName(node)
319 if nodeName != None:
320 nodeName = 'name="%s"' % nodeName
321 else:
322 nodeName = ''
323
324 debug("peachNode: " + name)
325
326
327 if parent != None:
328 parentPos = int(parent.getAttributeNS(None, 'pos'))
329 parentSize = int(parent.getAttributeNS(None, 'size'))
330 else:
331 parentPos = -1
332 parentSize = -1
333
334 self._currentPos = pos
335
336 if size == 0:
337
338 return '', 0, 0
339
340 if tabCount == 1:
341
342 self.findSizeRelations([node])
343
344 if name.find('-'):
345 newName = ''
346 for n in name.split('-'):
347 newName += n[:1].upper() + n[1:]
348 name = newName
349
350 self._groupName = name[:1].upper() + name[1:]
351 self._genName = name[:1].upper() + name[1:]
352 self._templates.append(self._genName)
353
354 name = node.getAttributeNS(None, 'name')
355
356 if len(node.childNodes) > 0:
357
358 curPos = pos
359 sizeOfChildren = 0
360
361 if tabCount == 1:
362 if len(showName) > 1: ret += tabs + '<!-- %s -->\n' % showName
363 ret += tabs + '<Template name="%s">\n' % self._genName
364 else:
365 ret += tabs + '<Block %s>\n' % nodeName
366
367 for child in node.childNodes:
368
369 sibling = child.nextSibling
370 if sibling != None:
371 siblingPos = int(sibling.getAttributeNS(None, 'pos'))
372 siblingSize = int(sibling.getAttributeNS(None, 'size'))
373 childPos = int(child.getAttributeNS(None, 'pos'))
374 childSize = int(child.getAttributeNS(None, 'size'))
375
376 if siblingPos == childPos and siblingSize < childSize:
377 debug("Found that crazy stuff" + child.getAttributeNS(None, 'name'))
378 ret += tabs + "\t<!-- Skipping %s, same as following fields -->\n" % child.getAttributeNS(None, 'name')
379 continue
380
381 childShow = child.getAttributeNS(None, 'show')
382
383
384
385 childRet, childSize, childPos = self.peachNode(child, tabCount + 1, size, node)
386
387 childPos = int(childPos)
388 childSize = int(childSize)
389
390
391
392 if childSize == 0:
393 if len(childRet) > 0:
394 ret += childRet
395 continue
396
397 if int(childPos) == pos + int(sizeOfChildren):
398 ret += childRet
399
400 else:
401 valueHex = node.getAttributeNS(None, 'value')
402 value = self.hex2bin(valueHex)
403
404
405
406 if curPos < childPos:
407 if len(valueHex) >= (childPos-pos)*2:
408 ret += tabs + "\t<!-- Found some extra bits... -->\n"
409 ret += tabs + "\t<Blob %s valueType=\"hex\" value=\"%s\" />\n" % (nodeName, valueHex[(curPos-pos)*2:(childPos-pos)*2])
410 else:
411 ret += tabs + "\t<!-- Found some extra bits, guessing they are z3r0 -->\n"
412 ret += tabs + "\t<Blob %s valueType=\"hex\" value=\"%s\" />\n\n" % (nodeName, ('00'*((childPos-pos) - (curPos-pos))))
413
414 ret += childRet
415
416 sizeOfChildren += childSize
417 curPos = childPos + childSize
418
419
420
421
422
423
424 if tabCount == 1:
425 name = self._genName[3:]
426 ret += tabs + '</Template>\n'
427 else:
428 ret += tabs + '</Block>\n'
429
430 else:
431
432 type = self.figureType(node)
433 valueHex = node.getAttributeNS(None, 'value')
434 show = node.getAttributeNS(None, 'show')
435 showName = node.getAttributeNS(None, 'showname')
436 if len(showName) < 1:
437 showName = show
438 value = self.hex2bin(valueHex)
439
440 if type != 'bit_flag':
441 if node.previousSibling != None:
442 previousSiblingPos = int(node.previousSibling.getAttributeNS(None, 'pos'))
443 previousSiblingSize = int(node.previousSibling.getAttributeNS(None, 'size'))
444
445 if pos == previousSiblingPos and size == previousSiblingSize:
446 debug("node same position and size of previousSibling")
447 return tabs + "<!-- *** Skipping %s, same position and size of previousSibling *** -->\n\n" % node.getAttributeNS(None, 'name'), 0, 0
448
449
450
451
452 if len(showName) > 0:
453 ret += tabs + '<!-- %s -->\n' % showName
454
455 if type.find('str') > -1:
456
457
458
459 if len(valueHex) == size*2:
460 str = 'valueType="hex" value="%s"' % valueHex
461 else:
462 str = 'value="%s"' % value
463
464 if type == 'str':
465
466 ret += tabs + '<String %s %s' % (nodeName, str)
467 if self._relations.has_key(node):
468 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
469 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</String>\n'
470 else:
471 ret += ' />\n'
472
473 elif type == 'p_str':
474
475 ret += tabs + '<String %s %s length="%d"' % (nodeName, str, size)
476 if self._relations.has_key(node):
477 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
478 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</String>\n'
479 else:
480 ret += ' />\n'
481
482 elif type == 'w_str':
483
484 ret += tabs + '<String %s type="wchar" %s' % (nodeName, str)
485 if self._relations.has_key(node):
486 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
487 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</String>\n'
488 else:
489 ret += ' />\n'
490
491 elif type == 'p_w_str':
492
493 ret += tabs + '<String %s type="wchar" length="%d" %s' % (nodeName, size/2, str)
494 if self._relations.has_key(node):
495 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
496 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</String>\n'
497 else:
498 ret += ' />\n'
499
500 elif type == 'byte' or type == 'uint8':
501 ret += tabs + '<Number %s size="8" valueType="hex" value="%s" signed="false"' % (nodeName, valueHex)
502 if self._relations.has_key(node):
503 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
504 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
505 else:
506 ret += ' />\n'
507
508 elif type == 'int16':
509 ret += tabs + ('<Number %s size="16" valueType="hex" value="%s" signed="true"' % (nodeName, valueHex))
510 if self._relations.has_key(node):
511 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
512 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
513 else:
514 ret += ' />\n'
515
516 elif type == 'uint16':
517 ret += tabs + ('<Number %s size="16" valueType="hex" value="%s" signed="false"' % (nodeName, valueHex))
518 if self._relations.has_key(node):
519 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
520 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
521 else:
522 ret += ' />\n'
523
524 elif type == 'n_int16':
525 ret += tabs + ('<Number %s size="16" valueType="hex" value="%s" signed="true" endian="big"' % (nodeName, valueHex))
526 if self._relations.has_key(node):
527 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
528 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
529 else:
530 ret += ' />\n'
531
532 elif type == 'n_uint16':
533 ret += tabs + ('<Number %s size="16" valueType="hex" value="%s" signed="false" endian="big"' % (nodeName, valueHex))
534 if self._relations.has_key(node):
535 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
536 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
537 else:
538 ret += ' />\n'
539
540
541 elif type == 'int32':
542 ret += tabs + ('<Number %s size="32" valueType="hex" value="%s" signed="true"' % (nodeName, valueHex))
543 if self._relations.has_key(node):
544 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
545 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
546 else:
547 ret += ' />\n'
548 elif type == 'uint32':
549 ret += tabs + ('<Number %s size="32" valueType="hex" value="%s" signed="false"' % (nodeName, valueHex))
550 if self._relations.has_key(node):
551 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
552 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
553 else:
554 ret += ' />\n'
555 elif type == 'n_int32':
556 ret += tabs + ('<Number %s size="32" valueType="hex" value="%s" signed="true" endian="big"' % (nodeName, valueHex))
557 if self._relations.has_key(node):
558 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
559 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
560 else:
561 ret += ' />\n'
562 elif type == 'n_uint32':
563 ret += tabs + ('<Number %s size="32" valueType="hex" value="%s" signed="false" endian="big"' % (nodeName, valueHex))
564 if self._relations.has_key(node):
565 of = self._relations[node].getAttributeNS(None, 'name').replace('.', '_')
566 ret += '>\n' + tabs + '\t<Relation type="size" of="'+of+'" />\n'+tabs+'</Number>\n'
567 else:
568 ret += ' />\n'
569
570 elif type == 'blob':
571 ret += tabs + '<Blob %s valueType="hex" value="%s" />\n' % (nodeName, valueHex)
572
573 elif type == 'ip':
574
575 ret += tabs + "<!-- TODO: Handle IP Address Better! -->\n"
576 ret += tabs + '<String %s value="%s">\n' % (nodeName, show)
577 ret += tabs + '\t<Transformer class="encode.Ipv4StringToOctet" />\n'
578 ret += tabs + '</String>\n'
579
580
581 elif type == 'n_ip':
582
583 ret += tabs + "<!-- TODO: Handle IP Address Better! -->\n"
584 ret += tabs + '<String %s value="%s">\n' % (nodeName, show)
585 ret += tabs + '\t<Transformer class="encode.Ipv4StringToNetworkOctet" />\n'
586 ret += tabs + '</String>\n'
587
588
589 elif type == 'bit_flag':
590
591
592 if node.previousSibling == None:
593
594
595 nodeNames = []
596 offsets = []
597 bits = []
598 shownames = []
599 length = 0
600
601 offset, bit = self.getFlagBits(node)
602 length += bit
603
604 offsets.append(offset)
605 bits.append(bit)
606 shownames.append(showName)
607
608 nodeName = self.getNodeName(node)
609 if nodeName != None:
610 nodeNames.append('name="%s"' % nodeName)
611 else:
612 nodeNames.append('')
613
614 sibling = node.nextSibling
615 while sibling != None:
616 offset, bit = self.getFlagBits(sibling)
617
618 length += bit
619
620 offsets.append(offset)
621 bits.append(bit)
622 shownames.append(sibling.getAttributeNS(None, 'showname'))
623
624 nodeName = self.getNodeName(sibling)
625 if nodeName != None:
626 nodeNames.append('name="%s"' % nodeName)
627 else:
628 nodeNames.append('')
629
630 sibling = sibling.nextSibling
631
632
633
634
635 while length % 2 != 0:
636 length += 1
637
638 parentName = self.getNodeName(node.parentNode)
639 if parentName != None:
640 ret += tabs + '<Flags name="%s" size="%d">\n' % (parentName, length)
641 else:
642 ret += tabs + '<Flags size="%d">\n' % length
643
644 for i in range(len(offsets)):
645 ret += tabs + '\t<Flag %s position="%d" size="%d" />\n' % (nodeNames[i], offsets[i], bits[i])
646
647 ret += tabs + "</Flags>\n"
648
649 else:
650 raise Exception("Unknown type: %s" % type)
651
652 return ret + '\n', size, pos
653
655 '''
656 Convert hex string to binary string
657 '''
658 ret = ''
659 for cnt in range(0, len(h), 2):
660 ret += chr(int(h[cnt:cnt+2],16))
661
662 return ret
663
665 '''
666 Is this a wchar string?
667 '''
668
669
670
671 if len(str) < 4 or len(str) % 2 != 0:
672 return False
673
674 for i in range(0, len(str), 2):
675 c = str[i]
676 c2 = str[i+1]
677
678
679
680
681 if c2 != '\0':
682 return False
683
684 o = ord(c)
685 if o < 32 or o > 126:
686 if c == '\n' or c == '\r' or c == '\t':
687 continue
688
689 return False
690
691 return True
692
694 '''
695 Is this a wchar string with nulls at the end?
696 '''
697
698
699
700 if len(str) < 4 or len(str) % 2 != 0:
701 return False
702
703 if str[-1] != '\0' or str[-2] != '\0':
704 return False
705
706 for i in range(0, len(str), 2):
707 c = str[i]
708 c2 = str[i+1]
709
710
711
712
713 if c2 != '\0':
714 return False
715
716 o = ord(c)
717 if o < 32 or o > 126:
718 if c == '\n' or c == '\r' or c == '\t' or c == '\0':
719 continue
720
721 return False
722
723 return True
724
726 '''
727 Is this a char string?
728 '''
729
730 if len(str) < 3:
731 return False
732
733 for c in str:
734 o = ord(c)
735 if o < 32 or o > 126:
736 if c == '\n' or c == '\r' or c == '\t':
737 continue
738
739 return False
740
741
742
743 return True
744
746 '''
747 Is this a char string with nulls at the end?
748 '''
749
750 if len(str) < 3:
751
752 return False
753
754 if str[-1] != '\0':
755
756 return False
757
758 for c in str:
759 o = ord(c)
760 if o < 32 or o > 126:
761 if c == '\n' or c == '\r' or c == '\t' or c == '\0':
762 continue
763
764 debug("odd char [%d]" % o)
765 return False
766
767 return True
768
770 '''
771 Checks out the showname field to see if we can determin
772 the number of bits this flag is and it's offset in the packet.
773 '''
774
775
776 show = node.getAttributeNS(None, 'showname')
777
778
779
780
781 show = show.replace(' ', '')
782
783
784 try:
785 result = self._regexFlagBit1.match(show)
786 firstDots = result.group(1)
787 number = result.group(2)
788 lastDots = result.group(3)
789
790 offset = len(firstDots)
791 bits = len(number)
792
793
794
795
796 if (len(firstDots) + len(number) + len(lastDots)) % 2 != 0:
797 debug("getFlagBits(): Something fishy about this!!! %d" % (len(firstDots) + len(number) + len(lastDots)))
798
799 return offset, bits
800 except:
801 return 0, 1
802
943
991
992
993
994
995
997
998 if len(argv) == 2:
999
1000 print "Select one of the following protocols:\n"
1001
1002 doc = Parse(argv[1])
1003 nodes = doc.xpath('descendant::proto')
1004
1005 for n in nodes:
1006 print "\t", n.getAttributeNS(None, 'name')
1007
1008 return ""
1009
1010 name = argv[1]
1011 doc = Parse(argv[1])
1012
1013 node = doc.xpath('descendant::proto[@name="%s"]' % argv[2])[0]
1014
1015 shark = PeachShark()
1016 shark.removeTextNodes(node.parentNode)
1017
1018 ret = '<?xml version="1.0" encoding="utf-8"?>\n<Peach xmlns="http://phed.org/2008/Peach" version="0.1" author="PeachShark" description="%s">\n' % argv[2]
1019 ret += """
1020 <!-- ==// Auto Generated by PeachShark //== -->
1021
1022 <!--
1023
1024 Please do the following before using this fuzzer:
1025
1026 1. Take a look through the generated output, see if it makes sense
1027 2. Verify the Publisher settings at the bottom, they are only a guess
1028 3. **UPDATE TARGET IP**
1029 4. Perform a WireShark capture of a couple packets to make sure
1030 they parse out okay.
1031
1032 -->
1033
1034 <Include ns="default" src="file:defaults.xml" />
1035 <Include ns="pt" src="file:PeachTypes.xml" />
1036
1037 """
1038
1039 sibling = node
1040 while sibling != None:
1041
1042
1043 debug("Handing node: " + sibling.getAttributeNS(None, 'name'))
1044 templateStr, s, p = shark.peachNode(sibling, 1, sibling.getAttributeNS(None, 'size'), None)
1045 ret += templateStr
1046 sibling = sibling.nextSibling
1047
1048 ret += '\t<Template name="SharkTemplate">\n'
1049
1050 for t in shark._templates:
1051 ret += '\t\t<Block ref="%s" />\n' % t
1052
1053 ret += """
1054 </Template>
1055
1056 <Test name="SharkTest">
1057 <Template ref="SharkTemplate" />
1058 %s
1059 </Test>
1060
1061 <Run name="DefaultRun">
1062 <Test ref="SharkTest" />
1063 </Run>
1064
1065 </Peach>\n""" % shark.figureOutPublisher(doc)
1066
1067 return ret
1068
1069 if __name__ == "__main__":
1070
1071 sys.stderr.write("\n]] PeachShark 2\n\n")
1072 sys.stderr.write("Loading pdml: %s\n\n" % sys.argv[1])
1073
1074 print DoTheShark(argv)
1075
1076
1077