Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
Classes | Functions | Variables
miasm2.jitter.loader.pe Namespace Reference

Classes

class  libimp_pe
 

Functions

def get_import_address_pe
 
def preload_pe
 
def is_redirected_export
 
def get_export_name_addr_list
 
def vm_load_pe
 
def vm_load_pe_lib
 
def vm_load_pe_libs
 
def vm_fix_imports_pe_libs
 
def vm2pe
 
def guess_arch
 

Variables

tuple log = logging.getLogger('loader_pe')
 
tuple hnd = logging.StreamHandler()
 
dictionary PE_machine
 

Function Documentation

def miasm2.jitter.loader.pe.get_export_name_addr_list (   e)

Definition at line 73 of file pe.py.

73 
75  out = []
76  # add func name
77  for i, n in enumerate(e.DirExport.f_names):
78  addr = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal]
79  f_name = n.name.name
80  # log.debug('%s %s' % (f_name, hex(e.rva2virt(addr.rva))))
81  out.append((f_name, e.rva2virt(addr.rva)))
82 
83  # add func ordinal
84  for i, o in enumerate(e.DirExport.f_nameordinals):
85  addr = e.DirExport.f_address[o.ordinal]
86  # log.debug('%s %s %s' % (o.ordinal, e.DirExport.expdesc.base,
87  # hex(e.rva2virt(addr.rva))))
88  out.append(
89  (o.ordinal + e.DirExport.expdesc.base, e.rva2virt(addr.rva)))
90  return out
91 
def get_export_name_addr_list
Definition: pe.py:73

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.get_import_address_pe (   e)

Definition at line 21 of file pe.py.

21 
23  import2addr = defaultdict(set)
24  if e.DirImport.impdesc is None:
25  return import2addr
26  for s in e.DirImport.impdesc:
27  # fthunk = e.rva2virt(s.firstthunk)
28  # l = "%2d %-25s %s" % (i, repr(s.dlldescname), repr(s))
29  libname = s.dlldescname.name.lower()
30  for ii, imp in enumerate(s.impbynames):
31  if isinstance(imp, pe.ImportByName):
32  funcname = imp.name
33  else:
34  funcname = imp
35  # l = " %2d %-16s" % (ii, repr(funcname))
36  import2addr[(libname, funcname)].add(
37  e.rva2virt(s.firstthunk + e._wsize * ii / 8))
38  return import2addr
39 
def get_import_address_pe
Definition: pe.py:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.guess_arch (   pe)
Return the architecture specified by the PE container @pe.
If unknown, return None

Definition at line 423 of file pe.py.

424 def guess_arch(pe):
425  """Return the architecture specified by the PE container @pe.
426  If unknown, return None"""
427  return PE_machine.get(pe.Coffhdr.machine, None)
def miasm2.jitter.loader.pe.is_redirected_export (   e,
  ad 
)

Definition at line 57 of file pe.py.

57 
58 def is_redirected_export(e, ad):
59  # test is ad points to code or dll name
60  out = ''
61  for i in xrange(0x200):
62  c = e.virt(ad + i)
63  if c == "\x00":
64  break
65  out += c
66  if not (c.isalnum() or c in "_.-+*$@&#()[]={}"):
67  return False
68  if not "." in out:
69  return False
70  i = out.find('.')
71  return out[:i], out[i + 1:]
72 
def is_redirected_export
Definition: pe.py:57

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.preload_pe (   vm,
  e,
  runtime_lib,
  patch_vm_imp = True 
)

Definition at line 40 of file pe.py.

40 
41 def preload_pe(vm, e, runtime_lib, patch_vm_imp=True):
42  fa = get_import_address_pe(e)
43  dyn_funcs = {}
44  # log.debug('imported funcs: %s' % fa)
45  for (libname, libfunc), ads in fa.items():
46  for ad in ads:
47  ad_base_lib = runtime_lib.lib_get_add_base(libname)
48  ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad)
49 
50  libname_s = canon_libname_libfunc(libname, libfunc)
51  dyn_funcs[libname_s] = ad_libfunc
52  if patch_vm_imp:
53  vm.set_mem(
54  ad, struct.pack(cstruct.size2type[e._wsize], ad_libfunc))
55  return dyn_funcs
56 
def get_import_address_pe
Definition: pe.py:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.vm2pe (   myjit,
  fname,
  libs = None,
  e_orig = None,
  min_addr = None,
  max_addr = None,
  min_section_offset = 0x1000,
  img_base = None,
  added_funcs = None 
)

Definition at line 229 of file pe.py.

