Esempio n. 1
0
    def __fetchList(self, rpctransport):
        # UDP only works over DCE/RPC version 4.
        if isinstance(rpctransport, transport.UDPTransport):
            dce = dcerpc_v4.DCERPC_v4(rpctransport)
        else:
            dce = dcerpc.DCERPC_v5(rpctransport)

        entries = []

        dce.connect()
        dce.bind(epm.MSRPC_UUID_PORTMAP)
        rpcepm = epm.DCERPCEpm(dce)

        resp = rpcepm.portmap_dump()
        while resp.get_entries_num() != 0:
            rpc_handle = resp.get_handle()
            ndrentry = resp.get_entry().get_entry()
            sb = transport.DCERPCStringBinding(ndrentry.get_string_binding())
            entry = epm.EpmEntry(
                uuid.bin_to_string(ndrentry.get_uuid()),
                ndrentry.get_version(),
                ndrentry.get_annotation(),
                uuid.bin_to_string(ndrentry.get_objuuid()),
                sb.get_protocol_sequence(),
                sb.get_endpoint(),
            )
            entries.append(entry)
            resp = rpcepm.portmap_dump(rpc_handle)

        dce.disconnect()

        return entries
Esempio n. 2
0
def get_dynamic_endpoint(interface: bytes,
                         target: str,
                         timeout: int = 5) -> str:
    string_binding = r"ncacn_ip_tcp:%s[135]" % target
    rpctransport = transport.DCERPCTransportFactory(string_binding)
    rpctransport.set_connect_timeout(timeout)
    dce = rpctransport.get_dce_rpc()
    logging.debug("Trying to resolve dynamic endpoint %s" %
                  repr(uuid.bin_to_string(interface)))
    try:
        dce.connect()
    except Exception as e:
        logging.warning("Failed to connect to endpoint mapper: %s" % e)
        return None
    try:
        endpoint = epm.hept_map(target,
                                interface,
                                protocol="ncacn_ip_tcp",
                                dce=dce)
        logging.debug("Resolved dynamic endpoint %s to %s" %
                      (repr(uuid.bin_to_string(interface)), repr(endpoint)))
        return endpoint
    except Exception:
        logging.debug("Failed to resolve dynamic endpoint %s" %
                      repr(uuid.bin_to_string(interface)))
        return None
Esempio n. 3
0
    def __fetchList(self, rpctransport):
        # UDP only works over DCE/RPC version 4.
        if isinstance(rpctransport, transport.UDPTransport):
            dce = dcerpc_v4.DCERPC_v4(rpctransport)
        else:
            dce = dcerpc.DCERPC_v5(rpctransport)

        entries = []

        dce.connect()
        dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)
        dce.bind(epm.MSRPC_UUID_PORTMAP)
        rpcepm = epm.DCERPCEpm(dce)

        resp = rpcepm.portmap_dump()
        while resp.get_entries_num() != 0:
            rpc_handle = resp.get_handle()
            ndrentry = resp.get_entry().get_entry()
            sb = transport.DCERPCStringBinding(ndrentry.get_string_binding())
            entry = epm.EpmEntry(uuid.bin_to_string(ndrentry.get_uuid()),
                                 ndrentry.get_version(),
                                 ndrentry.get_annotation(),
                                 uuid.bin_to_string(ndrentry.get_objuuid()),
                                 sb.get_protocol_sequence(), sb.get_endpoint())
            entries.append(entry)
            ##             print str(entry)
            resp = rpcepm.portmap_dump(rpc_handle)

        dce.disconnect()

        return entries
Esempio n. 4
0
        def get_enrollment_principals(entry):
            # Mostly taken from github.com/ly4k/Certipy/certipy/security.py
            sd = ldaptypes.SR_SECURITY_DESCRIPTOR()
            sd.fromString(entry["raw_attributes"]["nTSecurityDescriptor"][0])

            enrollment_uuids = [
                "00000000-0000-0000-0000-000000000000",  # All-Extended-Rights
                "0e10c968-78fb-11d2-90d4-00c04f79dc55",  # Certificate-Enrollment
                "a05b8cc2-17bc-4802-a710-e7c15ab866a2",  # Certificate-AutoEnrollment
            ]

            enrollment_principals = set()

            for ace in (a for a in sd["Dacl"]["Data"] if a["AceType"] ==
                        ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE):
                sid = format_sid(ace["Ace"]["Sid"].getData())
                if ace["Ace"]["ObjectTypeLen"] == 0:
                    uuid = bin_to_string(
                        ace["Ace"]["InheritedObjectType"]).lower()
                else:
                    uuid = bin_to_string(ace["Ace"]["ObjectType"]).lower()

                if not uuid in enrollment_uuids:
                    continue

                enrollment_principals.add(sid)

            return enrollment_principals
Esempio n. 5
0
 def dump(self):
     print("[VAULT_VPOL]")
     print("Version      : %8x (%d)" % (self['Version'], self['Version']))
     print("Guid         : %s" % bin_to_string(self['Guid']))
     print("Description  : %s" % (self['Description'].decode('utf-16le')))
     print("Size         : 0x%.8x (%d)" % (self['Size'], self['Size']))
     print("Guid2        : %s" % bin_to_string(self['Guid2']))
     print("Guid3        : %s" % bin_to_string(self['Guid3']))
     print("KeySize      : 0x%.8x (%d)" % (self['KeySize'], self['KeySize']))
     self['Blob'].dump()
     print()
Esempio n. 6
0
 def dump(self):
     print("[VAULT_VPOL]")
     print("Version      : %8x (%d)" % (self['Version'], self['Version']))
     print("Guid         : %s" % bin_to_string(self['Guid']))
     print("Description  : %s" % (self['Description'].decode('utf-16le')))
     print("Size         : 0x%.8x (%d)" % (self['Size'], self['Size']))
     print("Guid2        : %s" % bin_to_string(self['Guid2']))
     print("Guid3        : %s" % bin_to_string(self['Guid3']))
     print("KeySize      : 0x%.8x (%d)" %
           (self['KeySize'], self['KeySize']))
     self['Blob'].dump()
     print()
Esempio n. 7
0
 def dump(self):
     print("[BLOB]")
     print("Version          : %8x (%d)" % (self['Version'], self['Version']))
     print("Guid Credential  : %s" % bin_to_string(self['GuidCredential']))
     print("MasterKeyVersion : %8x (%d)" % (self['MasterKeyVersion'], self['MasterKeyVersion']))
     print("Guid MasterKey   : %s" % bin_to_string(self['GuidMasterKey']))
     print("Flags            : %8x (%s)" % (self['Flags'], getFlags(FLAGS, self['Flags'])))
     print("Description      : %s" % (self['Description'].decode('utf-16le')))
     print("CryptAlgo        : %.8x (%d) (%s)" % (self['CryptAlgo'], self['CryptAlgo'], ALGORITHMS(self['CryptAlgo']).name))
     print("Salt             : %s" % (hexlify(self['Salt'])))
     print("HMacKey          : %s" % (hexlify(self['HMacKey'])))
     print("HashAlgo         : %.8x (%d) (%s)" % (self['HashAlgo'], self['HashAlgo'], ALGORITHMS(self['HashAlgo']).name))
     print("HMac             : %s" % (hexlify(self['HMac'])))
     print("Data             : %s" % (hexlify(self['Data'])))
     print("Sign             : %s" % (hexlify(self['Sign'])))
     print()
Esempio n. 8
0
 def dump(self):
     print("[DOMAINKEY]")
     print("Version       : %8x (%d)" % (self['Version'], self['Version']))
     print("Guid          : %s" % bin_to_string(self['Guid']))
     print("SecretLen     : %8x (%d)" % (self['SecretLen'], self['SecretLen']))
     print("AccessCheckLen: %.8x (%d)" % (self['AccessCheckLen'], self['AccessCheckLen']))
     print("SecretData    : %s" % (hexlify(self['SecretData'])))
     print("AccessCheck   : %s" % (hexlify(self['AccessCheck'])))
     print()
Esempio n. 9
0
def can_add_member(ace):
    writeprivs = ace['Ace']['Mask'].hasPriv(
        ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_WRITE_PROP)
    if ace['AceType'] != ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE or ace['Ace'][
            'ObjectType'] == b'':
        return writeprivs
    userprivs = bin_to_string(
        ace['Ace']
        ['ObjectType']).lower() == 'bf9679c0-0de6-11d0-a285-00aa003049e2'
    return writeprivs and userprivs
