Beispiel #1
0
def register_sizes(regs, in_sizes):
    """Create dictionaries over register sizes and relations

    Given a list of lists of overlapping register names (e.g. ['eax','ax','al','ah']) and a list of input sizes,
    it returns the following:

    * all_regs    : list of all valid registers
    * sizes[reg]  : the size of reg in bits
    * bigger[reg] : list of overlapping registers bigger than reg
    * smaller[reg]: list of overlapping registers smaller than reg

    Used in i386/AMD64 shellcode, e.g. the mov-shellcode.

    Example:
        >>> regs = [['eax', 'ax', 'al', 'ah'],['ebx', 'bx', 'bl', 'bh'],
        ... ['ecx', 'cx', 'cl', 'ch'],
        ... ['edx', 'dx', 'dl', 'dh'],
        ... ['edi', 'di'],
        ... ['esi', 'si'],
        ... ['ebp', 'bp'],
        ... ['esp', 'sp'],
        ... ]
        >>> all_regs, sizes, bigger, smaller = register_sizes(regs, [32, 16, 8, 8])
        >>> all_regs
        ['eax', 'ax', 'al', 'ah', 'ebx', 'bx', 'bl', 'bh', 'ecx', 'cx', 'cl', 'ch', 'edx', 'dx', 'dl', 'dh', 'edi', 'di', 'esi', 'si', 'ebp', 'bp', 'esp', 'sp']
        >>> sizes
        {'ch': 8, 'cl': 8, 'ah': 8, 'edi': 32, 'al': 8, 'cx': 16, 'ebp': 32, 'ax': 16, 'edx': 32, 'ebx': 32, 'esp': 32, 'esi': 32, 'dl': 8, 'dh': 8, 'di': 16, 'bl': 8, 'bh': 8, 'eax': 32, 'bp': 16, 'dx': 16, 'bx': 16, 'ecx': 32, 'sp': 16, 'si': 16}
        >>> bigger
        {'ch': ['ecx', 'cx', 'ch'], 'cl': ['ecx', 'cx', 'cl'], 'ah': ['eax', 'ax', 'ah'], 'edi': ['edi'], 'al': ['eax', 'ax', 'al'], 'cx': ['ecx', 'cx'], 'ebp': ['ebp'], 'ax': ['eax', 'ax'], 'edx': ['edx'], 'ebx': ['ebx'], 'esp': ['esp'], 'esi': ['esi'], 'dl': ['edx', 'dx', 'dl'], 'dh': ['edx', 'dx', 'dh'], 'di': ['edi', 'di'], 'bl': ['ebx', 'bx', 'bl'], 'bh': ['ebx', 'bx', 'bh'], 'eax': ['eax'], 'bp': ['ebp', 'bp'], 'dx': ['edx', 'dx'], 'bx': ['ebx', 'bx'], 'ecx': ['ecx'], 'sp': ['esp', 'sp'], 'si': ['esi', 'si']}
        >>> smaller
        {'ch': [], 'cl': [], 'ah': [], 'edi': ['di'], 'al': [], 'cx': ['cl', 'ch'], 'ebp': ['bp'], 'ax': ['al', 'ah'], 'edx': ['dx', 'dl', 'dh'], 'ebx': ['bx', 'bl', 'bh'], 'esp': ['sp'], 'esi': ['si'], 'dl': [], 'dh': [], 'di': [], 'bl': [], 'bh': [], 'eax': ['ax', 'al', 'ah'], 'bp': [], 'dx': ['dl', 'dh'], 'bx': ['bl', 'bh'], 'ecx': ['cx', 'cl', 'ch'], 'sp': [], 'si': []}
    """
    sizes = {}
    bigger = {}
    smaller = {}

    for l in regs:
        for r, s in zip(l, in_sizes):
            sizes[r] = s

        for r in l:
            bigger[r] = [r_ for r_ in l if sizes[r_] > sizes[r] or r == r_]
            smaller[r] = [r_ for r_ in l if sizes[r_] < sizes[r]]

    return lists.concat(regs), sizes, bigger, smaller
Beispiel #2
0
    def libc_find(self, leaks: Dict[str, int]):
        '''identify a libc id from a `dict` of leaked addresses,
        returning its libc() representation on success.
        Raises IndexError if a single libc id is not isolated.

        Arguments:
            `leaks`: dict with key-pairs of symbol_name:addr
        
        Returns:
            a `libc()` object with `address` set in accordance with the
            leaked addresses provided in `leaks`.
        >>> db = context.libc_database = '/path/to/libc-database'
        >>> context.libc = db.libc_find({'printf': 0x7fff00064e80})
        Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/path/to/pwnscripts/pwnscripts/libcdb_query.py", line 234, in libc_find
            raise IndexError("incorrect number of libcs identified: %d" % len(found))
        IndexError: incorrect number of libcs identified: 4
        >>> context.libc = db.libc_find({'printf': 0x7fff00064e80, 'strstr': 0x7fff0009eb20})
        [*] b'found libc! id: libc6_2.27-3ubuntu1_amd64'
        [*] '/path/to/pwnscripts/libc-database/db/libc6_2.27-3ubuntu1_amd64.so'
            Arch:     amd64-64-little
            RELRO:    Partial RELRO
            Stack:    Canary found
            NX:       NX enabled
            PIE:      PIE enabled
        >>> hex(context.libc.address)
        0x7fff00000000
        '''
        args = concat([(k, hex(v)) for k, v in leaks.items()])
        found = self.find(*args).strip().split(b'\n')

        if len(found) == 1:  # if a single libc was isolated
            # NOTE: assuming ./find output format is "<url> (<id>)".
            # NOTE (continued): this behaviour has changed in the past!
            libcid = found[0].split(b'(')[-1][:-1]
            log.info(b'found libc! id: ' + libcid)
            lib = libc(db=self, id=libcid.decode('utf-8'))
            # Also help to calculate self.base
            a_func, an_addr = list(leaks.items())[0]
            lib.calc_base(a_func, an_addr)
            return lib
        raise IndexError("incorrect number of libcs identified: %d" %
                         len(found))