def clean_non_present_modules(pid, pgd): from api_internal import dispatch_module_remove_callback mods_to_remove = [] if pid is not None: if (pid, pgd) in modules: for base, mod in modules[(pid, pgd)].iteritems(): if not mod.is_present(): mods_to_remove.append((pid, pgd, base)) else: for pid, _pgd in modules.keys(): if _pgd == pgd: if (pid, _pgd) in modules: for base, mod in modules[(pid, _pgd)].iteritems(): if not mod.is_present(): mods_to_remove.append((pid, pgd, base)) for pid, pgd, base in mods_to_remove: # Callback notification dispatch_module_remove_callback( pid, pgd, base, modules[(pid, pgd)][base].get_size(), modules[(pid, pgd)][base].get_name(), modules[(pid, pgd)][base].get_fullname()) # Remove module del modules[(pid, pgd)][base]
def clean_non_present_modules(pid, pgd): from api_internal import dispatch_module_remove_callback mods_to_remove = [] if pid is not None: if (pid, pgd) in modules: for base, mod in modules[(pid, pgd)].iteritems(): if not mod.is_present(): mods_to_remove.append((pid, pgd, base)) else: for pid, _pgd in modules.keys(): if _pgd == pgd: if (pid, _pgd) in modules: for base, mod in modules[(pid, _pgd)].iteritems(): if not mod.is_present(): mods_to_remove.append((pid, pgd, base)) for pid, pgd, base in mods_to_remove: # Callback notification dispatch_module_remove_callback(pid, pgd, base, modules[(pid, pgd)][base].get_size(), modules[(pid, pgd)][base].get_name(), modules[(pid, pgd)][base].get_fullname()) # Remove module del modules[(pid, pgd)][base]
def windows_insert_module_internal(p_pid, p_pgd, base, size, fullname, basename, checksum, nt_header, update_symbols): from utils import get_addr_space from vmi import modules from vmi import symbols from vmi import Module from vmi import PseudoLDRDATA from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname) if p_pgd != 0: addr_space = get_addr_space(p_pgd) else: addr_space = get_addr_space() # First, we try to get the symbols from the cache if (checksum, fullname) in symbols: mod.set_symbols(symbols[(checksum, fullname)]) # If we are updating symbols (a simple module retrieval would # not require symbol extraction), and, either we dont have any # symbols on the cache, or we have an empty list (symbols could # not be retrieved for some reason, such as a missing memory page, # we try symbol resolution if update_symbols and ((checksum, fullname) not in symbols or len(symbols[(checksum, fullname)]) == 0): syms = {} export_dir = nt_header.OptionalHeader.DataDirectory[0] if export_dir: expdir = obj.Object('_IMAGE_EXPORT_DIRECTORY', offset=base + export_dir.VirtualAddress, vm=addr_space, parent=PseudoLDRDATA(base, basename, export_dir)) if expdir.valid(nt_header): # Ordinal, Function RVA, and Name Object for o, f, n in expdir._exported_functions(): if not isinstance(o, obj.NoneObject) and \ not isinstance(f, obj.NoneObject) and \ not isinstance(n, obj.NoneObject): syms[str(n)] = f.v() # If we managed to parse export table, update symbols, # no matter if it is empty if (checksum, fullname) not in symbols or len(syms) > len( symbols[(checksum, fullname)]): symbols[(checksum, fullname)] = syms # Even if it is empty, the module symbols are set # to an empty list, and thus are 'resolved'. # Anyway, in future updates, they could be resolved, # as we allow this in the first condition. mod.set_symbols(symbols[(checksum, fullname)]) # Add module to mods_pending, or # Update modules that may we might not have been # able to resolve symbols in the past if len(syms) == 0: if (checksum, fullname) not in mods_pending: mods_pending[(checksum, fullname)] = [] mods_pending[(checksum, fullname)].append(mod) else: if (checksum, fullname) in mods_pending and len( mods_pending[(checksum, fullname)]) > 0: for mod in mods_pending[(checksum, fullname)]: mod.set_symbols(syms) del mods_pending[(checksum, fullname)] else: # Since there is no export dir, we assume that it does # not have any symbols if (checksum, fullname) not in symbols: symbols[(checksum, fullname)] = [] # Even if it is empty, the module symbols are set # to an empty list, and thus are 'resolved'. # Anyway, in future updates, they could be resolved, # as we allow this in the first condition. mod.set_symbols(symbols[(checksum, fullname)]) # Add module to mods_pending, or if (checksum, fullname) not in mods_pending: mods_pending[(checksum, fullname)] = [] mods_pending[(checksum, fullname)].append(mod) #Module load/del notification if base in modules[(p_pid, p_pgd)]: if modules[(p_pid, p_pgd)][base].get_size() != size or \ modules[(p_pid, p_pgd)][base].get_checksum() != checksum or \ modules[(p_pid, p_pgd)][base].get_name() != basename or \ modules[(p_pid, p_pgd)][base].get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback( p_pid, p_pgd, base, modules[(p_pid, p_pgd)][base].get_size(), modules[(p_pid, p_pgd)][base].get_name(), modules[(p_pid, p_pgd)][base].get_fullname()) del modules[(p_pid, p_pgd)][base] modules[(p_pid, p_pgd)][base] = mod dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname) # If we updated the symbols and have a bigger list now, dont substitute the module # but update its symbols instead elif len(mod.get_symbols()) > len( modules[(p_pid, p_pgd)][base].get_symbols()): modules[(p_pid, p_pgd)][base].set_symbols(mod.get_symbols()) else: # Just notify of module load modules[(p_pid, p_pgd)][base] = mod dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname) # Mark the module as present modules[(p_pid, p_pgd)][base].set_present()
def linux_insert_module(task, pid, pgd, base, size, basename, fullname, update_symbols=False): from utils import ConfigurationManager as conf_m import volatility.obj as obj from vmi import add_symbols from vmi import get_symbols from vmi import has_symbols from vmi import add_module from vmi import has_module from vmi import get_module from vmi import Module from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback import api import hashlib pgd_for_memory_read = conf_m.addr_space.vtop(task.mm.pgd) or task.mm.pgd # Create module, use 0 as checksum as it is irrelevant here mod = Module(base, size, pid, pgd, 0, basename, fullname) #Module load/del notification if has_module(pid, pgd, base): ex_mod = get_module(pid, pgd, base) if ex_mod.get_size() != size or \ ex_mod.get_checksum() != checksum or \ ex_mod.get_name() != basename or \ ex_mod.get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback(pid, pgd, base, ex_mod.get_size(), ex_mod.get_name(), ex_mod.get_fullname()) add_module(pid, pgd, base, mod) dispatch_module_load_callback(pid, pgd, base, size, basename, fullname) else: # Just notify of module load dispatch_module_load_callback(pid, pgd, base, size, basename, fullname) add_module(pid, pgd, base, mod) # Mark the module as present get_module(pid, pgd, base).set_present() if update_symbols: # Compute the checksum of the ELF Header, as a way to avoid name # collisions on the symbol cache. May extend this hash to other parts # of the binary if necessary in the future. elf_hdr = obj.Object("elf_hdr", offset=base, vm=task.get_process_address_space()) if elf_hdr.is_valid(): elf_hdr_size = elf_hdr.elf_obj.size() buf = "" try: buf = api.r_va(pgd_for_memory_read, base, elf_hdr_size) except: pp_warning("Could not read ELF header at address %x" % base) if not has_symbols(fullname): syms = {} # Fetch symbols for sym in elf_hdr.symbols(): if sym.st_value == 0 or (sym.st_info & 0xf) != 2: continue sym_name = elf_hdr.symbol_name(sym) sym_offset = sym.st_value if sym_name in syms: if syms[sym_name] != sym_offset: # There are cases in which the same import is present twice, such as in this case: # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np" # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3 # 00000000000113a0 T # pthread_getaffinity_np@@GLIBC_2.3.4 sym_name = sym_name + "_" while sym_name in syms and syms[ sym_name] != sym_offset: sym_name = sym_name + "_" if sym_name not in syms: syms[sym_name] = sym_offset else: syms[sym_name] = sym_offset add_symbols(fullname, syms) mod.set_symbols(get_symbols(fullname)) return None
def linux_insert_kernel_module(module, base, size, basename, fullname, update_symbols=False): from vmi import add_module from vmi import has_module from vmi import get_module from vmi import has_symbols from vmi import get_symbols from vmi import add_symbols from vmi import Module from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback # Create module, use 0 as checksum as it is irrelevant here mod = Module(base, size, 0, 0, 0, basename, fullname) #Module load/del notification if has_module(0, 0, base): ex_mod = get_module(0, 0, base) if ex_mod.get_size() != size or \ ex_mod.get_checksum() != checksum or \ ex_mod.get_name() != basename or \ ex_mod.get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback(0, 0, base, ex_mod.get_size(), ex_mod.get_name(), ex_mod.get_fullname()) dispatch_module_load_callback(0, 0, base, size, basename, fullname) add_module(0, 0, base, mod) else: # Just notify of module load dispatch_module_load_callback(0, 0, base, size, basename, fullname) add_module(0, 0, base, mod) # Mark the module as present get_module(0, 0, base).set_present() if update_symbols: if not has_symbols(fullname): syms = {} try: ''' pp_debug("Processing symbols for module %s\n" % basename) ''' for sym_name, sym_offset in module.get_symbols(): if sym_name in syms: if syms[sym_name] != sym_offset: # There are cases in which the same import is present twice, such as in this case: # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np" # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3 # 00000000000113a0 T # pthread_getaffinity_np@@GLIBC_2.3.4 sym_name = sym_name + "_" while sym_name in syms and syms[ sym_name] != sym_offset: sym_name = sym_name + "_" if sym_name not in syms: syms[sym_name] = sym_offset else: syms[sym_name] = sym_offset add_symbols(fullname, syms) except Exception as e: # Probably could not fetch the symbols for this module pp_error("%s" % str(e)) pass mod.set_symbols(get_symbols(fullname)) return None
def linux_insert_kernel_module(module, base, size, basename, fullname, update_symbols=False): from vmi import modules from vmi import symbols from vmi import Module from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback # Create module, use 0 as checksum as it is irrelevant here mod = Module(base, size, 0, 0, 0, basename, fullname) # Add an entry in the module list, if necessary if (0, 0) not in modules: modules[(0, 0)] = {} #Module load/del notification if base in modules[(0, 0)]: if modules[(0, 0)][base].get_size() != size or \ modules[(0, 0)][base].get_checksum() != checksum or \ modules[(0, 0)][base].get_name() != basename or \ modules[(0, 0)][base].get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback( 0, 0, base, modules[(0, 0)][base].get_size(), modules[(0, 0)][base].get_name(), modules[(0, 0)][base].get_fullname()) del modules[(0, 0)][base] dispatch_module_load_callback(0, 0, base, size, basename, fullname) modules[(0, 0)][base] = mod else: # Just notify of module load dispatch_module_load_callback(0, 0, base, size, basename, fullname) modules[(0, 0)][base] = mod # Mark the module as present modules[(0, 0)][base].set_present() if update_symbols: # Use 0 as a checksum, here we should not have name collision checksum = 0 if (checksum, fullname) not in symbols: symbols[(checksum, fullname)] = {} syms = symbols[(checksum, fullname)] try: ''' pp_debug("Processing symbols for module %s\n" % basename) ''' for sym_name, sym_offset in module.get_symbols(): if sym_name in syms: if syms[sym_name] != sym_offset: # There are cases in which the same import is present twice, such as in this case: # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np" # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3 # 00000000000113a0 T # pthread_getaffinity_np@@GLIBC_2.3.4 sym_name = sym_name + "_" while sym_name in syms and syms[ sym_name] != sym_offset: sym_name = sym_name + "_" if sym_name not in syms: syms[sym_name] = sym_offset else: syms[sym_name] = sym_offset except Exception as e: # Probably could not fetch the symbols for this module pp_error("%s" % str(e)) pass mod.set_symbols(symbols[(checksum, fullname)]) return None
def windows_insert_module_internal(p_pid, p_pgd, base, size, fullname, basename, checksum, nt_header, update_symbols): from utils import get_addr_space from vmi import modules from vmi import symbols from vmi import Module from vmi import PseudoLDRDATA from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname) if p_pgd != 0: addr_space = get_addr_space(p_pgd) else: addr_space = get_addr_space() # Getting symbols, from cache! if (checksum, fullname) in symbols: mod.set_symbols(symbols[(checksum, fullname)]) elif update_symbols: syms = {} export_dir = nt_header.OptionalHeader.DataDirectory[0] if export_dir: expdir = obj.Object('_IMAGE_EXPORT_DIRECTORY', offset=base + export_dir.VirtualAddress, vm=addr_space, parent=PseudoLDRDATA(base, basename, export_dir)) if expdir.valid(nt_header): # Ordinal, Function RVA, and Name Object for o, f, n in expdir._exported_functions(): if not isinstance(o, obj.NoneObject) and \ not isinstance(f, obj.NoneObject) and \ not isinstance(n, obj.NoneObject): syms[str(n)] = f.v() if len(syms) > 0: symbols[(checksum, fullname)] = syms mod.set_symbols(syms) if (checksum, fullname) in mods_pending: for m in mods_pending[(checksum, fullname)]: m.set_symbols(syms) del mods_pending[(checksum, fullname)] else: if (checksum, fullname) in mods_pending: mods_pending[(checksum, fullname)].append(mod) else: mods_pending[(checksum, fullname)] = [mod] #Module load/del notification if base in modules[(p_pid, p_pgd)]: if modules[(p_pid, p_pgd)][base].get_size() != size or \ modules[(p_pid, p_pgd)][base].get_checksum() != checksum or \ modules[(p_pid, p_pgd)][base].get_name() != basename or \ modules[(p_pid, p_pgd)][base].get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback( p_pid, p_pgd, base, modules[(p_pid, p_pgd)][base].get_size(), modules[(p_pid, p_pgd)][base].get_name(), modules[(p_pid, p_pgd)][base].get_fullname()) del modules[(p_pid, p_pgd)][base] dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname) modules[(p_pid, p_pgd)][base] = mod else: # Just notify of module load dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname) modules[(p_pid, p_pgd)][base] = mod # Mark the module as present modules[(p_pid, p_pgd)][base].set_present()
def linux_insert_module(task, pid, pgd, base, size, basename, fullname, update_symbols=False): from utils import ConfigurationManager as conf_m import volatility.obj as obj from vmi import modules from vmi import symbols from vmi import Module from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback import api import hashlib pgd_for_memory_read = conf_m.addr_space.vtop(task.mm.pgd) or task.mm.pgd # Create module, use 0 as checksum as it is irrelevant here mod = Module(base, size, pid, pgd, 0, basename, fullname) # Add an entry in the module list, if necessary if (pid, pgd) not in modules: modules[(pid, pgd)] = {} #Module load/del notification if base in modules[(pid, pgd)]: if modules[(pid, pgd)][base].get_size() != size or \ modules[(pid, pgd)][base].get_checksum() != checksum or \ modules[(pid, pgd)][base].get_name() != basename or \ modules[(pid, pgd)][base].get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback(pid, pgd, base, modules[(pid, pgd)][base].get_size(), modules[(pid, pgd)][base].get_name(), modules[(pid, pgd)][base].get_fullname()) del modules[(pid, pgd)][base] dispatch_module_load_callback(pid, pgd, base, size, basename, fullname) modules[(pid, pgd)][base] = mod else: # Just notify of module load dispatch_module_load_callback(pid, pgd, base, size, basename, fullname) modules[(pid, pgd)][base] = mod # Mark the module as present modules[(pid, pgd)][base].set_present() if update_symbols: # Compute the checksum of the ELF Header, as a way to avoid name # collisions on the symbol cache. May extend this hash to other parts # of the binary if necessary in the future. elf_hdr = obj.Object( "elf_hdr", offset=base, vm=task.get_process_address_space()) if elf_hdr.is_valid(): elf_hdr_size = elf_hdr.elf_obj.size() buf = "" try: buf = api.r_va(pgd_for_memory_read, base, elf_hdr_size) except: pp_warning("Could not read ELF header at address %x" % base) h = hashlib.sha256() h.update(buf) checksum = h.hexdigest() if (checksum, fullname) not in symbols: symbols[(checksum, fullname)] = {} syms = symbols[(checksum, fullname)] # Fetch symbols for sym in elf_hdr.symbols(): if sym.st_value == 0 or (sym.st_info & 0xf) != 2: continue sym_name = elf_hdr.symbol_name(sym) sym_offset = sym.st_value if sym_name in syms: if syms[sym_name] != sym_offset: # There are cases in which the same import is present twice, such as in this case: # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np" # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3 # 00000000000113a0 T # pthread_getaffinity_np@@GLIBC_2.3.4 sym_name = sym_name + "_" while sym_name in syms and syms[sym_name] != sym_offset: sym_name = sym_name + "_" if sym_name not in syms: syms[sym_name] = sym_offset else: syms[sym_name] = sym_offset mod.set_symbols(symbols[(checksum, fullname)]) return None
def linux_insert_kernel_module(module, base, size, basename, fullname, update_symbols=False): from vmi import modules from vmi import symbols from vmi import Module from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback # Create module, use 0 as checksum as it is irrelevant here mod = Module(base, size, 0, 0, 0, basename, fullname) # Add an entry in the module list, if necessary if (0, 0) not in modules: modules[(0, 0)] = {} #Module load/del notification if base in modules[(0, 0)]: if modules[(0, 0)][base].get_size() != size or \ modules[(0, 0)][base].get_checksum() != checksum or \ modules[(0, 0)][base].get_name() != basename or \ modules[(0, 0)][base].get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback(0, 0, base, modules[(0, 0)][base].get_size(), modules[(0, 0)][base].get_name(), modules[(0, 0)][base].get_fullname()) del modules[(0, 0)][base] dispatch_module_load_callback(0, 0, base, size, basename, fullname) modules[(0, 0)][base] = mod else: # Just notify of module load dispatch_module_load_callback(0, 0, base, size, basename, fullname) modules[(0, 0)][base] = mod # Mark the module as present modules[(0, 0)][base].set_present() if update_symbols: # Use 0 as a checksum, here we should not have name collision checksum = 0 if (checksum, fullname) not in symbols: symbols[(checksum, fullname)] = {} syms = symbols[(checksum, fullname)] try: ''' pp_debug("Processing symbols for module %s\n" % basename) ''' for sym_name, sym_offset in module.get_symbols(): if sym_name in syms: if syms[sym_name] != sym_offset: # There are cases in which the same import is present twice, such as in this case: # nm /lib/x86_64-linux-gnu/libpthread-2.24.so | grep "pthread_getaffinity_np" # 00000000000113f0 T pthread_getaffinity_np@GLIBC_2.3.3 # 00000000000113a0 T # pthread_getaffinity_np@@GLIBC_2.3.4 sym_name = sym_name + "_" while sym_name in syms and syms[sym_name] != sym_offset: sym_name = sym_name + "_" if sym_name not in syms: syms[sym_name] = sym_offset else: syms[sym_name] = sym_offset except Exception as e: # Probably could not fetch the symbols for this module pp_error("%s" % str(e)) pass mod.set_symbols(symbols[(checksum, fullname)]) return None
def windows_insert_module_internal( p_pid, p_pgd, base, size, fullname, basename, checksum, update_symbols, do_stop = False): from utils import get_addr_space from vmi import add_symbols from vmi import get_symbols from vmi import has_symbols from vmi import Module from vmi import add_module from vmi import get_module from vmi import has_module from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback import pefile import api global filesystem global symbol_cache_must_be_saved if fullname.startswith("\\??\\"): fullname = fullname[4:] if fullname.upper().startswith("C:\\"): fullname = fullname[3:] if fullname.upper().startswith("\\SYSTEMROOT"): fullname = "\WINDOWS" + fullname[11:] fullname = fullname.replace("\\", "/") if fullname[-4:].upper() == ".SYS" and not "/" in fullname: fullname = "/WINDOWS/system32/DRIVERS/" + fullname fullname = fullname.lower() mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname) # First, we try to get the symbols from the cache if fullname != "" and has_symbols(fullname): mod.set_symbols(get_symbols(fullname)) # If we are updating symbols (a simple module retrieval would # not require symbol extraction), and we don't have any # symbols on the cache: elif fullname != "" and update_symbols: pp_debug("Symbols not found in cache, extracting from %s...\n" % fullname) unnamed_function_counter = 0 syms = {} # Here, fetch the file using the sleuthkit, and use # PE file to process it # First select the file system if not selected already if filesystem is None: for fs in api.get_filesystems(): file_list = api.open_guest_path(fs["index"], "") if isinstance(file_list, list) and len(file_list) > 0: if "windows" in [f.lower() for f in file_list]: filesystem = fs if filesystem is not None: # Try to read the file f = None try: f = api.open_guest_path(filesystem["index"], fullname) except Exception as e: pp_error("%s - %s\n" % (str(e), fullname)) if f is not None: data = f.read() pe = pefile.PE(data=data) if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"): for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: if exp.name is not None: syms[exp.name] = exp.address else: syms["unnamed_funcion_%d" % unnamed_function_counter] = exp.address unnamed_function_counter += 1 add_symbols(fullname, syms) mod.set_symbols(syms) # Even if it is empty, the module symbols are set # to an empty list, and thus are 'resolved'. # Anyway, in future updates, they could be resolved, # as we allow this in the first condition. symbol_cache_must_be_saved = True #Module load/del notification if has_module(p_pid, p_pgd, base): ex_mod = get_module(p_pid, p_pgd, base) # Module replacement, only if it is a different module, and also # take into consideration wow64 redirection. Never substitute the # wow64 version by the system32 version of the same dll if (ex_mod.get_fullname().lower() != fullname.lower()) and not ((ex_mod.get_name().lower() == basename.lower()) and ("windows/syswow64".lower() in ex_mod.get_fullname().lower()) and ("windows/system32" in fullname.lower())): # Notify of module deletion and module load dispatch_module_remove_callback(p_pid, p_pgd, base, ex_mod.get_size(), ex_mod.get_name(), ex_mod.get_fullname()) add_module(p_pid, p_pgd, base, mod) mod.set_present() dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname) # If we updated the symbols and have a bigger list now, dont substitute the module # but update its symbols instead elif len(mod.get_symbols()) > len(ex_mod.get_symbols()): ex_mod.set_symbols(mod.get_symbols()) # In any case, mark as present ex_mod.set_present() else: # Just notify of module load add_module(p_pid, p_pgd, base, mod) # Mark the module as present mod.set_present() dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname)
def windows_insert_module_internal(p_pid, p_pgd, base, size, fullname, basename, checksum, update_symbols): from utils import get_addr_space from vmi import modules from vmi import symbols from vmi import Module from api_internal import dispatch_module_load_callback from api_internal import dispatch_module_remove_callback import pefile import api global filesystem global symbol_cache_must_be_saved if fullname.startswith("\\??\\"): fullname = fullname[4:] if fullname.upper().startswith("C:\\"): fullname = fullname[3:] if fullname.upper().startswith("\\SYSTEMROOT"): fullname = "\WINDOWS" + fullname[11:] fullname = fullname.replace("\\", "/") if fullname[-4:].upper() == ".SYS" and not "/" in fullname: fullname = "/WINDOWS/system32/DRIVERS/" + fullname fullname = fullname.lower() mod = Module(base, size, p_pid, p_pgd, checksum, basename, fullname) # First, we try to get the symbols from the cache if fullname != "" and fullname in symbols.keys(): mod.set_symbols(symbols[fullname]) # If we are updating symbols (a simple module retrieval would # not require symbol extraction), and we don't have any # symbols on the cache: elif fullname != "" and update_symbols: unnamed_function_counter = 0 syms = {} # Here, fetch the file using the sleuthkit, and use # PE file to process it # First select the file system if not selected already if filesystem is None: for fs in api.get_filesystems(): file_list = api.open_guest_path(fs["index"], "") if isinstance(file_list, list) and len(file_list) > 0: if "windows" in [f.lower() for f in file_list]: filesystem = fs if filesystem is not None: # Try to read the file f = None try: f = api.open_guest_path(filesystem["index"], fullname) except Exception as e: pp_error("%s - %s\n" % (str(e), fullname)) if f is not None: data = f.read() pe = pefile.PE(data=data) if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"): for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: if exp.name is not None: syms[exp.name] = exp.address else: syms["unnamed_funcion_%d" % unnamed_function_counter] = exp.address unnamed_function_counter += 1 # If we managed to parse the export table, update the symbols # except if it is empty if fullname not in symbols.keys(): symbols[fullname] = syms # Even if it is empty, the module symbols are set # to an empty list, and thus are 'resolved'. # Anyway, in future updates, they could be resolved, # as we allow this in the first condition. mod.set_symbols(symbols[fullname]) symbol_cache_must_be_saved = True else: symbols[fullname] = {} mod.set_symbols(symbols[fullname]) #Module load/del notification if base in modules[(p_pid, p_pgd)]: if modules[(p_pid, p_pgd)][base].get_size() != size or \ modules[(p_pid, p_pgd)][base].get_checksum() != checksum or \ modules[(p_pid, p_pgd)][base].get_name() != basename or \ modules[(p_pid, p_pgd)][base].get_fullname() != fullname: # Notify of module deletion and module load dispatch_module_remove_callback( p_pid, p_pgd, base, modules[(p_pid, p_pgd)][base].get_size(), modules[(p_pid, p_pgd)][base].get_name(), modules[(p_pid, p_pgd)][base].get_fullname()) del modules[(p_pid, p_pgd)][base] modules[(p_pid, p_pgd)][base] = mod dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname) # If we updated the symbols and have a bigger list now, dont substitute the module # but update its symbols instead elif len(mod.get_symbols()) > len( modules[(p_pid, p_pgd)][base].get_symbols()): modules[(p_pid, p_pgd)][base].set_symbols(mod.get_symbols()) else: # Just notify of module load modules[(p_pid, p_pgd)][base] = mod dispatch_module_load_callback(p_pid, p_pgd, base, size, basename, fullname) # Mark the module as present modules[(p_pid, p_pgd)][base].set_present()