/// <summary> /// Serializes to byte array. /// @return serialized ACL. /// </summary> public byte[] ToByteArray() { int size = this.GetSize(); using var ms = new MemoryStream(size); var buff = new BinaryWriter(ms); // add revision buff.Write((byte)this.revision); // add reserved buff.Write((byte)0x00); // add size (2 bytes reversed) byte[] sizeSrc = NumberFacility.GetBytes(size); buff.Write(sizeSrc[3]); buff.Write(sizeSrc[2]); // add ace count (2 bytes reversed) byte[] aceCountSrc = NumberFacility.GetBytes(this.GetAceCount()); buff.Write(aceCountSrc[3]); buff.Write(aceCountSrc[2]); // add reserved (2 bytes) buff.Write((byte)0x00); buff.Write((byte)0x00); // add aces foreach (Ace ace in this.aces) { buff.Write(ace.ToByteArray()); } return(ms.ToArray()); }
/// <summary> /// Serializes to byte array. /// @return serialized ACE. /// </summary> public byte[] ToByteArray() { int size = this.GetSize(); using var ms = new MemoryStream(size); var buff = new BinaryWriter(ms); // Add type byte buff.Write((byte)this.type); // add flags byte byte flagSrc = this.GetFlags().Aggregate <AceFlag, byte>(0x00, (current, flag) => (byte)(current | (byte)flag)); buff.Write(flagSrc); // add size bytes (2 reversed) byte[] sizeSrc = NumberFacility.GetBytes(size); buff.Write(sizeSrc[3]); buff.Write(sizeSrc[2]); // add right mask buff.Write(Hex.Reverse(NumberFacility.GetUIntBytes(this.rights.AsUInt()))); // add object flags (from int to byte[] + reversed) if (this.objectFlags != null) { buff.Write(Hex.Reverse(NumberFacility.GetUIntBytes(this.objectFlags.AsUInt()))); } // add object type if (this.objectType != null) { buff.Write(this.objectType.Value.ToByteArray()); } // add inherited object type if (this.inheritedObjectType != null) { buff.Write(this.inheritedObjectType.Value.ToByteArray()); } // add sid buff.Write(this.sid.ToByteArray()); // add application data if (this.applicationData != null) { buff.Write(this.applicationData); } return(ms.ToArray()); }
/// <summary> /// Load the ACL from the buffer returning the last ACL segment position into the buffer. /// @param buff source buffer. /// @param start start loading position. /// @return last loading position. /// </summary> public void Parse(BinaryReader buff, long start) { buff.BaseStream.Seek(start, SeekOrigin.Begin); // read for Dacl byte[] bytes = NumberFacility.GetBytes(buff.ReadInt32()); this.revision = AclRevisionExtension.ParseValue(bytes[0]); bytes = NumberFacility.GetBytes(buff.ReadInt32()); int aceCount = NumberFacility.GetInt(bytes[1], bytes[0]); for (var i = 0; i < aceCount; i++) { Ace ace = new Ace(); this.aces.Add(ace); ace.Parse(buff); } }
/// <summary> /// Load the ACE from the buffer returning the last ACE segment position into the buffer. /// @param buff source buffer. /// @param start start loading position. /// @return last loading position. /// </summary> public void Parse(BinaryReader buff) { var start = buff.BaseStream.Position; byte[] bytes = NumberFacility.GetBytes(buff.ReadInt32()); this.type = AceTypeExtension.ParseValue(bytes[0]); this.flags = AceFlagExtension.ParseValue(bytes[1]); int size = NumberFacility.GetInt(bytes[3], bytes[2]); this.rights = AceRights.ParseValue(NumberFacility.GetReverseInt(buff.ReadInt32())); if (this.type == AceType.AccessAllowedObjectAceType || this.type == AceType.AccessDeniedObjectAceType) { this.objectFlags = AceObjectFlags.ParseValue(NumberFacility.GetReverseInt(buff.ReadInt32())); if (this.objectFlags.GetFlags().Contains(AceObjectFlags.Flag.AceObjectTypePresent)) { this.objectType = new Guid(buff.ReadBytes(16)); } if (this.objectFlags.GetFlags().Contains(AceObjectFlags.Flag.AceInheritedObjectTypePresent)) { this.inheritedObjectType = new Guid(buff.ReadBytes(16)); } } this.sid = new SID(); this.sid.Parse(buff); if (size > 0) { var lastPos = start + size; this.applicationData = new byte[lastPos - buff.BaseStream.Position]; for (var i = 0; i < applicationData.Length; i++) { this.applicationData[i] = buff.ReadByte(); } } }
/// <summary> /// Serializes SDDL as byte array. /// @return SDL as byte array. /// </summary> public byte[] ToByteArray() { using var ms = new MemoryStream(this.GetSize()); var buff = new BinaryWriter(ms); // add revision buff.Write(this.revision); // add reserved buff.Write((byte)0x00); // add contro flags buff.Write(this.controlFlags[1]); buff.Write(this.controlFlags[0]); // add offset owner buff.Seek(4, SeekOrigin.Begin); var nextAvailablePosition = 20; // add owner SID if (this.owner == null) { buff.Write(0); } else { buff.Write(Hex.Reverse(NumberFacility.GetBytes(nextAvailablePosition))); buff.Seek(nextAvailablePosition, SeekOrigin.Begin); buff.Write(this.owner.ToByteArray()); nextAvailablePosition += this.owner.GetSize(); } // add offset group buff.Seek(8, SeekOrigin.Begin); // add group SID if (this.group == null) { buff.Write(0); } else { buff.Write(Hex.Reverse(NumberFacility.GetBytes(nextAvailablePosition))); buff.Seek(nextAvailablePosition, SeekOrigin.Begin); buff.Write(this.group.ToByteArray()); nextAvailablePosition += this.group.GetSize(); } // add offset sacl buff.Seek(12, SeekOrigin.Begin); // add SACL if (this.sacl == null) { buff.Write(0); } else { buff.Write(Hex.Reverse(NumberFacility.GetBytes(nextAvailablePosition))); buff.Seek(nextAvailablePosition, SeekOrigin.Begin); buff.Write(this.sacl.ToByteArray()); nextAvailablePosition += this.sacl.GetSize(); } // add offset dacl buff.Seek(16, SeekOrigin.Begin); // add DACL if (this.dacl == null) { buff.Write(0); } else { buff.Write(Hex.Reverse(NumberFacility.GetBytes(nextAvailablePosition))); buff.Seek(nextAvailablePosition, SeekOrigin.Begin); buff.Write(this.dacl.ToByteArray()); } return(ms.ToArray()); }
/// <summary> /// Load the SDDL from the buffer returning the last SDDL segment position into the buffer. /// @param buff source buffer. /// @param start start loading position. /// @return last loading position. /// </summary> private void Parse(BinaryReader buff, long start) { // Revision (1 byte): An unsigned 8-bit value that specifies the revision of the SECURITY_DESCRIPTOR // structure. This field MUST be set to one. buff.BaseStream.Seek(start, SeekOrigin.Begin); byte[] header = NumberFacility.GetBytes(buff.ReadInt32()); this.revision = header[0]; // Control (2 bytes): An unsigned 16-bit field that specifies control access bit flags. The Self Relative // (SR) bit MUST be set when the security descriptor is in self-relative format. this.controlFlags = new[] { header[3], header[2] }; bool[] controlFlag = NumberFacility.GetBits(this.controlFlags); // OffsetOwner (4 bytes): An unsigned 32-bit integer that specifies the offset to the SID. This SID // specifies the owner of the object to which the security descriptor is associated. This must be a valid // offset if the OD flag is not set. If this field is set to zero, the OwnerSid field MUST not be present. var offsetOwnerValue = buff.ReadInt32(); if (!controlFlag[15]) { this.offsetOwner = NumberFacility.GetReverseUInt(offsetOwnerValue); } else { this.offsetOwner = 0; } // OffsetGroup (4 bytes): An unsigned 32-bit integer that specifies the offset to the SID. This SID // specifies the group of the object to which the security descriptor is associated. This must be a valid // offset if the GD flag is not set. If this field is set to zero, the GroupSid field MUST not be present. var offsetGroupValue = buff.ReadInt32(); if (!controlFlag[14]) { this.offsetGroup = NumberFacility.GetReverseUInt(offsetGroupValue); } else { this.offsetGroup = 0; } // OffsetSacl (4 bytes): An unsigned 32-bit integer that specifies the offset to the ACL that contains // system ACEs. Typically, the system ACL contains auditing ACEs (such as SYSTEM_AUDIT_ACE, // SYSTEM_AUDIT_CALLBACK_ACE, or SYSTEM_AUDIT_CALLBACK_OBJECT_ACE), and at most one Label ACE (as specified // in section 2.4.4.13). This must be a valid offset if the SP flag is set; if the SP flag is not set, this // field MUST be set to zero. If this field is set to zero, the Sacl field MUST not be present. var offsetSaclValue = buff.ReadInt32(); if (controlFlag[11]) { this.offsetSacl = NumberFacility.GetReverseUInt(offsetSaclValue); } else { this.offsetSacl = 0; } // OffsetDacl (4 bytes): An unsigned 32-bit integer that specifies the offset to the ACL that contains ACEs // that control access. Typically, the DACL contains ACEs that grant or deny access to principals or groups. // This must be a valid offset if the DP flag is set; if the DP flag is not set, this field MUST be set to // zero. If this field is set to zero, the Dacl field MUST not be present. var offsetDaclValue = buff.ReadInt32(); if (controlFlag[13]) { this.offsetDacl = NumberFacility.GetReverseUInt(offsetDaclValue); } else { this.offsetDacl = 0; } // OwnerSid (variable): The SID of the owner of the object. The length of the SID MUST be a multiple of 4. // This field MUST be present if the OffsetOwner field is not zero. if (this.offsetOwner > 0) { // read for OwnerSid this.owner = new SID(); this.owner.Parse(buff, this.offsetOwner); } // GroupSid (variable): The SID of the group of the object. The length of the SID MUST be a multiple of 4. // This field MUST be present if the GroupOwner field is not zero. if (this.offsetGroup > 0) { // read for GroupSid this.group = new SID(); this.group.Parse(buff, this.offsetGroup); } // Sacl (variable): The SACL of the object. The length of the SID MUST be a multiple of 4. This field MUST // be present if the SP flag is set. if (this.offsetSacl > 0) { // read for Sacl this.sacl = new Acl(); this.sacl.Parse(buff, this.offsetSacl); } // Dacl (variable): The DACL of the object. The length of the SID MUST be a multiple of 4. This field MUST // be present if the DP flag is set. if (this.offsetDacl > 0) { this.dacl = new Acl(); this.dacl.Parse(buff, this.offsetDacl); } }