Add verbatim mode to searches (default true)

This commit is contained in:
Jan Petykiewicz 2019-03-24 20:39:58 -07:00
parent 3b766be616
commit 522999cd61

View File

@ -9,7 +9,8 @@ import copy
import ctypes import ctypes
import logging import logging
from .utils import ctypes_buffer_t, search_buffer, ctypes_equal from . import utils
from .utils import ctypes_buffer_t
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
@ -240,7 +241,7 @@ class Process(metaclass=ABCMeta):
values = [self.read_memory(base + offset, buffer) for offset, buffer in targets] values = [self.read_memory(base + offset, buffer) for offset, buffer in targets]
return values return values
def search_addresses(self, addresses: List[int], needle_buffer: ctypes_buffer_t) -> List[int]: def search_addresses(self, addresses: List[int], needle_buffer: ctypes_buffer_t, verbatim: bool=True) -> List[int]:
""" """
Search for the provided value at each of the provided addresses, and return the addresses Search for the provided value at each of the provided addresses, and return the addresses
where it is found. where it is found.
@ -249,18 +250,26 @@ class Process(metaclass=ABCMeta):
:param needle_buffer: The value to search for. This should be a ctypes object of the same :param needle_buffer: The value to search for. This should be a ctypes object of the same
sorts as used by .read_memory(...), which will be compared to the contents of sorts as used by .read_memory(...), which will be compared to the contents of
memory at each of the given addresses. memory at each of the given addresses.
:param verbatim: If True, perform bitwise comparison when searching for needle_buffer.
If False, perform utils.ctypes_equal-based comparison. Default True.
:return: List of addresses where the needle_buffer was found. :return: List of addresses where the needle_buffer was found.
""" """
found = [] found = []
read_buffer = copy.copy(needle_buffer) read_buffer = copy.copy(needle_buffer)
if verbatim:
def compare(a, b):
return bytes(read_buffer) == bytes(needle_buffer)
else:
compare = utils.ctypes_equal
for address in addresses: for address in addresses:
read = self.read_memory(address, read_buffer) self.read_memory(address, read_buffer)
if ctypes_equal(needle_buffer, read): if compare(needle_buffer, read_buffer):
found.append(address) found.append(address)
return found return found
def search_all_memory(self, needle_buffer, writeable_only=True) -> List[int]: def search_all_memory(self, needle_buffer: ctypes_buffer_t, writeable_only: bool=True, verbatim: bool=True) -> List[int]:
""" """
Search the entire memory space accessible to the process for the provided value. Search the entire memory space accessible to the process for the provided value.
@ -268,14 +277,22 @@ class Process(metaclass=ABCMeta):
sorts as used by .read_memory(...), which will be compared to the contents of sorts as used by .read_memory(...), which will be compared to the contents of
memory at each accessible address. memory at each accessible address.
:param writeable_only: If True, only search regions where the process has write access. :param writeable_only: If True, only search regions where the process has write access.
Default True.
:param verbatim: If True, perform bitwise comparison when searching for needle_buffer.
If False, perform utils.ctypes_equal-based comparison. Default True.
:return: List of addresses where the needle_buffer was found. :return: List of addresses where the needle_buffer was found.
""" """
found = [] found = []
if verbatim:
search = utils.search_buffer_verbatim
else:
search = utils.search_buffer
for start, stop in self.list_mapped_regions(writeable_only): for start, stop in self.list_mapped_regions(writeable_only):
try: try:
region_buffer = (ctypes.c_byte * (stop - start))() region_buffer = (ctypes.c_byte * (stop - start))()
self.read_memory(start, region_buffer) self.read_memory(start, region_buffer)
found += [offset + start for offset in search_buffer(needle_buffer, region_buffer)] found += [offset + start for offset in search(needle_buffer, region_buffer)]
except OSError: except OSError:
logger.error('Failed to read in range 0x{} - 0x{}'.format(start, stop)) logger.error('Failed to read in range 0x{} - 0x{}'.format(start, stop))
return found return found