def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype="physical") ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanDriver().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the _DRIVER_OBJECT from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() extension_obj = obj.Object( "_DRIVER_EXTENSION", vm=address_space, offset=( offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_DRIVER_EXTENSION", pool_alignment) ), native_vm=kernel_as, ) ## The _DRIVER_OBJECT is immediately below the _DRIVER_EXTENSION driver_obj = obj.Object( "_DRIVER_OBJECT", vm=address_space, offset=extension_obj.obj_offset - common.pool_align(kernel_as, "_DRIVER_OBJECT", pool_alignment), native_vm=kernel_as, ) ## The _OBJECT_HEADER is immediately below the _DRIVER_OBJECT object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=driver_obj.obj_offset - address_space.profile.get_obj_offset("_OBJECT_HEADER", "Body"), native_vm=kernel_as, ) ## Skip unallocated objects # if object_obj.Type == 0xbad0b0b0: # continue if object_obj.get_object_type() != "Driver": continue yield (object_obj, driver_obj, extension_obj)
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype='physical') ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanDriver().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the _DRIVER_OBJECT from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() extension_obj = obj.Object( "_DRIVER_EXTENSION", vm=address_space, offset=(offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_DRIVER_EXTENSION", pool_alignment)), native_vm=kernel_as) ## The _DRIVER_OBJECT is immediately below the _DRIVER_EXTENSION driver_obj = obj.Object( "_DRIVER_OBJECT", vm=address_space, offset=extension_obj.obj_offset - common.pool_align(kernel_as, "_DRIVER_OBJECT", pool_alignment), native_vm=kernel_as) ## The _OBJECT_HEADER is immediately below the _DRIVER_OBJECT object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=driver_obj.obj_offset - address_space.profile.get_obj_offset('_OBJECT_HEADER', 'Body'), native_vm=kernel_as) ## Skip unallocated objects #if object_obj.Type == 0xbad0b0b0: # continue if object_obj.get_object_type() != "Driver": continue yield (object_obj, driver_obj, extension_obj)
def check(self, found): ## The offset of the object is determined by subtracting the offset ## of the PoolTag member to get the start of Pool Object. This done ## because PoolScanners search for the PoolTag. pool_base = found - self.address_space.profile.get_obj_offset( '_POOL_HEADER', 'PoolTag') pool_obj = obj.Object("_POOL_HEADER", vm=self.address_space, offset=pool_base) ## We work out the _EPROCESS from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(self.address_space).PoolAlignment.v() eprocess = obj.Object( "_EPROCESS", vm=self.address_space, offset=pool_base + pool_obj.BlockSize * pool_alignment - common.pool_align(self.address_space, '_EPROCESS', pool_alignment)) if (eprocess.Pcb.DirectoryTableBase == 0): return False if (eprocess.Pcb.DirectoryTableBase % 0x20 != 0): return False list_head = eprocess.ThreadListHead if (list_head.Flink < self.kernel) or (list_head.Blink < self.kernel): return False return True
def get_object_bottom_up(self, struct_name, object_type, skip_type_check): """Get the windows object contained within this pool by using the bottom-up approach to finding the object """ if not object_type: return obj.Object( struct_name, vm=self.obj_vm, offset=self.obj_offset + self.obj_vm.profile.get_obj_size("_POOL_HEADER"), native_vm=self.obj_native_vm, ) pool_alignment = obj.VolMagic(self.obj_vm).PoolAlignment.v() the_object = obj.Object( struct_name, vm=self.obj_vm, offset=( self.obj_offset + self.BlockSize * pool_alignment - common.pool_align(self.obj_vm, struct_name, pool_alignment) ), native_vm=self.obj_native_vm, ) header = the_object.get_object_header() if skip_type_check or header.get_object_type() == object_type: return the_object else: return obj.NoneObject("Cannot find the object")
def check(self, found): ## The offset of the object is determined by subtracting the offset ## of the PoolTag member to get the start of Pool Object. This done ## because PoolScanners search for the PoolTag. pool_base = found - self.address_space.profile.get_obj_offset("_POOL_HEADER", "PoolTag") pool_obj = obj.Object("_POOL_HEADER", vm=self.address_space, offset=pool_base) ## We work out the _EPROCESS from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(self.address_space).PoolAlignment.v() eprocess = obj.Object( "_EPROCESS", vm=self.address_space, offset=pool_base + pool_obj.BlockSize * pool_alignment - common.pool_align(self.address_space, "_EPROCESS", pool_alignment), ) if eprocess.Pcb.DirectoryTableBase == 0: return False if eprocess.Pcb.DirectoryTableBase % 0x20 != 0: return False list_head = eprocess.ThreadListHead if (list_head.Flink < self.kernel) or (list_head.Blink < self.kernel): return False return True
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype = 'physical') ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanSymlink().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm = address_space, offset = offset) ## We work out the object from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() link_obj = obj.Object("_OBJECT_SYMBOLIC_LINK", vm = address_space, offset = (offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_OBJECT_SYMBOLIC_LINK", pool_alignment)), native_vm = kernel_as) ## The _OBJECT_HEADER is immediately below the _OBJECT_SYMBOLIC_LINK object_obj = obj.Object( "_OBJECT_HEADER", vm = address_space, offset = link_obj.obj_offset - address_space.profile.get_obj_offset('_OBJECT_HEADER', 'Body'), native_vm = kernel_as ) if object_obj.get_object_type() != "SymbolicLink": continue yield object_obj, link_obj
def get_object_bottom_up(self, struct_name, object_type, skip_type_check): """Get the windows object contained within this pool by using the bottom-up approach to finding the object """ if not object_type: return obj.Object(struct_name, vm = self.obj_vm, offset = self.obj_offset + self.obj_vm.profile.get_obj_size("_POOL_HEADER"), native_vm = self.obj_native_vm) pool_alignment = obj.VolMagic(self.obj_vm).PoolAlignment.v() the_object = obj.Object(struct_name, vm = self.obj_vm, offset = (self.obj_offset + self.BlockSize * pool_alignment - common.pool_align(self.obj_vm, struct_name, pool_alignment)), native_vm = self.obj_native_vm) header = the_object.get_object_header() if (skip_type_check or header.get_object_type() == object_type): return the_object else: return obj.NoneObject("Cannot find the object")
def object_offset(self, found, address_space): """ This returns the offset of the object contained within this pool allocation. """ pool_base = found - \ self.buffer.profile.get_obj_offset('_POOL_HEADER', 'PoolTag') pool_obj = obj.Object("_POOL_HEADER", vm = address_space, offset = pool_base) pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() object_base = (pool_base + pool_obj.BlockSize * pool_alignment - common.pool_align(address_space, 'tagWINDOWSTATION', pool_alignment)) return object_base
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype="physical") ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanMutant().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the _DRIVER_OBJECT from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() mutant = obj.Object( "_KMUTANT", vm=address_space, offset=( offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_KMUTANT", pool_alignment) ), native_vm=kernel_as, ) ## The _OBJECT_HEADER is immediately below the _KMUTANT object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=mutant.obj_offset - address_space.profile.get_obj_offset("_OBJECT_HEADER", "Body"), native_vm=kernel_as, ) if object_obj.get_object_type() != "Mutant": continue ## Skip unallocated objects ##if object_obj.Type == 0xbad0b0b0: ## continue if self._config.SILENT: if len(object_obj.NameInfo.Name) == 0: continue yield (object_obj, mutant)
def object_offset(self, found, address_space): """ This returns the offset of the object contained within this pool allocation. """ pool_base = found - \ self.buffer.profile.get_obj_offset('_POOL_HEADER', 'PoolTag') pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=pool_base) pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() object_base = (pool_base + pool_obj.BlockSize * pool_alignment - common.pool_align( address_space, 'tagWINDOWSTATION', pool_alignment)) return object_base
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype='physical') ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanMutant().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the _DRIVER_OBJECT from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() mutant = obj.Object( "_KMUTANT", vm=address_space, offset=( offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_KMUTANT", pool_alignment)), native_vm=kernel_as) ## The _OBJECT_HEADER is immediately below the _KMUTANT object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=mutant.obj_offset - address_space.profile.get_obj_offset('_OBJECT_HEADER', 'Body'), native_vm=kernel_as) if object_obj.get_object_type() != "Mutant": continue ## Skip unallocated objects ##if object_obj.Type == 0xbad0b0b0: ## continue if self._config.SILENT: if len(object_obj.NameInfo.Name) == 0: continue yield (object_obj, mutant)
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype="physical") ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanFile().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the _FILE_OBJECT from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() file_obj = obj.Object( "_FILE_OBJECT", vm=address_space, offset=( offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_FILE_OBJECT", pool_alignment) ), native_vm=kernel_as, ) ## The _OBJECT_HEADER is immediately below the _FILE_OBJECT object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=file_obj.obj_offset - address_space.profile.get_obj_offset("_OBJECT_HEADER", "Body"), native_vm=kernel_as, ) if object_obj.get_object_type() != "File": continue ## If the string is not reachable we skip it if not file_obj.FileName.v(): continue yield (object_obj, file_obj)
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype='physical') ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanFile().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the _FILE_OBJECT from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() file_obj = obj.Object( "_FILE_OBJECT", vm=address_space, offset=(offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_FILE_OBJECT", pool_alignment)), native_vm=kernel_as) ## The _OBJECT_HEADER is immediately below the _FILE_OBJECT object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=file_obj.obj_offset - address_space.profile.get_obj_offset('_OBJECT_HEADER', 'Body'), native_vm=kernel_as) if object_obj.get_object_type() != "File": continue ## If the string is not reachable we skip it if not file_obj.FileName.v(): continue yield (object_obj, file_obj)
def object_offset(self, found, address_space): """ This returns the offset of the object contained within this pool allocation. """ ## The offset of the object is determined by subtracting the offset ## of the PoolTag member to get the start of Pool Object and then ## walking backwards based on pool alignment and pool size. pool_base = found - self.buffer.profile.get_obj_offset( '_POOL_HEADER', 'PoolTag') pool_obj = obj.Object("_POOL_HEADER", vm = address_space, offset = pool_base) ## We work out the _EPROCESS from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() object_base = (pool_base + pool_obj.BlockSize * pool_alignment - common.pool_align(address_space, '_EPROCESS', pool_alignment)) return object_base
def object_offset(self, found, address_space): """ This returns the offset of the object contained within this pool allocation. """ ## The offset of the object is determined by subtracting the offset ## of the PoolTag member to get the start of Pool Object and then ## walking backwards based on pool alignment and pool size. pool_base = found - self.buffer.profile.get_obj_offset( '_POOL_HEADER', 'PoolTag') pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=pool_base) ## We work out the _EPROCESS from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() object_base = ( pool_base + pool_obj.BlockSize * pool_alignment - common.pool_align(address_space, '_EPROCESS', pool_alignment)) return object_base
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype='physical') ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanSymlink().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the object from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() link_obj = obj.Object( "_OBJECT_SYMBOLIC_LINK", vm=address_space, offset=(offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_OBJECT_SYMBOLIC_LINK", pool_alignment)), native_vm=kernel_as) ## The _OBJECT_HEADER is immediately below the _OBJECT_SYMBOLIC_LINK object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=link_obj.obj_offset - address_space.profile.get_obj_offset('_OBJECT_HEADER', 'Body'), native_vm=kernel_as) if object_obj.get_object_type() != "SymbolicLink": continue yield object_obj, link_obj