Esempio n. 10
0
def can_create_users(ace):
    createprivs = ace['Ace']['Mask'].hasPriv(
        ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_CREATE_CHILD)
    if ace['AceType'] != ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE or ace['Ace'][
            'ObjectType'] == b'':
        return False
    userprivs = bin_to_string(
        ace['Ace']
        ['ObjectType']).lower() == 'bf967aba-0de6-11d0-a285-00aa003049e2'
    return createprivs and userprivs
Esempio n. 11
0
    def __fetch(self, dce):
        output = {}
        domain_info = dssp.hDsRolerGetPrimaryDomainInformation(dce, 1)

        output['Machine Role'] = self.MACHINE_ROLES[domain_info['DomainInfo']['DomainInfoBasic']['MachineRole']]
        output['NetBIOS Domain Name'] = domain_info['DomainInfo']['DomainInfoBasic']['DomainNameFlat']
        output['Domain Name'] = domain_info['DomainInfo']['DomainInfoBasic']['DomainNameDns']
        output['Forest Name'] = domain_info['DomainInfo']['DomainInfoBasic']['DomainForestName']
        output['Domain GUID'] = bin_to_string(domain_info['DomainInfo']['DomainInfoBasic']['DomainGuid'])

        return output
Esempio n. 12
0
 def dump(self):
     print("[DOMAINKEY]")
     print("Version       : %8x (%d)" % (self['Version'], self['Version']))
     print("Guid          : %s" % bin_to_string(self['Guid']))
     print("SecretLen     : %8x (%d)" %
           (self['SecretLen'], self['SecretLen']))
     print("AccessCheckLen: %.8x (%d)" %
           (self['AccessCheckLen'], self['AccessCheckLen']))
     print("SecretData    : %s" % (hexlify(self['SecretData'])))
     print("AccessCheck   : %s" % (hexlify(self['AccessCheck'])))
     print()
Esempio n. 13
0
 def aceApplies(ace, objectClasses):
     '''
     Checks if an ACE applies to this object (based on object classes).
     Note that this function assumes you already verified that InheritedObjectType is set (via the flag).
     If this is not set, the ACE applies to all object types.
     '''
     objectTypeGuid = bin_to_string(ace['Ace']['InheritedObjectType']).lower()
     for objectType, guid in OBJECTTYPE_GUID_MAP.items():
         if objectType in objectClasses and objectTypeGuid:
             return True
     # If none of these match, the ACE does not apply to this object
     return False
Esempio n. 14
0
 def dump(self):
     print("[VCRD]")
     print("SchemaGuid  : %s" % bin_to_string(self['SchemaGuid']))
     print("LastWritten : %s" % (datetime.utcfromtimestamp(getUnixTime(self['LastWritten']))))
     print("FriendlyName: %s" % (self['FriendlyName'].decode('utf-16le')))
     print()
     for i,entry in enumerate(self.mapEntries):
         entry.dump()
         self.attributes[i].dump()
     print()
     print("Remaining   : %s" % (hexlify(self['Data'])))
     print()
Esempio n. 15
0
 def aceApplies(ace, objectClasses):
     '''
     Checks if an ACE applies to this object (based on object classes).
     Note that this function assumes you already verified that InheritedObjectType is set (via the flag).
     If this is not set, the ACE applies to all object types.
     '''
     objectTypeGuid = bin_to_string(
         ace['Ace']['InheritedObjectType']).lower()
     for objectType, guid in OBJECTTYPE_GUID_MAP.iteritems():
         if objectType in objectClasses and objectTypeGuid:
             return True
     # If none of these match, the ACE does not apply to this object
     return False
Esempio n. 16
0
 def dump(self):
     print("[VCRD]")
     print("SchemaGuid  : %s" % bin_to_string(self['SchemaGuid']))
     print("LastWritten : %s" %
           (datetime.utcfromtimestamp(getUnixTime(self['LastWritten']))))
     print("FriendlyName: %s" % (self['FriendlyName'].decode('utf-16le')))
     print()
     for i, entry in enumerate(self.mapEntries):
         entry.dump()
         self.attributes[i].dump()
     print()
     print("Remaining   : %s" % (hexlify(self['Data'])))
     print()
Esempio n. 17
0
 def dump(self):
         print("[CRED]")
         print("version         : %8x (%d)" % (self['version'], self['version']))
         print("GUID            : %s" % bin_to_string(self['Guid']))
         print("HashAlgo        : %8x (%s)" % (self['HashAlgo'], ALGORITHMS(self['HashAlgo']).name))
         print("rounds          : %8x (%d)" % (self['rounds'], self['rounds']))
         print("sidLen          : %8x (%d)" % (self['sidLen'], self['sidLen']))
         print("CryptAlgo       : %8x (%s)" % (self['CryptAlgo'], ALGORITHMS(self['CryptAlgo']).name))
         print("shaHashLen      : %8x (%d)" % (self['shaHashLen'], self['shaHashLen']))
         print("ntHashLen       : %8x (%d)" % (self['ntHashLen'], self['ntHashLen']))
         print("Salt            : %s" % hexlify(self['Salt']))
         print("SID             : %s" % (bin_to_sid(self['SID'])))
         print("data             : %s" % hexlify(self['data']))
         print()
Esempio n. 18
0
 def dump(self):
     print("[BLOB]")
     print("Version          : %8x (%d)" %
           (self['Version'], self['Version']))
     print("Guid Credential  : %s" % bin_to_string(self['GuidCredential']))
     print("MasterKeyVersion : %8x (%d)" %
           (self['MasterKeyVersion'], self['MasterKeyVersion']))
     print("Guid MasterKey   : %s" % bin_to_string(self['GuidMasterKey']))
     print("Flags            : %8x (%s)" %
           (self['Flags'], getFlags(FLAGS, self['Flags'])))
     print("Description      : %s" %
           (self['Description'].decode('utf-16le')))
     print("CryptAlgo        : %.8x (%d) (%s)" %
           (self['CryptAlgo'], self['CryptAlgo'],
            ALGORITHMS(self['CryptAlgo']).name))
     print("Salt             : %s" % (hexlify(self['Salt'])))
     print("HMacKey          : %s" % (hexlify(self['HMacKey'])))
     print("HashAlgo         : %.8x (%d) (%s)" %
           (self['HashAlgo'], self['HashAlgo'], ALGORITHMS(
               self['HashAlgo']).name))
     print("HMac             : %s" % (hexlify(self['HMac'])))
     print("Data             : %s" % (hexlify(self['Data'])))
     print("Sign             : %s" % (hexlify(self['Sign'])))
     print()
Esempio n. 19
0
def DiscoverDNSport(target):
	trans = transport.SMBTransport(target, 139, 'epmapper')
	trans.connect()
	dce = dcerpc.DCERPC_v5(trans)
	dce.bind(uuid.uuidtup_to_bin(('E1AF8308-5D1F-11C9-91A4-08002B14A0FA','3.0')))
	pm = epm.DCERPCEpm(dce)
	handle = '\x00'*20
	while 1:
		dump = pm.portmap_dump(handle)
		if not dump.get_entries_num():
			break
		handle = dump.get_handle()
		entry = dump.get_entry().get_entry()
		if(uuid.bin_to_string(entry.get_uuid()) == '50ABC2A4-574D-40B3-9D66-EE4FD5FBA076'):
			port = entry.get_string_binding().split('[')[1][:-1]
			return int(port)

	print '[-] Could not locate DNS port; Target might not be running DNS'
Esempio n. 20
0
def DiscoverDNSport(target):
    trans = transport.SMBTransport(target, 139, 'epmapper')
    trans.connect()
    dce = dcerpc.DCERPC_v5(trans)
    dce.bind(
        uuid.uuidtup_to_bin(('E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0')))
    pm = epm.DCERPCEpm(dce)
    handle = '\x00' * 20
    while 1:
        dump = pm.portmap_dump(handle)
        if not dump.get_entries_num():
            break
        handle = dump.get_handle()
        entry = dump.get_entry().get_entry()
        if (uuid.bin_to_string(
                entry.get_uuid()) == '50ABC2A4-574D-40B3-9D66-EE4FD5FBA076'):
            port = entry.get_string_binding().split('[')[1][:-1]
            return int(port)

    print '[-] Could not locate DNS port; Target might not be running DNS'
def parse_EPM_Entries(entries):

    endpoints = {}

    for entry in entries:

        entry_Object = entry.get('object')
        entry_Tower_pointer = entry.get('tower')
        entry_Annotation = entry.get('annotation')

        entry_ObjectStr = uuid.bin_to_string(entry_Object)

        entry_Floors = (entry_Tower_pointer.fields).get('Floors')
        entry_NumberOfFloors = (
            entry_Tower_pointer.fields).get('NumberOfFloors')

        entry_Tower_Floor_Info = parse_EPM_Entry_Floors(entry_Floors)

        from pprint import pprint

        pprint(entry_Tower_Floor_Info)
