def testLegacyDataMigration(self): res = rdf_memory.YaraProcessDumpResponse(dumped_processes=[ rdf_memory.YaraProcessDumpInformation(dump_files=[ rdf_paths.PathSpec(path="C:\\Foo\\Bar\\%s_%d_%x_%x.tmp" % ("my_proc", 123, 111, 222), pathtype="TMPFILE"), rdf_paths.PathSpec(path="/foo/bar/%s_%d_%x_%x.tmp" % ("my_proc", 123, 456, 789), pathtype="TMPFILE") ]) ]) memory._MigrateLegacyDumpFilesToMemoryAreas(res) self.assertEqual( res, rdf_memory.YaraProcessDumpResponse(dumped_processes=[ rdf_memory.YaraProcessDumpInformation(memory_regions=[ rdf_memory.YaraProcessMemoryRegion( start=111, size=111, file=rdf_paths.PathSpec( path="/C:/Foo/Bar/%s_%d_%x_%x.tmp" % ("my_proc", 123, 111, 222), pathtype="TMPFILE")), rdf_memory.YaraProcessMemoryRegion( start=456, size=333, file=rdf_paths.PathSpec( path="/foo/bar/%s_%d_%x_%x.tmp" % ("my_proc", 123, 456, 789), pathtype="TMPFILE")) ]) ]))
def Regions(self, skip_special_regions=False, skip_executable_regions=False): """Returns an iterator over the readable regions for this process.""" offset = self.min_addr while True: if offset >= self.max_addr: break mbi = self.VirtualQueryEx(offset) offset = mbi.BaseAddress chunk = mbi.RegionSize protect = mbi.Protect state = mbi.State region = rdf_memory.YaraProcessMemoryRegion( start=offset, size=mbi.RegionSize, is_executable=bool(protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))) is_special = ( protect & PAGE_NOCACHE or protect & PAGE_WRITECOMBINE or protect & PAGE_GUARD) offset += chunk if (state & MEM_FREE or state & MEM_RESERVE or (skip_special_regions and is_special) or (skip_executable_regions and region.is_executable)): continue yield region
def Regions(self, skip_mapped_files=False, skip_shared_regions=False, skip_executable_regions=False, skip_readonly_regions=False): del skip_mapped_files del skip_shared_regions del skip_executable_regions del skip_readonly_regions for region in self.regions: yield rdf_memory.YaraProcessMemoryRegion( start=region.start, size=region.size, is_executable=region.is_executable)
def _MigrateLegacyDumpFilesToMemoryAreas(response): """Migrates a YPDR from dump_files to memory_regions inplace.""" for info in response.dumped_processes: for dump_file in info.dump_files: # filename = "%s_%d_%x_%x.tmp" % (process.name, pid, start, end) # process.name can contain underscores. Split exactly 3 _ from the right. path_without_ext, _ = dump_file.Basename().rsplit(".", 1) _, _, start, end = path_without_ext.rsplit("_", 3) start = int(start, 16) end = int(end, 16) info.memory_regions.Append( rdf_memory.YaraProcessMemoryRegion( file=_CanonicalizeLegacyWindowsPathSpec(dump_file), start=start, size=end - start, )) # Remove dump_files, since new clients do not set it anymore. info.dump_files = None
def Regions(self, skip_mapped_files=False, skip_shared_regions=False, skip_executable_regions=False, skip_readonly_regions=False): """Returns an iterator over the readable regions for this process.""" try: maps_file = open("/proc/" + str(self.pid) + "/maps", "r") except OSError as e: raise process_error.ProcessError(e) with maps_file: for line in maps_file: m = self.maps_re.match(line) if not m: continue start = int(m.group(1), 16) end = int(m.group(2), 16) region_protec = m.group(3) inode = int(m.group(6)) is_executable = "x" in region_protec if "r" in region_protec: if skip_mapped_files and inode != 0: continue if skip_shared_regions and "s" in region_protec: continue if skip_executable_regions and is_executable: continue if skip_readonly_regions and "w" not in region_protec: continue yield rdf_memory.YaraProcessMemoryRegion( start=start, size=end - start, is_executable=is_executable)
def Regions(self, skip_executable_regions=False, skip_shared_regions=False, skip_readonly_regions=False): """Iterates over the readable regions for this process. We use mach_vm_region_recurse here to get a fine grained view of the process' memory space. The algorithm is that for some regions, the function returns is_submap=True which means that there are actually subregions that we need to examine by increasing the depth and calling the function again. For example, there are two regions, addresses 1000-2000 and 2000-3000 where 1000-2000 has two subregions, 1100-1200 and 1300-1400. In that case we would call: mvrr(address=0, depth=0) -> (1000-2000, is_submap=True) mvrr(address=0, depth=1) -> (1100-1200, is_submap=False) mvrr(address=1200, depth=1) -> (1300-1400, is_submap=False) mvrr(address=1400, depth=1) -> (2000-3000, is_submap=False) At this point, we know we went out of the original submap which ends at 2000. We need to recheck the region at 2000, it could be submap = True at depth 0 so we call mvrr(address=1400, depth=0) -> (2000-3000, is_submap=False) Args: skip_executable_regions: Skips executable sections. skip_shared_regions: Skips shared sections. Includes mapped files. skip_readonly_regions: Skips readonly sections. Yields: Pairs (address, length) for each identified region. """ address = ctypes.c_ulong(0) mapsize = ctypes.c_ulong(0) count = ctypes.c_uint32(submap_info_size) sub_info = vm_region_submap_short_info_data_64() depth = 0 depth_end_addresses = {} while True: c_depth = ctypes.c_uint32(depth) r = libc.mach_vm_region_recurse(self.task, ctypes.pointer(address), ctypes.pointer(mapsize), ctypes.pointer(c_depth), ctypes.pointer(sub_info), ctypes.pointer(count)) # If we get told "invalid address", we have crossed into kernel land... if r == 1: break if r != 0: raise process_error.ProcessError( "Error in mach_vm_region, ret=%s" % r) if depth > 0 and address.value >= depth_end_addresses[depth]: del depth_end_addresses[depth] depth -= 1 continue p = sub_info.protection is_executable = p & VM_PROT_EXECUTE if skip_executable_regions and is_executable: address.value += mapsize.value continue if skip_shared_regions and sub_info.share_mode in [ SM_COW, SM_SHARED, SM_TRUESHARED ]: address.value += mapsize.value continue if not p & VM_PROT_READ: address.value += mapsize.value continue writable = p & VM_PROT_WRITE if skip_readonly_regions and not writable: address.value += mapsize.value continue if sub_info.is_submap: depth += 1 depth_end_addresses[depth] = address.value + mapsize.value else: yield rdf_memory.YaraProcessMemoryRegion( start=address.value, size=mapsize.value, is_executable=is_executable) address.value += mapsize.value