def unbits(s, endian='big'): """unbits(s, endian = 'big') -> str Converts an iterable of bits into a string. Arguments: s: Iterable of bits endian (str): The string "little" or "big", which specifies the bits endianness. Returns: A string of the decoded bits. Example: >>> unbits([1]) b'\\x80' >>> unbits([1], endian = 'little') b'\\x01' >>> unbits(bits(b'hello'), endian = 'little') b'\\x16\\xa666\\xf6' """ if endian == 'little': u = lambda s: packing._p8lu(int(s[::-1], 2)) elif endian == 'big': u = lambda s: packing._p8lu(int(s, 2)) else: raise ValueError("unbits(): 'endian' must be either 'little' or 'big'") out = b'' cur = b'' for c in s: if c in ['1', 1, True]: cur += b'1' elif c in ['0', 0, False]: cur += b'0' else: raise ValueError( "unbits(): cannot decode the value %r into a bit" % c) if len(cur) == 8: out += u(cur) cur = b'' if cur: out += u(cur.ljust(8, b'0')) return out
def xor_pair(data, avoid=b'\x00\n'): """xor_pair(data, avoid = '\\x00\\n') -> None or (str, str) Finds two strings that will xor into a given string, while only using a given alphabet. Arguments: data (str): The desired string. avoid: The list of disallowed characters. Defaults to nulls and newlines. Returns: Two strings which will xor to the given string. If no such two strings exist, then None is returned. Example: >>> xor_pair(b"test") (b'\\x01\\x01\\x01\\x01', b'udru') """ if isinstance(data, six.integer_types): data = packing.pack(data) if not isinstance(avoid, (bytes, bytearray)): avoid = avoid.encode('utf-8') avoid = bytearray(avoid) alphabet = list(packing._p8lu(n) for n in range(256) if n not in avoid) res1 = b'' res2 = b'' for c1 in bytearray(data): if context.randomize: random.shuffle(alphabet) for c2 in alphabet: c3 = packing._p8lu(c1 ^ packing.u8(c2)) if c3 in alphabet: res1 += c2 res2 += c3 break else: return None return res1, res2
def style_byte(by): hbyte = '%02x' % by b = packing._p8lu(by) abyte = chr(by) if isprint(b) else '·' if hbyte in style: st = style[hbyte] elif isprint(b): st = style.get('printable') else: st = style.get('nonprintable') if st: hbyte = st(hbyte) abyte = st(abyte) return hbyte, abyte
def xor_key(data, avoid=b'\x00\n', size=None): r"""xor_key(data, size=None, avoid='\x00\n') -> None or (int, str) Finds a ``size``-width value that can be XORed with a string to produce ``data``, while neither the XOR value or XOR string contain any bytes in ``avoid``. Arguments: data (str): The desired string. avoid: The list of disallowed characters. Defaults to nulls and newlines. size (int): Size of the desired output value, default is word size. Returns: A tuple containing two strings; the XOR key and the XOR string. If no such pair exists, None is returned. Example: >>> xor_key(b"Hello, world") (b'\x01\x01\x01\x01', b'Idmmn-!vnsme') """ size = size or context.bytes if len(data) % size: log.error("Data must be padded to size for xor_key") words = lists.group(size, data) columns = [b''] * size for word in words: for i, byte in enumerate(bytearray(word)): columns[i] += bytearray((byte, )) avoid = bytearray(avoid) alphabet = bytearray(n for n in range(256) if n not in avoid) result = b'' for column in columns: if context.randomize: random.shuffle(alphabet) for c2 in alphabet: if all(c ^ c2 in alphabet for c in column): result += packing._p8lu(c2) break else: return None return result, xor(data, result)
def _leak(self, addr, n, recurse=True): """_leak(addr, n) => str Leak ``n`` consecutive bytes starting at ``addr``. Returns: A string of length ``n``, or :const:`None`. """ if not self.relative and addr < 0: return None addresses = [addr+i for i in range(n)] for address in addresses: # Cache hit if address in self.cache: continue # Cache miss, get the data from the leaker data = None try: data = self.leak(address) except Exception as e: if self.reraise: raise if data: for i,byte in enumerate(bytearray(data)): self.cache[address+i] = _p8lu(byte) # We could not leak this particular byte, search backwards # to see if another request will satisfy it elif recurse: for i in range(1, self.search_range): data = self._leak(address-i, i+1, False) if address in self.cache: break else: return None # Ensure everything is in the cache if not all(a in self.cache for a in addresses): return None # Cache is filled, satisfy the request return b''.join(self.cache[addr+i] for i in range(n))
def sets(self, addr, val, null_terminate = True): r"""Set known string at `addr`, which will be optionally be null-terminated Note that this method is a bit dumb about how it handles the data. It will null-terminate the data, but it will not stop at the first null. Examples: >>> l = MemLeak(lambda x: b'') >>> l.cache == {} True >>> l.sets(0, b'H\x00ello') >>> l.cache == {0: b'H', 1: b'\x00', 2: b'e', 3: b'l', 4: b'l', 5: b'o', 6: b'\x00'} True """ if null_terminate: val += b'\x00' for i,b in enumerate(bytearray(val)): self.cache[addr+i] = _p8lu(b)
def update_cyclic_pregenerated(size): global cyclic_pregen while size > len(cyclic_pregen): cyclic_pregen += packing._p8lu(next(de_bruijn_gen))
def get(n): rv = 0 for s in strs: rv ^= s[n % len(s)] return packing._p8lu(rv)
def compare(self, address, bts): for i, byte in enumerate(bytearray(bts)): if self.n(address + i, 1) != _p8lu(byte): return False return True
def _set(self, addr, val, ndx, size): addr += ndx * size for i,b in enumerate(bytearray(pack(val, size*8))): self.cache[addr+i] = _p8lu(b)