230  added_funcs=None):
231  if e_orig:
232  size = e_orig._wsize
233  else:
234  size = 32
235  mye = pe_init.PE(wsize=size)
236 
237  if min_addr is None and e_orig is not None:
238  min_addr = min([e_orig.rva2virt(s.addr) for s in e_orig.SHList])
239  if max_addr is None and e_orig is not None:
240  max_addr = max([e_orig.rva2virt(s.addr + s.size)
241  for s in e_orig.SHList])
242 
243  if img_base is None:
244  img_base = e_orig.NThdr.ImageBase
245 
246  mye.NThdr.ImageBase = img_base
247  all_mem = myjit.vm.get_all_memory()
248  addrs = all_mem.keys()
249  addrs.sort()
250  mye.Opthdr.AddressOfEntryPoint = mye.virt2rva(myjit.pc)
251  first = True
252  for ad in addrs:
253  if not min_addr <= ad < max_addr:
254  continue
255  log.debug("0x%x", ad)
256  if first:
257  mye.SHList.add_section(
258  "%.8X" % ad,
259  addr=ad - mye.NThdr.ImageBase,
260  data=all_mem[ad]['data'],
261  offset=min_section_offset)
262  else:
263  mye.SHList.add_section(
264  "%.8X" % ad,
265  addr=ad - mye.NThdr.ImageBase,
266  data=all_mem[ad]['data'])
267  first = False
268  if libs:
269  if added_funcs is not None:
270  # name_inv = dict([(x[1], x[0]) for x in libs.name2off.items()])
271 
272  for addr, funcaddr in added_func:
273  libbase, dllname = libs.fad2info[funcaddr]
274  libs.lib_get_add_func(libbase, dllname, addr)
275 
276  new_dll = libs.gen_new_lib(mye, mye.virt.is_addr_in)
277  else:
278  new_dll = {}
279 
280  log.debug('%s', new_dll)
281 
282  mye.DirImport.add_dlldesc(new_dll)
283  s_imp = mye.SHList.add_section("import", rawsize=len(mye.DirImport))
284  mye.DirImport.set_rva(s_imp.addr)
285  log.debug('%r', mye.SHList)
286  if e_orig:
287  # resource
288  xx = str(mye)
289  mye.content = xx
290  ad = e_orig.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva
291  log.debug('dirres 0x%x', ad)
292  if ad != 0:
293  mye.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva = ad
294  mye.DirRes = pe.DirRes.unpack(xx, ad, mye)
295  # log.debug('%s' % repr(mye.DirRes))
296  s_res = mye.SHList.add_section(
297  name="myres", rawsize=len(mye.DirRes))
298  mye.DirRes.set_rva(s_res.addr)
299  log.debug('%r', mye.DirRes)
300  # generation
301  open(fname, 'w').write(str(mye))
302  return mye
303 

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.vm_fix_imports_pe_libs (   lib_imgs,
  libs,
  lib_path_base = "win_dll",
  patch_vm_imp = True,
  kargs 
)

Definition at line 221 of file pe.py.

222  patch_vm_imp=True, **kargs):
223  for e in lib_imgs.values():
224  preload_pe(e, libs, patch_vm_imp)
225 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.vm_load_pe (   vm,
  fdata,
  align_s = True,
  load_hdr = True,
  kargs 
)
Load a PE in memory (@vm) from a data buffer @fdata
@vm: VmMngr instance
@fdata: data buffer to parse
@align_s: (optional) If False, keep gaps between section
@load_hdr: (optional) If False, do not load the NThdr in memory
Return the corresponding PE instance.

Extra arguments are passed to PE instanciation.
If all sections are aligned, they will be mapped on several different pages
Otherwise, a big page is created, containing all sections

Definition at line 92 of file pe.py.

