├── .github
├── FUNDING.yml
├── banner.png
├── example_dn.png
├── example_value.png
└── workflows
│ ├── commit.yaml
│ └── release.yaml
├── .gitignore
├── README.md
├── go.mod
├── go.sum
├── main.go
└── src
├── go.mod
├── go.sum
├── ldap
├── ldap.go
├── sid.go
└── utils.go
├── logger
└── logger.go
├── main.go
└── windows
├── RelativeIDs.go
└── sAMAccountType.go
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: p0dalirius
4 | patreon: Podalirius
5 |
--------------------------------------------------------------------------------
/.github/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheManticoreProject/DescribeNTSecurityDescriptor/be5d346c17d1dfac9198770cea70041e47cf89ce/.github/banner.png
--------------------------------------------------------------------------------
/.github/example_dn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheManticoreProject/DescribeNTSecurityDescriptor/be5d346c17d1dfac9198770cea70041e47cf89ce/.github/example_dn.png
--------------------------------------------------------------------------------
/.github/example_value.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheManticoreProject/DescribeNTSecurityDescriptor/be5d346c17d1dfac9198770cea70041e47cf89ce/.github/example_value.png
--------------------------------------------------------------------------------
/.github/workflows/commit.yaml:
--------------------------------------------------------------------------------
1 | name: Build on commit
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 |
8 | jobs:
9 | build:
10 | name: Build Release Assets
11 | runs-on: ubuntu-latest
12 |
13 | strategy:
14 | matrix:
15 | os: [linux, windows, darwin]
16 | arch: [amd64, arm64, 386]
17 | binaryname: [DescribeNTSecurityDescriptor]
18 | # Exclude incompatible couple of GOOS and GOARCH values
19 | exclude:
20 | - os: darwin
21 | arch: 386
22 |
23 | env:
24 | GO111MODULE: 'on'
25 | CGO_ENABLED: '0'
26 |
27 | steps:
28 | - name: Checkout Repository
29 | uses: actions/checkout@v3
30 |
31 | - name: Set up Go
32 | uses: actions/setup-go@v4
33 | with:
34 | go-version: '1.22.1'
35 |
36 | - name: Build Binary
37 | env:
38 | GOOS: ${{ matrix.os }}
39 | GOARCH: ${{ matrix.arch }}
40 | run: |
41 | mkdir -p build
42 | ls -lha
43 | OUTPUT_PATH="../build/${{ matrix.binaryname }}-${{ matrix.os }}-${{ matrix.arch }}"
44 | # Build the binary
45 | cd ./src/;
46 | go build -ldflags="-s -w" -o $OUTPUT_PATH${{ matrix.os == 'windows' && '.exe' || '' }}
47 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | name: Build and Release
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | build:
9 | name: Build Release Assets
10 | runs-on: ubuntu-latest
11 |
12 | strategy:
13 | matrix:
14 | os: [linux, windows, darwin]
15 | arch: [amd64, arm64, 386]
16 | binaryname: [DescribeNTSecurityDescriptor]
17 | # Exclude incompatible couple of GOOS and GOARCH values
18 | exclude:
19 | - os: darwin
20 | arch: 386
21 |
22 | env:
23 | GO111MODULE: 'on'
24 | CGO_ENABLED: '0'
25 |
26 | steps:
27 | - name: Checkout Repository
28 | uses: actions/checkout@v3
29 |
30 | - name: Set up Go
31 | uses: actions/setup-go@v4
32 | with:
33 | go-version: '1.22.1'
34 |
35 | - name: Build Binary
36 | env:
37 | GOOS: ${{ matrix.os }}
38 | GOARCH: ${{ matrix.arch }}
39 | run: |
40 | mkdir -p bin
41 | ls -lha
42 | OUTPUT_PATH="../build/${{ matrix.binaryname }}-${{ matrix.os }}-${{ matrix.arch }}"
43 | # Build the binary
44 | cd ./src/;
45 | go build -ldflags="-s -w" -o $OUTPUT_PATH${{ matrix.os == 'windows' && '.exe' || '' }}
46 |
47 | - name: Prepare Release Assets
48 | if: ${{ success() }}
49 | run: |
50 | mkdir -p ./release/
51 | cp ./build/${{ matrix.binaryname }}-* ./release/
52 |
53 | - name: Upload the Release binaries
54 | uses: svenstaro/upload-release-action@v2
55 | with:
56 | repo_token: ${{ secrets.GITHUB_TOKEN }}
57 | tag: ${{ github.ref }}
58 | file: ./release/${{ matrix.binaryname }}-*
59 | file_glob: true
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # If you prefer the allow list template instead of the deny list, see community template:
2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3 | #
4 | # Binaries for programs and plugins
5 | *.exe
6 | *.exe~
7 | *.dll
8 | *.so
9 | *.dylib
10 |
11 | # Test binary, built with `go test -c`
12 | *.test
13 |
14 | # Output of the go coverage tool, specifically when used with LiteIDE
15 | *.out
16 |
17 | # Dependency directories (remove the comment below to include it)
18 | # vendor/
19 |
20 | # Go workspace file
21 | go.work
22 | go.work.sum
23 |
24 | # env file
25 | .env
26 |
27 | # Builds dir
28 | ./bin/
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 | A cross-platform tool to parse and describe the contents of a raw ntSecurityDescriptor structure.
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | ## Features
13 |
14 | - [x] Reads source value from a file containing a raw ntSecurityDescriptor structure, in raw bytes, hex string or base64 string formats.
15 | - [x] Reads source value from the LDAP.
16 | - [ ] Outputs a human readable summary of accesses with `--summary`
17 | - [x] Parsing of Access Control Entries (ACE) of various types:
18 | - [x] ACE type [`ACCESS_ALLOWED_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/72e7c7ea-bc02-4c74-a619-818a16bf6adb?wt.mc_id=SEC-MVP-5005286)
19 | - [x] ACE type [`ACCESS_ALLOWED_OBJECT_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c79a383c-2b3f-4655-abe7-dcbb7ce0cfbe?wt.mc_id=SEC-MVP-5005286)
20 | - [x] ACE type [`ACCESS_DENIED_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/b1e1321d-5816-4513-be67-b65d8ae52fe8?wt.mc_id=SEC-MVP-5005286)
21 | - [x] ACE type [`ACCESS_DENIED_OBJECT_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/8720fcf3-865c-4557-97b1-0b3489a6c270?wt.mc_id=SEC-MVP-5005286)
22 | - [x] ACE type [`ACCESS_ALLOWED_CALLBACK_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c9579cf4-0f4a-44f1-9444-422dfb10557a?wt.mc_id=SEC-MVP-5005286)
23 | - [x] ACE type [`ACCESS_DENIED_CALLBACK_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/35adad6b-fda5-4cc1-b1b5-9beda5b07d2e?wt.mc_id=SEC-MVP-5005286)
24 | - [x] ACE type [`ACCESS_ALLOWED_CALLBACK_OBJECT_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/fe1838ea-ea34-4a5e-b40e-eb870f8322ae?wt.mc_id=SEC-MVP-5005286)
25 | - [x] ACE type [`ACCESS_DENIED_CALLBACK_OBJECT_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/4652f211-82d5-4b90-bd58-43bf3b0fc48d?wt.mc_id=SEC-MVP-5005286)
26 | - [x] ACE type [`SYSTEM_AUDIT_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/9431fd0f-5b9a-47f0-b3f0-3015e2d0d4f9?wt.mc_id=SEC-MVP-5005286)
27 | - [x] ACE type [`SYSTEM_AUDIT_OBJECT_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/c8da72ae-6b54-4a05-85f4-e2594936d3d5?wt.mc_id=SEC-MVP-5005286)
28 | - [x] ACE type [`SYSTEM_AUDIT_CALLBACK_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/bd6b6fd8-4bef-427e-9a43-b9b46457e934?wt.mc_id=SEC-MVP-5005286)
29 | - [x] ACE type [`SYSTEM_MANDATORY_LABEL_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/25fa6565-6cb0-46ab-a30a-016b32c4939a?wt.mc_id=SEC-MVP-5005286)
30 | - [x] ACE type [`SYSTEM_AUDIT_CALLBACK_OBJECT_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/949b02e7-f55d-4c26-969f-52a009597469?wt.mc_id=SEC-MVP-5005286)
31 | - [x] ACE type [`SYSTEM_RESOURCE_ATTRIBUTE_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/352944c7-4fb6-4988-8036-0a25dcedc730?wt.mc_id=SEC-MVP-5005286)
32 | - [x] ACE type [`SYSTEM_SCOPED_POLICY_ID_ACE`](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/aa0c0f62-4b4c-44f0-9718-c266a6accd9f?wt.mc_id=SEC-MVP-5005286)
33 | - [x] Parsing of SID
34 | - [x] Connect to LDAP to resolve sAMAccountNames of not well known SIDs
35 | - [x] Resolve names of well known SIDs
36 | - [ ] Parsing of Access Control Lists (ACL):
37 | - [ ] Print if ACL is in [canonical form](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/20233ed8-a6c6-4097-aafa-dd545ed24428?wt.mc_id=SEC-MVP-5005286)
38 |
39 |
40 | ## Usage
41 |
42 | ```
43 | $ ./DescribeNTSecurityDescriptor -h
44 | DescribeNTSecurityDescriptor - by Remi GASCOU (Podalirius) @ TheManticoreProject - v1.3.0
45 |
46 | Usage: DescribeNTSecurityDescriptor [--debug] [--domain ] [--username ] [--password ] [--hashes ] [--dc-ip ] [--port ] [--use-ldaps] [--distinguished-name ] [--file-hex ] [--file-base64 ] [--file-raw ] [--value-hex ] [--value-base64 ]
47 |
48 | -d, --debug Debug mode. (default: false)
49 |
50 | Authentication:
51 | -d, --domain Active Directory domain to authenticate to. (default: "")
52 | -u, --username User to authenticate as. (default: "")
53 | -p, --password Password to authenticate with. (default: "")
54 | -H, --hashes NT/LM hashes, format is LMhash:NThash. (default: "")
55 |
56 | LDAP Connection Settings:
57 | -dc, --dc-ip IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted, it will use the domain part (FQDN) specified in the identity parameter. (default: "")
58 | -P, --port Port number to connect to LDAP server. (default: 389)
59 | -l, --use-ldaps Use LDAPS instead of LDAP. (default: false)
60 |
61 | Source Values:
62 | -D, --distinguished-name Distinguished Name. (default: "")
63 | -fh, --file-hex Path to file containing the hexadecimal string value of NTSecurityDescriptor. (default: "")
64 | -fb, --file-base64 Path to file containing the base64 encoded value of NTSecurityDescriptor. (default: "")
65 | -fr, --file-raw Path to file containing the raw binary value of NTSecurityDescriptor. (default: "")
66 | -vh, --value-hex Raw hexadecimal string value of NTSecurityDescriptor. (default: "")
67 | -vb, --value-base64 Raw base64 encoded value of NTSecurityDescriptor. (default: "")
68 | ```
69 |
70 |
71 | ## Demonstration with a `--distinguished-name`
72 |
73 | ```bash
74 | ./DescribeNTSecurityDescriptor --debug --username "Administrator" --domain "LAB.local" --password "Admin123!" --dc-ip "10.0.0.201" --distinguished-name "CN=Administrator,CN=Users,DC=LAB,DC=local"
75 | ```
76 |
77 | 
78 |
79 | ## Demonstration with a `--value-hex`
80 |
81 | ```bash
82 | ./DescribeNTSecurityDescriptor --username "Administrator" --domain "LAB.local" --password "Admin123!" --dc-ip "10.0.0.201" --debug --value-hex "0100149ccc000000e800000014000000a000000004008c00030000000240140020000c00010100000000000100000000075a38002000000003000000be3b0ef3f09fd111b6030000f80367c1a57a96bfe60dd011a28500aa003049e2010100000000000100000000075a38002000000003000000bf3b0ef3f09fd111b6030000f80367c1a57a96bfe60dd011a28500aa003049e201010000000000010000000002002c000100000000002400ff010f0001050000000000051500000028bb82279261b9fe2474aa5d0002000001050000000000051500000028bb82279261b9fe2474aa5d0002000001050000000000051500000028bb82279261b9fe2000000"
83 | ```
84 |
85 | 
86 |
87 |
88 | ## Building the project
89 |
90 | To build the project, use the following Docker command in this directory:
91 |
92 | ```bash
93 | docker run -v $(pwd):/workspace/ podalirius/build-go-project
94 | ```
95 |
96 | Or, if you want to build it manually, you can use the following commands:
97 |
98 | ```
99 | GOOS=linux GOARCH=amd64; mkdir -p "/workspace/bin/linux/${GOOS}/${GOARCH}/" && /usr/local/go/bin/go build -o "/workspace/bin/linux/${GOOS}/${GOARCH}/DescribeNTSecurityDescriptor" -buildvcs=false
100 | ```
101 |
102 | ## Contributing
103 |
104 | Pull requests are welcome. Feel free to open an issue if you want to add other features.
105 |
106 | ## Credits
107 | - [@p0dalirius](https://github.com/p0dalirius) for the creation of the [DescribeNTSecurityDescriptor](https://github.com/p0dalirius/DescribeNTSecurityDescriptor) project before transferring it to TheManticoreProject.
108 |
109 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TheManticoreProject/DescribeNTSecurityDescriptor
2 |
3 | go 1.24.0
4 |
5 | require (
6 | github.com/TheManticoreProject/Manticore v1.0.1
7 | github.com/TheManticoreProject/goopts v1.2.1
8 | github.com/TheManticoreProject/winacl v1.2.11
9 | )
10 |
11 | require (
12 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
13 | github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
14 | github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
15 | github.com/go-ldap/ldap/v3 v3.4.11 // indirect
16 | github.com/google/uuid v1.6.0 // indirect
17 | github.com/hashicorp/go-uuid v1.0.3 // indirect
18 | github.com/jcmturner/aescts/v2 v2.0.0 // indirect
19 | github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
20 | github.com/jcmturner/gofork v1.7.6 // indirect
21 | github.com/jcmturner/goidentity/v6 v6.0.1 // indirect
22 | github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
23 | github.com/jcmturner/rpc/v2 v2.0.3 // indirect
24 | golang.org/x/crypto v0.38.0 // indirect
25 | golang.org/x/net v0.39.0 // indirect
26 | )
27 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
2 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
3 | github.com/TheManticoreProject/Manticore v1.0.1 h1:b4MFQyiDrnADDFfu0bwAoVmgMEegd9nyMk6bCQUGaj0=
4 | github.com/TheManticoreProject/Manticore v1.0.1/go.mod h1:2YzwHihKSODuo1YP0UuHL/AgcwkQLtc5j/ihuvke4/k=
5 | github.com/TheManticoreProject/goopts v1.2.1 h1:/VhIRpQNEvbo01Yi6WHK6KG9SyNVi2yb6AIsOviqJ3Q=
6 | github.com/TheManticoreProject/goopts v1.2.1/go.mod h1:NaM3hXXCeN+x9ZSlkS6Bm8i8Lfqe28/rveBsfrMUrAo=
7 | github.com/TheManticoreProject/winacl v1.2.11 h1:0v1bHqzAYZ4H/mRuO7Agu2Rq+p9QXWs4SC8NI26NTwM=
8 | github.com/TheManticoreProject/winacl v1.2.11/go.mod h1:Xji/qLzY8AkdBNXRgOS7g+UBEuqMQBBZllr+rl7Hzko=
9 | github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
10 | github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
11 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
13 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
14 | github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
15 | github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
16 | github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
17 | github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
18 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
19 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
20 | github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
21 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
22 | github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
23 | github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
24 | github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
25 | github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
26 | github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
27 | github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
28 | github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
29 | github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
30 | github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
31 | github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
32 | github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
33 | github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
34 | github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
35 | github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
36 | github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
37 | github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
38 | github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
39 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
40 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
41 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
42 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
43 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
44 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
45 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
46 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
47 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
48 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
49 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
50 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
51 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
52 | golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
53 | golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
54 | golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
55 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
56 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
57 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
58 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
59 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
60 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
61 | golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
62 | golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
63 | golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
64 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
65 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
66 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
67 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
68 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
69 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
70 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
71 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
72 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
73 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
74 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
75 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
76 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
77 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
78 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
79 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
80 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
81 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
82 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
83 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
84 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
85 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
86 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
87 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
88 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/base64"
5 | "encoding/hex"
6 | "fmt"
7 | "os"
8 |
9 | "github.com/TheManticoreProject/Manticore/logger"
10 | "github.com/TheManticoreProject/Manticore/network/ldap"
11 | "github.com/TheManticoreProject/Manticore/windows/credentials"
12 | "github.com/TheManticoreProject/goopts/parser"
13 | "github.com/TheManticoreProject/winacl/securitydescriptor"
14 | )
15 |
16 | var (
17 | // Configuration
18 | useLdaps bool
19 | debug bool
20 |
21 | // Network settings
22 | domainController string
23 | ldapPort int
24 |
25 | // Authentication details
26 | authDomain string
27 | authUsername string
28 | authPassword string
29 | authHashes string
30 | useKerberos bool
31 |
32 | // Source values
33 | distinguishedName string
34 |
35 | sourceFileHex string
36 | sourceFileBase64 string
37 | sourceFileRaw string
38 | valueHex string
39 | valueBase64 string
40 | )
41 |
42 | func parseArgs() {
43 | ap := parser.ArgumentsParser{Banner: "DescribeNTSecurityDescriptor - by Remi GASCOU (Podalirius) @ TheManticoreProject - v1.3.1"}
44 |
45 | // Configuration flags
46 | ap.NewBoolArgument(&debug, "-d", "--debug", false, "Debug mode.")
47 |
48 | // Source value
49 | group_sourceValues, err := ap.NewRequiredMutuallyExclusiveArgumentGroup("Source Values")
50 | if err != nil {
51 | fmt.Printf("[error] Error creating ArgumentGroup: %s\n", err)
52 | } else {
53 | group_sourceValues.NewStringArgument(&distinguishedName, "-D", "--distinguished-name", "", false, "Distinguished Name.")
54 | // File sources
55 | group_sourceValues.NewStringArgument(&sourceFileHex, "-fh", "--file-hex", "", false, "Path to file containing the hexadecimal string value of NTSecurityDescriptor.")
56 | group_sourceValues.NewStringArgument(&sourceFileBase64, "-fb", "--file-base64", "", false, "Path to file containing the base64 encoded value of NTSecurityDescriptor.")
57 | group_sourceValues.NewStringArgument(&sourceFileRaw, "-fr", "--file-raw", "", false, "Path to file containing the raw binary value of NTSecurityDescriptor.")
58 | // Value sources
59 | group_sourceValues.NewStringArgument(&valueHex, "-vh", "--value-hex", "", false, "Raw hexadecimal string value of NTSecurityDescriptor.")
60 | group_sourceValues.NewStringArgument(&valueBase64, "-vb", "--value-base64", "", false, "Raw base64 encoded value of NTSecurityDescriptor.")
61 | }
62 |
63 | group_ldapSettings, err := ap.NewArgumentGroup("LDAP Connection Settings")
64 | if err != nil {
65 | fmt.Printf("[error] Error creating ArgumentGroup: %s\n", err)
66 | } else {
67 | group_ldapSettings.NewStringArgument(&domainController, "-dc", "--dc-ip", "", false, "IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted, it will use the domain part (FQDN) specified in the identity parameter.")
68 | group_ldapSettings.NewTcpPortArgument(&ldapPort, "-P", "--port", 389, false, "Port number to connect to LDAP server.")
69 | group_ldapSettings.NewBoolArgument(&useLdaps, "-l", "--use-ldaps", false, "Use LDAPS instead of LDAP.")
70 | group_ldapSettings.NewBoolArgument(&useKerberos, "-k", "--use-kerberos", false, "Use Kerberos instead of NTLM.")
71 | }
72 |
73 | group_auth, err := ap.NewArgumentGroup("Authentication")
74 | if err != nil {
75 | fmt.Printf("[error] Error creating ArgumentGroup: %s\n", err)
76 | } else {
77 | group_auth.NewStringArgument(&authDomain, "-d", "--domain", "", false, "Active Directory domain to authenticate to.")
78 | group_auth.NewStringArgument(&authUsername, "-u", "--username", "", false, "User to authenticate as.")
79 | group_auth.NewStringArgument(&authPassword, "-p", "--password", "", false, "Password to authenticate with.")
80 | group_auth.NewStringArgument(&authHashes, "-H", "--hashes", "", false, "NT/LM hashes, format is LMhash:NThash.")
81 | }
82 |
83 | ap.Parse()
84 |
85 | if useLdaps && !group_ldapSettings.LongNameToArgument["--port"].IsPresent() {
86 | ldapPort = 636
87 | }
88 |
89 | if len(distinguishedName) != 0 && (len(domainController) == 0 || len(authUsername) == 0 || len(authPassword) == 0) {
90 | logger.Warn("Error: Options --dc-ip, --username, --password are required when using --distinguished-name.")
91 | os.Exit(1)
92 | }
93 | }
94 |
95 | func main() {
96 | parseArgs()
97 |
98 | creds, err := credentials.NewCredentials(authDomain, authUsername, authPassword, authHashes)
99 | if err != nil {
100 | logger.Warn(fmt.Sprintf("Error creating credentials: %s", err))
101 | return
102 | }
103 |
104 | rawNtsdValue := []byte{}
105 |
106 | // Parsing input values for hex format
107 | if len(rawNtsdValue) == 0 && (len(sourceFileHex) != 0 || len(valueHex) != 0) {
108 | value_hex_string := ""
109 | if len(valueHex) != 0 {
110 | value_hex_string = valueHex
111 | }
112 | if len(sourceFileHex) != 0 {
113 | data, err := os.ReadFile(sourceFileHex)
114 | if err != nil {
115 | logger.Warn(fmt.Sprintf("Error reading file: %s", err))
116 | return
117 | }
118 | value_hex_string = string(data)
119 | }
120 | // Decoding the hex string
121 | if len(value_hex_string) != 0 {
122 | if len(value_hex_string)%2 == 1 {
123 | // encoding/hex: odd length hex string
124 | value_hex_string = value_hex_string + "0"
125 | }
126 | value, err := hex.DecodeString(value_hex_string)
127 | if err != nil {
128 | logger.Warn(fmt.Sprintf("Error decoding Hex value: %s", err))
129 | return
130 | } else {
131 | rawNtsdValue = value
132 | }
133 | }
134 | }
135 |
136 | // Parsing input values for base64 format
137 | if len(rawNtsdValue) == 0 && (len(sourceFileBase64) != 0 || len(valueBase64) != 0) {
138 | value_base64_string := ""
139 | if len(valueBase64) != 0 {
140 | value_base64_string = valueBase64
141 | }
142 | if len(sourceFileBase64) != 0 {
143 | data, err := os.ReadFile(sourceFileBase64)
144 | if err != nil {
145 | logger.Warn(fmt.Sprintf("Error reading file: %s", err))
146 | return
147 | }
148 | value_base64_string = string(data)
149 | }
150 |
151 | // Decoding the base64 string
152 | if len(value_base64_string) != 0 {
153 | value, err := base64.StdEncoding.DecodeString(value_base64_string)
154 | if err != nil {
155 | logger.Warn(fmt.Sprintf("Error decoding Base64 value: %s", err))
156 | return
157 | } else {
158 | rawNtsdValue = value
159 | }
160 | }
161 | }
162 |
163 | // Parsing input values for raw format
164 | if len(rawNtsdValue) == 0 && len(sourceFileRaw) != 0 {
165 | data, err := os.ReadFile(sourceFileRaw)
166 | if err != nil {
167 | logger.Warn(fmt.Sprintf("Error reading file: %s", err))
168 | return
169 | }
170 | rawNtsdValue = data
171 | }
172 |
173 | if len(rawNtsdValue) == 0 && len(distinguishedName) != 0 {
174 | // Parsing input values for Distinguished Name
175 | if debug {
176 | if !useLdaps {
177 | logger.Debug(fmt.Sprintf("Connecting to remote ldap://%s:%d ...", domainController, ldapPort))
178 | } else {
179 | logger.Debug(fmt.Sprintf("Connecting to remote ldaps://%s:%d ...", domainController, ldapPort))
180 | }
181 | }
182 | ldapSession := ldap.Session{}
183 | ldapSession.InitSession(domainController, ldapPort, creds, useLdaps, useKerberos)
184 | connected, err := ldapSession.Connect()
185 | if err != nil {
186 | logger.Warn(fmt.Sprintf("Error connecting to LDAP: %s", err))
187 | return
188 | }
189 |
190 | if connected {
191 | logger.Info(fmt.Sprintf("Connected as '%s\\%s'", authDomain, authUsername))
192 |
193 | query := fmt.Sprintf("(distinguishedName=%s)", distinguishedName)
194 |
195 | if debug {
196 | logger.Debug(fmt.Sprintf("LDAP query used: %s", query))
197 | }
198 |
199 | attributes := []string{"distinguishedName", "ntSecurityDescriptor"}
200 | ldapResults, err := ldapSession.QueryWholeSubtree("", query, attributes)
201 | if err != nil {
202 | logger.Warn(fmt.Sprintf("Error querying LDAP: %s", err))
203 | return
204 | }
205 |
206 | for _, entry := range ldapResults {
207 | if debug {
208 | logger.Debug(fmt.Sprintf("| distinguishedName: %s", entry.GetAttributeValue("distinguishedName")))
209 | }
210 | rawNtsdValue = entry.GetEqualFoldRawAttributeValue("ntSecurityDescriptor")
211 | }
212 | } else {
213 | if debug {
214 | logger.Warn("Error: Could not create ldapSession.")
215 | }
216 | }
217 | }
218 |
219 | if len(rawNtsdValue) != 0 {
220 | ntsd := securitydescriptor.NtSecurityDescriptor{}
221 | logger.Debug(fmt.Sprintf("| ntSecurityDescriptor: %s", hex.EncodeToString(rawNtsdValue)))
222 | _, err := ntsd.Unmarshal(rawNtsdValue)
223 | if err != nil {
224 | logger.Warn(fmt.Sprintf("Error unmarshalling NTSecurityDescriptor: %s", err))
225 | return
226 | }
227 | ntsd.Describe(0)
228 | } else {
229 | logger.Warn("No NTSecurityDescriptor found in source values.")
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/src/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/TheManticoreProject/DescribeNTSecurityDescriptor
2 |
3 | go 1.24.0
4 |
5 | require (
6 | github.com/TheManticoreProject/goopts v1.1.7
7 | github.com/TheManticoreProject/winacl v1.2.6
8 | github.com/go-ldap/ldap/v3 v3.4.10
9 | )
10 |
11 | require (
12 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
13 | github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
14 | github.com/google/uuid v1.6.0 // indirect
15 | golang.org/x/crypto v0.37.0 // indirect
16 | )
17 |
--------------------------------------------------------------------------------
/src/go.sum:
--------------------------------------------------------------------------------
1 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
2 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
3 | github.com/TheManticoreProject/goopts v1.1.7 h1:fYuaUnZsL4X9InmHmpd1cgAfS8u0TMymTI3ke+Pp0sk=
4 | github.com/TheManticoreProject/goopts v1.1.7/go.mod h1:NaM3hXXCeN+x9ZSlkS6Bm8i8Lfqe28/rveBsfrMUrAo=
5 | github.com/TheManticoreProject/winacl v1.2.6 h1:2LiMx7l811UBqwYAOqvHNSfRJTbqITmUZbtkFjXzYsI=
6 | github.com/TheManticoreProject/winacl v1.2.6/go.mod h1:Xji/qLzY8AkdBNXRgOS7g+UBEuqMQBBZllr+rl7Hzko=
7 | github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
8 | github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
9 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
11 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12 | github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
13 | github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
14 | github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
15 | github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
16 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
17 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
18 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
19 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
20 | github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
21 | github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
22 | github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
23 | github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
24 | github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
25 | github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
26 | github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
27 | github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
28 | github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
29 | github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
30 | github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
31 | github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
32 | github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
33 | github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
34 | github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
35 | github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
36 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
37 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
38 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
39 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
40 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
41 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
42 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
43 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
44 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
45 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
46 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
47 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
48 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
49 | golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
50 | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
51 | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
52 | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
53 | golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
54 | golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
55 | golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
56 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
57 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
58 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
59 | golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
60 | golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
61 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
62 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
63 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
64 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
65 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
66 | golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
67 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
68 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
69 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
70 | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
71 | golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
72 | golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
73 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
74 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
75 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
76 | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
77 | golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
78 | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
79 | golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
80 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
81 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
82 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
83 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
84 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
85 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
86 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
87 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
88 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
89 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
90 | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
91 | golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
92 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
93 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
94 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
95 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
96 | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
97 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
98 | golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
99 | golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
100 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
101 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
102 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
103 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
104 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
105 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
106 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
107 | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
108 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
109 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
110 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
111 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
112 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
113 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
114 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
115 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
116 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
117 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
118 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
119 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
120 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
121 |
--------------------------------------------------------------------------------
/src/ldap/ldap.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "github.com/TheManticoreProject/DescribeNTSecurityDescriptor/logger"
5 |
6 | "crypto/tls"
7 | "fmt"
8 | "strings"
9 |
10 | "github.com/go-ldap/ldap/v3"
11 | )
12 |
13 | type Entry ldap.Entry
14 |
15 | type Session struct {
16 | // Network
17 | host string
18 | port int
19 | connection *ldap.Conn
20 | // Credentials
21 | domain string
22 | username string
23 | password string
24 | // Config
25 | debug bool
26 | useldaps bool
27 | }
28 |
29 | type Domain struct {
30 | NetBIOSName string `json:"netbiosName"`
31 | DNSName string `json:"dnsName"`
32 | DistinguishedName string `json:"distinguishedName"`
33 | SID string `json:"sid"`
34 | }
35 |
36 | func (s *Session) InitSession(host string, port int, useldaps bool, domain string, username string, password string, debug bool) {
37 | // Network
38 | s.host = host
39 | s.port = port
40 | // Credentials
41 | s.domain = domain
42 | s.username = username
43 | s.password = password
44 | // Config
45 | s.useldaps = useldaps
46 | s.debug = debug
47 | }
48 |
49 | func (s *Session) Connect() bool {
50 | // Check if TCP port is valid
51 | if s.port < 1 || s.port > 65535 {
52 | logger.Warn("Invalid port number. Port must be in the range 1-65535.")
53 | return false
54 | }
55 |
56 | // Set up LDAP connection
57 | var ldapConnection *ldap.Conn
58 | var err error
59 |
60 | // Check if LDAPS is available
61 | if s.useldaps {
62 | // LDAPS connection
63 | ldapConnection, err = ldap.DialURL(
64 | fmt.Sprintf("ldaps://%s:%d", s.host, s.port),
65 | ldap.DialWithTLSConfig(&tls.Config{
66 | InsecureSkipVerify: true,
67 | }),
68 | )
69 | if err != nil {
70 | logger.Warn(fmt.Sprintf("Error connecting to LDAPS server: %s", err))
71 | return false
72 | }
73 | //
74 | } else {
75 | // Regular LDAP connection
76 | ldapConnection, err = ldap.DialURL(fmt.Sprintf("ldap://%s:%d", s.host, s.port))
77 | if err != nil {
78 | logger.Warn(fmt.Sprintf("Error connecting to LDAP server: %s", err))
79 | return false
80 | }
81 | }
82 |
83 | // Bind with credentials if provided
84 | if len(s.password) > 0 {
85 | // Binding with credentials
86 | if s.debug {
87 | logger.Debug(fmt.Sprintf("Performing authenticated NTLM bind as '%s\\%s' ...", s.domain, s.username))
88 | }
89 | err = ldapConnection.NTLMBind(s.domain, s.username, s.password)
90 | if err != nil {
91 | logger.Warn(fmt.Sprintf("Error binding: %s", err))
92 | return false
93 | }
94 |
95 | } else {
96 | // Unauthenticated Bind
97 | bindDN := ""
98 | if s.username != "" {
99 | bindDN = fmt.Sprintf("%s@%s", s.username, s.domain)
100 | if s.debug {
101 | logger.Debug(fmt.Sprintf("Using bindDN: '%s'", bindDN))
102 | }
103 | }
104 |
105 | if s.debug {
106 | logger.Debug("Performing unauthenticated bind ...")
107 | }
108 | err = ldapConnection.UnauthenticatedBind(bindDN)
109 | if err != nil {
110 | logger.Warn(fmt.Sprintf("Error binding: %s", err))
111 | }
112 | }
113 |
114 | s.connection = ldapConnection
115 | return true
116 | }
117 |
118 | func (s *Session) ReConnect() bool {
119 | s.connection.Close()
120 | return s.Connect()
121 | }
122 |
123 | func GetRootDSE(ldapSession *Session) *ldap.Entry {
124 | // Specify LDAP search parameters
125 | // https://pkg.go.dev/gopkg.in/ldap.v3#NewSearchRequest
126 | searchRequest := ldap.NewSearchRequest(
127 | // Base DN blank
128 | "",
129 | // Scope Base
130 | ldap.ScopeBaseObject,
131 | // DerefAliases
132 | ldap.NeverDerefAliases,
133 | // SizeLimit
134 | 1,
135 | // TimeLimit
136 | 0,
137 | // TypesOnly
138 | false,
139 | // Search filter
140 | "(objectClass=*)",
141 | // Attributes to retrieve
142 | []string{"*"},
143 | // Controls
144 | nil,
145 | )
146 |
147 | // Perform LDAP search
148 | searchResult, err := ldapSession.connection.Search(searchRequest)
149 | if err != nil {
150 | logger.Warn(fmt.Sprintf("Error searching LDAP: %s", err))
151 | return nil
152 | }
153 |
154 | return searchResult.Entries[0]
155 | }
156 |
157 | func RawQuery(ldapSession *Session, baseDN string, query string, attributes []string, scope int) []*ldap.Entry {
158 | debug := false
159 |
160 | // Parsing parameters
161 | if len(baseDN) == 0 {
162 | baseDN = "defaultNamingContext"
163 | }
164 | if strings.ToLower(baseDN) == "defaultnamingcontext" {
165 | rootDSE := GetRootDSE(ldapSession)
166 | if debug {
167 | logger.Debug(fmt.Sprintf("Using defaultNamingContext %s ...\n", rootDSE.GetAttributeValue("defaultNamingContext")))
168 | }
169 | baseDN = rootDSE.GetAttributeValue("defaultNamingContext")
170 | } else if strings.ToLower(baseDN) == "configurationnamingcontext" {
171 | rootDSE := GetRootDSE(ldapSession)
172 | if debug {
173 | logger.Debug(fmt.Sprintf("Using configurationNamingContext %s ...\n", rootDSE.GetAttributeValue("configurationNamingContext")))
174 | }
175 | baseDN = rootDSE.GetAttributeValue("configurationNamingContext")
176 | } else if strings.ToLower(baseDN) == "schemanamingcontext" {
177 | rootDSE := GetRootDSE(ldapSession)
178 | if debug {
179 | logger.Debug(fmt.Sprintf("Using schemaNamingContext CN=Schema,%s ...\n", rootDSE.GetAttributeValue("configurationNamingContext")))
180 | }
181 | baseDN = fmt.Sprintf("CN=Schema,%s", rootDSE.GetAttributeValue("configurationNamingContext"))
182 |
183 | }
184 |
185 | if (scope != ldap.ScopeBaseObject) && (scope != ldap.ScopeSingleLevel) && (scope != ldap.ScopeWholeSubtree) {
186 | scope = ldap.ScopeWholeSubtree
187 | }
188 |
189 | // Specify LDAP search parameters
190 | // https://pkg.go.dev/gopkg.in/ldap.v3#NewSearchRequest
191 | searchRequest := ldap.NewSearchRequest(
192 | // Base DN
193 | baseDN,
194 | // Scope
195 | scope,
196 | // DerefAliases
197 | ldap.NeverDerefAliases,
198 | // SizeLimit
199 | 0,
200 | // TimeLimit
201 | 0,
202 | // TypesOnly
203 | false,
204 | // Search filter
205 | query,
206 | // Attributes to retrieve
207 | attributes,
208 | // Controls
209 | nil,
210 | )
211 |
212 | // Perform LDAP search
213 | searchResult, err := ldapSession.connection.SearchWithPaging(searchRequest, 1000)
214 | if err != nil {
215 | logger.Warn(fmt.Sprintf("Error searching LDAP: %s", err))
216 | return nil
217 | }
218 |
219 | return searchResult.Entries
220 | }
221 |
222 | func QueryBaseObject(ldapSession *Session, baseDN string, query string, attributes []string) []*ldap.Entry {
223 | entries := RawQuery(ldapSession, baseDN, query, attributes, ldap.ScopeBaseObject)
224 | return entries
225 | }
226 |
227 | func QuerySingleLevel(ldapSession *Session, baseDN string, query string, attributes []string) []*ldap.Entry {
228 | entries := RawQuery(ldapSession, baseDN, query, attributes, ldap.ScopeSingleLevel)
229 | return entries
230 | }
231 |
232 | func QueryWholeSubtree(ldapSession *Session, baseDN string, query string, attributes []string) []*ldap.Entry {
233 | entries := RawQuery(ldapSession, baseDN, query, attributes, ldap.ScopeWholeSubtree)
234 | return entries
235 | }
236 |
237 | func QueryAllNamingContexts(ldapSession *Session, query string, attributes []string, scope int) []*ldap.Entry {
238 | // Fetch the RootDSE entry to get the naming contexts
239 | rootDSE := GetRootDSE(ldapSession)
240 | if rootDSE == nil {
241 | // logger.Warn("Could not retrieve RootDSE.")
242 | return nil
243 | }
244 |
245 | // Retrieve the namingContexts attribute
246 | namingContexts := rootDSE.GetAttributeValues("namingContexts")
247 | if len(namingContexts) == 0 {
248 | //logger.Warn("No naming contexts found.")
249 | return nil
250 | }
251 |
252 | // Store all entries from all naming contexts
253 | var allEntries []*ldap.Entry
254 |
255 | // Iterate over each naming context and perform the query
256 | for _, context := range namingContexts {
257 | entries := RawQuery(ldapSession, context, query, attributes, scope)
258 | if entries != nil {
259 | allEntries = append(allEntries, entries...)
260 | }
261 | }
262 |
263 | return allEntries
264 | }
265 |
--------------------------------------------------------------------------------
/src/ldap/sid.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "encoding/binary"
5 | "fmt"
6 | "strings"
7 | )
8 |
9 | // ParseSIDFromBytes parses raw bytes representing an SID and returns the SID string
10 | func ParseSIDFromBytes(sidBytes []byte) string {
11 | debug := false
12 |
13 | // Ensure the SID has a valid format
14 | if len(sidBytes) < 8 || sidBytes[0] != 1 {
15 | return ""
16 | }
17 |
18 | // Extract revisionLevel
19 | revisionLevel := int(sidBytes[0])
20 | if debug {
21 | fmt.Printf("revisionLevel = 0x%02x\n", revisionLevel)
22 | fmt.Println(sidBytes[1:])
23 | }
24 | // Extract subAuthorityCount
25 | subAuthorityCount := int(sidBytes[1])
26 | if debug {
27 | fmt.Printf("subAuthorityCount = 0x%02x\n", subAuthorityCount)
28 | fmt.Println(sidBytes[2:])
29 | }
30 |
31 | // Extract identifierAuthority
32 | identifierAuthority := uint64(sidBytes[2+0]) << 40
33 | identifierAuthority |= uint64(sidBytes[2+1]) << 32
34 | identifierAuthority |= uint64(sidBytes[2+2]) << 24
35 | identifierAuthority |= uint64(sidBytes[2+3]) << 16
36 | identifierAuthority |= uint64(sidBytes[2+4]) << 8
37 | identifierAuthority |= uint64(sidBytes[2+5])
38 | if debug {
39 | fmt.Printf("identifierAuthority = 0x%08x\n", identifierAuthority)
40 | fmt.Println(sidBytes[8:])
41 | }
42 |
43 | // Extract subAuthorities
44 | subAuthorities := make([]string, 0)
45 | for k := 0; k < subAuthorityCount-1; k++ {
46 | subAuthority := binary.LittleEndian.Uint32(sidBytes[8+(4*k):])
47 | subAuthorities = append(subAuthorities, fmt.Sprintf("%d", subAuthority))
48 | if debug {
49 | fmt.Printf("subAuthority = 0x%08x\n", subAuthority)
50 | fmt.Println(sidBytes[8+(4*k):])
51 | }
52 | }
53 |
54 | // Parse the relativeIdentifier
55 | relativeIdentifier := binary.LittleEndian.Uint32(sidBytes[8+((subAuthorityCount-1)*4):])
56 | if debug {
57 | fmt.Printf("relativeIdentifier = 0x%08x\n", relativeIdentifier)
58 | fmt.Println(sidBytes[8+((subAuthorityCount-1)*4):])
59 | }
60 |
61 | // Construct the parsed SID
62 | parsedSID := fmt.Sprintf("S-%d-%d-%s-%d", revisionLevel, identifierAuthority, strings.Join(subAuthorities, "-"), relativeIdentifier)
63 |
64 | return parsedSID
65 | }
66 |
--------------------------------------------------------------------------------
/src/ldap/utils.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 | "strings"
7 | "time"
8 | )
9 |
10 | const UnixTimestampStart int64 = 116444736000000000 // Monday, January 1, 1601 12:00:00 AM
11 |
12 | func GetDomainFromDistinguishedName(distinguishedName string) string {
13 | domainParts := strings.Split(distinguishedName, ",")
14 |
15 | domain := ""
16 | for _, part := range domainParts {
17 | if strings.HasPrefix(part, "DC=") {
18 | domain += strings.TrimPrefix(part, "DC=") + "."
19 | }
20 | }
21 |
22 | domain = strings.TrimSuffix(domain, ".")
23 |
24 | return domain
25 | }
26 |
27 | func ConvertLDAPTimeStampToUnixTimeStamp(value string) int64 {
28 | convertedValue := int64(0)
29 |
30 | if len(value) != 0 {
31 | valueInt, err := strconv.ParseInt(value, 10, 64)
32 |
33 | if err != nil {
34 | fmt.Printf("[!] Error converting value to int64: %s\n", err)
35 | return convertedValue
36 | }
37 |
38 | if valueInt < UnixTimestampStart {
39 | // Typically for dates on year 1601
40 | convertedValue = 0
41 | } else {
42 | delta := int64((valueInt - UnixTimestampStart) * 100)
43 | convertedValue = int64(time.Unix(0, delta).Unix())
44 | }
45 | }
46 |
47 | return convertedValue
48 | }
49 |
50 | func ConvertLDAPDurationToSeconds(value string) int64 {
51 | convertedValue := int64(0)
52 |
53 | if len(value) != 0 {
54 | valueInt, err := strconv.ParseInt(value, 10, 64)
55 | if err != nil {
56 | fmt.Printf("[!] Error converting value to int64: %s\n", err)
57 | return convertedValue
58 | }
59 |
60 | if valueInt < 0 {
61 | valueInt = valueInt * int64(-1)
62 | }
63 |
64 | // Convert intervals of 100-nanoseconds to Seconds
65 | convertedValue = valueInt / int64(1e7)
66 | }
67 |
68 | return convertedValue
69 | }
70 |
71 | func ConvertSecondsToLDAPDuration(value int64) string {
72 | convertedValue := fmt.Sprintf("%d", value*int64(1e7))
73 | return convertedValue
74 | }
75 |
76 | func ConvertUnixTimeStampToLDAPTimeStamp(value time.Time) int64 {
77 | ldapvalue := value.Unix() * (1e7)
78 | ldapvalue = ldapvalue + UnixTimestampStart
79 | return int64(ldapvalue)
80 | }
81 |
--------------------------------------------------------------------------------
/src/logger/logger.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | func Info(message string) {
9 | currentTime := time.Now().Format("2006-01-02 15:04:05")
10 | fmt.Printf("[%s] INFO: %s\n", currentTime, message)
11 | }
12 |
13 | func Warn(message string) {
14 | currentTime := time.Now().Format("2006-01-02 15:04:05")
15 | fmt.Printf("[%s] WARN: %s\n", currentTime, message)
16 | }
17 |
18 | func Debug(message string) {
19 | currentTime := time.Now().Format("2006-01-02 15:04:05")
20 | fmt.Printf("[%s] DEBUG: %s\n", currentTime, message)
21 | }
22 |
--------------------------------------------------------------------------------
/src/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/TheManticoreProject/DescribeNTSecurityDescriptor/ldap"
7 | "github.com/TheManticoreProject/DescribeNTSecurityDescriptor/logger"
8 |
9 | "encoding/base64"
10 | "encoding/hex"
11 | "fmt"
12 |
13 | "github.com/TheManticoreProject/goopts/parser"
14 | "github.com/TheManticoreProject/winacl/securitydescriptor"
15 | )
16 |
17 | var (
18 | // Configuration
19 | useLdaps bool
20 | debug bool
21 |
22 | // Network settings
23 | domainController string
24 | ldapPort int
25 |
26 | // Authentication details
27 | authDomain string
28 | authUsername string
29 | authPassword string
30 | authHashes string
31 |
32 | // Source values
33 | distinguishedName string
34 |
35 | sourceFileHex string
36 | sourceFileBase64 string
37 | sourceFileRaw string
38 | valueHex string
39 | valueBase64 string
40 | )
41 |
42 | func parseArgs() {
43 | ap := parser.ArgumentsParser{Banner: "DescribeNTSecurityDescriptor - by Remi GASCOU (Podalirius) @ TheManticoreProject - v1.3.0"}
44 |
45 | // Configuration flags
46 | ap.NewBoolArgument(&debug, "-d", "--debug", false, "Debug mode.")
47 |
48 | // Source value
49 | group_sourceValues, err := ap.NewRequiredMutuallyExclusiveArgumentGroup("Source Values")
50 | if err != nil {
51 | fmt.Printf("[error] Error creating ArgumentGroup: %s\n", err)
52 | } else {
53 | group_sourceValues.NewStringArgument(&distinguishedName, "-D", "--distinguished-name", "", false, "Distinguished Name.")
54 | // File sources
55 | group_sourceValues.NewStringArgument(&sourceFileHex, "-fh", "--file-hex", "", false, "Path to file containing the hexadecimal string value of NTSecurityDescriptor.")
56 | group_sourceValues.NewStringArgument(&sourceFileBase64, "-fb", "--file-base64", "", false, "Path to file containing the base64 encoded value of NTSecurityDescriptor.")
57 | group_sourceValues.NewStringArgument(&sourceFileRaw, "-fr", "--file-raw", "", false, "Path to file containing the raw binary value of NTSecurityDescriptor.")
58 | // Value sources
59 | group_sourceValues.NewStringArgument(&valueHex, "-vh", "--value-hex", "", false, "Raw hexadecimal string value of NTSecurityDescriptor.")
60 | group_sourceValues.NewStringArgument(&valueBase64, "-vb", "--value-base64", "", false, "Raw base64 encoded value of NTSecurityDescriptor.")
61 | }
62 |
63 | group_ldapSettings, err := ap.NewArgumentGroup("LDAP Connection Settings")
64 | if err != nil {
65 | fmt.Printf("[error] Error creating ArgumentGroup: %s\n", err)
66 | } else {
67 | group_ldapSettings.NewStringArgument(&domainController, "-dc", "--dc-ip", "", false, "IP Address of the domain controller or KDC (Key Distribution Center) for Kerberos. If omitted, it will use the domain part (FQDN) specified in the identity parameter.")
68 | group_ldapSettings.NewTcpPortArgument(&ldapPort, "-P", "--port", 389, false, "Port number to connect to LDAP server.")
69 | group_ldapSettings.NewBoolArgument(&useLdaps, "-l", "--use-ldaps", false, "Use LDAPS instead of LDAP.")
70 | }
71 |
72 | group_auth, err := ap.NewArgumentGroup("Authentication")
73 | if err != nil {
74 | fmt.Printf("[error] Error creating ArgumentGroup: %s\n", err)
75 | } else {
76 | group_auth.NewStringArgument(&authDomain, "-d", "--domain", "", false, "Active Directory domain to authenticate to.")
77 | group_auth.NewStringArgument(&authUsername, "-u", "--username", "", false, "User to authenticate as.")
78 | group_auth.NewStringArgument(&authPassword, "-p", "--password", "", false, "Password to authenticate with.")
79 | group_auth.NewStringArgument(&authHashes, "-H", "--hashes", "", false, "NT/LM hashes, format is LMhash:NThash.")
80 | }
81 |
82 | ap.Parse()
83 |
84 | if useLdaps && !group_ldapSettings.LongNameToArgument["--port"].IsPresent() {
85 | ldapPort = 636
86 | }
87 |
88 | if len(distinguishedName) != 0 && (len(domainController) == 0 || len(authUsername) == 0 || len(authPassword) == 0) {
89 | logger.Warn("Error: Options --dc-ip, --username, --password are required when using --distinguished-name.")
90 | os.Exit(1)
91 | }
92 | }
93 |
94 | func main() {
95 | parseArgs()
96 |
97 | rawNtsdValue := []byte{}
98 |
99 | // Parsing input values for hex format
100 | if len(rawNtsdValue) == 0 && (len(sourceFileHex) != 0 || len(valueHex) != 0) {
101 | value_hex_string := ""
102 | if len(valueHex) != 0 {
103 | value_hex_string = valueHex
104 | }
105 | if len(sourceFileHex) != 0 {
106 | data, err := os.ReadFile(sourceFileHex)
107 | if err != nil {
108 | logger.Warn(fmt.Sprintf("Error reading file: %s", err))
109 | return
110 | }
111 | value_hex_string = string(data)
112 | }
113 | // Decoding the hex string
114 | if len(value_hex_string) != 0 {
115 | if len(value_hex_string)%2 == 1 {
116 | // encoding/hex: odd length hex string
117 | value_hex_string = value_hex_string + "0"
118 | }
119 | value, err := hex.DecodeString(value_hex_string)
120 | if err != nil {
121 | logger.Warn(fmt.Sprintf("Error decoding Hex value: %s", err))
122 | return
123 | } else {
124 | rawNtsdValue = value
125 | }
126 | }
127 | }
128 |
129 | // Parsing input values for base64 format
130 | if len(rawNtsdValue) == 0 && (len(sourceFileBase64) != 0 || len(valueBase64) != 0) {
131 | value_base64_string := ""
132 | if len(valueBase64) != 0 {
133 | value_base64_string = valueBase64
134 | }
135 | if len(sourceFileBase64) != 0 {
136 | data, err := os.ReadFile(sourceFileBase64)
137 | if err != nil {
138 | logger.Warn(fmt.Sprintf("Error reading file: %s", err))
139 | return
140 | }
141 | value_base64_string = string(data)
142 | }
143 |
144 | // Decoding the base64 string
145 | if len(value_base64_string) != 0 {
146 | value, err := base64.StdEncoding.DecodeString(value_base64_string)
147 | if err != nil {
148 | logger.Warn(fmt.Sprintf("Error decoding Base64 value: %s", err))
149 | return
150 | } else {
151 | rawNtsdValue = value
152 | }
153 | }
154 | }
155 |
156 | // Parsing input values for raw format
157 | if len(rawNtsdValue) == 0 && len(sourceFileRaw) != 0 {
158 | data, err := os.ReadFile(sourceFileRaw)
159 | if err != nil {
160 | logger.Warn(fmt.Sprintf("Error reading file: %s", err))
161 | return
162 | }
163 | rawNtsdValue = data
164 | }
165 |
166 | if len(rawNtsdValue) == 0 && len(distinguishedName) != 0 {
167 | // Parsing input values for Distinguished Name
168 | if debug {
169 | if !useLdaps {
170 | logger.Debug(fmt.Sprintf("Connecting to remote ldap://%s:%d ...", domainController, ldapPort))
171 | } else {
172 | logger.Debug(fmt.Sprintf("Connecting to remote ldaps://%s:%d ...", domainController, ldapPort))
173 | }
174 | }
175 | ldapSession := ldap.Session{}
176 | ldapSession.InitSession(
177 | domainController,
178 | ldapPort,
179 | useLdaps,
180 | authDomain,
181 | authUsername,
182 | authPassword,
183 | debug,
184 | )
185 | connected := ldapSession.Connect()
186 |
187 | if connected {
188 | logger.Info(fmt.Sprintf("Connected as '%s\\%s'", authDomain, authUsername))
189 |
190 | query := fmt.Sprintf("(distinguishedName=%s)", distinguishedName)
191 |
192 | if debug {
193 | logger.Debug(fmt.Sprintf("LDAP query used: %s", query))
194 | }
195 |
196 | attributes := []string{"distinguishedName", "ntSecurityDescriptor"}
197 | ldapResults := ldap.QueryWholeSubtree(&ldapSession, "", query, attributes)
198 |
199 | for _, entry := range ldapResults {
200 | if debug {
201 | logger.Debug(fmt.Sprintf("| distinguishedName: %s", entry.GetAttributeValue("distinguishedName")))
202 | }
203 | rawNtsdValue = entry.GetEqualFoldRawAttributeValue("ntSecurityDescriptor")
204 | }
205 | } else {
206 | if debug {
207 | logger.Warn("Error: Could not create ldapSession.")
208 | }
209 | }
210 | }
211 |
212 | if len(rawNtsdValue) != 0 {
213 | ntSecurityDescriptor := securitydescriptor.NtSecurityDescriptor{}
214 | logger.Debug(fmt.Sprintf("| ntSecurityDescriptor: %s", hex.EncodeToString(rawNtsdValue)))
215 | ntSecurityDescriptor.Parse(rawNtsdValue)
216 | ntSecurityDescriptor.Describe(0)
217 | } else {
218 | logger.Warn("No NTSecurityDescriptor found in source values.")
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/src/windows/RelativeIDs.go:
--------------------------------------------------------------------------------
1 | package windows
2 |
3 | // Predefined RIDs
4 | // Src: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/565a6584-3061-4ede-a531-f5c53826504b
5 | const (
6 | RID_DOMAIN_USER_KRBTGT = 0x000001F6
7 | RID_DOMAIN_USER_ADMIN = 0x000001F4
8 | RID_DOMAIN_USER_GUEST = 0x000001F5
9 | RID_DOMAIN_GROUP_ADMINS = 0x00000200
10 | RID_DOMAIN_GROUP_USERS = 0x00000201
11 | RID_DOMAIN_GROUP_GUESTS = 0x00000202
12 | RID_DOMAIN_GROUP_COMPUTERS = 0x00000203
13 | RID_DOMAIN_GROUP_CONTROLLERS = 0x00000204
14 | RID_DOMAIN_GROUP_CERT_PUBLISHERS = 0x00000205
15 | RID_DOMAIN_GROUP_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS = 0x000001F2
16 | RID_DOMAIN_GROUP_SCHEMA_ADMINS = 0x00000206
17 | RID_DOMAIN_GROUP_ENTERPRISE_ADMINS = 0x00000207
18 | RID_DOMAIN_GROUP_POLICY_ADMINS = 0x00000208
19 | RID_DOMAIN_GROUP_READONLY_CONTROLLERS = 0x00000209
20 | RID_DOMAIN_GROUP_CLONEABLE_CONTROLLERS = 0x0000020A
21 | RID_DOMAIN_GROUP_CDC_RESERVED = 0x0000020C
22 | RID_DOMAIN_GROUP_PROTECTED_USERS = 0x0000020D
23 | RID_DOMAIN_GROUP_KEY_ADMINS = 0x0000020E
24 | RID_DOMAIN_GROUP_ENTERPRISE_KEY_ADMINS = 0x0000020F
25 | RID_DOMAIN_GROUP_DENIED_RODC_PASSWORD_REPLICATION = 0x0000023C
26 | RID_DOMAIN_GROUP_ALIAS_CERTSVC_DCOM_ACCESS = 0x0000023E
27 | )
28 |
29 | var DomainRIDs = []int{
30 | RID_DOMAIN_USER_KRBTGT,
31 | RID_DOMAIN_USER_ADMIN,
32 | RID_DOMAIN_USER_GUEST,
33 | RID_DOMAIN_GROUP_ADMINS,
34 | RID_DOMAIN_GROUP_USERS,
35 | RID_DOMAIN_GROUP_GUESTS,
36 | RID_DOMAIN_GROUP_COMPUTERS,
37 | RID_DOMAIN_GROUP_CONTROLLERS,
38 | RID_DOMAIN_GROUP_CERT_PUBLISHERS,
39 | RID_DOMAIN_GROUP_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS,
40 | RID_DOMAIN_GROUP_SCHEMA_ADMINS,
41 | RID_DOMAIN_GROUP_ENTERPRISE_ADMINS,
42 | RID_DOMAIN_GROUP_POLICY_ADMINS,
43 | RID_DOMAIN_GROUP_READONLY_CONTROLLERS,
44 | RID_DOMAIN_GROUP_CLONEABLE_CONTROLLERS,
45 | RID_DOMAIN_GROUP_CDC_RESERVED,
46 | RID_DOMAIN_GROUP_PROTECTED_USERS,
47 | RID_DOMAIN_GROUP_KEY_ADMINS,
48 | RID_DOMAIN_GROUP_ENTERPRISE_KEY_ADMINS,
49 | RID_DOMAIN_GROUP_DENIED_RODC_PASSWORD_REPLICATION,
50 | RID_DOMAIN_GROUP_ALIAS_CERTSVC_DCOM_ACCESS,
51 | }
52 |
53 | // Local RID
54 | // Src: https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids
55 | const (
56 | RID_LOCAL_ADMINS = 0x00000220
57 | RID_LOCAL_USERS = 0x00000221
58 | RID_LOCAL_GUESTS = 0x00000222
59 | RID_LOCAL_POWER_USERS = 0x00000223
60 | RID_LOCAL_ACCOUNT_OPS = 0x00000224
61 | RID_LOCAL_SERVER_OPS = 0x00000225
62 | RID_LOCAL_PRINT_OPS = 0x00000226
63 | RID_LOCAL_BACKUP_OPS = 0x00000227
64 | RID_LOCAL_REPLICATOR = 0x00000228
65 | RID_LOCAL_RAS_SERVERS = 0x00000229
66 | RID_LOCAL_PREW2KCOMPACCESS = 0x0000022A
67 | RID_LOCAL_REMOTE_DESKTOP_USERS = 0x0000022B
68 | RID_LOCAL_NETWORK_CONFIGURATION_OPS = 0x0000022C
69 | RID_LOCAL_INCOMING_FOREST_TRUST_BUILDERS = 0x0000022D
70 | RID_LOCAL_MONITORING_USERS = 0x0000022E
71 | RID_LOCAL_LOGGING_USERS = 0x0000022F
72 | RID_LOCAL_AUTHORIZATIONACCESS = 0x00000230
73 | RID_LOCAL_TS_LICENSE_SERVERS = 0x00000231
74 | RID_LOCAL_DCOM_USERS = 0x00000232
75 | RID_LOCAL_IUSERS = 0x00000238
76 | RID_LOCAL_CRYPTO_OPERATORS = 0x00000239
77 | RID_LOCAL_CACHEABLE_PRINCIPALS_GROUP = 0x0000023B
78 | RID_LOCAL_NON_CACHEABLE_PRINCIPALS_GROUP = 0x0000023C
79 | RID_LOCAL_EVENT_LOG_READERS_GROUP = 0x0000023D
80 | RID_LOCAL_CERTSVC_DCOM_ACCESS_GROUP = 0x0000023E
81 | RID_LOCAL_RDS_REMOTE_ACCESS_SERVERS = 0x0000023F
82 | RID_LOCAL_RDS_ENDPOINT_SERVERS = 0x00000240
83 | RID_LOCAL_RDS_MANAGEMENT_SERVERS = 0x00000241
84 | RID_LOCAL_HYPER_V_ADMINS = 0x00000242
85 | RID_LOCAL_ACCESS_CONTROL_ASSISTANCE_OPS = 0x00000243
86 | RID_LOCAL_REMOTE_MANAGEMENT_USERS = 0x00000244
87 | RID_LOCAL_DEFAULT_ACCOUNT = 0x00000245
88 | RID_LOCAL_STORAGE_REPLICA_ADMINS = 0x00000246
89 | RID_LOCAL_DEVICE_OWNERS = 0x00000247
90 | )
91 |
92 | var LocalRIDs = []int{
93 | RID_LOCAL_ADMINS,
94 | RID_LOCAL_USERS,
95 | RID_LOCAL_GUESTS,
96 | RID_LOCAL_POWER_USERS,
97 | RID_LOCAL_ACCOUNT_OPS,
98 | RID_LOCAL_SERVER_OPS,
99 | RID_LOCAL_PRINT_OPS,
100 | RID_LOCAL_BACKUP_OPS,
101 | RID_LOCAL_REPLICATOR,
102 | RID_LOCAL_RAS_SERVERS,
103 | RID_LOCAL_PREW2KCOMPACCESS,
104 | RID_LOCAL_REMOTE_DESKTOP_USERS,
105 | RID_LOCAL_NETWORK_CONFIGURATION_OPS,
106 | RID_LOCAL_INCOMING_FOREST_TRUST_BUILDERS,
107 | RID_LOCAL_MONITORING_USERS,
108 | RID_LOCAL_LOGGING_USERS,
109 | RID_LOCAL_AUTHORIZATIONACCESS,
110 | RID_LOCAL_TS_LICENSE_SERVERS,
111 | RID_LOCAL_DCOM_USERS,
112 | RID_LOCAL_IUSERS,
113 | RID_LOCAL_CRYPTO_OPERATORS,
114 | RID_LOCAL_CACHEABLE_PRINCIPALS_GROUP,
115 | RID_LOCAL_NON_CACHEABLE_PRINCIPALS_GROUP,
116 | RID_LOCAL_EVENT_LOG_READERS_GROUP,
117 | RID_LOCAL_CERTSVC_DCOM_ACCESS_GROUP,
118 | RID_LOCAL_RDS_REMOTE_ACCESS_SERVERS,
119 | RID_LOCAL_RDS_ENDPOINT_SERVERS,
120 | RID_LOCAL_RDS_MANAGEMENT_SERVERS,
121 | RID_LOCAL_HYPER_V_ADMINS,
122 | RID_LOCAL_ACCESS_CONTROL_ASSISTANCE_OPS,
123 | RID_LOCAL_REMOTE_MANAGEMENT_USERS,
124 | RID_LOCAL_DEFAULT_ACCOUNT,
125 | RID_LOCAL_STORAGE_REPLICA_ADMINS,
126 | RID_LOCAL_DEVICE_OWNERS,
127 | }
128 |
--------------------------------------------------------------------------------
/src/windows/sAMAccountType.go:
--------------------------------------------------------------------------------
1 | package windows
2 |
3 | // sAMAccountType Values
4 | // Src: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/e742be45-665d-4576-b872-0bc99d1e1fbe
5 | const (
6 | SAM_DOMAIN_OBJECT = 0x00000000
7 | SAM_GROUP_OBJECT = 0x10000000
8 | SAM_NON_SECURITY_GROUP_OBJECT = 0x10000001
9 | SAM_ALIAS_OBJECT = 0x20000000
10 | SAM_NON_SECURITY_ALIAS_OBJECT = 0x20000001
11 | SAM_USER_OBJECT = 0x30000000
12 | SAM_MACHINE_ACCOUNT = 0x30000001
13 | SAM_TRUST_ACCOUNT = 0x30000002
14 | SAM_APP_BASIC_GROUP = 0x40000000
15 | SAM_APP_QUERY_GROUP = 0x40000001
16 | )
17 |
--------------------------------------------------------------------------------