Esempio n. 22
0
    def parseRow(self, token, tuplemode=False):
        # TODO: This REALLY needs to be improved. Right now we don't support correctly all the data types
        # help would be appreciated ;)
        if len(token) == 1:
            return 0

        row = [] if tuplemode else {}

        origDataLen = len(token['Data'])
        data = token['Data']
        for col in self.colMeta:
            _type = col['Type']
            if (_type == TDS_NVARCHARTYPE) |\
               (_type == TDS_NCHARTYPE):
                #print "NVAR 0x%x" % _type
                charLen = struct.unpack('<H', data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                if charLen != 0xFFFF:
                    value = data[:charLen].decode('utf-16le')
                    data = data[charLen:]
                else:
                    value = 'NULL'

            elif (_type == TDS_BIGVARCHRTYPE):
                charLen = struct.unpack('<H', data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                if charLen != 0xFFFF:
                    value = data[:charLen]
                    data = data[charLen:]
                else:
                    value = 'NULL'

            elif (_type == TDS_GUIDTYPE):
                uuidLen = ord(data[0])
                data = data[1:]
                if uuidLen > 0:
                    uu = data[:uuidLen]
                    value = uuid.bin_to_string(uu)
                    data = data[uuidLen:]
                else:
                    value = 'NULL'

            elif (_type == TDS_NTEXTTYPE) |\
                 (_type == TDS_IMAGETYPE) :
                # Skip the pointer data
                charLen = ord(data[0])
                if charLen == 0:
                    value = 'NULL'
                    data = data[1:]
                else:
                    data = data[1 + charLen + 8:]
                    charLen = struct.unpack('<L',
                                            data[:struct.calcsize('<L')])[0]
                    data = data[struct.calcsize('<L'):]
                    if charLen != 0xFFFF:
                        if _type == TDS_NTEXTTYPE:
                            value = data[:charLen].decode('utf-16le')
                        else:
                            value = binascii.b2a_hex(data[:charLen])
                        data = data[charLen:]
                    else:
                        value = 'NULL'

            elif (_type == TDS_TEXTTYPE):
                # Skip the pointer data
                charLen = ord(data[0])
                if charLen == 0:
                    value = 'NULL'
                    data = data[1:]
                else:
                    data = data[1 + charLen + 8:]
                    charLen = struct.unpack('<L',
                                            data[:struct.calcsize('<L')])[0]
                    data = data[struct.calcsize('<L'):]
                    if charLen != 0xFFFF:
                        value = data[:charLen]
                        data = data[charLen:]
                    else:
                        value = 'NULL'

            elif (_type == TDS_BIGVARBINTYPE) |\
                 (_type == TDS_BIGBINARYTYPE):
                charLen = struct.unpack('<H', data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                if charLen != 0xFFFF:
                    value = binascii.b2a_hex(data[:charLen])
                    data = data[charLen:]
                else:
                    value = 'NULL'

            elif (_type == TDS_DATETIM4TYPE) |\
                 (_type == TDS_DATETIMNTYPE) |\
                 (_type == TDS_DATETIMETYPE):
                value = ''
                if _type == TDS_DATETIMNTYPE:
                    # For DATETIMNTYPE, the only valid lengths are 0x04 and 0x08, which map to smalldatetime and
                    # datetime SQL data _types respectively.
                    if ord(data[0]) == 4:
                        _type = TDS_DATETIM4TYPE
                    elif ord(data[0]) == 8:
                        _type = TDS_DATETIMETYPE
                    else:
                        value = 'NULL'
                    data = data[1:]
                if (_type == TDS_DATETIMETYPE):
                    # datetime is represented in the following sequence:
                    # * One 4-byte signed integer that represents the number of days since January 1, 1900. Negative
                    #   numbers are allowed to represents dates since January 1, 1753.
                    # * One 4-byte unsigned integer that represents the number of one three-hundredths of a second
                    #  (300 counts per second) elapsed since 12 AM that day.
                    dateValue = struct.unpack('<l', data[:4])[0]
                    data = data[4:]
                    if dateValue < 0:
                        baseDate = datetime.date(1753, 1, 1)
                    else:
                        baseDate = datetime.date(1900, 1, 1)
                    timeValue = struct.unpack('<L', data[:4])[0]
                    data = data[4:]
                elif (_type == TDS_DATETIM4TYPE):
                    # Small datetime
                    # 2.2.5.5.1.8
                    # Date/Times
                    # smalldatetime is represented in the following sequence:
                    # * One 2-byte unsigned integer that represents the number of days since January 1, 1900.
                    # * One 2-byte unsigned integer that represents the number of minutes elapsed since 12 AM that
                    #   day.
                    dateValue = struct.unpack('<H',
                                              data[:struct.calcsize('<H')])[0]
                    data = data[struct.calcsize('<H'):]
                    timeValue = struct.unpack('<H',
                                              data[:struct.calcsize('<H')])[0]
                    data = data[struct.calcsize('<H'):]
                    baseDate = datetime.date(1900, 1, 1)
                if value != 'NULL':
                    dateValue = datetime.date.fromordinal(
                        baseDate.toordinal() + dateValue)
                    hours, mod = divmod(timeValue / 300, 60 * 60)
                    minutes, second = divmod(mod, 60)
                    value = datetime.datetime(dateValue.year, dateValue.month,
                                              dateValue.day, hours, minutes,
                                              second)

            elif (_type == TDS_INT4TYPE) |\
                 (_type == TDS_MONEY4TYPE) |\
                 (_type == TDS_FLT4TYPE):
                #print "INT4"
                value = struct.unpack('<l', data[:struct.calcsize('<l')])[0]
                data = data[struct.calcsize('<l'):]

            elif (_type == TDS_FLTNTYPE):
                valueSize = ord(data[:1])
                if valueSize == 4:
                    fmt = '<f'
                elif valueSize == 8:
                    fmt = '<d'

                data = data[1:]

                if valueSize > 0:
                    value = struct.unpack(fmt, data[:valueSize])[0]
                    data = data[valueSize:]
                else:
                    value = 'NULL'

            elif _type == TDS_MONEYNTYPE:
                valueSize = ord(data[:1])
                if valueSize == 4:
                    fmt = '<l'
                elif valueSize == 8:
                    fmt = '<q'

                data = data[1:]

                if valueSize > 0:
                    value = struct.unpack(fmt, data[:valueSize])[0]
                    if valueSize == 4:
                        value = float(value) / math.pow(10, 4)
                    else:
                        value = float(value >> 32) / math.pow(10, 4)
                    data = data[valueSize:]
                else:
                    value = 'NULL'

            elif _type == TDS_BIGCHARTYPE:
                #print "BIGC"
                charLen = struct.unpack('<H', data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                value = data[:charLen]
                data = data[charLen:]

            elif (_type == TDS_INT8TYPE) |\
                 (_type == TDS_FLT8TYPE) |\
                 (_type == TDS_MONEYTYPE):
                #print "DATETIME"
                value = struct.unpack('<q', data[:struct.calcsize('<q')])[0]
                data = data[struct.calcsize('<q'):]

            elif (_type == TDS_INT2TYPE):
                #print "INT2TYPE"
                value = struct.unpack('<H', (data[:2]))[0]
                data = data[2:]

            elif (_type == TDS_DATENTYPE):
                # date is represented as one 3-byte unsigned integer that represents the number of days since
                # January 1, year 1.
                valueSize = ord(data[:1])
                data = data[1:]
                if valueSize > 0:
                    dateBytes = data[:valueSize]
                    dateValue = struct.unpack('<L', '\x00' + dateBytes)[0]
                    value = datetime.date.fromtimestamp(dateValue)
                    data = data[valueSize:]
                else:
                    value = 'NULL'

            elif (_type == TDS_BITTYPE) |\
                 (_type == TDS_INT1TYPE):
                #print "BITTYPE"
                value = ord(data[:1])
                data = data[1:]

            elif (_type == TDS_NUMERICNTYPE) |\
                 (_type == TDS_DECIMALNTYPE):
                valueLen = ord(data[:1])
                data = data[1:]
                value = data[:valueLen]
                data = data[valueLen:]
                precision = ord(col['TypeData'][1])
                scale = ord(col['TypeData'][2])
                if valueLen > 0:
                    isPositiveSign = ord(value[0])
                    if (valueLen - 1) == 2:
                        fmt = '<H'
                    elif (valueLen - 1) == 4:
                        fmt = '<L'
                    elif (valueLen - 1) == 8:
                        fmt = '<Q'
                    else:
                        # Still don't know how to handle higher values
                        value = "TODO: Interpret TDS_NUMERICNTYPE correctly"
                    number = struct.unpack(fmt, value[1:])[0]
                    number /= math.pow(precision, scale)
                    if isPositiveSign == 0:
                        number *= -1
                    value = number
                else:
                    value = 'NULL'

            elif (_type == TDS_BITNTYPE):
                #print "BITNTYPE"
                valueSize = ord(data[:1])
                data = data[1:]
                if valueSize > 0:
                    if valueSize == 1:
                        value = ord(data[:valueSize])
                    else:
                        value = data[:valueSize]
                else:
                    value = 'NULL'
                data = data[valueSize:]

            elif (_type == TDS_INTNTYPE):
                valueSize = ord(data[:1])
                if valueSize == 1:
                    fmt = '<B'
                elif valueSize == 2:
                    fmt = '<h'
                elif valueSize == 4:
                    fmt = '<l'
                elif valueSize == 8:
                    fmt = '<q'
                else:
                    fmt = ''

                data = data[1:]

                if valueSize > 0:
                    value = struct.unpack(fmt, data[:valueSize])[0]
                    data = data[valueSize:]
                else:
                    value = 'NULL'
            elif (_type == TDS_SSVARIANTTYPE):
                self.__logger.logMessage(
                    "ParseRow: SQL Variant type not yet supported :(")
                raise
            else:
                self.__logger.logMessage(
                    "ParseROW: Unsupported data type: 0%x" % _type)
                raise

            if tuplemode:
                row.append(value)
            else:
                row[col['Name']] = value

        self.rows.append(row)

        return (origDataLen - len(data))
Esempio n. 23
0
    def nspi_dump_tables(self, options):
        self.exch.set_output_type(options.output_type)

        if options.lookup_type == None or options.lookup_type == 'MINIMAL':
            propTags = NSPIAttacks.PROPS_MINUMAL
        elif options.lookup_type == 'EXTENDED':
            propTags = NSPIAttacks.PROPS_EXTENDED
        elif options.lookup_type == 'GUIDS':
            propTags = NSPIAttacks.PROPS_GUID
        else:
            # FULL
            propTags = []

        if options.name != None and options.name.lower() in ['gal', 'default global address list', 'global address list']:
            logging.info("Lookuping Global Address List")
            table_MId = 0
        else:
            # 2.2.8
            # The client obtains Minimal Entry IDs for STAT ContainerID
            # from the server's address book hierarchy table
            #
            # We cannot convert the GUID to a MId via NspiDNToMId or similar operations because it
            # may not work in Multi-Tenant environments
            self.exch.load_htable()

            if options.guid != None:
                logging.info("Search for an address book with objectGUID = %s" % options.guid)
                guid = uuid.string_to_bin(options.guid)
                name = None
            else:
                guid = None
                name = options.name

            table_MId = 0

            for MId in self.exch.htable:
                if MId == 0:
                    # GAL
                    continue

                if guid is not None:
                    # -guid
                    if self.exch.htable[MId]['guid'] == guid:
                        logging.debug("MId %d is assigned for %s object" % (MId, options.guid))
                        logging.info("Lookuping %s" % self.exch.htable[MId]['name'])
                        table_MId = MId
                        break
                else:
                    # -name
                    if self.exch.htable[MId]['name'] == name:
                        guid = uuid.bin_to_string(self.exch.htable[MId]['guid'])
                        logging.debug("MId %d is assigned for %s object" % (MId, guid))
                        logging.info("Lookuping address book with objectGUID = %s" % guid)
                        table_MId = MId
                        break

            if table_MId == 0:
                logging.error("Specified address book not found!")
                sys.exit(1)

        self.exch.req_print_table_rows(table_MId, propTags, options.rows_per_request)
Esempio n. 24
0
    def dump(self):
        print("[CAPI]")
        print("Version          : %8x (%d)" % (self['Version'], self['Version']))
        print("UniqueNameLen    : %8x (%d)" % (self['UniqueNameLen'], self['UniqueNameLen']))
        print("SiPublicKeyLen   : %8x (%d)" % (self['SiPublicKeyLen'], self['SiPublicKeyLen']))
        print("SiPrivateKeyLen  : %8x (%d)" % (self['SiPrivateKeyLen'], self['SiPrivateKeyLen']))

        print("Unique Name      : (%s)" % self['UniqueName'].decode('utf-8'))
        print("Hash             : (%s)" % ((self['Hash'])))
        print("PublicKey        : (%s)" % (hexlify(self['PublicKey'])))
        print()

        print("pkVersion       : (%s)" % (self['pkVersion']))
        print("guidProvider     : (%s)" % (bin_to_string(self['guidProvider'])))

        print("MasterKeyVersion : %8x (%d)" % (self['MasterKeyVersion_'], self['MasterKeyVersion_']))
        print("guidMasterKey    : (%s)" % (bin_to_string(self['guidMasterKey'])))

        print("Flags            : %8x (%s)" % (self['Flags'], getFlags(FLAGS, self['Flags'])))
        print("DescriptionLen   : %8x (%d)" % (self['DescriptionLen'], self['DescriptionLen']))

        print("Description      : %s" % (self['Description'].decode('utf-16le')))
        print("CryptAlgo        : %.8x (%d) (%s)" % (self['CryptAlgo'], self['CryptAlgo'], ALGORITHMS(self['CryptAlgo']).name))
        print("CryptAlgoLen     : %8x (%d)" % (self['CryptAlgoLen'], self['CryptAlgoLen']))
        print("SaltLen          : %8x (%d)" % (self['SaltLen'], self['SaltLen']))

        print("Salt             : %s" % (hexlify(self['Salt'])))
        print("HMacKeyLen : %8x (%d)" % (self['HMacKeyLen'], self['HMacKeyLen']))
        print("HMacKey          : %s" % (hexlify(self['HMacKey'])))
        #print("HashAlgoLen          : %s " % bytes(hexlify(self['HashAlgoLen'])))
        print("HashAlgo         : %.8x (%d) (%s)" % (self['HashAlgo'], self['HashAlgo'], ALGORITHMS(self['HashAlgo']).name))
        print("HMac             : %s" % (hexlify(self['HMac'])))
        print("DataLen          : %8x (%d)" % (self['DataLen'], self['DataLen']))
        print("Data             : %s" % (hexlify(self['Data'])))
        print("SignLen          : %8x (%d)" % (self['SignLen'], self['SignLen']))
        print("Sign             : %s" % (hexlify(self['Sign'])))
        print()


        print("expkVersion       : (%s)" % (self['expkVersion']))
        print("exguidProvider     : (%s)" % (bin_to_string(self['exguidProvider'])))

        print("exMasterKeyVersion : %8x (%d)" % (self['exMasterKeyVersion_'], self['exMasterKeyVersion_']))
        print("exguidMasterKey    : (%s)" % (bin_to_string(self['exguidMasterKey'])))

        print("exFlags            : %8x (%s)" % (self['exFlags'], getFlags(FLAGS, self['exFlags'])))
        print("exDescriptionLen   : %8x (%d)" % (self['exDescriptionLen'], self['exDescriptionLen']))

        print("exDescription      : %s" % (self['exDescription'].decode('utf-16le')))
        print("exCryptAlgo        : %.8x (%d) (%s)" % (self['exCryptAlgo'], self['exCryptAlgo'], ALGORITHMS(self['exCryptAlgo']).name))
        print("exCryptAlgoLen     : %8x (%d)" % (self['exCryptAlgoLen'], self['exCryptAlgoLen']))
        print("exSaltLen          : %8x (%d)" % (self['exSaltLen'], self['exSaltLen']))

        print("exSalt             : %s" % (hexlify(self['exSalt'])))
        print("exHMacKeyLen : %8x (%d)" % (self['exHMacKeyLen'], self['exHMacKeyLen']))
        print("exHMacKey          : %s" % (hexlify(self['exHMacKey'])))
        #print("exHashAlgoLen          : %s " % bytes(hexlify(self['exHashAlgoLen'])))
        print("exHashAlgo         : %.8x (%d) (%s)" % (self['exHashAlgo'], self['exHashAlgo'], ALGORITHMS(self['exHashAlgo']).name))
        print("exHMac2Key         : %s" % (hexlify(self['exHMac2Key'])))
        print("exDataLen          : %8x (%d)" % (self['exDataLen'], self['exDataLen']))
        print("exData             : %s" % (hexlify(self['exData'])))
        print("exSignLen          : %8x (%d)" % (self['exSignLen'], self['exSignLen']))
        print("exSign             : %s" % (hexlify(self['exSign'])))
        print()
Esempio n. 25
0
 def checkSecurityDescriptors(self, entries, privs, membersids, sidmapping, domainDumper):
     standardrights = [
         self.GENERIC_ALL,
         self.GENERIC_WRITE,
         self.GENERIC_READ,
         ACCESS_MASK.WRITE_DACL
     ]
     for entry in entries:
         if entry['type'] != 'searchResEntry':
             continue
         dn = entry['dn']
         try:
             sdData = entry['raw_attributes']['nTSecurityDescriptor'][0]
         except IndexError:
             # We don't have the privileges to read this security descriptor
             continue
         hasFullControl = False
         secDesc = ldaptypes.SR_SECURITY_DESCRIPTOR()
         secDesc.fromString(sdData)
         if secDesc['OwnerSid'] != '' and secDesc['OwnerSid'].formatCanonical() in membersids:
             sid = secDesc['OwnerSid'].formatCanonical()
             LOG.debug('Permission found: Full Control on %s; Reason: Owner via %s' % (dn, sidmapping[sid]))
             hasFullControl = True
         # Iterate over all the ACEs
         for ace in secDesc['Dacl'].aces:
             sid = ace['Ace']['Sid'].formatCanonical()
             if ace['AceType'] != ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE and ace['AceType'] != ACCESS_ALLOWED_ACE.ACE_TYPE:
                 continue
             if not ace.hasFlag(ACE.INHERITED_ACE) and ace.hasFlag(ACE.INHERIT_ONLY_ACE):
                 # ACE is set on this object, but only inherited, so not applicable to us
                 continue
             # Check if the ACE has restrictions on object type
             if ace['AceType'] == ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE \
                 and ace.hasFlag(ACE.INHERITED_ACE) \
                 and ace['Ace'].hasFlag(ACCESS_ALLOWED_OBJECT_ACE.ACE_INHERITED_OBJECT_TYPE_PRESENT):
                 # Verify if the ACE applies to this object type
                 inheritedObjectType = bin_to_string(ace['Ace']['InheritedObjectType']).lower()
                 if not self.aceApplies(inheritedObjectType, entry['raw_attributes']['objectClass'][-1]):
                     continue
             # Check for non-extended rights that may not apply to us
             if ace['Ace']['Mask']['Mask'] in standardrights or ace['Ace']['Mask'].hasPriv(ACCESS_MASK.WRITE_DACL):
                 # Check if this applies to our objecttype
                 if ace['AceType'] == ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE  and ace['Ace'].hasFlag(ACCESS_ALLOWED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT):
                     objectType = bin_to_string(ace['Ace']['ObjectType']).lower()
                     if not self.aceApplies(objectType, entry['raw_attributes']['objectClass'][-1]):
                         # LOG.debug('ACE does not apply, only to %s', objectType)
                         continue
             if sid in membersids:
                 # Generic all
                 if ace['Ace']['Mask'].hasPriv(self.GENERIC_ALL):
                     ace.dump()
                     LOG.debug('Permission found: Full Control on %s; Reason: GENERIC_ALL via %s' % (dn, sidmapping[sid]))
                     hasFullControl = True
                 if can_create_users(ace) or hasFullControl:
                     if not hasFullControl:
                         LOG.debug('Permission found: Create users in %s; Reason: Granted to %s' % (dn, sidmapping[sid]))
                     if dn == 'CN=Users,%s' % domainDumper.root:
                         # We can create users in the default container, this is preferred
                         privs['create'] = True
                         privs['createIn'] = dn
                     else:
                         # Could be a different OU where we have access
                         # store it until we find a better place
                         if privs['createIn'] != 'CN=Users,%s' % domainDumper.root and 'organizationalUnit' in entry['raw_attributes']['objectClass']:
                             privs['create'] = True
                             privs['createIn'] = dn
                 if can_add_member(ace) or hasFullControl:
                     if 'group' in entry['raw_attributes']['objectClass']:
                         # We can add members to a group
                         if not hasFullControl:
                             LOG.debug('Permission found: Add member to %s; Reason: Granted to %s' % (dn, sidmapping[sid]))
                         privs['escalateViaGroup'] = True
                         privs['escalateGroup'] = dn
                 if ace['Ace']['Mask'].hasPriv(ACCESS_MASK.WRITE_DACL) or hasFullControl:
                     if not hasFullControl:
                         LOG.debug('Permission found: Write Dacl of %s; Reason: Granted to %s' % (dn, sidmapping[sid]))
                     # We can modify the domain Dacl
                     if 'domain' in entry['raw_attributes']['objectClass']:
                         privs['aclEscalate'] = True
                         privs['aclEscalateIn'] = dn
Esempio n. 26
0
def parse_uuid(_uuid):
    return uuid.bin_to_string(_uuid)
Esempio n. 27
0
 def get_object_type(self):
     if self.has_flag(self.ACE_OBJECT_TYPE_PRESENT):
         return bin_to_string(self.data.ObjectType)
     return None
Esempio n. 28
0
 def get_inherited_object_type(self):
     if self.has_flag(self.ACE_INHERITED_OBJECT_TYPE_PRESENT):
         return bin_to_string(self.data.InheritedObjectType)
     return None
Esempio n. 29
0
 def dump(self):
     print("[CREDHIST]")
     print("Version       : %8x (%d)" % (self['Version'], self['Version']))
     print("Guid          : %s" % bin_to_string(self['Guid']))
     print()
def parse_EPM_Entry_Floors(entry_Floors):

    entry_Tower_Floor_Info = {
        'UUID': [],
        'NDR_UUID': [],
        'IP': '',
        'PIPE': [],
        'NETBIOS': [],
        'APPLICATION': '',
        'PROTOCOL': ''
    }

    for floor in entry_Floors:

        protocol = floor.getData()[2]
        protocol = int(ord(protocol))

        if protocol == PROTO_ID_UUID:
            floor_fields = floor.fields

            # import ipdb; ipdb.set_trace()

            floor_MajorVersion = floor_fields.get('MajorVersion')
            floor_MinorVersion = floor_fields.get('MinorVersion')
            floor_InterfaceIdent = floor_fields.get('InterfaceIdent')
            floor_RHSByteCount = floor_fields.get('RHSByteCount')

            # different UUID definition in EPMFloor Structure from (impacket/dcerpc/v5/epm.py)
            floor_InterfaceUUID = floor_fields.get('InterfaceUUID')
            floor_DataRepUuid = floor_fields.get('DataRepUuid')

            floor_LHSByteCount = floor_fields.get('LHSByteCount')

            floor_UUID = floor_InterfaceUUID if floor_InterfaceUUID else floor_DataRepUuid
            floor_UUIDStr = uuid.bin_to_string(floor_UUID)

            floor_Version = float("%s.%s" %
                                  (floor_MajorVersion, floor_MinorVersion))

            if not floor_UUIDStr: continue

            if floor_UUIDStr.upper() in (NDR64_UUID, NDR32_UUID):
                entry_Tower_Floor_Info['NDR_UUID'] = (floor_UUIDStr,
                                                      floor_Version)
            else:
                entry_Tower_Floor_Info['UUID'] = (floor_UUIDStr, floor_Version)

        elif protocol == PROTO_ID_IP:
            floor_fields = floor.fields

            entry_Tower_Floor_Info['IP'] = socket.inet_ntoa(
                floor_fields['RelatedData'])

        elif protocol in (PROTO_ID_NAMED_PIPES, PROTO_ID_NAMED_PIPES_2):

            floor_fields = floor.fields
            named_pipe = floor_fields.get('RelatedData')

            if not named_pipe: continue
            if named_pipe not in entry_Tower_Floor_Info['PIPE']:
                entry_Tower_Floor_Info['PIPE'].append(named_pipe)

        elif protocol == PROTO_ID_NETBIOS:
            floor_fields = floor.fields
            netbios_name = floor_fields.get('RelatedData')

            if not netbios_name: continue
            if netbios_name not in entry_Tower_Floor_Info['NETBIOS']:
                entry_Tower_Floor_Info['NETBIOS'].append(netbios_name)

    entry_UUID = entry_Tower_Floor_Info['UUID']
    if entry_UUID:

        # Add APPLICATION Info into entry_Tower_Floor_Info
        _uuid, _ver = entry_UUID

        key = uuid.uuidtup_to_bin(uuid.string_to_uuidtup(_uuid))[:18]
        application = epm.KNOWN_UUIDS[key] if key in epm.KNOWN_UUIDS else 'N/A'

        entry_Tower_Floor_Info['APPLICATION'] = application

        # Add POTOCOL Info into entry_Tower_Floor_Info
        key = _uuid[:36]
        protocol = epm.KNOWN_PROTOCOLS[
            key] if key in epm.KNOWN_PROTOCOLS else 'N/A'

        entry_Tower_Floor_Info['PROTOCOL'] = protocol

    return entry_Tower_Floor_Info
Esempio n. 31
0
def simplifyPropertyRow(rowSetElem):
    row = {}

    for prop in rowSetElem['lpProps']:
        prop_name_in_union = prop['Value'].structure[0][0]
        prop_value = prop['Value'].fields[prop_name_in_union]

        PropTag = prop['ulPropTag']

        if isinstance(prop_value, SHORT) or \
           isinstance(prop_value, USHORT) or \
           isinstance(prop_value, LONG) or \
           isinstance(prop_value, ULONG):
            row[PropTag] = int(prop_value['Data'])
        elif isinstance(prop_value, LPWSTR):
            if PropTag in [0x8c38001f]:
                # What is this field for?
                row[PropTag] = ExchBinaryObject(
                    prop_value['Data'].encode("utf-16le")[:-2])
            else:
                row[PropTag] = prop_value['Data'][:-1]
        elif isinstance(prop_value, LPSTR):
            row[PropTag] = prop_value['Data'][:-1]
        elif isinstance(prop_value, Binary_r):
            value = b''.join(prop_value['lpb'])

            if PropTag in [0x80270102, 0x8c750102]:
                value = EXCH_SID(value)
            elif PropTag == 0x300b0102:
                value = value[:-1].decode("utf-8")
            elif value[4:20] == GUID_NSPI and value[
                    20:
                    24] == b'\x01\x00\x00\x00' and value[:
                                                         4] == b'\x00\x00\x00\x00':
                value = PermanentEntryID(value)
            elif value[:4] == b'\x87\x00\x00\x00' and value[
                    20:24] == b'\x01\x00\x00\x00' and len(value) == 32:
                value = EphemeralEntryID(value)
            elif PropTag in [0x8c6d0102, 0x68c40102, 0x8c730102, 0x0ff80102]:
                value = uuid.bin_to_string(value).lower()
            elif PropTag == 0x0ff60102:
                value = unpack('<l', value)[0]
            else:
                value = ExchBinaryObject(value)

            row[PropTag] = value
        elif isinstance(prop_value, BinaryArray_r):
            array = []
            for value in prop_value['lpbin']:
                array.append(b''.join(value['lpb']))
            row[PropTag] = array
        elif isinstance(prop_value, StringArray_r):
            array = []
            for value in prop_value['lppszA']:
                array.append(value['Data'][:-1])
            row[PropTag] = array
        elif isinstance(prop_value, WStringArray_r):
            array = []
            for value in prop_value['lppszW']:
                array.append(value['Data'][:-1])
            row[PropTag] = array
        elif isinstance(prop_value, FILETIME):
            row[PropTag] = datetime.fromtimestamp( \
                getUnixTime(unpack('<Q', prop_value.getData())[0]))
        else:
            row[PropTag] = prop_value

    return row
Esempio n. 32
0
 def dump(self):
     print("[CREDHIST]")
     print("Version       : %8x (%d)" % (self['Version'], self['Version']))
     print("Guid          : %s" % bin_to_string(self['Guid']))
     print()
Esempio n. 33
0
def parse_uuid(_uuid):
    return uuid.bin_to_string(_uuid)
Esempio n. 34
0
    def parseRow(self,token,tuplemode=False):
        # TODO: This REALLY needs to be improved. Right now we don't support correctly all the data types
        # help would be appreciated ;) 
        if len(token) == 1:
            return 0

        row = [] if tuplemode else {}

        origDataLen = len(token['Data'])
        data = token['Data']
        for col in self.colMeta:
            _type = col['Type']
            if (_type == TDS_NVARCHARTYPE) |\
               (_type == TDS_NCHARTYPE):
                #print "NVAR 0x%x" % _type
                charLen = struct.unpack('<H',data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                if charLen != 0xFFFF:
                    value = data[:charLen].decode('utf-16le')
                    data = data[charLen:]
                else:
                    value = 'NULL'

            elif (_type == TDS_BIGVARCHRTYPE): 
                charLen = struct.unpack('<H',data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                if charLen != 0xFFFF:
                    value = data[:charLen]
                    data = data[charLen:]
                else:
                    value = 'NULL'

            elif (_type == TDS_GUIDTYPE):
                uuidLen = ord(data[0])
                data = data[1:]
                if uuidLen > 0:
                    uu = data[:uuidLen]
                    value = uuid.bin_to_string(uu)
                    data = data[uuidLen:]
                else:
                    value = 'NULL'
                
            elif (_type == TDS_NTEXTTYPE) |\
                 (_type == TDS_IMAGETYPE) :
                # Skip the pointer data
                charLen = ord(data[0])
                if charLen == 0:
                    value = 'NULL'
                    data = data[1:]
                else:
                    data = data[1+charLen+8:]
                    charLen = struct.unpack('<L',data[:struct.calcsize('<L')])[0]
                    data = data[struct.calcsize('<L'):]
                    if charLen != 0xFFFF:
                        if _type == TDS_NTEXTTYPE:
                            value = data[:charLen].decode('utf-16le')
                        else:
                            value = binascii.b2a_hex(data[:charLen])
                        data = data[charLen:]
                    else:
                        value = 'NULL'
                
            elif (_type == TDS_TEXTTYPE): 
                # Skip the pointer data
                charLen = ord(data[0])
                if charLen == 0:
                    value = 'NULL'
                    data = data[1:]
                else:
                    data = data[1+charLen+8:]
                    charLen = struct.unpack('<L',data[:struct.calcsize('<L')])[0]
                    data = data[struct.calcsize('<L'):]
                    if charLen != 0xFFFF:
                        value = data[:charLen]
                        data = data[charLen:]
                    else:
                        value = 'NULL'

            elif (_type == TDS_BIGVARBINTYPE) |\
                 (_type == TDS_BIGBINARYTYPE):
                charLen = struct.unpack('<H',data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                if charLen != 0xFFFF:
                    value = binascii.b2a_hex(data[:charLen])
                    data = data[charLen:]
                else:
                    value = 'NULL'

            elif (_type == TDS_DATETIM4TYPE) |\
                 (_type == TDS_DATETIMNTYPE) |\
                 (_type == TDS_DATETIMETYPE):
                value = ''    
                if _type == TDS_DATETIMNTYPE:
                    # For DATETIMNTYPE, the only valid lengths are 0x04 and 0x08, which map to smalldatetime and
                    # datetime SQL data types respectively.
                    if ord(data[0]) == 4:
                        _type = TDS_DATETIM4TYPE
                    elif ord(data[0]) == 8:
                        _type = TDS_DATETIMETYPE
                    else:
                        value = 'NULL'
                    data = data[1:]
                if (_type == TDS_DATETIMETYPE):
                    # datetime is represented in the following sequence:
                    # * One 4-byte signed integer that represents the number of days since January 1, 1900. Negative
                    #   numbers are allowed to represents dates since January 1, 1753.
                    # * One 4-byte unsigned integer that represents the number of one three-hundredths of a second
                    #  (300 counts per second) elapsed since 12 AM that day.
                    dateValue = struct.unpack('<l',data[:4])[0]
                    data = data[4:]
                    if dateValue < 0:
                        baseDate = datetime.date(1753,1,1)
                    else:
                        baseDate = datetime.date(1900,1,1)
                    timeValue = struct.unpack('<L',data[:4])[0]
                    data = data[4:] 
                elif (_type == TDS_DATETIM4TYPE):
                    # Small datetime
                    # 2.2.5.5.1.8
                    # Date/Times
                    # smalldatetime is represented in the following sequence:
                    # * One 2-byte unsigned integer that represents the number of days since January 1, 1900.
                    # * One 2-byte unsigned integer that represents the number of minutes elapsed since 12 AM that
                    #   day.
                    dateValue = struct.unpack('<H',data[:struct.calcsize('<H')])[0]
                    data = data[struct.calcsize('<H'):]
                    timeValue = struct.unpack('<H',data[:struct.calcsize('<H')])[0]
                    data = data[struct.calcsize('<H'):]
                    baseDate = datetime.date(1900,1,1)
                if value != 'NULL':
                    dateValue = datetime.date.fromordinal(baseDate.toordinal() + dateValue)
                    hours, mod = divmod(timeValue/300, 60*60)
                    minutes, second = divmod(mod, 60)
                    value = datetime.datetime(dateValue.year, dateValue.month, dateValue.day, hours, minutes, second)

            elif (_type == TDS_INT4TYPE) |\
                 (_type == TDS_MONEY4TYPE) |\
                 (_type == TDS_FLT4TYPE):
                #print "INT4"
                value = struct.unpack('<l',data[:struct.calcsize('<l')])[0]
                data = data[struct.calcsize('<l'):]

            elif (_type == TDS_FLTNTYPE):
                valueSize = ord(data[:1])
                if valueSize == 4:
                    fmt = '<f'
                elif valueSize == 8:
                    fmt = '<d'

                data = data[1:]

                if valueSize > 0:
                    value = struct.unpack(fmt,data[:valueSize])[0]
                    data = data[valueSize:]
                else:
                    value = 'NULL'

            elif _type == TDS_MONEYNTYPE:
                valueSize = ord(data[:1])
                if valueSize == 4:
                    fmt = '<l'
                elif valueSize == 8:
                    fmt = '<q'

                data = data[1:]

                if valueSize > 0:
                    value = struct.unpack(fmt,data[:valueSize])[0]
                    if valueSize == 4:
                        value = float(value) / math.pow(10,4)
                    else:
                        value = float(value >> 32) / math.pow(10,4)
                    data = data[valueSize:]
                else:
                    value = 'NULL'

                
            elif _type == TDS_BIGCHARTYPE:
                #print "BIGC"
                charLen = struct.unpack('<H',data[:struct.calcsize('<H')])[0]
                data = data[struct.calcsize('<H'):]
                value = data[:charLen]
                data = data[charLen:]

            elif (_type == TDS_INT8TYPE) |\
                 (_type == TDS_FLT8TYPE) |\
                 (_type == TDS_MONEYTYPE):
                #print "DATETIME"
                value = struct.unpack('<q',data[:struct.calcsize('<q')])[0]
                data = data[struct.calcsize('<q'):]


            elif (_type == TDS_INT2TYPE):
                #print "INT2TYPE"
                value = struct.unpack('<H',(data[:2]))[0]
                data = data[2:]

            elif (_type == TDS_DATENTYPE):
                # date is represented as one 3-byte unsigned integer that represents the number of days since
                # January 1, year 1.
                valueSize = ord(data[:1])
                data = data[1:]
                if valueSize > 0:
                    dateBytes = data[:valueSize]
                    dateValue = struct.unpack('<L','\x00'+dateBytes)[0]
                    value = datetime.date.fromtimestamp(dateValue)
                    data = data[valueSize:]
                else:
                    value = 'NULL'

            elif (_type == TDS_BITTYPE) |\
                 (_type == TDS_INT1TYPE):
                #print "BITTYPE"
                value = ord(data[:1])
                data = data[1:]

            elif (_type == TDS_NUMERICNTYPE) |\
                 (_type == TDS_DECIMALNTYPE):
                valueLen = ord(data[:1])
                data = data[1:]
                value = data[:valueLen]
                data = data[valueLen:]
                precision = ord(col['TypeData'][1])
                scale = ord(col['TypeData'][2])
                if valueLen > 0:
                    isPositiveSign = ord(value[0])
                    if (valueLen-1) == 2:
                        fmt = '<H'
                    elif (valueLen-1) == 4:
                        fmt = '<L'
                    elif (valueLen-1) == 8:
                        fmt = '<Q'
                    else:
                        # Still don't know how to handle higher values
                        value = "TODO: Interpret TDS_NUMERICNTYPE correctly"
                    number = struct.unpack(fmt, value[1:])[0]
                    number /= math.pow(precision, scale)
                    if isPositiveSign == 0:
                        number *= -1 
                    value = number
                else:
                    value = 'NULL'

            elif (_type == TDS_BITNTYPE):
                #print "BITNTYPE"
                valueSize = ord(data[:1])
                data = data[1:]
                if valueSize > 0:
                    if valueSize == 1:
                        value = ord(data[:valueSize])
                    else:
                        value = data[:valueSize]
                else:
                    value = 'NULL'
                data = data[valueSize:]

            elif (_type == TDS_INTNTYPE):
                valueSize = ord(data[:1])
                if valueSize == 1:
                    fmt = '<B'
                elif valueSize == 2:
                    fmt = '<h'
                elif valueSize == 4:
                    fmt = '<l'
                elif valueSize == 8:
                    fmt = '<q'
                else:
                    fmt = ''

                data = data[1:]

                if valueSize > 0:
                    value = struct.unpack(fmt,data[:valueSize])[0]
                    data = data[valueSize:]
                else:
                    value = 'NULL'
            elif (_type == TDS_SSVARIANTTYPE):
                print "ParseRow: SQL Variant type not yet supported :("
                raise
            else:
                print "ParseROW: Unsupported data type: 0%x" % _type
                raise

            if tuplemode:
                row.append(value)
            else:
                row[col['Name']] = value


        self.rows.append(row)

        return (origDataLen - len(data))
Esempio n. 35
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf= MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(decryptedKey)
                    key = domain_master_key['buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1'))
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug("Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % hexlify(backupkey))
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug("Exporting certificate to file {}".format(name + ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug("Exporting private key to file {}".format(name + ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey)))
                        print("\n")
            return


        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print('You must specify either -vcrd or -vpol parameter. Type --help for more info')
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(attribute['IV']) == 16:
                                cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode('utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[blob['FriendlyName'].decode('utf-16le')[:-1]](cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
Esempio n. 36
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf = MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security and self.options.sid is None:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.system and self.options.security:
                # Use SID + hash
                # We have hives, let's try to decrypt with them
                self.getLSA()
                key1, key2 = self.deriveKeysFromUserkey(
                    self.options.sid, self.dpapiSystem['UserKey'])
                decryptedKey = mk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted Backup key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted Backup key with UserKey + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key and self.options.sid:
                key = unhexlify(self.options.key[2:])
                key1, key2 = self.deriveKeysFromUserkey(self.options.sid, key)
                decryptedKey = mk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted key with key provided + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted key with key provided + SID')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(
                        decryptedKey)
                    key = domain_master_key[
                        'buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' %
                          hexlify(key).decode('latin-1'))
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug(
                            "Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % hexlify(backupkey).decode('latin-1'))
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][
                        backup_key['KeyLength']:backup_key['KeyLength'] +
                        backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug(
                            "Exporting certificate to file {}".format(name +
                                                                      ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug(
                            "Exporting private key to file {}".format(name +
                                                                      ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" %
                              (hexlify(backupkey).decode('latin-1')))
                        print("\n")
            return

        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print(
                    'You must specify either -vcrd or -vpol parameter. Type --help for more info'
                )
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(
                                    attribute['IV']) == 16:
                                cipher = AES.new(key,
                                                 AES.MODE_CBC,
                                                 iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode(
                                'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[
                                blob['FriendlyName'].decode('utf-16le')[:-1]](
                                    cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return
        elif self.options.action.upper() == 'UNPROTECT':
            fp = open(options.file, 'rb')
            data = fp.read()
            blob = DPAPI_BLOB(data)

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                if self.options.entropy_file is not None:
                    fp2 = open(self.options.entropy_file, 'rb')
                    entropy = fp2.read()
                    fp2.close()
                elif self.options.entropy is not None:
                    entropy = b(self.options.entropy)
                else:
                    entropy = None

                decrypted = blob.decrypt(key, entropy)
                if decrypted is not None:
                    print('Successfully decrypted data')
                    hexdump(decrypted)
                    return
            else:
                # Just print the data
                blob.dump()

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
Esempio n. 37
0
def can_create_users(ace):
    createprivs = ace['Ace']['Mask'].hasPriv(ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_CREATE_CHILD)
    if ace['AceType'] != ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE or ace['Ace']['ObjectType'] == '':
        return False
    userprivs = bin_to_string(ace['Ace']['ObjectType']).lower() == 'bf967aba-0de6-11d0-a285-00aa003049e2'
    return createprivs and userprivs
Esempio n. 38
0
    def checkSecurityDescriptors(self, entries, privs, membersids, sidmapping,
                                 domainDumper):
        standardrights = [
            self.GENERIC_ALL, self.GENERIC_WRITE, self.GENERIC_READ,
            ACCESS_MASK.WRITE_DACL
        ]
        for entry in entries:
            if entry['type'] != 'searchResEntry':
                continue
            dn = entry['dn']
            try:
                sdData = entry['raw_attributes']['nTSecurityDescriptor'][0]
            except IndexError:
                # We don't have the privileges to read this security descriptor
                LOG.debug('Access to security descriptor was denied for DN %s',
                          dn)
                continue
            hasFullControl = False
            secDesc = ldaptypes.SR_SECURITY_DESCRIPTOR()
            secDesc.fromString(sdData)
            if secDesc['OwnerSid'] != '' and secDesc[
                    'OwnerSid'].formatCanonical() in membersids:
                sid = secDesc['OwnerSid'].formatCanonical()
                LOG.debug(
                    'Permission found: Full Control on %s; Reason: Owner via %s'
                    % (dn, sidmapping[sid]))
                hasFullControl = True
            # Iterate over all the ACEs
            for ace in secDesc['Dacl'].aces:
                sid = ace['Ace']['Sid'].formatCanonical()
                if ace['AceType'] != ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE and ace[
                        'AceType'] != ACCESS_ALLOWED_ACE.ACE_TYPE:
                    continue
                if not ace.hasFlag(ACE.INHERITED_ACE) and ace.hasFlag(
                        ACE.INHERIT_ONLY_ACE):
                    # ACE is set on this object, but only inherited, so not applicable to us
                    continue

                # Check if the ACE has restrictions on object type (inherited case)
                if ace['AceType'] == ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE \
                    and ace.hasFlag(ACE.INHERITED_ACE) \
                    and ace['Ace'].hasFlag(ACCESS_ALLOWED_OBJECT_ACE.ACE_INHERITED_OBJECT_TYPE_PRESENT):
                    # Verify if the ACE applies to this object type
                    inheritedObjectType = bin_to_string(
                        ace['Ace']['InheritedObjectType']).lower()
                    if not self.aceApplies(
                            inheritedObjectType,
                            entry['raw_attributes']['objectClass'][-1]):
                        continue
                # Check for non-extended rights that may not apply to us
                if ace['Ace']['Mask']['Mask'] in standardrights or ace['Ace'][
                        'Mask'].hasPriv(ACCESS_MASK.WRITE_DACL):
                    # Check if this applies to our objecttype
                    if ace['AceType'] == ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE and ace[
                            'Ace'].hasFlag(ACCESS_ALLOWED_OBJECT_ACE.
                                           ACE_OBJECT_TYPE_PRESENT):
                        objectType = bin_to_string(
                            ace['Ace']['ObjectType']).lower()
                        if not self.aceApplies(
                                objectType,
                                entry['raw_attributes']['objectClass'][-1]):
                            # LOG.debug('ACE does not apply, only to %s', objectType)
                            continue
                if sid in membersids:
                    # Generic all
                    if ace['Ace']['Mask'].hasPriv(self.GENERIC_ALL):
                        ace.dump()
                        LOG.debug(
                            'Permission found: Full Control on %s; Reason: GENERIC_ALL via %s'
                            % (dn, sidmapping[sid]))
                        hasFullControl = True
                    if can_create_users(ace) or hasFullControl:
                        if not hasFullControl:
                            LOG.debug(
                                'Permission found: Create users in %s; Reason: Granted to %s'
                                % (dn, sidmapping[sid]))
                        if dn == 'CN=Users,%s' % domainDumper.root:
                            # We can create users in the default container, this is preferred
                            privs['create'] = True
                            privs['createIn'] = dn
                        else:
                            # Could be a different OU where we have access
                            # store it until we find a better place
                            if privs[
                                    'createIn'] != 'CN=Users,%s' % domainDumper.root and b'organizationalUnit' in entry[
                                        'raw_attributes']['objectClass']:
                                privs['create'] = True
                                privs['createIn'] = dn
                    if can_add_member(ace) or hasFullControl:
                        if b'group' in entry['raw_attributes']['objectClass']:
                            # We can add members to a group
                            if not hasFullControl:
                                LOG.debug(
                                    'Permission found: Add member to %s; Reason: Granted to %s'
                                    % (dn, sidmapping[sid]))
                            privs['escalateViaGroup'] = True
                            privs['escalateGroup'] = dn
                    if ace['Ace']['Mask'].hasPriv(
                            ACCESS_MASK.WRITE_DACL) or hasFullControl:
                        # Check if the ACE is an OBJECT ACE, if so the WRITE_DACL is applied to
                        # a property, which is both weird and useless, so we skip it
                        if ace['AceType'] == ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE \
                            and ace['Ace'].hasFlag(ACCESS_ALLOWED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT):
                            # LOG.debug('Skipping WRITE_DACL since it has an ObjectType set')
                            continue
                        if not hasFullControl:
                            LOG.debug(
                                'Permission found: Write Dacl of %s; Reason: Granted to %s'
                                % (dn, sidmapping[sid]))
                        # We can modify the domain Dacl
                        if b'domain' in entry['raw_attributes']['objectClass']:
                            privs['aclEscalate'] = True
                            privs['aclEscalateIn'] = dn
Esempio n. 39
0
def can_add_member(ace):
    writeprivs = ace['Ace']['Mask'].hasPriv(ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_WRITE_PROP)
    if ace['AceType'] != ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE or ace['Ace']['ObjectType'] == '':
        return writeprivs
    userprivs = bin_to_string(ace['Ace']['ObjectType']).lower() == 'bf9679c0-0de6-11d0-a285-00aa003049e2'
    return writeprivs and userprivs
Esempio n. 40
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf= MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(decryptedKey)
                    key = domain_master_key['buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1'))
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce,
                                              resp['PolicyHandle'], name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug("Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % hexlify(backupkey).decode('latin-1'))
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug("Exporting certificate to file {}".format(name + ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug("Exporting private key to file {}".format(name + ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey).decode('latin-1')))
                        print("\n")
            return


        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print('You must specify either -vcrd or -vpol parameter. Type --help for more info')
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(attribute['IV']) == 16:
                                cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode('utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[blob['FriendlyName'].decode('utf-16le')[:-1]](cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
Esempio n. 41
0
    def print_htable(self, parent_guid=None):
        MIds_print = []

        for MId in self.htable:
            if parent_guid == None and 'parent_guid' not in self.htable[MId]:
                MIds_print.append(MId)
            elif parent_guid != None and 'parent_guid' in self.htable[MId] and self.htable[MId]['parent_guid'] == parent_guid:
                MIds_print.append(MId)

        for MId in MIds_print:
            ab = self.htable[MId]
            ab['printed'] = True
            indent = '    ' * ab['depth']

            # Table name
            print("%s%s" % (indent, ab['name']))

            # Count
            if 'count' in ab:
                print("%sTotalRecs: %d" % (indent, ab['count']))

            # Table params
            if MId != 0:
                guid = uuid.bin_to_string(ab['guid']).lower()
                print("%sGuid: %s" % (indent, guid))
            else:
                print("%sGuid: None" % indent)

            if ab['is_master'] != 0:
                print("%sPR_EMS_AB_IS_MASTER attribute is set!" % indent)

            if self._extended_output:
                dword = NSPIAttacks._int_to_dword(MId)
                print("%sAssigned MId: 0x%.08X (%d)" % (indent, dword, MId))

                if 'start_mid' in ab:
                    dword = NSPIAttacks._int_to_dword(ab['start_mid'])
                    if dword == 2:
                        print("%sAssigned first record MId: 0x00000002 (MID_END_OF_TABLE)" % indent)
                    else:
                        print("%sAssigned first record MId: 0x%.08X (%d)" % (indent, dword, ab['start_mid']))

                flags = parse_bitmask(PR_CONTAINER_FLAGS_VALUES, ab['flags'])
                print("%sFlags: %s" % (indent, flags))

            print()

            if MId != 0:
                self.print_htable(parent_guid=ab['guid'])

        if parent_guid == None:
            for MId in self.htable:
                if self.htable[MId]['printed'] == False:
                    print("Found parentless object!")
                    print("Name: %s" % self.htable[MId]['name'])
                    print("Guid: %s" % uuid.bin_to_string(self.htable[MId]['guid']).lower())
                    print("Parent guid: %s" % uuid.bin_to_string(self.htable[MId]['parent_guid']).lower())
                    dword = NSPIAttacks._int_to_dword(MId) if MId < 0 else MId
                    print("Assigned MId: 0x%.08X (%d)" % (dword, MId))
                    flags = parse_bitmask(PR_CONTAINER_FLAGS_VALUES, self.htable[MId]['flags'])
                    print("Flags: %s" % flags)
                    if self.htable[MId]['is_master'] != 0:
                        print("%sPR_EMS_AB_IS_MASTER attribute is set!" % indent)
                    print()