92 
93 def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, **kargs):
94  """Load a PE in memory (@vm) from a data buffer @fdata
95  @vm: VmMngr instance
96  @fdata: data buffer to parse
97  @align_s: (optional) If False, keep gaps between section
98  @load_hdr: (optional) If False, do not load the NThdr in memory
99  Return the corresponding PE instance.
100 
101  Extra arguments are passed to PE instanciation.
102  If all sections are aligned, they will be mapped on several different pages
103  Otherwise, a big page is created, containing all sections
104  """
105  # Parse and build a PE instance
106  pe = pe_init.PE(fdata, **kargs)
107 
108  # Check if all section are aligned
109  aligned = True
110  for section in pe.SHList:
111  if section.addr & 0xFFF:
112  aligned = False
113  break
114 
115  if aligned:
116  # Loader NT header
117  if load_hdr:
118  # Header length
119  hdr_len = max(0x200, pe.NThdr.sizeofheaders)
120  # Page minimum size
121  min_len = min(pe.SHList[0].addr, 0x1000)
122 
123  # Get and pad the pe_hdr
124  pe_hdr = pe.content[:hdr_len] + max(
125  0, (min_len - hdr_len)) * "\x00"
126  vm.add_memory_page(pe.NThdr.ImageBase, PAGE_READ | PAGE_WRITE,
127  pe_hdr)
128 
129  # Align sections size
130  if align_s:
131  # Use the next section address to compute the new size
132  for i, section in enumerate(pe.SHList[:-1]):
133  new_size = pe.SHList[i + 1].addr - section.addr
134  section.size = new_size
135  section.rawsize = new_size
136  section.data = strpatchwork.StrPatchwork(
137  section.data[:new_size])
138  section.offset = section.addr
139 
140  # Last section alignement
141  last_section = pe.SHList[-1]
142  last_section.size = (last_section.size + 0xfff) & 0xfffff000
143 
144  # Pad sections with null bytes and map them
145  for section in pe.SHList:
146  data = str(section.data)
147  data += "\x00" * (section.size - len(data))
148  vm.add_memory_page(pe.rva2virt(section.addr),
149  PAGE_READ | PAGE_WRITE, data)
150 
151  return pe
152 
153  # At least one section is not aligned
154  log.warning('PE is not aligned, creating big section')
155  min_addr = 0 if load_hdr else None
156  max_addr = None
157  data = ""
158 
159  for i, section in enumerate(pe.SHList):
160  if i < len(pe.SHList) - 1:
161  # If it is not the last section, use next section address
162  section.size = pe.SHList[i + 1].addr - section.addr
163  section.rawsize = section.size
164  section.offset = section.addr
165 
166  # Update min and max addresses
167  if min_addr is None or section.addr < min_addr:
168  min_addr = section.addr
169  max_section_len = max(section.size, len(section.data))
170  if max_addr is None or section.addr + max_section_len > max_addr:
171  max_addr = section.addr + max_section_len
172 
173  min_addr = pe.rva2virt(min_addr)
174  max_addr = pe.rva2virt(max_addr)
175  log.debug('Min: 0x%x, Max: 0x%x, Size: 0x%x', min_addr, max_addr,
176  (max_addr - min_addr))
177 
178  # Create only one big section containing the whole PE
179  vm.add_memory_page(min_addr,
180  PAGE_READ | PAGE_WRITE,
181  (max_addr - min_addr) * "\x00")
182 
183  # Copy each sections content in memory
184  for section in pe.SHList:
185  log.debug('Map 0x%x bytes to 0x%x', len(section.data),
186  pe.rva2virt(section.addr))
187  vm.set_mem(pe.rva2virt(section.addr), str(section.data))
188 
189  return pe
190 

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.vm_load_pe_lib (   vm,
  fname_in,
  libs,
  lib_path_base,
  kargs 
)
Call vm_load_pe on @fname_in and update @libs accordingly
@vm: VmMngr instance
@fname_in: library name
@libs: libimp_pe instance
@lib_path_base: DLLs relative path
Return the corresponding PE instance
Extra arguments are passed to vm_load_pe

Definition at line 191 of file pe.py.

192 def vm_load_pe_lib(vm, fname_in, libs, lib_path_base, **kargs):
193  """Call vm_load_pe on @fname_in and update @libs accordingly
194  @vm: VmMngr instance
195  @fname_in: library name
196  @libs: libimp_pe instance
197  @lib_path_base: DLLs relative path
198  Return the corresponding PE instance
199  Extra arguments are passed to vm_load_pe
200  """
201  fname = os.path.join(lib_path_base, fname_in)
202  with open(fname) as fstream:
203  pe = vm_load_pe(vm, fstream.read(), **kargs)
204  libs.add_export_lib(pe, fname_in)
205  return pe
206 

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.jitter.loader.pe.vm_load_pe_libs (   vm,
  libs_name,
  libs,
  lib_path_base = "win_dll",
  kargs 
)
Call vm_load_pe_lib on each @libs_name filename
@vm: VmMngr instance
@libs_name: list of str
@libs: libimp_pe instance
@lib_path_base: (optional) DLLs relative path
Return a dictionnary Filename -> PE instances
Extra arguments are passed to vm_load_pe_lib

Definition at line 207 of file pe.py.

208 def vm_load_pe_libs(vm, libs_name, libs, lib_path_base="win_dll", **kargs):
209  """Call vm_load_pe_lib on each @libs_name filename
210  @vm: VmMngr instance
211  @libs_name: list of str
212  @libs: libimp_pe instance
213  @lib_path_base: (optional) DLLs relative path
214  Return a dictionnary Filename -> PE instances
215  Extra arguments are passed to vm_load_pe_lib
216  """
217  return {fname: vm_load_pe_lib(vm, fname, libs, lib_path_base, **kargs)
218  for fname in libs_name}
219 

+ Here is the call graph for this function:

Variable Documentation

tuple miasm2.jitter.loader.pe.hnd = logging.StreamHandler()

Definition at line 15 of file pe.py.

tuple miasm2.jitter.loader.pe.log = logging.getLogger('loader_pe')

Definition at line 14 of file pe.py.

dictionary miasm2.jitter.loader.pe.PE_machine
Initial value:
1 = {0x14c: "x86_32",
2  0x8664: "x86_64",
3  }

Definition at line 418 of file pe.py.