def buffer(sendprintf: Callable[[bytes],bytes], maxlen=20) -> int: '''Bruteforcer to locate the offset of the input string itself. i.e. if buffer() returns 6, printf("%6$d") gives the value of p32("%6$p") Arguments: `sendprintf`: a function that simulates a single printf() call. This is much like the function passable to pwntools' FmtStr(). e.g. def printf(l: bytes): r = process('./mybinary') r.send(l) return r.recvline() buffer = fsb.find_offset.buffer(printf) `maxlen`: the maximum length of the input. If no value is given, the program assumes maxlen=20. Larger values of `maxlen` will allow for faster offset guessing. ''' # Note: if config.PRINTF_MAX becomes really large, this might break guess_n = (maxlen-len("0x%10$x\n")) // context.bytes # So long as more than 1 guess can be done at a time: if guess_n > 1: '''Let's say guess_n=3 words worth of cyclic() can be inputted. If config.PRINTF_MIN=5, then the first payload ought to be cyclic(3*context.bytes) + "0x%{}$x\n".format(5+(3-1)) because the first guess should be able to catch any offset in the range range(config.PRINTF_MIN, config.PRINTF_MIN+guess_n) ''' for offset in range(config.PRINTF_MIN+guess_n-1, config.PRINTF_MAX+guess_n-1, guess_n): payload = cyclic(guess_n*context.bytes) + "0x%{}$x\n".format(offset).encode() extract = sendprintf(payload) if b"(nil)" in extract: extract = 0 else: extract = unpack_hex(extract) # Error will be -1 if extract != -1 and 0 <= (found := cyclic_find(p32(extract))) < len(payload): assert found%context.bytes == 0 # if not, the offset is non-aligned log.info('%s for buffer: %d' % (__name__, offset-found//context.bytes)) return offset-found//context.bytes raise RuntimeError # Give up
def offset(self, **kwargs): try: length_ = kwargs['length'] self.__offset = bytes(length_ * 'x', self.__encoding) except KeyError: try: target_ = kwargs['match'] if type(target_) == 'int': target_ = pack(target_) elif type(target_) == 'str': target_ = bytes(target_, self.__encoding) length_ = cyclic_find(target_, n=len(target_)) - len( self.__padding) - len(self.__eip) self.__offset = bytes(length_ * 'x', self.__encoding) print(f"[+] Offset => {self.__offset}\n") except KeyError: raise ValueError( "[-] Only 'length' and 'match' are valid arguments\n")
def main(): args = parser.parse_args() alphabet = args.alphabet subsize = args.length if args.lookup: pat = args.lookup if pat.startswith('0x'): pat = packing.pack(int(pat[2:], 16), subsize * 8, 'little', 'unsigned') elif pat.isdigit(): pat = packing.pack(int(pat, 10), subsize * 8, 'little', 'unsigned') if len(pat) != 4: log.critical('Subpattern must be 4 bytes') sys.exit(1) if not all(c in alphabet for c in pat): log.critical( 'Pattern contains characters not present in the alphabet') sys.exit(1) offset = cyclic.cyclic_find(pat, alphabet, subsize) if offset == -1: log.critical('Given pattern does not exist in cyclic pattern') sys.exit(1) else: print offset else: want = args.count result = cyclic.cyclic(want, alphabet, subsize) got = len(result) if got < want: log.failure("Alphabet too small (max length = %i)" % got) sys.stdout.write(result) if sys.stdout.isatty(): sys.stdout.write('\n')
def main(): args = parser.parse_args() alphabet = args.alphabet subsize = args.length if args.lookup: pat = args.lookup if pat.startswith('0x'): pat = packing.pack(int(pat[2:], 16), subsize*8, 'little', False) elif pat.isdigit(): pat = packing.pack(int(pat, 10), subsize*8, 'little', False) if len(pat) != subsize: log.critical('Subpattern must be %d bytes' % subsize) sys.exit(1) if not all(c in alphabet for c in pat): log.critical('Pattern contains characters not present in the alphabet') sys.exit(1) offset = cyclic.cyclic_find(pat, alphabet, subsize) if offset == -1: log.critical('Given pattern does not exist in cyclic pattern') sys.exit(1) else: print offset else: want = args.count result = cyclic.cyclic(want, alphabet, subsize) got = len(result) if got < want: log.failure("Alphabet too small (max length = %i)" % got) sys.stdout.write(result) if sys.stdout.isatty(): sys.stdout.write('\n')
def check_pattern(s): print("[+] Checking pattern") index = pattern.cyclic_find(s, alphabet=string.ascii_letters) print("[+] Pattern at {}".format(index)) exit(0)