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
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))