def from_buffer(buff, object_type=None): sd = SECURITY_DESCRIPTOR(object_type) sd.Revision = int.from_bytes(buff.read(1), 'little', signed=False) sd.Sbz1 = int.from_bytes(buff.read(1), 'little', signed=False) sd.Control = SE_SACL( int.from_bytes(buff.read(2), 'little', signed=False)) OffsetOwner = int.from_bytes(buff.read(4), 'little', signed=False) OffsetGroup = int.from_bytes(buff.read(4), 'little', signed=False) OffsetSacl = int.from_bytes(buff.read(4), 'little', signed=False) OffsetDacl = int.from_bytes(buff.read(4), 'little', signed=False) if OffsetOwner > 0: buff.seek(OffsetOwner) sd.Owner = SID.from_buffer(buff) if OffsetGroup > 0: buff.seek(OffsetGroup) sd.Group = SID.from_buffer(buff) if OffsetSacl > 0: buff.seek(OffsetSacl) sd.Sacl = ACL.from_buffer(buff, object_type) if OffsetDacl > 0: buff.seek(OffsetDacl) sd.Dacl = ACL.from_buffer(buff, object_type) return sd
async def add_priv_dcsync(self, user_dn, forest_dn=None): """Adds DCSync rights to the given user by modifying the forest's Security Descriptor to add GetChanges and GetChangesAll ACE""" try: #getting SID of target dn user_sid, err = await self.get_objectsid_for_dn(user_dn) if err is not None: raise err if forest_dn is None: forest_dn = self._ldapinfo.distinguishedName res, err = await self.get_objectacl_by_dn(forest_dn) if err is not None: raise err if res is None: raise Exception('Failed to get forest\'s SD') forest_sd = SECURITY_DESCRIPTOR.from_bytes(res) new_sd = copy.deepcopy(forest_sd) ace_1 = ACCESS_ALLOWED_OBJECT_ACE() ace_1.Sid = SID.from_string(user_sid) ace_1.ObjectType = GUID.from_string( '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2') ace_1.Mask = ADS_ACCESS_MASK.CONTROL_ACCESS ace_1.AceFlags = 0 new_sd.Dacl.aces.append(ace_1) ace_2 = ACCESS_ALLOWED_OBJECT_ACE() ace_2.Sid = SID.from_string(user_sid) ace_2.ObjectType = GUID.from_string( '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2') ace_2.Mask = ADS_ACCESS_MASK.CONTROL_ACCESS ace_2.AceFlags = 0 new_sd.Dacl.aces.append(ace_2) changes = { 'nTSecurityDescriptor': [('replace', [new_sd.to_bytes()])] } _, err = await self.modify(forest_dn, changes) if err is not None: raise err return True, None except Exception as e: return False, e
def LookupAccountNameW(lpSystemName, accountname): _LookupAccountNameW = windll.advapi32.LookupAccountNameW _LookupAccountNameW.argtypes = [ LPWSTR, LPWSTR, PSID, LPDWORD, LPWSTR, LPDWORD, LPDWORD ] _LookupAccountNameW.restype = BOOL cbSid = DWORD(0) cchReferencedDomainName = DWORD(0) peUse = DWORD(0) lpAccountName = ctypes.create_unicode_buffer(accountname) _LookupAccountNameW(lpSystemName, lpAccountName, None, byref(cbSid), None, byref(cchReferencedDomainName), byref(peUse)) error = GetLastError() if error != ERROR_INSUFFICIENT_BUFFER: raise (ctypes.WinError(error)) sid = ctypes.create_string_buffer(b'', cbSid.value) psid = ctypes.cast(ctypes.pointer(sid), PSID) lpReferencedDomainName = ctypes.create_unicode_buffer( u'', cchReferencedDomainName.value + 1) success = _LookupAccountNameW(lpSystemName, lpAccountName, psid, byref(cbSid), lpReferencedDomainName, byref(cchReferencedDomainName), byref(peUse)) if not success: raise ctypes.WinError() buff = MemoryBuffer(psid.value) sid = SID.from_buffer(buff) #LocalFree(psid) return sid, lpReferencedDomainName.value, peUse.value
def from_ldap(entry): adi = MSADDomainTrust() adi.sn = entry['attributes'].get('sn') adi.cn = entry['attributes'].get('cn') adi.distinguishedName = entry['attributes'].get('distinguishedName') adi.objectGUID = entry['attributes'].get('objectGUID') adi.instanceType = entry['attributes'].get('instanceType') adi.whenCreated = entry['attributes'].get('whenCreated') adi.whenChanged = entry['attributes'].get('whenChanged') adi.name = entry['attributes'].get('name') adi.securityIdentifier = entry['attributes'].get('securityIdentifier') adi.trustDirection = entry['attributes'].get('trustDirection') adi.trustPartner = entry['attributes'].get('trustPartner') adi.trustPosixOffset = entry['attributes'].get('trustPosixOffset') adi.trustType = entry['attributes'].get('trustType') adi.trustAttributes = entry['attributes'].get('trustAttributes') adi.flatName = entry['attributes'].get('flatName') adi.dSCorePropagationData = entry['attributes'].get( 'dSCorePropagationData') if adi.securityIdentifier is not None: adi.securityIdentifier = SID.from_bytes(adi.securityIdentifier) if adi.trustType is not None: adi.trustType = TrustType(adi.trustType) if adi.trustDirection is not None: adi.trustDirection = TrustDirection(adi.trustDirection) return adi
def from_ldap(entry): t = MSADTokenGroup() t.cn = entry['attributes'].get('cn') t.distinguishedName = entry['attributes'].get('distinguishedName') t.objectGUID = entry['attributes'].get('objectGUID') t.objectSid = entry['attributes'].get('objectSid') for sid_data in entry['attributes']['tokenGroups']: t.tokengroups.append(SID.from_bytes(sid_data)) return t
async def do_changeowner(self, new_owner_sid, target_dn, target_attribute=None): """Changes the owner in a Security Descriptor to the new_owner_sid on an LDAP object or on an LDAP object's attribute identified by target_dn and target_attribute. target_attribute can be omitted to change the target_dn's SD's owner""" try: await self.do_ldapinfo(False) await self.do_adinfo(False) try: new_owner_sid = SID.from_string(new_owner_sid) except: print('Incorrect SID!') return False, Exception('Incorrect SID') target_sd = None if target_attribute is None or target_attribute == '': target_attribute = 'nTSecurityDescriptor' res, err = await self.connection.get_objectacl_by_dn(target_dn) if err is not None: raise err target_sd = SECURITY_DESCRIPTOR.from_bytes(res) else: query = '(distinguishedName=%s)' % target_dn async for entry, err in self.connection.pagedsearch( query, [target_attribute]): if err is not None: raise err print(entry['attributes'][target_attribute]) target_sd = SECURITY_DESCRIPTOR.from_bytes( entry['attributes'][target_attribute]) break else: print('Target DN not found!') return False, Exception('Target DN not found!') new_sd = copy.deepcopy(target_sd) new_sd.Owner = new_owner_sid changes = {target_attribute: [('replace', [new_sd.to_bytes()])]} _, err = await self.connection.modify(target_dn, changes) if err is not None: raise err print('Change OK!') except: traceback.print_exc()
def ConvertStringSidToSidW(sid_str): _ConvertStringSidToSidW = windll.advapi32.ConvertStringSidToSidW _ConvertStringSidToSidW.argtypes = [ PVOID, PVOID ] #[HANDLE, SE_OBJECT_TYPE, DWORD, PSID, PSID, PACL, PACL, PSECURITY_DESCRIPTOR] _ConvertStringSidToSidW.restype = DWORD _ConvertStringSidToSidW.errcheck = RaiseIfZero cstr_sid = ctypes.create_string_buffer(sid_str.encode('utf-16-le')) ppSecurityDescriptor = ctypes.pointer(ctypes.c_uint(0)) _ConvertStringSidToSidW(cstr_sid, byref(ppSecurityDescriptor)) buff = MemoryBuffer(ctypes.addressof(ppSecurityDescriptor.contents)) sd = SID.from_buffer(buff) LocalFree(ppSecurityDescriptor) return sd
async def do_addenrollmentright(self, certtemplatename, user_dn): """Grants enrollment rights to a user (by DN) for the specified certificate template.""" try: user_sid, err = await self.connection.get_objectsid_for_dn(user_dn) if err is not None: raise err template = None async for template, err in self.connection.list_certificate_templates( certtemplatename): if err is not None: raise err break if template is None: raise Exception("Template could not be found!") template = typing.cast(MSADCertificateTemplate, template) new_sd = copy.deepcopy(template.nTSecurityDescriptor) ace = ACCESS_ALLOWED_OBJECT_ACE() ace.Sid = SID.from_string(user_sid) ace.ObjectType = GUID.from_string(EX_RIGHT_CERTIFICATE_ENROLLMENT) ace.AceFlags = AceFlags(0) ace.Mask = ADS_ACCESS_MASK.READ_PROP | ADS_ACCESS_MASK.WRITE_PROP | ADS_ACCESS_MASK.CONTROL_ACCESS ace.Flags = ACE_OBJECT_PRESENCE.ACE_OBJECT_TYPE_PRESENT new_sd.Dacl.aces.append(ace) _, err = await self.connection.set_objectacl_by_dn( template.distinguishedName, new_sd.to_bytes(), flags=SDFlagsRequest.DACL_SECURITY_INFORMATION) if err is not None: raise err print('SD set sucessfully') return True except: traceback.print_exc() return False
async def add_priv_addmember(self, user_dn, group_dn): """Adds AddMember rights to the user on the group specified by group_dn""" try: #getting SID of target dn user_sid, err = await self.get_objectsid_for_dn(user_dn) if err is not None: raise err res, err = await self.get_objectacl_by_dn(group_dn) if err is not None: raise err if res is None: raise Exception('Failed to get forest\'s SD') group_sd = SECURITY_DESCRIPTOR.from_bytes(res) new_sd = copy.deepcopy(group_sd) ace_1 = ACCESS_ALLOWED_OBJECT_ACE() ace_1.Sid = SID.from_string(user_sid) ace_1.ObjectType = GUID.from_string( 'bf9679c0-0de6-11d0-a285-00aa003049e2') ace_1.Mask = ADS_ACCESS_MASK.WRITE_PROP ace_1.AceFlags = 0 new_sd.Dacl.aces.append(ace_1) changes = { 'nTSecurityDescriptor': [('replace', [new_sd.to_bytes()])] } _, err = await self.modify(group_dn, changes) if err is not None: raise err return True, None except Exception as e: return False, e
def list_x2sid(x): t = [] for s in x: t.append(str(SID.from_bytes(s))) return t
def x2sid(x): return str(SID.from_bytes(x[0]))
def from_sddl(sddl: str, object_type=None, domain_sid=None): sd = SECURITY_DESCRIPTOR(object_type=object_type) params = sddl.split(':') np = [params[0]] i = 1 while i < len(params): np.append(params[i][:-1]) np.append(params[i][-1]) i += 1 params = {} i = 0 while i < len(np): if np[i] == ')': break params[np[i]] = np[i + 1] i += 2 sd.Control = SE_SACL.SE_SELF_RELATIVE fk = None if 'D' in params: fk = 'D' elif 'S' in params: fk = 'S' if fk is not None: if '(' in params[fk]: flags, acl = params[fk].split('(', 1) else: flags = params[fk] if flags.upper().find('P') != -1: sd.Control |= SE_SACL.SE_DACL_PROTECTED sd.Control |= SE_SACL.SE_SACL_PROTECTED flags = flags.replace('P', '') for _ in range(len(flags)): x = flags[:2] cf = sddl_acl_control_flags[x] if cf == SE_SACL.SE_DACL_AUTO_INHERIT_REQ: sd.Control |= SE_SACL.SE_DACL_AUTO_INHERIT_REQ sd.Control |= SE_SACL.SE_SACL_AUTO_INHERIT_REQ elif cf == SE_SACL.SE_DACL_AUTO_INHERITED: sd.Control |= SE_SACL.SE_DACL_AUTO_INHERITED sd.Control |= SE_SACL.SE_SACL_AUTO_INHERITED else: sd.Control |= cf flags = flags[2:] if flags == '': break if 'O' in params: sd.Owner = SID.from_sddl(params['O'], domain_sid=domain_sid) if 'G' in params: sd.Group = SID.from_sddl(params['G'], domain_sid=domain_sid) if 'D' in params: sd.Control |= SE_SACL.SE_DACL_PRESENT acl = params['D'] m = acl.find('(') if m != -1: sd.Dacl = ACL.from_sddl(acl[m:], object_type=object_type, domain_sid=domain_sid) if 'S' in params: sd.Control |= SE_SACL.SE_SACL_PRESENT acl = params['S'] m = acl.find('(') if m != -1: sd.Sacl = ACL.from_sddl(acl[m:], object_type=object_type, domain_sid=domain_sid) return sd
def get_user_for_sid(sid_str): sid = SID.from_string(sid_str) username, domain, use = LookupAccountSidW(None, sid.to_bytes()) return '%s\\%s' % (domain, username)