Package Libs :: Module pelib
[hide private]
[frames] | no frames]

Source Code for Module Libs.pelib

   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   
44 -def hexdump(buf):
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
63 -def readStringFromFile(fd, offset):
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
96 -class PEError(Exception): pass
97
98 -class MZ:
99
100 - def __init__(self):
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
110 - def getSize(self):
111 return struct.calcsize(self.fmt)
112
113 - def get(self, data):
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
142 - def raw(self):
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
154 - def getPEOffset(self):
155 return self.e_lfanew
156
157 -class ImageImportByName:
158 - def __init__(self):
159 self.fmt = "<H" 160 self.Hint=0 161 self.Name=""
162
163 - def get(self, data):
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
170 - def getSize(self):
171 return len(self.Name) +3 # 1 for \0 + 2 for Hint
172
173 - def raw(self):
174 return struct.pack(self.fmt, self.Hint) + self.Name + "\0"
175
176 -class ImportDescriptor:
177 - def __init__(self):
178 self.fmt= "<LLLLL" 179 self.OriginalFirstThunk= self.TimeDateStamp= self.ForwarderChain= self.Name=\ 180 self.FirstThunk=0 181 self.sName ="" 182 self.Imports={}
183
184 - def get(self, data):
185 (self.OriginalFirstThunk, self.TimeDateStamp, self.ForwarderChain, self.Name,\ 186 self.FirstThunk) = struct.unpack(self.fmt, data)
187
188 - def setSname(self, name):
189 self.sName= name
190
191 - def setImport(self, name, obj):
192 self.Imports[name] = obj
193
194 - def raw(self):
195 return struct.pack(self.fmt, self.OriginalFirstThunk, self.TimeDateStamp, self.ForwarderChain, self.Name,\ 196 self.FirstThunk)
197
198 - def getSize(self):
199 return struct.calcsize(self.fmt)
200 201 #typedef struct _IMAGE_DATA_DIRECTORY { 202 # ULONG VirtualAddress; 203 # ULONG Size; 204 #} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; 205 206
207 -class Directory:
208
209 - def __init__(self):
210 self.VirtualAddress = self.Size = 0
211
212 - def get(self, data):
213 (self.VirtualAddress, self.Size) = struct.unpack("2L", data)
214
215 - def raw(self):
216 return struct.pack("2L", self.VirtualAddress, self.Size)
217
218 - def getSize(self):
219 return 0x8
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
234 -class ImageExportDirectory:
235 - def __init__(self):
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
242 - def setName(self, name):
243 self.sName = name
244
245 - def getSize(self):
246 return struct.calcsize(self.fmt)
247
248 - def get(self, data):
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
253 - def raw(self):
254 return struct.pack(self.fmt, self.Characteristics, self.TimeDateStamp, self.MajorVersion, self.MinorVersion, self.Name, self.Base,\ 255 self.NumberOfFunctions, self.NumberOfNames, self.AddressOfFunctions, self.AddressOfNames, \ 256 self.AddressOfNameOrdinals)
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
278 -class Section:
279 - def __init__(self):
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
287 - def getSize(self):
288 return struct.calcsize(self.fmt) + 8
289
290 - def has(self, rva, imagebase=0):
291 return rva >= (self.VirtualAddress+imagebase) and rva < (self.VirtualAddress+self.VirtualSize+imagebase)
292
293 - def hasOffset(self, offset):
294 return offset >= self.PointerToRawData and offset < (self.PointerToRawData + self.VirtualSize)
295 296
297 - def get(self, data):
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
309 - def raw(self):
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
330 -class IMGhdr:
331 - def __init__(self):
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
341 - def get(self, data):
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
353 - def getSize(self):
354 return struct.calcsize(self.imagefmt)
355
356 - def raw(self):
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
409 -class IMGOPThdr:
410 - def __init__(self):
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
422 - def getSize(self):
423 return struct.calcsize(self.optionalfmt)
424
425 - def Print(self):
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.SizeOfI