From 307ec609e8cf38f90d0762771b07a0e4e9656d81 Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Tue, 29 Jun 2021 13:28:14 -0400 Subject: [PATCH 1/8] ocd --- models/ntsecuritydescriptor.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/models/ntsecuritydescriptor.go b/models/ntsecuritydescriptor.go index 1165bca..bdd8503 100644 --- a/models/ntsecuritydescriptor.go +++ b/models/ntsecuritydescriptor.go @@ -3,6 +3,7 @@ package models import ( "bytes" "fmt" + "golang.org/x/sys/windows" ) @@ -32,5 +33,11 @@ type NtSecurityDescriptorHeader struct { } func (s NtSecurityDescriptor) String() string { - return fmt.Sprintf("Parsed Security Descriptor:\n Offsets:\n Owner=%v Group=%v Sacl=%v Dacl=%v\n", s.Header.OffsetOwner, s.Header.OffsetGroup, s.Header.OffsetDacl, s.Header.OffsetSacl) + return fmt.Sprintf( + "Parsed Security Descriptor:\n Offsets:\n Owner=%v Group=%v Sacl=%v Dacl=%v\n", + s.Header.OffsetOwner, + s.Header.OffsetGroup, + s.Header.OffsetDacl, + s.Header.OffsetSacl, + ) } From 35f13e72052e86f91ff86d121f7b8bf6d9d16c01 Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Tue, 29 Jun 2021 19:53:02 -0400 Subject: [PATCH 2/8] reorg --- .gitignore | 1 + models/sid.go | 23 ------- parsers/ace.go | 66 ------------------- {models => pkg}/ace.go | 8 +-- pkg/acebuilder.go | 64 ++++++++++++++++++ {models => pkg}/acl.go | 2 +- pkg/guid.go | 17 +++++ models/ntsecuritydescriptor.go => pkg/ntsd.go | 2 +- .../ntsdbuilder.go | 22 +++---- parsers/generic.go => pkg/sid.go | 34 ++++++---- 10 files changed, 118 insertions(+), 121 deletions(-) create mode 100644 .gitignore delete mode 100644 models/sid.go delete mode 100644 parsers/ace.go rename {models => pkg}/ace.go (98%) create mode 100644 pkg/acebuilder.go rename {models => pkg}/acl.go (91%) create mode 100644 pkg/guid.go rename models/ntsecuritydescriptor.go => pkg/ntsd.go (98%) rename parsers/ntsecuritydescriptor.go => pkg/ntsdbuilder.go (70%) rename parsers/generic.go => pkg/sid.go (60%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb94ebf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +testdata/ \ No newline at end of file diff --git a/models/sid.go b/models/sid.go deleted file mode 100644 index b08d11c..0000000 --- a/models/sid.go +++ /dev/null @@ -1,23 +0,0 @@ -package models - -import ( - "fmt" - "strings" -) - -type SID struct { - Revision byte - NumAuthorities byte - Authority []byte - SubAuthorities []uint32 -} - -func (s SID) String() string { - var sb strings.Builder - - sb.WriteString(fmt.Sprintf("S-%v-%v", s.Revision, int(s.Authority[5]))) - for i := 0; i < int(s.NumAuthorities); i++ { - sb.WriteString(fmt.Sprintf("-%v", s.SubAuthorities[i])) - } - return sb.String() -} diff --git a/parsers/ace.go b/parsers/ace.go deleted file mode 100644 index 19cd4b5..0000000 --- a/parsers/ace.go +++ /dev/null @@ -1,66 +0,0 @@ -package parsers - -import ( - "bytes" - "encoding/binary" - "fmt" - - "github.com/kgoins/go-winacl/models" -) - -func ParseAce(buf *bytes.Buffer) models.ACE { - ace := models.ACE{} - - ace.Header = ReadACEHeader(buf) - binary.Read(buf, binary.LittleEndian, &ace.AccessMask) - switch ace.Header.Type { - case models.AceTypeAccessAllowed, models.AceTypeAccessDenied, models.AceTypeSystemAudit, models.AceTypeSystemAlarm, models.AceTypeAccessAllowedCallback, models.AceTypeAccessDeniedCallback, models.AceTypeSystemAuditCallback, models.AceTypeSystemAlarmCallback: - ace.ObjectAce = ReadBasicAce(buf, ace.Header.Size) - case models.AceTypeAccessAllowedObject, models.AceTypeAccessDeniedObject, models.AceTypeSystemAuditObject, models.AceTypeSystemAlarmObject, models.AceTypeAccessAllowedCallbackObject, models.AceTypeAccessDeniedCallbackObject, models.AceTypeSystemAuditCallbackObject, models.AceTypeSystemAlarmCallbackObject: - ace.ObjectAce = ReadAdvancedAce(buf, ace.Header.Size) - } - - return ace -} - -func ReadACEHeader(buf *bytes.Buffer) models.ACEHeader { - header := models.ACEHeader{} - binary.Read(buf, binary.LittleEndian, &header.Type) - binary.Read(buf, binary.LittleEndian, &header.Flags) - binary.Read(buf, binary.LittleEndian, &header.Size) - return header -} - -func ReadBasicAce(buf *bytes.Buffer, totalSize uint16) models.BasicAce { - oa := models.BasicAce{} - - if sid, err := ReadSID(buf, int(totalSize-8)); err != nil { - fmt.Printf("Error reading sid: %v\n", err) - } else { - oa.SecurityIdentifier = sid - } - return oa -} - -func ReadAdvancedAce(buf *bytes.Buffer, totalSize uint16) models.AdvancedAce { - oa := models.AdvancedAce{} - binary.Read(buf, binary.LittleEndian, &oa.Flags) - offset := 12 - if (oa.Flags & uint32(models.ACEInheritanceFlagsObjectTypePresent)) != 0 { - oa.ObjectType = ReadGUID(buf) - offset += 16 - } - - if (oa.Flags & uint32(models.ACEInheritanceFlagsInheritedObjectTypePresent)) != 0 { - oa.InheritedObjectType = ReadGUID(buf) - offset += 16 - } - - // Header+AccessMask is 16 bytes, other members are 36 bytes. - if sid, err := ReadSID(buf, int(totalSize)-offset); err != nil { - fmt.Printf("Error reading sid: %v\n", err) - } else { - oa.SecurityIdentifier = sid - } - return oa -} diff --git a/models/ace.go b/pkg/ace.go similarity index 98% rename from models/ace.go rename to pkg/ace.go index d4005b8..63584b5 100644 --- a/models/ace.go +++ b/pkg/ace.go @@ -1,9 +1,10 @@ -package models +package winacl import ( "fmt" - "golang.org/x/sys/windows" "strings" + + "golang.org/x/sys/windows" ) type AceType byte @@ -115,8 +116,7 @@ type SystemAuditAce BasicAce type SystemAlarmAce BasicAce // No idea what this actually is and it doesn't appear to be documented anywhere -type AccessAllowedCompoundAce struct { -} +type AccessAllowedCompoundAce struct{} type AccessAllowedObjectAce AdvancedAce type AccessDeniedObjectAce AdvancedAce diff --git a/pkg/acebuilder.go b/pkg/acebuilder.go new file mode 100644 index 0000000..d5074f0 --- /dev/null +++ b/pkg/acebuilder.go @@ -0,0 +1,64 @@ +package winacl + +import ( + "bytes" + "encoding/binary" + "fmt" +) + +func ParseAce(buf *bytes.Buffer) ACE { + ace := ACE{} + + ace.Header = ReadACEHeader(buf) + binary.Read(buf, binary.LittleEndian, &ace.AccessMask) + switch ace.Header.Type { + case AceTypeAccessAllowed, AceTypeAccessDenied, AceTypeSystemAudit, AceTypeSystemAlarm, AceTypeAccessAllowedCallback, AceTypeAccessDeniedCallback, AceTypeSystemAuditCallback, AceTypeSystemAlarmCallback: + ace.ObjectAce = ReadBasicAce(buf, ace.Header.Size) + case AceTypeAccessAllowedObject, AceTypeAccessDeniedObject, AceTypeSystemAuditObject, AceTypeSystemAlarmObject, AceTypeAccessAllowedCallbackObject, AceTypeAccessDeniedCallbackObject, AceTypeSystemAuditCallbackObject, AceTypeSystemAlarmCallbackObject: + ace.ObjectAce = ReadAdvancedAce(buf, ace.Header.Size) + } + + return ace +} + +func ReadACEHeader(buf *bytes.Buffer) ACEHeader { + header := ACEHeader{} + binary.Read(buf, binary.LittleEndian, &header.Type) + binary.Read(buf, binary.LittleEndian, &header.Flags) + binary.Read(buf, binary.LittleEndian, &header.Size) + return header +} + +func ReadBasicAce(buf *bytes.Buffer, totalSize uint16) BasicAce { + oa := BasicAce{} + + if sid, err := ReadSID(buf, int(totalSize-8)); err != nil { + fmt.Printf("Error reading sid: %v\n", err) + } else { + oa.SecurityIdentifier = sid + } + return oa +} + +func ReadAdvancedAce(buf *bytes.Buffer, totalSize uint16) AdvancedAce { + oa := AdvancedAce{} + binary.Read(buf, binary.LittleEndian, &oa.Flags) + offset := 12 + if (oa.Flags & uint32(ACEInheritanceFlagsObjectTypePresent)) != 0 { + oa.ObjectType = ReadGUID(buf) + offset += 16 + } + + if (oa.Flags & uint32(ACEInheritanceFlagsInheritedObjectTypePresent)) != 0 { + oa.InheritedObjectType = ReadGUID(buf) + offset += 16 + } + + // Header+AccessMask is 16 bytes, other members are 36 bytes. + if sid, err := ReadSID(buf, int(totalSize)-offset); err != nil { + fmt.Printf("Error reading sid: %v\n", err) + } else { + oa.SecurityIdentifier = sid + } + return oa +} diff --git a/models/acl.go b/pkg/acl.go similarity index 91% rename from models/acl.go rename to pkg/acl.go index e78a389..fbcf9d1 100644 --- a/models/acl.go +++ b/pkg/acl.go @@ -1,4 +1,4 @@ -package models +package winacl type ACL struct { Header ACLHeader diff --git a/pkg/guid.go b/pkg/guid.go new file mode 100644 index 0000000..32c4752 --- /dev/null +++ b/pkg/guid.go @@ -0,0 +1,17 @@ +package winacl + +import ( + "bytes" + "encoding/binary" + + "golang.org/x/sys/windows" +) + +func ReadGUID(buf *bytes.Buffer) windows.GUID { + guid := windows.GUID{} + binary.Read(buf, binary.LittleEndian, &guid.Data1) + binary.Read(buf, binary.LittleEndian, &guid.Data2) + binary.Read(buf, binary.LittleEndian, &guid.Data3) + binary.Read(buf, binary.LittleEndian, &guid.Data4) + return guid +} diff --git a/models/ntsecuritydescriptor.go b/pkg/ntsd.go similarity index 98% rename from models/ntsecuritydescriptor.go rename to pkg/ntsd.go index bdd8503..ca7a755 100644 --- a/models/ntsecuritydescriptor.go +++ b/pkg/ntsd.go @@ -1,4 +1,4 @@ -package models +package winacl import ( "bytes" diff --git a/parsers/ntsecuritydescriptor.go b/pkg/ntsdbuilder.go similarity index 70% rename from parsers/ntsecuritydescriptor.go rename to pkg/ntsdbuilder.go index f8c6929..cfb4d1f 100644 --- a/parsers/ntsecuritydescriptor.go +++ b/pkg/ntsdbuilder.go @@ -1,23 +1,21 @@ -package parsers +package winacl import ( "bytes" "encoding/binary" - - "github.com/kgoins/go-winacl/models" ) -func ParseNtSecurityDescriptor(ntSecurityDescriptorBytes []byte) (models.NtSecurityDescriptor, error) { +func ParseNtSecurityDescriptor(ntSecurityDescriptorBytes []byte) (NtSecurityDescriptor, error) { var buf = bytes.NewBuffer(ntSecurityDescriptorBytes) - ntsd := models.NtSecurityDescriptor{} + ntsd := NtSecurityDescriptor{} ntsd.Header = ReadNTSDHeader(buf) ntsd.DACL = ReadACL(buf) return ntsd, nil } -func ReadNTSDHeader(buf *bytes.Buffer) models.NtSecurityDescriptorHeader { - var descriptor = models.NtSecurityDescriptorHeader{} +func ReadNTSDHeader(buf *bytes.Buffer) NtSecurityDescriptorHeader { + var descriptor = NtSecurityDescriptorHeader{} binary.Read(buf, binary.LittleEndian, &descriptor.Revision) binary.Read(buf, binary.LittleEndian, &descriptor.Sbz1) @@ -30,8 +28,8 @@ func ReadNTSDHeader(buf *bytes.Buffer) models.NtSecurityDescriptorHeader { return descriptor } -func ReadACLHeader(buf *bytes.Buffer) models.ACLHeader { - var header = models.ACLHeader{} +func ReadACLHeader(buf *bytes.Buffer) ACLHeader { + var header = ACLHeader{} binary.Read(buf, binary.LittleEndian, &header.Revision) binary.Read(buf, binary.LittleEndian, &header.Sbz1) binary.Read(buf, binary.LittleEndian, &header.Size) @@ -41,10 +39,10 @@ func ReadACLHeader(buf *bytes.Buffer) models.ACLHeader { return header } -func ReadACL(buf *bytes.Buffer) models.ACL { - acl := models.ACL{} +func ReadACL(buf *bytes.Buffer) ACL { + acl := ACL{} acl.Header = ReadACLHeader(buf) - acl.Aces = make([]models.ACE, 0, acl.Header.AceCount) + acl.Aces = make([]ACE, 0, acl.Header.AceCount) for i := 0; i < int(acl.Header.AceCount); i++ { ace := ParseAce(buf) diff --git a/parsers/generic.go b/pkg/sid.go similarity index 60% rename from parsers/generic.go rename to pkg/sid.go index b428ca6..32c228a 100644 --- a/parsers/generic.go +++ b/pkg/sid.go @@ -1,25 +1,32 @@ -package parsers +package winacl import ( "bytes" "encoding/binary" "errors" - - "github.com/kgoins/go-winacl/models" - "golang.org/x/sys/windows" + "fmt" + "strings" ) -func ReadGUID(buf *bytes.Buffer) windows.GUID { - guid := windows.GUID{} - binary.Read(buf, binary.LittleEndian, &guid.Data1) - binary.Read(buf, binary.LittleEndian, &guid.Data2) - binary.Read(buf, binary.LittleEndian, &guid.Data3) - binary.Read(buf, binary.LittleEndian, &guid.Data4) - return guid +type SID struct { + Revision byte + NumAuthorities byte + Authority []byte + SubAuthorities []uint32 +} + +func (s SID) String() string { + var sb strings.Builder + + sb.WriteString(fmt.Sprintf("S-%v-%v", s.Revision, int(s.Authority[5]))) + for i := 0; i < int(s.NumAuthorities); i++ { + sb.WriteString(fmt.Sprintf("-%v", s.SubAuthorities[i])) + } + return sb.String() } -func ReadSID(buf *bytes.Buffer, sidLength int) (models.SID, error) { - sid := models.SID{} +func ReadSID(buf *bytes.Buffer, sidLength int) (SID, error) { + sid := SID{} data := buf.Next(sidLength) if revision := data[0]; revision != 1 { @@ -43,5 +50,4 @@ func ReadSID(buf *bytes.Buffer, sidLength int) (models.SID, error) { return sid, nil } - } From 81af98240dd849405dcd2084bc7eb3a95dc54d39 Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Tue, 29 Jun 2021 20:19:19 -0400 Subject: [PATCH 3/8] added test for building ntsd --- go.mod | 5 ++++- go.sum | 10 ++++++++++ pkg/ntsdbuilder_test.go | 29 +++++++++++++++++++++++++++++ pkg/testutils_test.go | 5 +++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 pkg/ntsdbuilder_test.go create mode 100644 pkg/testutils_test.go diff --git a/go.mod b/go.mod index c3e8083..3ee96c2 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/kgoins/go-winacl go 1.16 -require golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 +require ( + github.com/stretchr/testify v1.7.0 + golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 +) diff --git a/go.sum b/go.sum index e731adb..2dc15cf 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,12 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 h1:ZBu6861dZq7xBnG1bn5SRU0vA8nx42at4+kP07FMTog= golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/ntsdbuilder_test.go b/pkg/ntsdbuilder_test.go new file mode 100644 index 0000000..9c8153e --- /dev/null +++ b/pkg/ntsdbuilder_test.go @@ -0,0 +1,29 @@ +package winacl_test + +import ( + "encoding/base64" + "io/ioutil" + "path/filepath" + "testing" + + winacl "github.com/kgoins/go-winacl/pkg" + "github.com/stretchr/testify/require" +) + +func TestBuildNTSD(t *testing.T) { + r := require.New(t) + + testFile := filepath.Join(getTestDataDir(), "ntsd.b64") + testBytes, err := ioutil.ReadFile(testFile) + r.NoError(err) + + ntsdBytes, err := base64.StdEncoding.DecodeString(string(testBytes)) + r.NoError(err) + + ntsd, err := winacl.ParseNtSecurityDescriptor(ntsdBytes) + r.NoError(err) + + dacl := ntsd.DACL + r.NotNil(dacl) + r.Equal(dacl.Header.AceCount, len(dacl.Aces)) +} diff --git a/pkg/testutils_test.go b/pkg/testutils_test.go new file mode 100644 index 0000000..676adc4 --- /dev/null +++ b/pkg/testutils_test.go @@ -0,0 +1,5 @@ +package winacl_test + +func getTestDataDir() string { + return "../testdata" +} From e4881a7cbb7a74d478726f264c8c878c63e6e007 Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Tue, 29 Jun 2021 20:26:52 -0400 Subject: [PATCH 4/8] mass function rename --- pkg/acebuilder.go | 22 ++++++++--------- pkg/acl.go | 29 ++++++++++++++++++++++ pkg/guid.go | 2 +- pkg/ntsd.go | 24 +++++++++++++++++++ pkg/ntsdbuilder.go | 53 ----------------------------------------- pkg/ntsdbuilder_test.go | 2 +- pkg/sid.go | 2 +- 7 files changed, 67 insertions(+), 67 deletions(-) delete mode 100644 pkg/ntsdbuilder.go diff --git a/pkg/acebuilder.go b/pkg/acebuilder.go index d5074f0..619601c 100644 --- a/pkg/acebuilder.go +++ b/pkg/acebuilder.go @@ -6,22 +6,22 @@ import ( "fmt" ) -func ParseAce(buf *bytes.Buffer) ACE { +func NewAce(buf *bytes.Buffer) ACE { ace := ACE{} - ace.Header = ReadACEHeader(buf) + ace.Header = NewACEHeader(buf) binary.Read(buf, binary.LittleEndian, &ace.AccessMask) switch ace.Header.Type { case AceTypeAccessAllowed, AceTypeAccessDenied, AceTypeSystemAudit, AceTypeSystemAlarm, AceTypeAccessAllowedCallback, AceTypeAccessDeniedCallback, AceTypeSystemAuditCallback, AceTypeSystemAlarmCallback: - ace.ObjectAce = ReadBasicAce(buf, ace.Header.Size) + ace.ObjectAce = NewBasicAce(buf, ace.Header.Size) case AceTypeAccessAllowedObject, AceTypeAccessDeniedObject, AceTypeSystemAuditObject, AceTypeSystemAlarmObject, AceTypeAccessAllowedCallbackObject, AceTypeAccessDeniedCallbackObject, AceTypeSystemAuditCallbackObject, AceTypeSystemAlarmCallbackObject: - ace.ObjectAce = ReadAdvancedAce(buf, ace.Header.Size) + ace.ObjectAce = NewAdvancedAce(buf, ace.Header.Size) } return ace } -func ReadACEHeader(buf *bytes.Buffer) ACEHeader { +func NewACEHeader(buf *bytes.Buffer) ACEHeader { header := ACEHeader{} binary.Read(buf, binary.LittleEndian, &header.Type) binary.Read(buf, binary.LittleEndian, &header.Flags) @@ -29,10 +29,10 @@ func ReadACEHeader(buf *bytes.Buffer) ACEHeader { return header } -func ReadBasicAce(buf *bytes.Buffer, totalSize uint16) BasicAce { +func NewBasicAce(buf *bytes.Buffer, totalSize uint16) BasicAce { oa := BasicAce{} - if sid, err := ReadSID(buf, int(totalSize-8)); err != nil { + if sid, err := NewSID(buf, int(totalSize-8)); err != nil { fmt.Printf("Error reading sid: %v\n", err) } else { oa.SecurityIdentifier = sid @@ -40,22 +40,22 @@ func ReadBasicAce(buf *bytes.Buffer, totalSize uint16) BasicAce { return oa } -func ReadAdvancedAce(buf *bytes.Buffer, totalSize uint16) AdvancedAce { +func NewAdvancedAce(buf *bytes.Buffer, totalSize uint16) AdvancedAce { oa := AdvancedAce{} binary.Read(buf, binary.LittleEndian, &oa.Flags) offset := 12 if (oa.Flags & uint32(ACEInheritanceFlagsObjectTypePresent)) != 0 { - oa.ObjectType = ReadGUID(buf) + oa.ObjectType = NewGUID(buf) offset += 16 } if (oa.Flags & uint32(ACEInheritanceFlagsInheritedObjectTypePresent)) != 0 { - oa.InheritedObjectType = ReadGUID(buf) + oa.InheritedObjectType = NewGUID(buf) offset += 16 } // Header+AccessMask is 16 bytes, other members are 36 bytes. - if sid, err := ReadSID(buf, int(totalSize)-offset); err != nil { + if sid, err := NewSID(buf, int(totalSize)-offset); err != nil { fmt.Printf("Error reading sid: %v\n", err) } else { oa.SecurityIdentifier = sid diff --git a/pkg/acl.go b/pkg/acl.go index fbcf9d1..b1c1258 100644 --- a/pkg/acl.go +++ b/pkg/acl.go @@ -1,5 +1,10 @@ package winacl +import ( + "bytes" + "encoding/binary" +) + type ACL struct { Header ACLHeader Aces []ACE @@ -12,3 +17,27 @@ type ACLHeader struct { AceCount uint16 Sbz2 uint16 } + +func NewACLHeader(buf *bytes.Buffer) ACLHeader { + var header = ACLHeader{} + binary.Read(buf, binary.LittleEndian, &header.Revision) + binary.Read(buf, binary.LittleEndian, &header.Sbz1) + binary.Read(buf, binary.LittleEndian, &header.Size) + binary.Read(buf, binary.LittleEndian, &header.AceCount) + binary.Read(buf, binary.LittleEndian, &header.Sbz2) + + return header +} + +func NewACL(buf *bytes.Buffer) ACL { + acl := ACL{} + acl.Header = NewACLHeader(buf) + acl.Aces = make([]ACE, 0, acl.Header.AceCount) + + for i := 0; i < int(acl.Header.AceCount); i++ { + ace := NewAce(buf) + acl.Aces = append(acl.Aces, ace) + } + + return acl +} diff --git a/pkg/guid.go b/pkg/guid.go index 32c4752..bbb891f 100644 --- a/pkg/guid.go +++ b/pkg/guid.go @@ -7,7 +7,7 @@ import ( "golang.org/x/sys/windows" ) -func ReadGUID(buf *bytes.Buffer) windows.GUID { +func NewGUID(buf *bytes.Buffer) windows.GUID { guid := windows.GUID{} binary.Read(buf, binary.LittleEndian, &guid.Data1) binary.Read(buf, binary.LittleEndian, &guid.Data2) diff --git a/pkg/ntsd.go b/pkg/ntsd.go index ca7a755..93f32fb 100644 --- a/pkg/ntsd.go +++ b/pkg/ntsd.go @@ -2,6 +2,7 @@ package winacl import ( "bytes" + "encoding/binary" "fmt" "golang.org/x/sys/windows" @@ -41,3 +42,26 @@ func (s NtSecurityDescriptor) String() string { s.Header.OffsetSacl, ) } + +func NewNtSecurityDescriptor(ntsdBytes []byte) (NtSecurityDescriptor, error) { + var buf = bytes.NewBuffer(ntsdBytes) + ntsd := NtSecurityDescriptor{} + ntsd.Header = NewNTSDHeader(buf) + ntsd.DACL = NewACL(buf) + + return ntsd, nil +} + +func NewNTSDHeader(buf *bytes.Buffer) NtSecurityDescriptorHeader { + var descriptor = NtSecurityDescriptorHeader{} + + binary.Read(buf, binary.LittleEndian, &descriptor.Revision) + binary.Read(buf, binary.LittleEndian, &descriptor.Sbz1) + binary.Read(buf, binary.LittleEndian, &descriptor.Control) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetOwner) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetGroup) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetSacl) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetDacl) + + return descriptor +} diff --git a/pkg/ntsdbuilder.go b/pkg/ntsdbuilder.go deleted file mode 100644 index cfb4d1f..0000000 --- a/pkg/ntsdbuilder.go +++ /dev/null @@ -1,53 +0,0 @@ -package winacl - -import ( - "bytes" - "encoding/binary" -) - -func ParseNtSecurityDescriptor(ntSecurityDescriptorBytes []byte) (NtSecurityDescriptor, error) { - var buf = bytes.NewBuffer(ntSecurityDescriptorBytes) - ntsd := NtSecurityDescriptor{} - ntsd.Header = ReadNTSDHeader(buf) - ntsd.DACL = ReadACL(buf) - - return ntsd, nil -} - -func ReadNTSDHeader(buf *bytes.Buffer) NtSecurityDescriptorHeader { - var descriptor = NtSecurityDescriptorHeader{} - - binary.Read(buf, binary.LittleEndian, &descriptor.Revision) - binary.Read(buf, binary.LittleEndian, &descriptor.Sbz1) - binary.Read(buf, binary.LittleEndian, &descriptor.Control) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetOwner) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetGroup) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetSacl) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetDacl) - - return descriptor -} - -func ReadACLHeader(buf *bytes.Buffer) ACLHeader { - var header = ACLHeader{} - binary.Read(buf, binary.LittleEndian, &header.Revision) - binary.Read(buf, binary.LittleEndian, &header.Sbz1) - binary.Read(buf, binary.LittleEndian, &header.Size) - binary.Read(buf, binary.LittleEndian, &header.AceCount) - binary.Read(buf, binary.LittleEndian, &header.Sbz2) - - return header -} - -func ReadACL(buf *bytes.Buffer) ACL { - acl := ACL{} - acl.Header = ReadACLHeader(buf) - acl.Aces = make([]ACE, 0, acl.Header.AceCount) - - for i := 0; i < int(acl.Header.AceCount); i++ { - ace := ParseAce(buf) - acl.Aces = append(acl.Aces, ace) - } - - return acl -} diff --git a/pkg/ntsdbuilder_test.go b/pkg/ntsdbuilder_test.go index 9c8153e..8704224 100644 --- a/pkg/ntsdbuilder_test.go +++ b/pkg/ntsdbuilder_test.go @@ -20,7 +20,7 @@ func TestBuildNTSD(t *testing.T) { ntsdBytes, err := base64.StdEncoding.DecodeString(string(testBytes)) r.NoError(err) - ntsd, err := winacl.ParseNtSecurityDescriptor(ntsdBytes) + ntsd, err := winacl.NewNtSecurityDescriptor(ntsdBytes) r.NoError(err) dacl := ntsd.DACL diff --git a/pkg/sid.go b/pkg/sid.go index 32c228a..607fd55 100644 --- a/pkg/sid.go +++ b/pkg/sid.go @@ -25,7 +25,7 @@ func (s SID) String() string { return sb.String() } -func ReadSID(buf *bytes.Buffer, sidLength int) (SID, error) { +func NewSID(buf *bytes.Buffer, sidLength int) (SID, error) { sid := SID{} data := buf.Next(sidLength) From 80edefe1c9d87e71de5c60e498632b7987e33e2e Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Tue, 29 Jun 2021 20:39:19 -0400 Subject: [PATCH 5/8] rm'd unused ntsd types --- pkg/ntsd.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkg/ntsd.go b/pkg/ntsd.go index 93f32fb..0575137 100644 --- a/pkg/ntsd.go +++ b/pkg/ntsd.go @@ -8,13 +8,6 @@ import ( "golang.org/x/sys/windows" ) -type RawSecurityDescriptor []byte -type ParsedSecurityDescriptor struct { - Buf *bytes.Buffer - Descriptor NtSecurityDescriptor -} -type BufferedSecurityDescriptor *bytes.Buffer - type NtSecurityDescriptor struct { Header NtSecurityDescriptorHeader DACL ACL From 06c75720a49ea8894bd69b9366615f3897eb7bdb Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Wed, 30 Jun 2021 14:27:15 -0400 Subject: [PATCH 6/8] did the needful for parsing out windows systems sids --- go.mod | 1 + go.sum | 4 + pkg/ntsd.go | 28 ++---- pkg/{ntsdbuilder_test.go => ntsd_test.go} | 30 +++++-- pkg/ntsdheader.go | 65 ++++++++++++++ pkg/sys_adapter.go | 103 ++++++++++++++++++++++ 6 files changed, 204 insertions(+), 27 deletions(-) rename pkg/{ntsdbuilder_test.go => ntsd_test.go} (55%) create mode 100644 pkg/ntsdheader.go create mode 100644 pkg/sys_adapter.go diff --git a/go.mod b/go.mod index 3ee96c2..50e0d0a 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/kgoins/go-winacl go 1.16 require ( + github.com/audibleblink/bamflags v0.2.0 github.com/stretchr/testify v1.7.0 golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 ) diff --git a/go.sum b/go.sum index 2dc15cf..ad6bb2d 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,16 @@ +github.com/audibleblink/bamflags v0.2.0 h1:xLsR8OO2mmbhpQglTvSKNJMnmQMI9L884eJ15zbu4mI= +github.com/audibleblink/bamflags v0.2.0/go.mod h1:zpuLMpykftgB88SHYGBa1urg0uHn01R2pjeBed+JhB8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 h1:ZBu6861dZq7xBnG1bn5SRU0vA8nx42at4+kP07FMTog= golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/ntsd.go b/pkg/ntsd.go index 0575137..22d143e 100644 --- a/pkg/ntsd.go +++ b/pkg/ntsd.go @@ -2,7 +2,6 @@ package winacl import ( "bytes" - "encoding/binary" "fmt" "golang.org/x/sys/windows" @@ -16,16 +15,6 @@ type NtSecurityDescriptor struct { Group windows.SID } -type NtSecurityDescriptorHeader struct { - Revision byte - Sbz1 byte - Control uint16 - OffsetOwner uint32 - OffsetGroup uint32 - OffsetSacl uint32 - OffsetDacl uint32 -} - func (s NtSecurityDescriptor) String() string { return fmt.Sprintf( "Parsed Security Descriptor:\n Offsets:\n Owner=%v Group=%v Sacl=%v Dacl=%v\n", @@ -45,16 +34,11 @@ func NewNtSecurityDescriptor(ntsdBytes []byte) (NtSecurityDescriptor, error) { return ntsd, nil } -func NewNTSDHeader(buf *bytes.Buffer) NtSecurityDescriptorHeader { - var descriptor = NtSecurityDescriptorHeader{} - - binary.Read(buf, binary.LittleEndian, &descriptor.Revision) - binary.Read(buf, binary.LittleEndian, &descriptor.Sbz1) - binary.Read(buf, binary.LittleEndian, &descriptor.Control) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetOwner) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetGroup) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetSacl) - binary.Read(buf, binary.LittleEndian, &descriptor.OffsetDacl) +func (s NtSecurityDescriptor) GetSDDL() (string, error) { + secDesc, err := BuildSysNtsd(s) + if err != nil { + return "", err + } - return descriptor + return secDesc.String(), nil } diff --git a/pkg/ntsdbuilder_test.go b/pkg/ntsd_test.go similarity index 55% rename from pkg/ntsdbuilder_test.go rename to pkg/ntsd_test.go index 8704224..a833d43 100644 --- a/pkg/ntsdbuilder_test.go +++ b/pkg/ntsd_test.go @@ -10,14 +10,20 @@ import ( "github.com/stretchr/testify/require" ) -func TestBuildNTSD(t *testing.T) { - r := require.New(t) - +func getTestNtsdBytes() ([]byte, error) { testFile := filepath.Join(getTestDataDir(), "ntsd.b64") testBytes, err := ioutil.ReadFile(testFile) - r.NoError(err) + if err != nil { + return nil, err + } + + return base64.StdEncoding.DecodeString(string(testBytes)) +} - ntsdBytes, err := base64.StdEncoding.DecodeString(string(testBytes)) +func TestBuildNTSD(t *testing.T) { + r := require.New(t) + + ntsdBytes, err := getTestNtsdBytes() r.NoError(err) ntsd, err := winacl.NewNtSecurityDescriptor(ntsdBytes) @@ -27,3 +33,17 @@ func TestBuildNTSD(t *testing.T) { r.NotNil(dacl) r.Equal(dacl.Header.AceCount, len(dacl.Aces)) } + +func TestGetSDDL(t *testing.T) { + r := require.New(t) + + ntsdBytes, err := getTestNtsdBytes() + r.NoError(err) + + ntsd, err := winacl.NewNtSecurityDescriptor(ntsdBytes) + r.NoError(err) + + sddl, err := ntsd.GetSDDL() + r.NoError(err) + r.NotEmpty(sddl) +} diff --git a/pkg/ntsdheader.go b/pkg/ntsdheader.go new file mode 100644 index 0000000..6a719ef --- /dev/null +++ b/pkg/ntsdheader.go @@ -0,0 +1,65 @@ +package winacl + +import ( + "bytes" + "encoding/binary" + + "github.com/audibleblink/bamflags" + "golang.org/x/sys/windows" +) + +type NtSecurityDescriptorHeader struct { + Revision byte + Sbz1 byte + Control uint16 + OffsetOwner uint32 + OffsetGroup uint32 + OffsetSacl uint32 + OffsetDacl uint32 +} + +type NtsdDefaultedFlags struct { + OwnerDefaulted bool + GroupDefaulted bool + DACLDefaulted bool + SACLDefaulted bool +} + +// Ref: https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptordacl +func (h NtSecurityDescriptorHeader) GetDefaultedFlagsFromControl() (f NtsdDefaultedFlags, err error) { + f.OwnerDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_OWNER_DEFAULTED) + if err != nil { + return + } + + f.GroupDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_GROUP_DEFAULTED) + if err != nil { + return + } + + f.SACLDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_SACL_DEFAULTED) + if err != nil { + return + } + + f.DACLDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_DACL_DEFAULTED) + if err != nil { + return + } + + return +} + +func NewNTSDHeader(buf *bytes.Buffer) NtSecurityDescriptorHeader { + var descriptor = NtSecurityDescriptorHeader{} + + binary.Read(buf, binary.LittleEndian, &descriptor.Revision) + binary.Read(buf, binary.LittleEndian, &descriptor.Sbz1) + binary.Read(buf, binary.LittleEndian, &descriptor.Control) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetOwner) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetGroup) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetSacl) + binary.Read(buf, binary.LittleEndian, &descriptor.OffsetDacl) + + return descriptor +} diff --git a/pkg/sys_adapter.go b/pkg/sys_adapter.go new file mode 100644 index 0000000..90f1fb1 --- /dev/null +++ b/pkg/sys_adapter.go @@ -0,0 +1,103 @@ +package winacl + +import "golang.org/x/sys/windows" + +func BuildSysSID(sid SID) (*windows.SID, error) { + sidStr := sid.String() + return windows.StringToSid(sidStr) +} + +func GetTrusteeFromAce(ace ACE) (t windows.TRUSTEE, err error) { + sid := ace.ObjectAce.GetPrincipal() + sysSID, err := BuildSysSID(sid) + if err != nil { + return + } + + t.TrusteeForm = windows.TRUSTEE_IS_SID + t.TrusteeType = windows.TRUSTEE_IS_UNKNOWN + t.TrusteeValue = windows.TrusteeValueFromSID(sysSID) + + return +} + +func BuildSysAce(ace ACE) (sysACE windows.EXPLICIT_ACCESS, err error) { + trustee, err := GetTrusteeFromAce(ace) + if err != nil { + return + } + + sysACE.AccessPermissions = ace.AccessMask + sysACE.AccessMode = windows.ACCESS_MODE(ace.Header.Type) + sysACE.Inheritance = uint32(ace.Header.Flags) + sysACE.Trustee = trustee + + return +} + +func BuildSysAcl(acl ACL) (*windows.ACL, error) { + sysAces := make([]windows.EXPLICIT_ACCESS, 0, len(acl.Aces)) + + for _, ace := range acl.Aces { + sysAce, err := BuildSysAce(ace) + if err != nil { + return nil, err + } + + sysAces = append(sysAces, sysAce) + } + + return windows.ACLFromEntries(sysAces, nil) +} + +func BuildSysNtsd(ntsd NtSecurityDescriptor) (secDesc *windows.SECURITY_DESCRIPTOR, err error) { + secDesc, err = windows.NewSecurityDescriptor() + if err != nil { + return + } + + err = secDesc.SetControl( + windows.SECURITY_DESCRIPTOR_CONTROL(ntsd.Header.Control), + windows.SECURITY_DESCRIPTOR_CONTROL(ntsd.Header.Control), + ) + if err != nil { + return + } + + defaultedFlags, err := ntsd.Header.GetDefaultedFlagsFromControl() + if err != nil { + return + } + + err = secDesc.SetGroup(&ntsd.Group, defaultedFlags.GroupDefaulted) + if err != nil { + return + } + + err = secDesc.SetOwner(&ntsd.Owner, defaultedFlags.OwnerDefaulted) + if err != nil { + return + } + + sacl, err := BuildSysAcl(ntsd.SACL) + if err != nil { + return + } + + err = secDesc.SetSACL(sacl, (sacl == nil), defaultedFlags.SACLDefaulted) + if err != nil { + return + } + + dacl, err := BuildSysAcl(ntsd.DACL) + if err != nil { + return + } + + err = secDesc.SetDACL(dacl, (dacl == nil), defaultedFlags.DACLDefaulted) + if err != nil { + return + } + + return +} From a0d911fba68aef77cf2637b01e8d3a46f239de1a Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Wed, 30 Jun 2021 16:33:18 -0400 Subject: [PATCH 7/8] reorg and removed all deps on sys/windows to allow for xplat builds --- pkg/ace.go | 6 +-- pkg/guid.go | 13 ++++-- pkg/ntsd.go | 15 +------ pkg/ntsd_test.go | 14 ------ pkg/ntsdheader.go | 35 --------------- pkg/sid.go | 8 +++- pkg/sys_adapter.go | 103 --------------------------------------------- 7 files changed, 21 insertions(+), 173 deletions(-) delete mode 100644 pkg/sys_adapter.go diff --git a/pkg/ace.go b/pkg/ace.go index 63584b5..0593ef2 100644 --- a/pkg/ace.go +++ b/pkg/ace.go @@ -96,9 +96,9 @@ func (s BasicAce) GetPrincipal() SID { } type AdvancedAce struct { - Flags uint32 //4 bytes - ObjectType windows.GUID //16 bytes - InheritedObjectType windows.GUID + Flags uint32 //4 bytes + ObjectType GUID //16 bytes + InheritedObjectType GUID SecurityIdentifier SID } diff --git a/pkg/guid.go b/pkg/guid.go index bbb891f..360f7ed 100644 --- a/pkg/guid.go +++ b/pkg/guid.go @@ -3,12 +3,17 @@ package winacl import ( "bytes" "encoding/binary" - - "golang.org/x/sys/windows" ) -func NewGUID(buf *bytes.Buffer) windows.GUID { - guid := windows.GUID{} +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +func NewGUID(buf *bytes.Buffer) GUID { + guid := GUID{} binary.Read(buf, binary.LittleEndian, &guid.Data1) binary.Read(buf, binary.LittleEndian, &guid.Data2) binary.Read(buf, binary.LittleEndian, &guid.Data3) diff --git a/pkg/ntsd.go b/pkg/ntsd.go index 22d143e..d27de0b 100644 --- a/pkg/ntsd.go +++ b/pkg/ntsd.go @@ -3,16 +3,14 @@ package winacl import ( "bytes" "fmt" - - "golang.org/x/sys/windows" ) type NtSecurityDescriptor struct { Header NtSecurityDescriptorHeader DACL ACL SACL ACL - Owner windows.SID - Group windows.SID + Owner SID + Group SID } func (s NtSecurityDescriptor) String() string { @@ -33,12 +31,3 @@ func NewNtSecurityDescriptor(ntsdBytes []byte) (NtSecurityDescriptor, error) { return ntsd, nil } - -func (s NtSecurityDescriptor) GetSDDL() (string, error) { - secDesc, err := BuildSysNtsd(s) - if err != nil { - return "", err - } - - return secDesc.String(), nil -} diff --git a/pkg/ntsd_test.go b/pkg/ntsd_test.go index a833d43..1a54f46 100644 --- a/pkg/ntsd_test.go +++ b/pkg/ntsd_test.go @@ -33,17 +33,3 @@ func TestBuildNTSD(t *testing.T) { r.NotNil(dacl) r.Equal(dacl.Header.AceCount, len(dacl.Aces)) } - -func TestGetSDDL(t *testing.T) { - r := require.New(t) - - ntsdBytes, err := getTestNtsdBytes() - r.NoError(err) - - ntsd, err := winacl.NewNtSecurityDescriptor(ntsdBytes) - r.NoError(err) - - sddl, err := ntsd.GetSDDL() - r.NoError(err) - r.NotEmpty(sddl) -} diff --git a/pkg/ntsdheader.go b/pkg/ntsdheader.go index 6a719ef..896fc46 100644 --- a/pkg/ntsdheader.go +++ b/pkg/ntsdheader.go @@ -3,9 +3,6 @@ package winacl import ( "bytes" "encoding/binary" - - "github.com/audibleblink/bamflags" - "golang.org/x/sys/windows" ) type NtSecurityDescriptorHeader struct { @@ -18,38 +15,6 @@ type NtSecurityDescriptorHeader struct { OffsetDacl uint32 } -type NtsdDefaultedFlags struct { - OwnerDefaulted bool - GroupDefaulted bool - DACLDefaulted bool - SACLDefaulted bool -} - -// Ref: https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptordacl -func (h NtSecurityDescriptorHeader) GetDefaultedFlagsFromControl() (f NtsdDefaultedFlags, err error) { - f.OwnerDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_OWNER_DEFAULTED) - if err != nil { - return - } - - f.GroupDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_GROUP_DEFAULTED) - if err != nil { - return - } - - f.SACLDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_SACL_DEFAULTED) - if err != nil { - return - } - - f.DACLDefaulted, err = bamflags.Contains(int64(h.Control), windows.SE_DACL_DEFAULTED) - if err != nil { - return - } - - return -} - func NewNTSDHeader(buf *bytes.Buffer) NtSecurityDescriptorHeader { var descriptor = NtSecurityDescriptorHeader{} diff --git a/pkg/sid.go b/pkg/sid.go index 607fd55..827a3d2 100644 --- a/pkg/sid.go +++ b/pkg/sid.go @@ -18,10 +18,16 @@ type SID struct { func (s SID) String() string { var sb strings.Builder - sb.WriteString(fmt.Sprintf("S-%v-%v", s.Revision, int(s.Authority[5]))) + sb.WriteString(fmt.Sprintf( + "S-%v-%v", + s.Revision, + int(s.Authority[5]), + )) + for i := 0; i < int(s.NumAuthorities); i++ { sb.WriteString(fmt.Sprintf("-%v", s.SubAuthorities[i])) } + return sb.String() } diff --git a/pkg/sys_adapter.go b/pkg/sys_adapter.go deleted file mode 100644 index 90f1fb1..0000000 --- a/pkg/sys_adapter.go +++ /dev/null @@ -1,103 +0,0 @@ -package winacl - -import "golang.org/x/sys/windows" - -func BuildSysSID(sid SID) (*windows.SID, error) { - sidStr := sid.String() - return windows.StringToSid(sidStr) -} - -func GetTrusteeFromAce(ace ACE) (t windows.TRUSTEE, err error) { - sid := ace.ObjectAce.GetPrincipal() - sysSID, err := BuildSysSID(sid) - if err != nil { - return - } - - t.TrusteeForm = windows.TRUSTEE_IS_SID - t.TrusteeType = windows.TRUSTEE_IS_UNKNOWN - t.TrusteeValue = windows.TrusteeValueFromSID(sysSID) - - return -} - -func BuildSysAce(ace ACE) (sysACE windows.EXPLICIT_ACCESS, err error) { - trustee, err := GetTrusteeFromAce(ace) - if err != nil { - return - } - - sysACE.AccessPermissions = ace.AccessMask - sysACE.AccessMode = windows.ACCESS_MODE(ace.Header.Type) - sysACE.Inheritance = uint32(ace.Header.Flags) - sysACE.Trustee = trustee - - return -} - -func BuildSysAcl(acl ACL) (*windows.ACL, error) { - sysAces := make([]windows.EXPLICIT_ACCESS, 0, len(acl.Aces)) - - for _, ace := range acl.Aces { - sysAce, err := BuildSysAce(ace) - if err != nil { - return nil, err - } - - sysAces = append(sysAces, sysAce) - } - - return windows.ACLFromEntries(sysAces, nil) -} - -func BuildSysNtsd(ntsd NtSecurityDescriptor) (secDesc *windows.SECURITY_DESCRIPTOR, err error) { - secDesc, err = windows.NewSecurityDescriptor() - if err != nil { - return - } - - err = secDesc.SetControl( - windows.SECURITY_DESCRIPTOR_CONTROL(ntsd.Header.Control), - windows.SECURITY_DESCRIPTOR_CONTROL(ntsd.Header.Control), - ) - if err != nil { - return - } - - defaultedFlags, err := ntsd.Header.GetDefaultedFlagsFromControl() - if err != nil { - return - } - - err = secDesc.SetGroup(&ntsd.Group, defaultedFlags.GroupDefaulted) - if err != nil { - return - } - - err = secDesc.SetOwner(&ntsd.Owner, defaultedFlags.OwnerDefaulted) - if err != nil { - return - } - - sacl, err := BuildSysAcl(ntsd.SACL) - if err != nil { - return - } - - err = secDesc.SetSACL(sacl, (sacl == nil), defaultedFlags.SACLDefaulted) - if err != nil { - return - } - - dacl, err := BuildSysAcl(ntsd.DACL) - if err != nil { - return - } - - err = secDesc.SetDACL(dacl, (dacl == nil), defaultedFlags.DACLDefaulted) - if err != nil { - return - } - - return -} From 52c8a15abfd933ccd1788a53abcb90593d1726ab Mon Sep 17 00:00:00 2001 From: kgoins <14044530+kgoins@users.noreply.github.com> Date: Wed, 30 Jun 2021 16:36:43 -0400 Subject: [PATCH 8/8] removed windows pkg dep from ace.go --- go.mod | 1 - go.sum | 5 +---- pkg/ace.go | 6 +++--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 50e0d0a..3ee96c2 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/kgoins/go-winacl go 1.16 require ( - github.com/audibleblink/bamflags v0.2.0 github.com/stretchr/testify v1.7.0 golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 ) diff --git a/go.sum b/go.sum index ad6bb2d..7269144 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,13 @@ -github.com/audibleblink/bamflags v0.2.0 h1:xLsR8OO2mmbhpQglTvSKNJMnmQMI9L884eJ15zbu4mI= -github.com/audibleblink/bamflags v0.2.0/go.mod h1:zpuLMpykftgB88SHYGBa1urg0uHn01R2pjeBed+JhB8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750 h1:ZBu6861dZq7xBnG1bn5SRU0vA8nx42at4+kP07FMTog= golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/ace.go b/pkg/ace.go index 0593ef2..df26204 100644 --- a/pkg/ace.go +++ b/pkg/ace.go @@ -3,8 +3,6 @@ package winacl import ( "fmt" "strings" - - "golang.org/x/sys/windows" ) type AceType byte @@ -48,10 +46,12 @@ const ( ACEInheritanceFlagsInheritedObjectTypePresent = 0x02 ) +type ACEAccessMask uint32 + //Header + AccessMask is 16 bytes type ACE struct { Header ACEHeader - AccessMask windows.ACCESS_MASK + AccessMask ACEAccessMask ObjectAce ObjectAce }