├── .github
├── pull_request_template.md
└── workflows
│ ├── build.yml
│ ├── cla.yml
│ └── publish.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Directory.Build.props
├── Dockerfile
├── LICENSE
├── README.md
├── SharpHoundCommon.sln
├── docfx
├── CONTRIBUTING.md
├── Docfx.csproj
├── api
│ └── index.md
├── coverage
│ └── index.md
├── docfx.json
├── index.md
├── templates
│ └── discordfx
│ │ ├── layout
│ │ └── _master.tmpl
│ │ ├── partials
│ │ ├── footer.tmpl.partial
│ │ ├── head.tmpl.partial
│ │ ├── li.tmpl.partial
│ │ ├── logo.tmpl.partial
│ │ ├── navbar.tmpl.partial
│ │ ├── scripts.tmpl.partial
│ │ └── toc.tmpl.partial
│ │ └── styles
│ │ ├── colors.css
│ │ ├── discord.css
│ │ ├── down-arrow.svg
│ │ ├── jquery.twbsPagination.js
│ │ ├── main.css
│ │ ├── main.js
│ │ └── url.min.js
└── toc.yml
├── nuget.config
├── sleet.json
├── src
├── CommonLib
│ ├── AsyncEnumerable.cs
│ ├── CSVComputerStatus.cs
│ ├── Cache.cs
│ ├── CommonLib.cs
│ ├── ConcurrentHashSet.cs
│ ├── ConnectionPoolManager.cs
│ ├── DirectoryObjects
│ │ ├── DirectoryEntryWrapper.cs
│ │ ├── DirectoryObjectExtensions.cs
│ │ ├── IDirectoryObject.cs
│ │ └── SearchResultEntryWrapper.cs
│ ├── Enums
│ │ ├── CAExtensionTypes.cs
│ │ ├── CertificationAuthorityRights.cs
│ │ ├── CollectionMethod.cs
│ │ ├── CommonOids.cs
│ │ ├── DataType.cs
│ │ ├── DirectoryPaths.cs
│ │ ├── EdgeNames.cs
│ │ ├── EventIds.cs
│ │ ├── KerberosEncryptionTypes.cs
│ │ ├── LDAPProperties.cs
│ │ ├── LSAPrivileges.cs
│ │ ├── Labels.cs
│ │ ├── LdapErrorCodes.cs
│ │ ├── LdapFailureReason.cs
│ │ ├── LdapOption.cs
│ │ ├── LdapOptionValue.cs
│ │ ├── LdapSupportedSaslMechanisms.cs
│ │ ├── NamingContext.cs
│ │ ├── ObjectClass.cs
│ │ ├── PKICertificateAuthorityFlags.cs
│ │ ├── PKICertificateNameFlag.cs
│ │ ├── PKIEnrollmentFlag.cs
│ │ ├── PKIPrivateKeyFlag.cs
│ │ ├── TrustAttributes.cs
│ │ ├── TrustDirection.cs
│ │ ├── TrustType.cs
│ │ └── UAC.cs
│ ├── Exceptions
│ │ ├── LdapAuthenticationException.cs
│ │ ├── LdapConnectionException.cs
│ │ └── NoLdapDataException.cs
│ ├── Extensions.cs
│ ├── Helpers.cs
│ ├── ILdapUtils.cs
│ ├── IRegistryKey.cs
│ ├── Impersonate.cs
│ ├── LdapConfig.cs
│ ├── LdapConnectionPool.cs
│ ├── LdapConnectionWrapper.cs
│ ├── LdapProducerQueryGenerator.cs
│ ├── LdapQueries
│ │ ├── CommonFilters.cs
│ │ ├── CommonPaths.cs
│ │ ├── CommonProperties.cs
│ │ └── LdapFilter.cs
│ ├── LdapQueryParameters.cs
│ ├── LdapQuerySetupResult.cs
│ ├── LdapResult.cs
│ ├── LdapUtils.cs
│ ├── Logging
│ │ ├── Logging.cs
│ │ ├── NoOpLogger.cs
│ │ └── PassThroughLogger.cs
│ ├── NativeMethods.cs
│ ├── Ntlm
│ │ ├── HttpClientFactory.cs
│ │ ├── HttpNtlmAuthenticationService.cs
│ │ ├── HttpTransport.cs
│ │ ├── INtlmTransport.cs
│ │ ├── LdapNative.cs
│ │ ├── LdapNativeException.cs
│ │ ├── LdapTransport.cs
│ │ └── NtlmAuthenticationHandler.cs
│ ├── OutputTypes
│ │ ├── ACE.cs
│ │ ├── AIACA.cs
│ │ ├── APIResult.cs
│ │ ├── APIResults
│ │ │ ├── AceRegistryAPIResult.cs
│ │ │ ├── BoolRegistryAPIResult.cs
│ │ │ ├── EnrollmentAgentRegistryAPIResult.cs
│ │ │ ├── IntRegistryAPIResult.cs
│ │ │ ├── LSAPrivilegeAPIResult.cs
│ │ │ ├── LocalGroupAPIResult.cs
│ │ │ ├── SessionAPIResult.cs
│ │ │ └── UserRightsAssignmentAPIResult.cs
│ │ ├── CAHttpEndpoint.cs
│ │ ├── CARegistryData.cs
│ │ ├── CertTemplate.cs
│ │ ├── CertificateExtension.cs
│ │ ├── Computer.cs
│ │ ├── Container.cs
│ │ ├── Domain.cs
│ │ ├── DomainController.cs
│ │ ├── DomainTrust.cs
│ │ ├── EnterpriseCA.cs
│ │ ├── GPLink.cs
│ │ ├── GPO.cs
│ │ ├── Group.cs
│ │ ├── IssuancePolicy.cs
│ │ ├── LocalGroup.cs
│ │ ├── MetaTag.cs
│ │ ├── NTAuthStore.cs
│ │ ├── NamedPrincipal.cs
│ │ ├── NtlmSession.cs
│ │ ├── OU.cs
│ │ ├── OutputBase.cs
│ │ ├── OutputWrapper.cs
│ │ ├── RegistryData.cs
│ │ ├── ResultingGPOChanges.cs
│ │ ├── RootCA.cs
│ │ ├── SPNPrivilege.cs
│ │ ├── Session.cs
│ │ ├── TypedPrincipal.cs
│ │ └── User.cs
│ ├── Processors
│ │ ├── ACEGuids.cs
│ │ ├── ACLProcessor.cs
│ │ ├── CAEnrollmentProcessor.cs
│ │ ├── CachedLocalItem.cs
│ │ ├── CertAbuseProcessor.cs
│ │ ├── ComputerAvailability.cs
│ │ ├── ComputerSessionProcessor.cs
│ │ ├── ContainerProcessor.cs
│ │ ├── DCLdapProcessor.cs
│ │ ├── DCRegistryProcessor.cs
│ │ ├── DomainTrustProcessor.cs
│ │ ├── EventLogProcessor.cs
│ │ ├── GPOLocalGroupProcessor.cs
│ │ ├── GroupProcessor.cs
│ │ ├── LdapPropertyProcessor.cs
│ │ ├── LocalGroupProcessor.cs
│ │ ├── PortScanner.cs
│ │ ├── RegistryProcessor.cs
│ │ ├── RegistryResult.cs
│ │ ├── SPNProcessors.cs
│ │ ├── SmbProcessor.cs
│ │ ├── UserRightsAssignmentProcessor.cs
│ │ └── WebClientServiceProcessor.cs
│ ├── ResolvedSearchResult.cs
│ ├── Result.cs
│ ├── SMB
│ │ ├── NetBIOS
│ │ │ ├── NetBIOSHeader.cs
│ │ │ └── NetBIOSSessionType.cs
│ │ ├── SMB1
│ │ │ ├── SMB1Command.cs
│ │ │ ├── SMB1Dialect.cs
│ │ │ ├── SMB1Flags.cs
│ │ │ ├── SMB1Flags2.cs
│ │ │ ├── SMB1Header.cs
│ │ │ └── SMB1NegotiateRequest.cs
│ │ ├── SMB2
│ │ │ ├── SMB2CompressionAlgorithm.cs
│ │ │ ├── SMB2Constants.cs
│ │ │ ├── SMB2Dialect.cs
│ │ │ ├── SMB2EncryptionAlgorithm.cs
│ │ │ ├── SMB2HashAlgorithm.cs
│ │ │ ├── SMB2Header.cs
│ │ │ ├── SMB2NegotiateContexts.cs
│ │ │ ├── SMB2NegotiateRequest.cs
│ │ │ ├── SMB2RdmaTransformType.cs
│ │ │ └── SMB2SigningAlgorithm.cs
│ │ └── SmbScanner.cs
│ ├── SecurityDescriptor.cs
│ ├── SharpHoundCommonLib.csproj
│ ├── ThirdParty
│ │ └── PSOpenAD
│ │ │ ├── Authentication.cs
│ │ │ └── SSPI.cs
│ ├── WellKnownPrincipal.cs
│ └── packages.config
└── SharpHoundRPC
│ ├── Extensions.cs
│ ├── Handles
│ ├── BasePointer.cs
│ ├── LSAHandle.cs
│ ├── LSAPointer.cs
│ ├── NetAPIPointer.cs
│ ├── SAMHandle.cs
│ ├── SAMPointer.cs
│ └── SAMSidArray.cs
│ ├── LSANative
│ ├── LSAEnums.cs
│ ├── LSAMethods.cs
│ ├── LSAStructs.cs
│ └── UserRights.cs
│ ├── NTStatus.cs
│ ├── NetAPINative
│ ├── NetAPIEnums.cs
│ ├── NetAPIMethods.cs
│ ├── NetAPIResult.cs
│ ├── NetAPIReturns.cs
│ └── NetAPIStructs.cs
│ ├── PortScanner
│ └── IPortScanner.cs
│ ├── RPCException.cs
│ ├── Registry
│ ├── DotNetWmiRegistryStrategy.cs
│ ├── ICollectionStrategy.cs
│ ├── NativeUtils.cs
│ ├── RegistryQuery.cs
│ ├── RegistryQueryResult.cs
│ ├── RemoteRegistryStrategy.cs
│ ├── StrategyExecutor.cs
│ ├── StrategyExecutorResult.cs
│ └── StrategyResult.cs
│ ├── Result.cs
│ ├── SAMRPCNative
│ ├── SAMEnums.cs
│ ├── SAMMethods.cs
│ └── SAMStructs.cs
│ ├── Shared
│ ├── SharedEnums.cs
│ └── SharedStructs.cs
│ ├── SharpHoundRPC.csproj
│ └── Wrappers
│ ├── ILSAPolicy.cs
│ ├── ISAMAlias.cs
│ ├── ISAMDomain.cs
│ ├── ISAMServer.cs
│ ├── LSABase.cs
│ ├── LSAPolicy.cs
│ ├── SAMAlias.cs
│ ├── SAMBase.cs
│ ├── SAMDomain.cs
│ └── SAMServer.cs
└── test
└── unit
├── .gitignore
├── ACLProcessorTest.cs
├── AsyncEnumerableTests.cs
├── CAEnrollmentProcessorTest.cs
├── CacheTest.cs
├── CertAbuseProcessorTest.cs
├── CommonLibHelperTests.cs
├── CommonLibTest.csproj
├── ComputerAvailabilityTests.cs
├── ComputerSessionProcessorTest.cs
├── ContainerProcessorTest.cs
├── DCLdapProcessorTest.cs
├── DirectoryObjectTests.cs
├── DomainTrustProcessorTest.cs
├── Facades
├── Consts.cs
├── FacadeHelpers.cs
├── LSAMocks
│ ├── DCMocks
│ │ └── MockDCLSAPolicy.cs
│ ├── ErrorCaseMocks
│ │ ├── MockFailLSAPolicy_GetLocalDomainInformation.cs
│ │ └── MockFailLSAPolicy_GetResolvedPrincipalsWithPrivilege.cs
│ └── WorkstationMocks
│ │ └── MockWorkstationLSAPolicy.cs
├── MockDirectoryObject.cs
├── MockExtentions.cs
├── MockLdapUtils.cs
├── MockSAMDomain.cs
├── MockableDomain.cs
├── MockableForest.cs
├── MockableSearchResultEntry.cs
└── SAMMocks
│ ├── DCMocks
│ ├── MockDCAliasAdministrators.cs
│ ├── MockDCAliasUsers.cs
│ ├── MockDCDomainBuiltIn.cs
│ └── MockDCSAMServer.cs
│ ├── ErrorCaseMocks
│ └── LocalGroupProcessorErrorCases
│ │ ├── MockFailAliasAdministrators_PreviouslyCached.cs
│ │ ├── MockFailAlias_PreviouslyCached.cs
│ │ ├── MockFailDomainBuiltIn_GetAliases.cs
│ │ ├── MockFailDomainBuiltIn_GetMembers.cs
│ │ ├── MockFailDomainBuiltIn_OpenAlias.cs
│ │ ├── MockFailDomainBuiltIn_PreviouslyCached.cs
│ │ ├── MockFailSAMAliasUsers_GetMembers.cs
│ │ ├── MockFailSAMServer_GetAliases.cs
│ │ ├── MockFailSAMServer_GetDomains.cs
│ │ ├── MockFailSAMServer_GetMachineSid.cs
│ │ ├── MockFailSAMServer_GetMembers.cs
│ │ ├── MockFailSAMServer_LookupPrincipalBySid.cs
│ │ ├── MockFailSAMServer_OpenAlias.cs
│ │ ├── MockFailSAMServer_OpenDomain.cs
│ │ └── MockFailSAMServer_PreviouslyCached.cs
│ └── WorkstationMocks
│ ├── MockWorkstationAliasAdministrators.cs
│ ├── MockWorkstationAliasRDP.cs
│ ├── MockWorkstationAliasTestGroup.cs
│ ├── MockWorkstationDomainBuiltIn.cs
│ ├── MockWorkstationDomainWIN10.cs
│ └── MockWorkstationSAMServer.cs
├── GPOLocalGroupProcessorTest.cs
├── GroupProcessorTest.cs
├── HttpNtlmAuthenticationServiceTest.cs
├── LDAPFilterTest.cs
├── LDAPUtilsTest.cs
├── LdapConnectionPoolTest.cs
├── LdapPropertyTests.cs
├── LocalGroupProcessorTest.cs
├── SMBScannerTest.cs
├── SPNProcessorsTest.cs
├── SmbProcessorTest.cs
├── SmokeTest.cs
├── TestLogger.cs
├── TestPrivateMethod.cs
├── UserRightsAssignmentProcessorTest.cs
├── Utils.cs
├── WebClientServiceProcessorTest.cs
└── WellKnownPrincipalTest.cs
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 |
4 |
5 | ## Motivation and Context
6 |
7 |
8 |
9 |
10 | ## How Has This Been Tested?
11 |
12 |
13 |
14 |
15 |
16 | ## Screenshots (if appropriate):
17 |
18 | ## Types of changes
19 |
20 |
21 |
22 | - [ ] Chore (a change that does not modify the application functionality)
23 | - [ ] Bug fix (non-breaking change which fixes an issue)
24 | - [ ] New feature (non-breaking change which adds functionality)
25 | - [ ] Breaking change (fix or feature that would cause existing functionality to change)
26 |
27 | ## Checklist:
28 |
29 |
30 |
31 |
32 | - [ ] Documentation updates are needed, and have been made accordingly.
33 | - [ ] I have added and/or updated tests to cover my changes.
34 | - [ ] All new and existing tests passed.
35 | - [ ] My changes include a database migration.
36 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | runs-on: windows-latest
8 | steps:
9 | - uses: actions/checkout@v3
10 |
11 | - name: Setup .NET
12 | uses: actions/setup-dotnet@v3
13 | with:
14 | dotnet-version: |
15 | 7.0.x
16 | 5.0.x
17 |
18 | - name: Restore dependencies
19 | run: dotnet restore
20 |
21 | - name: Build
22 | run: dotnet build
23 |
24 | - name: Test
25 | run: dotnet test
26 |
--------------------------------------------------------------------------------
/.github/workflows/cla.yml:
--------------------------------------------------------------------------------
1 | name: "CLA Assistant"
2 | on:
3 | issue_comment:
4 | types: [created]
5 | pull_request_target:
6 | types: [opened,closed,synchronize]
7 |
8 | jobs:
9 | CLAssistant:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: "CLA Assistant"
13 | if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
14 | uses: contributor-assistant/github-action@v2.2.1
15 | env:
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 | PERSONAL_ACCESS_TOKEN : ${{ secrets.REPO_SCOPE }}
18 | with:
19 | path-to-signatures: 'signatures.json'
20 | path-to-document: 'https://github.com/BloodHoundAD/CLA/blob/main/ICLA.md'
21 | branch: 'main'
22 | remote-organization-name: BloodHoundAD
23 | remote-repository-name: CLA
24 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # SharpHoundCommon Contributing Guide
2 |
3 | ## Prerequisites
4 |
5 | ### Tools
6 |
7 | - [.NET SDK](https://docs.microsoft.com/en-us/dotnet/core/install/)
8 |
9 | ## Build
10 |
11 | ```powershell
12 | dotnet build
13 | ```
14 |
15 | ## Unit Test
16 |
17 | This project is configured to generate test coverage every time tests are run and produces a HTML report at
18 | [./docfx/coverage/report](./docfx/coverage/report).
19 |
20 | ```powershell
21 | dotnet test
22 | ```
23 |
24 | ## Documentation
25 |
26 | Documentation is generated into HTML from Markdown using [docfx](https://dotnet.github.io/docfx/).
27 |
28 | To build the docs:
29 |
30 | ```powershell
31 | dotnet build docfx
32 | ```
33 |
34 | To preview the docs:
35 |
36 | ```powershell
37 | dotnet build docfx
38 | dotnet build docfx -t:Serve
39 | ```
40 |
41 | To preview the docs with test coverage:
42 |
43 | ```powershell
44 | dotnet test
45 | dotnet build docfx
46 | dotnet build docfx -t:Serve
47 | ```
48 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <_Parameter1>CommonLibTest
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mono:6.12.0
2 |
3 | # Install .NET SDK
4 | ENV DOTNET_VERSION=7.0
5 |
6 | RUN curl -sSL https://dot.net/v1/dotnet-install.sh \
7 | | bash -s -- -Channel $DOTNET_VERSION -InstallDir /usr/share/dotnet \
8 | && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet
9 |
10 | WORKDIR /build
11 |
12 | CMD [ "dotnet", "build" ]
13 |
14 | ## Build Docker image (one time):
15 | # docker build -t shc-build . --no-cache
16 |
17 | ## Build solution (every time):
18 | # docker run --rm -v .:/build shc-build
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SharpHoundCommon
2 | Common library used by SharpHound.
3 |
4 | 
5 | [](https://www.nuget.org/packages/SharpHoundCommon)
6 | 
7 | [](https://bloodhoundad.github.io/SharpHoundCommon/coverage/report/index.html)
8 | [](https://bloodhoundad.github.io/SharpHoundCommon/index.html)
9 |
10 | ## Prerequisites
11 | * .NET Core 5.0
12 | * Visual Studio 2019 Build Tools
13 |
14 | ## Building
15 | ```
16 | dotnet restore
17 | dotnet build
18 | ```
19 |
20 | ### Contributors
21 |
22 | Check out the [CONTRIBUTING](./CONTRIBUTING.md) guide.
23 |
--------------------------------------------------------------------------------
/SharpHoundCommon.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | #
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHoundCommonLib", "src\CommonLib\SharpHoundCommonLib.csproj", "{88EB8B09-EB8A-4E59-BBF7-CA5374DFA9EB}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonLibTest", "test\unit\CommonLibTest.csproj", "{F1E060CB-58D0-42A7-9BBC-E08C6FD5DD43}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Docfx", "docfx\Docfx.csproj", "{BD8C7EB8-F357-4499-8C08-76B42F600076}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHoundRPC", "src\SharpHoundRPC\SharpHoundRPC.csproj", "{4F06116D-88A7-4601-AB28-B48F2857D458}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {88EB8B09-EB8A-4E59-BBF7-CA5374DFA9EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {88EB8B09-EB8A-4E59-BBF7-CA5374DFA9EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {88EB8B09-EB8A-4E59-BBF7-CA5374DFA9EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {88EB8B09-EB8A-4E59-BBF7-CA5374DFA9EB}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {F1E060CB-58D0-42A7-9BBC-E08C6FD5DD43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {F1E060CB-58D0-42A7-9BBC-E08C6FD5DD43}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {F1E060CB-58D0-42A7-9BBC-E08C6FD5DD43}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {F1E060CB-58D0-42A7-9BBC-E08C6FD5DD43}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {BD8C7EB8-F357-4499-8C08-76B42F600076}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {BD8C7EB8-F357-4499-8C08-76B42F600076}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {BD8C7EB8-F357-4499-8C08-76B42F600076}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {BD8C7EB8-F357-4499-8C08-76B42F600076}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {4F06116D-88A7-4601-AB28-B48F2857D458}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {4F06116D-88A7-4601-AB28-B48F2857D458}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {4F06116D-88A7-4601-AB28-B48F2857D458}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {4F06116D-88A7-4601-AB28-B48F2857D458}.Release|Any CPU.Build.0 = Release|Any CPU
34 | EndGlobalSection
35 | EndGlobal
36 |
--------------------------------------------------------------------------------
/docfx/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ../CONTRIBUTING.md
--------------------------------------------------------------------------------
/docfx/Docfx.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net5.0
4 | false
5 | $([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), `..`, `docs`))
6 | 8002
7 | $(MSBuildThisFileDirectory)docfx.log
8 |
9 |
10 |
11 |
12 |
13 |
14 | mono
15 | <_CmdPrefix Condition="'$(CmdPrefix)' != ''">$(CmdPrefix)
16 | $([System.IO.Path]::Combine($(Pkgdocfx_console), `tools`, `docfx.exe`))
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/docfx/api/index.md:
--------------------------------------------------------------------------------
1 | # SharpHoundCommon API Reference
2 |
--------------------------------------------------------------------------------
/docfx/coverage/index.md:
--------------------------------------------------------------------------------
1 | # Test Coverage
2 |
3 |
4 |
--------------------------------------------------------------------------------
/docfx/docfx.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": [{
3 | "src": [{
4 | "files": ["**.csproj"],
5 | "exclude": ["**/bin/**", "**/obj/**"],
6 | "src": "../src"
7 | }],
8 | "dest": "api",
9 | "disableGitFeatures": false,
10 | "disableDefaultFilter": false
11 | }],
12 | "build": {
13 | "content": [{
14 | "files": [
15 | "api/**.yml",
16 | "api/index.md"
17 | ]
18 | }, {
19 | "files": [
20 | "coverage/**.md",
21 | "coverage/**/toc.yml",
22 | "toc.yml",
23 | "*.md"
24 | ]
25 | }],
26 | "resource": [{
27 | "files": [
28 | "coverage/**.json",
29 | "coverage/report/**",
30 | "images/**"
31 | ]
32 | }],
33 | "overwrite": [{
34 | "files": [
35 | "apidoc/**.md"
36 | ],
37 | "exclude": [
38 | "obj/**",
39 | "_site/**"
40 | ]
41 | }],
42 | "dest": "../docs",
43 | "globalMetadataFiles": [],
44 | "fileMetadataFiles": [],
45 | "template": ["default", "templates/discordfx"],
46 | "postProcessors": [],
47 | "markdownEngineName": "markdig",
48 | "noLangKeyword": false,
49 | "keepFileLink": false,
50 | "cleanupCacheHistory": false,
51 | "disableGitFeatures": false
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/docfx/index.md:
--------------------------------------------------------------------------------
1 | ../README.md
--------------------------------------------------------------------------------
/docfx/templates/discordfx/layout/_master.tmpl:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 | {{!include(/^styles/.*/)}}
3 | {{!include(/^fonts/.*/)}}
4 | {{!include(favicon.ico)}}
5 | {{!include(logo.svg)}}
6 | {{!include(search-stopwords.json)}}
7 |
8 |
9 |
10 |
11 | {{>partials/head}}
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 | {{>partials/logo}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
47 |
48 |
49 |
50 |
51 |
52 | {{^_disableBreadcrumb}}
53 | {{>partials/breadcrumb}}
54 | {{/_disableBreadcrumb}}
55 |
56 |
57 | {{!body}}
58 |
59 |
60 |
61 |
62 |
63 |
64 | {{>partials/scripts}}
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/partials/footer.tmpl.partial:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/partials/head.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 |
6 | {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}
7 |
8 |
9 |
10 | {{#_description}} {{/_description}}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | {{#_noindex}} {{/_noindex}}
20 | {{#_enableSearch}} {{/_enableSearch}}
21 | {{#_enableNewTab}} {{/_enableNewTab}}
22 |
23 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/partials/li.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 | {{#items}}
5 | {{^dropdown}}
6 |
7 | {{^leaf}}
8 |
9 | {{/leaf}}
10 | {{#topicHref}}
11 |
12 | {{/topicHref}}
13 | {{^topicHref}}
14 | {{{name}}}
15 | {{/topicHref}}
16 |
17 | {{^leaf}}
18 | {{>partials/li}}
19 | {{/leaf}}
20 |
21 | {{/dropdown}}
22 | {{#dropdown}}
23 |
24 | {{name}}
25 |
28 |
29 | {{/dropdown}}
30 | {{/items}}
31 |
32 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/partials/logo.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 | Sharphound.Common
5 | {{_appName}}
6 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/partials/navbar.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 |
6 | {{>partials/logo}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/partials/scripts.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/partials/toc.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
6 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/styles/colors.css:
--------------------------------------------------------------------------------
1 | /* Color schemes */
2 | :root
3 | {
4 | /* General */
5 | --main-bg-color: #36393f;
6 | --footer-bg-color: rgba(0,0,0,.4);
7 | --table-strip-bg-color: #121315;
8 | --table-header-bg-color: #202225;;
9 | --table-header-color: hsla(0,0%,100%,.8);
10 | --table-header-border-color: #040405;
11 |
12 | /* Text */
13 | --text-color: #dcddde;
14 | --link-color: #00b0f4;
15 | --link-hover-color: #4bd5ff;
16 | --link-active-color: #fff;
17 | --link-active-bg-color: #7289da;
18 | --h3-color: #ffffff85;
19 | --h4-color: #ffffffeb;
20 | --h5-color: #ffffffd1;
21 |
22 | /* Topbar */
23 | --topbar-bg-color: #18191c;
24 |
25 | /* Button */
26 | --button-color: #747f8d;
27 |
28 | /* Sidebar */
29 | --separator-color: #4f545c;
30 | --sidebar-bg-color: #2f3136;
31 | --sidebar-item-color: #b9bbbe;
32 | --sidebar-item-2nd-color: hsla(0,0%,100%,.35);
33 | --sidebar-item-3rd-color: hsla(0,0%,100%,.25);
34 |
35 | /* Scrollbar */
36 | --scrollbar-bg-color: transparent;
37 | --scrollbar-thumb-bg-color: rgba(0,0,0,.4);
38 | --scrollbar-thumb-border-color: transparent;
39 |
40 | /* Alerts and Blocks */
41 | --alert-info-border-color: rgba(114,137,218,.5);
42 | --alert-info-bg-color: rgba(114,137,218,.1);
43 |
44 | --alert-warning-border-color: rgba(250,166,26,.5);
45 | --alert-warning-bg-color: rgba(250,166,26,.1);
46 |
47 | --alert-danger-border-color: rgba(240,71,71,.5);
48 | --alert-danger-bg-color: rgba(240,71,71,.1);
49 |
50 | --alert-tip-border-color: rgba(255,255,255,.5);
51 | --alert-tip-bg-color: rgba(255,255,255,.1);
52 |
53 | --blockquote-border-color: rgba(255,255,255,.5);
54 | --blockquote-bg-color: rgba(255,255,255,.1);
55 |
56 | --breadcrumb-bg-color: #2f3136;
57 |
58 | /* Code Higlighting */
59 | --code-bg-color: #18191c;
60 | --code-color: #8790A3;
61 | --code-keyword-color: #569cd6;
62 | --code-comment-color: #57a64a;
63 | --code-macro-color: #beb7ff;
64 | --code-string-color: #d69d85;
65 | --code-string-escape-color: #ffd68f;
66 | --code-field-color: #c8c8c8;
67 | --code-function-color: #dcdcaa;
68 | --code-control-color: #d8a0df;
69 | --code-class-color: #4ec9b0;
70 | --code-number-color: #b5cea8;
71 | --code-params-color: #9a9a9a;
72 | --code-breakpoint-color: #8c2f2f;
73 | }
74 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/styles/down-arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/docfx/templates/discordfx/styles/main.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SpecterOps/SharpHoundCommon/367fc765656a347ec7b6d0350123045f52bb7c17/docfx/templates/discordfx/styles/main.css
--------------------------------------------------------------------------------
/docfx/templates/discordfx/styles/main.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.
2 |
3 | function toggleMenu() {
4 |
5 | var x = document.getElementById("sidebar");
6 | var b = document.getElementById("blackout");
7 |
8 | if (x.style.left === "0px")
9 | {
10 | x.style.left = "-350px";
11 | b.classList.remove("showThat");
12 | b.classList.add("hideThat");
13 | }
14 | else
15 | {
16 | x.style.left = "0px";
17 | b.classList.remove("hideThat");
18 | b.classList.add("showThat");
19 | }
20 | }
--------------------------------------------------------------------------------
/docfx/templates/discordfx/styles/url.min.js:
--------------------------------------------------------------------------------
1 | /*! url - v1.8.6 - 2013-11-22 */window.url=function(){function a(a){return!isNaN(parseFloat(a))&&isFinite(a)}return function(b,c){var d=c||window.location.toString();if(!b)return d;b=b.toString(),"//"===d.substring(0,2)?d="http:"+d:1===d.split("://").length&&(d="http://"+d),c=d.split("/");var e={auth:""},f=c[2].split("@");1===f.length?f=f[0].split(":"):(e.auth=f[0],f=f[1].split(":")),e.protocol=c[0],e.hostname=f[0],e.port=f[1]||("https"===e.protocol.split(":")[0].toLowerCase()?"443":"80"),e.pathname=(c.length>3?"/":"")+c.slice(3,c.length).join("/").split("?")[0].split("#")[0];var g=e.pathname;"/"===g.charAt(g.length-1)&&(g=g.substring(0,g.length-1));var h=e.hostname,i=h.split("."),j=g.split("/");if("hostname"===b)return h;if("domain"===b)return/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/.test(h)?h:i.slice(-2).join(".");if("sub"===b)return i.slice(0,i.length-2).join(".");if("port"===b)return e.port;if("protocol"===b)return e.protocol.split(":")[0];if("auth"===b)return e.auth;if("user"===b)return e.auth.split(":")[0];if("pass"===b)return e.auth.split(":")[1]||"";if("path"===b)return e.pathname;if("."===b.charAt(0)){if(b=b.substring(1),a(b))return b=parseInt(b,10),i[0>b?i.length+b:b-1]||""}else{if(a(b))return b=parseInt(b,10),j[0>b?j.length+b:b]||"";if("file"===b)return j.slice(-1)[0];if("filename"===b)return j.slice(-1)[0].split(".")[0];if("fileext"===b)return j.slice(-1)[0].split(".")[1]||"";if("?"===b.charAt(0)||"#"===b.charAt(0)){var k=d,l=null;if("?"===b.charAt(0)?k=(k.split("?")[1]||"").split("#")[0]:"#"===b.charAt(0)&&(k=k.split("#")[1]||""),!b.charAt(1))return k;b=b.substring(1),k=k.split("&");for(var m=0,n=k.length;n>m;m++)if(l=k[m].split("="),l[0]===b)return l[1]||"";return null}}return""}}(),"undefined"!=typeof jQuery&&jQuery.extend({url:function(a,b){return window.url(a,b)}});
--------------------------------------------------------------------------------
/docfx/toc.yml:
--------------------------------------------------------------------------------
1 | - name: Api Documentation
2 | href: api/
3 | homepage: api/index.md
4 | - name: Contributing
5 | href: CONTRIBUTING.md
6 | - name: Test Coverage
7 | href: coverage/index.md
8 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/sleet.json:
--------------------------------------------------------------------------------
1 | {
2 | "sources": [
3 | {
4 | "name": "feed",
5 | "type": "s3",
6 | "path": "https://s3.amazonaws.com/bloodhound-ad",
7 | "region": "us-east-1",
8 | "bucketName": "bloodhound-ad"
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/src/CommonLib/AsyncEnumerable.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 |
5 | namespace SharpHoundCommonLib;
6 |
7 | public static class AsyncEnumerable {
8 | public static IAsyncEnumerable Empty() => EmptyAsyncEnumerable.Instance;
9 |
10 | private sealed class EmptyAsyncEnumerable : IAsyncEnumerable {
11 | public static readonly EmptyAsyncEnumerable Instance = new();
12 | private readonly IAsyncEnumerator _enumerator = new EmptyAsyncEnumerator();
13 | public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) {
14 | return _enumerator;
15 | }
16 | }
17 |
18 | private sealed class EmptyAsyncEnumerator : IAsyncEnumerator {
19 | public ValueTask DisposeAsync() => default;
20 | public ValueTask MoveNextAsync() => new(false);
21 | public T Current => default;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/CommonLib/CSVComputerStatus.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using System.Text.RegularExpressions;
3 |
4 | namespace SharpHoundCommonLib
5 | {
6 | public class CSVComputerStatus
7 | {
8 | public const string StatusSuccess = "Success";
9 | public string ComputerName { get; set; }
10 | public string Task { get; set; }
11 | public string Status { get; set; }
12 |
13 | ///
14 | /// Converts to CSV format for output
15 | ///
16 | ///
17 | public string ToCsv()
18 | {
19 | return $"{StringToCsvCell(ComputerName)}, {StringToCsvCell(Task)}, {StringToCsvCell(Status)}";
20 | }
21 |
22 | ///
23 | /// Helper function to escape text before encoding to CSV
24 | ///
25 | ///
26 | ///
27 | private static string StringToCsvCell(string str)
28 | {
29 | if (str == null)
30 | return null;
31 | str = Regex.Replace(str, @"\t|\n|\r", "");
32 | var mustQuote = str.Contains(",") || str.Contains("\"") || str.Contains("\r") || str.Contains("\n");
33 | if (!mustQuote) return str;
34 | var sb = new StringBuilder();
35 | sb.Append("\"");
36 | foreach (var nextChar in str)
37 | {
38 | sb.Append(nextChar);
39 | if (nextChar == '"')
40 | sb.Append("\"");
41 | }
42 |
43 | sb.Append("\"");
44 | return sb.ToString();
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/CommonLib/CommonLib.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 |
3 | namespace SharpHoundCommonLib
4 | {
5 | public class CommonLib
6 | {
7 | private static bool _initialized;
8 |
9 | ///
10 | /// Initializes the common library with a log and cache instance.
11 | /// If log/cache aren't provided, will use defaults
12 | ///
13 | ///
14 | ///
15 | public static void InitializeCommonLib(ILogger log = null, Cache cache = null)
16 | {
17 | if (_initialized)
18 | {
19 | log?.LogWarning("Common Library is already initialized");
20 | return;
21 | }
22 |
23 | _initialized = true;
24 | if (log != null)
25 | Logging.ConfigureLogging(log);
26 |
27 | if (cache == null)
28 | {
29 | var newCache = Cache.CreateNewCache();
30 | Cache.SetCacheInstance(newCache);
31 | }
32 | else
33 | {
34 | Cache.SetCacheInstance(cache);
35 | }
36 | }
37 |
38 | ///
39 | /// Replaces the current logging instance with a new one
40 | ///
41 | ///
42 | public static void ReconfigureLogging(ILogger log)
43 | {
44 | Logging.ConfigureLogging(log);
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/CommonLib/ConcurrentHashSet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpHoundCommonLib;
6 |
7 | ///
8 | /// A concurrent implementation of a hashset using a ConcurrentDictionary as the backing structure.
9 | ///
10 | public class ConcurrentHashSet : IDisposable{
11 | private ConcurrentDictionary _backingDictionary;
12 |
13 | public ConcurrentHashSet() {
14 | _backingDictionary = new ConcurrentDictionary();
15 | }
16 |
17 | public ConcurrentHashSet(StringComparer comparison) {
18 | _backingDictionary = new ConcurrentDictionary(comparison);
19 | }
20 |
21 | ///
22 | /// Attempts to add an item to the set. Returns true if adding was successful, false otherwise
23 | ///
24 | ///
25 | ///
26 | public bool Add(string item) {
27 | return _backingDictionary.TryAdd(item, byte.MinValue);
28 | }
29 |
30 | ///
31 | /// Attempts to remove an item from the set. Returns true of removing was successful, false otherwise
32 | ///
33 | ///
34 | ///
35 | public bool Remove(string item) {
36 | return _backingDictionary.TryRemove(item, out _);
37 | }
38 |
39 | ///
40 | /// Checks if the given item is in the set
41 | ///
42 | ///
43 | ///
44 | public bool Contains(string item) {
45 | return _backingDictionary.ContainsKey(item);
46 | }
47 |
48 | ///
49 | /// Returns all values in the set
50 | ///
51 | ///
52 | public IEnumerable Values() {
53 | return _backingDictionary.Keys;
54 | }
55 |
56 | public void Dispose() {
57 | _backingDictionary = null;
58 | GC.SuppressFinalize(this);
59 | }
60 | }
--------------------------------------------------------------------------------
/src/CommonLib/DirectoryObjects/IDirectoryObject.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Security.Cryptography.X509Certificates;
3 |
4 | namespace SharpHoundCommonLib;
5 |
6 | public interface IDirectoryObject {
7 | bool TryGetDistinguishedName(out string value);
8 | bool TryGetProperty(string propertyName, out string value);
9 | bool TryGetByteProperty(string propertyName, out byte[] value);
10 | bool TryGetArrayProperty(string propertyName, out string[] value);
11 | bool TryGetByteArrayProperty(string propertyName, out byte[][] value);
12 | bool TryGetLongProperty(string propertyName, out long value);
13 | bool TryGetCertificateArrayProperty(string propertyName, out X509Certificate2[] value);
14 | bool TryGetSecurityIdentifier(out string securityIdentifier);
15 | bool TryGetGuid(out string guid);
16 | string GetProperty(string propertyName);
17 | byte[] GetByteProperty(string propertyName);
18 | int PropertyCount(string propertyName);
19 | IEnumerable PropertyNames();
20 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/CAExtensionTypes.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | // From https://learn.microsoft.com/en-us/windows/win32/seccertenroll/supported-extensions
4 | public static class CAExtensionTypes
5 | {
6 | public const string AuthorityInformationAccess = "1.3.6.1.5.5.7.1.1";
7 | public const string AuthorityKeyIdentifier = "2.5.29.35";
8 | public const string BasicConstraints = "2.5.29.19";
9 | public const string NameConstraints = "2.5.29.30";
10 | public const string EnhancedKeyUsage = "2.5.29.37";
11 | public const string KeyUsage = "2.5.29.15";
12 | public const string SubjectAlternativeNames = "2.5.29.17";
13 | public const string SubjectKeyIdentifier = "2.5.29.14";
14 | }
15 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/CertificationAuthorityRights.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums
4 | {
5 | [Flags]
6 | public enum CertificationAuthorityRights
7 | {
8 | ManageCA = 1, // Administrator
9 | ManageCertificates = 2, // Officer
10 | Auditor = 4,
11 | Operator = 8,
12 | Read = 256,
13 | Enroll = 512
14 | }
15 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/CollectionMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums {
4 | [Flags]
5 | public enum CollectionMethod {
6 | None = 0,
7 | Group = 1,
8 | LocalAdmin = 1 << 1,
9 | GPOLocalGroup = 1 << 2,
10 | Session = 1 << 3,
11 | LoggedOn = 1 << 4,
12 | Trusts = 1 << 5,
13 | ACL = 1 << 6,
14 | Container = 1 << 7,
15 | RDP = 1 << 8,
16 | ObjectProps = 1 << 9,
17 | SessionLoop = 1 << 10,
18 | LoggedOnLoop = 1 << 11,
19 | DCOM = 1 << 12,
20 | SPNTargets = 1 << 13,
21 | PSRemote = 1 << 14,
22 | UserRights = 1 << 15,
23 | CARegistry = 1 << 16,
24 | DCRegistry = 1 << 17,
25 | CertServices = 1 << 18,
26 | LdapServices = 1 << 19,
27 | WebClientService = 1 << 21,
28 | SmbInfo = 1 << 22,
29 | NTLMRegistry = 1 << 23,
30 | //TODO: Re-introduce this when we're ready for Event Log collection
31 | //EventLogs = 1 << 23,
32 | LocalGroups = DCOM | RDP | LocalAdmin | PSRemote,
33 | ComputerOnly = LocalGroups | Session | UserRights | CARegistry | DCRegistry | WebClientService | SmbInfo | NTLMRegistry,
34 | DCOnly = ACL | Container | Group | ObjectProps | Trusts | GPOLocalGroup | CertServices,
35 |
36 | Default = Group | Session | Trusts | ACL | ObjectProps | LocalGroups | SPNTargets | Container | CertServices |
37 | LdapServices | SmbInfo | WebClientService,
38 |
39 | All = Default | LoggedOn | GPOLocalGroup | UserRights | CARegistry | DCRegistry | WebClientService |
40 | LdapServices | NTLMRegistry
41 | }
42 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/CommonOids.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | // More can be found here: https://www.pkisolutions.com/object-identifiers-oid-in-pki/
4 | public static class CommonOids
5 | {
6 | public static string AnyPurpose = "2.5.29.37.0";
7 | public static string ClientAuthentication = "1.3.6.1.5.5.7.3.2";
8 | public static string PKINITClientAuthentication = "1.3.6.1.5.2.3.4";
9 | public static string SmartcardLogon = "1.3.6.1.4.1.311.20.2.2";
10 | public static string CertificateRequestAgent = "1.3.6.1.4.1.311.20.2.1";
11 | public static string CertificateRequestAgentPolicy = "1.3.6.1.4.1.311.20.2.1";
12 | }
13 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/DataType.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | public static class DataType
4 | {
5 | public const string Users = "users";
6 | public const string Groups = "groups";
7 | public const string Computers = "computers";
8 | public const string Domains = "domains";
9 | public const string GPOs = "gpos";
10 | public const string OUs = "ous";
11 | public const string Containers = "containers";
12 | public const string RootCAs = "rootcas";
13 | public const string AIACAs = "aiacas";
14 | public const string NTAuthStores = "ntauthstores";
15 | public const string EnterpriseCAs = "enterprisecas";
16 | public const string CertTemplates = "certtemplates";
17 | public const string IssuancePolicies = "issuancepolicies";
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/CommonLib/Enums/DirectoryPaths.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | public static class DirectoryPaths
4 | {
5 | public const string EnterpriseCALocation = "CN=Enrollment Services,CN=Public Key Services,CN=Services";
6 | public const string RootCALocation = "CN=Certification Authorities,CN=Public Key Services,CN=Services";
7 | public const string AIACALocation = "CN=AIA,CN=Public Key Services,CN=Services";
8 | public const string CertTemplateLocation = "CN=Certificate Templates,CN=Public Key Services,CN=Services";
9 | public const string NTAuthStoreLocation = "CN=NTAuthCertificates,CN=Public Key Services,CN=Services";
10 | public const string PKILocation = "CN=Public Key Services,CN=Services";
11 | public const string ConfigLocation = "CN=Configuration";
12 | public const string OIDContainerLocation = "CN=OID,CN=Public Key Services,CN=Services";
13 | }
14 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/EdgeNames.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | public static class EdgeNames
4 | {
5 | public const string GenericWrite = "GenericWrite";
6 | public const string Owns = "Owns";
7 | public const string GenericAll = "GenericAll";
8 | public const string WriteDacl = "WriteDacl";
9 | public const string WriteOwner = "WriteOwner";
10 | public const string AddSelf = "AddSelf";
11 | public const string GetChanges = "GetChanges";
12 | public const string GetChangesAll = "GetChangesAll";
13 | public const string GetChangesInFilteredSet = "GetChangesInFilteredSet";
14 | public const string AllExtendedRights = "AllExtendedRights";
15 | public const string ForceChangePassword = "ForceChangePassword";
16 | public const string AddAllowedToAct = "AddAllowedToAct";
17 | public const string ReadLAPSPassword = "ReadLAPSPassword";
18 | public const string ReadGMSAPassword = "ReadGMSAPassword";
19 | public const string AddMember = "AddMember";
20 | public const string WriteSPN = "WriteSPN";
21 | public const string AddKeyCredentialLink = "AddKeyCredentialLink";
22 | public const string SQLAdmin = "SQLAdmin";
23 | public const string WriteAccountRestrictions = "WriteAccountRestrictions";
24 | public const string WriteGPLink = "WriteGPLink";
25 |
26 | //CertAbuse edges
27 | public const string WritePKIEnrollmentFlag = "WritePKIEnrollmentFlag";
28 | public const string WritePKINameFlag = "WritePKINameFlag";
29 | public const string ManageCA = "ManageCA";
30 | public const string ManageCertificates = "ManageCertificates";
31 | public const string Enroll = "Enroll";
32 | }
33 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/EventIds.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums;
2 |
3 | public class EventIds {
4 | public static int LogonEvent = 4624;
5 | public static int ValidateCredentialsEvent = 4776;
6 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/KerberosEncryptionTypes.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | public class KerberosEncryptionTypes
4 | {
5 | public const int DES_CBC_CRC = 1;
6 | public const int DES_CBC_MD5 = 2;
7 | public const int RC4_HMAC_MD5 = 4;
8 | public const int AES128_CTS_HMAC_SHA1_96 = 8;
9 | public const int AES256_CTS_HMAC_SHA1_96 = 16;
10 | }
11 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/Labels.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | public enum Label
4 | {
5 | Base = 0,
6 | User,
7 | Computer,
8 | Group,
9 | LocalGroup,
10 | LocalUser,
11 | GPO,
12 | Domain,
13 | OU,
14 | Container,
15 | Configuration,
16 | CertTemplate,
17 | RootCA,
18 | AIACA,
19 | EnterpriseCA,
20 | NTAuthStore,
21 | IssuancePolicy
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/CommonLib/Enums/LdapErrorCodes.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums {
2 | public enum LdapErrorCodes : int {
3 | Success = 0,
4 | StrongAuthRequired = 8,
5 | SaslBindInProgress = 14,
6 | InvalidCredentials = 49,
7 | Busy = 51,
8 | ServerDown = 81,
9 | LocalError = 82,
10 | KerberosAuthType = 83,
11 | }
12 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/LdapFailureReason.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums {
2 | public enum LdapFailureReason
3 | {
4 | None,
5 | NoData,
6 | FailedBind,
7 | FailedRequest,
8 | FailedAuthentication,
9 | AuthenticationException,
10 | Unknown
11 | }
12 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/LdapOption.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums {
2 | public enum LdapOption : int {
3 | Ssl = 0x0A,
4 | ProtocolVersion = 0x11,
5 | ResultCode = 0x31,
6 | ServerError = 0x33,
7 | ServerCertificate = 0x81,
8 | Sign = 0x95,
9 | Encrypt = 0x96,
10 | Timeout = 0x5002,
11 | }
12 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/LdapOptionValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SharpHoundCommonLib.Enums {
8 | public enum LdapOptionValue : int {
9 | Off = 0,
10 | On = 1,
11 | Version3 = 3,
12 | };
13 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/LdapSupportedSaslMechanisms.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SharpHoundCommonLib.Enums {
8 | public static class LdapSupportedSaslMechanisms {
9 | public const string GSSAPI = "GSSAPI";
10 | public const string GSS_SPNEGO = "GSS-SPNEGO";
11 | public const string EXTERNAL = "EXTERNAL";
12 | public const string DIGEST_MD5 = "DIGEST_MD5";
13 | }
14 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/NamingContext.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums {
2 | public enum NamingContext
3 | {
4 | Default,
5 | Configuration,
6 | Schema,
7 | }
8 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/ObjectClass.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums;
2 |
3 | public static class ObjectClass {
4 | public const string GroupPolicyContainerClass = "groupPolicyContainer";
5 | public const string OrganizationalUnitClass = "organizationalUnit";
6 | public const string DomainClass = "domain";
7 | public const string ContainerClass = "container";
8 | public const string ConfigurationClass = "configuration";
9 | public const string PKICertificateTemplateClass = "pKICertificateTemplate";
10 | public const string PKIEnrollmentServiceClass = "pKIEnrollmentService";
11 | public const string CertificationAuthorityClass = "certificationAuthority";
12 | public const string OIDContainerClass = "msPKI-Enterprise-Oid";
13 | public const string GMSAClass = "msds-groupmanagedserviceaccount";
14 | public const string MSAClass = "msds-managedserviceaccount";
15 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/PKICertificateAuthorityFlags.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums
4 | {
5 | [Flags]
6 | public enum PKICertificateAuthorityFlags
7 | {
8 | NO_TEMPLATE_SUPPORT = 0x00000001,
9 | SUPPORTS_NT_AUTHENTICATION = 0x00000002,
10 | CA_SUPPORTS_MANUAL_AUTHENTICATION = 0x00000004,
11 | CA_SERVERTYPE_ADVANCED = 0x00000008
12 | }
13 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/PKICertificateNameFlag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums
4 | {
5 | [Flags]
6 | public enum PKICertificateNameFlag : uint
7 | {
8 | ENROLLEE_SUPPLIES_SUBJECT = 0x00000001,
9 | ADD_EMAIL = 0x00000002,
10 | ADD_OBJ_GUID = 0x00000004,
11 | OLD_CERT_SUPPLIES_SUBJECT_AND_ALT_NAME = 0x00000008,
12 | ADD_DIRECTORY_PATH = 0x00000100,
13 | ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME = 0x00010000,
14 | SUBJECT_ALT_REQUIRE_DOMAIN_DNS = 0x00400000,
15 | SUBJECT_ALT_REQUIRE_SPN = 0x00800000,
16 | SUBJECT_ALT_REQUIRE_DIRECTORY_GUID = 0x01000000,
17 | SUBJECT_ALT_REQUIRE_UPN = 0x02000000,
18 | SUBJECT_ALT_REQUIRE_EMAIL = 0x04000000,
19 | SUBJECT_ALT_REQUIRE_DNS = 0x08000000,
20 | SUBJECT_REQUIRE_DNS_AS_CN = 0x10000000,
21 | SUBJECT_REQUIRE_EMAIL = 0x20000000,
22 | SUBJECT_REQUIRE_COMMON_NAME = 0x40000000,
23 | SUBJECT_REQUIRE_DIRECTORY_PATH = 0x80000000
24 | }
25 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/PKIEnrollmentFlag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums
4 | {
5 | // from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/ec71fd43-61c2-407b-83c9-b52272dec8a1
6 | // and from certutil.exe -v -dstemplate
7 | [Flags]
8 | public enum PKIEnrollmentFlag : uint
9 | {
10 | NONE = 0x00000000,
11 | INCLUDE_SYMMETRIC_ALGORITHMS = 0x00000001,
12 | PEND_ALL_REQUESTS = 0x00000002,
13 | PUBLISH_TO_KRA_CONTAINER = 0x00000004,
14 | PUBLISH_TO_DS = 0x00000008,
15 | AUTO_ENROLLMENT_CHECK_USER_DS_CERTIFICATE = 0x00000010,
16 | AUTO_ENROLLMENT = 0x00000020,
17 | CT_FLAG_DOMAIN_AUTHENTICATION_NOT_REQUIRED = 0x80,
18 | PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT = 0x00000040,
19 | USER_INTERACTION_REQUIRED = 0x00000100,
20 | ADD_TEMPLATE_NAME = 0x200,
21 | REMOVE_INVALID_CERTIFICATE_FROM_PERSONAL_STORE = 0x00000400,
22 | ALLOW_ENROLL_ON_BEHALF_OF = 0x00000800,
23 | ADD_OCSP_NOCHECK = 0x00001000,
24 | ENABLE_KEY_REUSE_ON_NT_TOKEN_KEYSET_STORAGE_FULL = 0x00002000,
25 | NOREVOCATIONINFOINISSUEDCERTS = 0x00004000,
26 | INCLUDE_BASIC_CONSTRAINTS_FOR_EE_CERTS = 0x00008000,
27 | ALLOW_PREVIOUS_APPROVAL_KEYBASEDRENEWAL_VALIDATE_REENROLLMENT = 0x00010000,
28 | ISSUANCE_POLICIES_FROM_REQUEST = 0x00020000,
29 | SKIP_AUTO_RENEWAL = 0x00040000,
30 | NO_SECURITY_EXTENSION = 0x00080000
31 | }
32 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/PKIPrivateKeyFlag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums
4 | {
5 | // from https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/f6122d87-b999-4b92-bff8-f465e8949667
6 | [Flags]
7 | public enum PKIPrivateKeyFlag : uint
8 | {
9 | REQUIRE_PRIVATE_KEY_ARCHIVAL = 0x00000001,
10 | EXPORTABLE_KEY = 0x00000010,
11 | STRONG_KEY_PROTECTION_REQUIRED = 0x00000020,
12 | REQUIRE_ALTERNATE_SIGNATURE_ALGORITHM = 0x00000040,
13 | REQUIRE_SAME_KEY_RENEWAL = 0x00000080,
14 | USE_LEGACY_PROVIDER = 0x00000100,
15 | ATTEST_NONE = 0x00000000,
16 | ATTEST_REQUIRED = 0x00002000,
17 | ATTEST_PREFERRED = 0x00001000,
18 | ATTESTATION_WITHOUT_POLICY = 0x00004000,
19 | EK_TRUST_ON_USE = 0x00000200,
20 | EK_VALIDATE_CERT = 0x00000400,
21 | EK_VALIDATE_KEY = 0x00000800,
22 | HELLO_LOGON_KEY = 0x00200000
23 | }
24 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/TrustAttributes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums
4 | {
5 | [Flags]
6 | public enum TrustAttributes
7 | {
8 | NonTransitive = 0x1,
9 | UplevelOnly = 0x2,
10 | QuarantinedDomain = 0x4,
11 | ForestTransitive = 0x8,
12 | CrossOrganization = 0x10,
13 | WithinForest = 0x20,
14 | TreatAsExternal = 0x40,
15 | UsesRc4Encryption = 0x80,
16 | TrustUsesAes = 0x100,
17 | CrossOrganizationNoTGTDelegation = 0x200,
18 | PIMTrust = 0x400,
19 | CrossOrganizationEnableTGTDelegation = 0x800,
20 | DisableAuthTargetValidation = 0x1000,
21 | Unknown = 0x400000,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/CommonLib/Enums/TrustDirection.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | public enum TrustDirection
4 | {
5 | Disabled = 0,
6 | Inbound = 1,
7 | Outbound = 2,
8 | Bidirectional = 3
9 | }
10 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/TrustType.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Enums
2 | {
3 | public enum TrustType
4 | {
5 | TreeRoot,
6 | ParentChild,
7 | CrossLink,
8 | External,
9 | Forest,
10 | Kerberos,
11 | Unknown
12 | }
13 | }
--------------------------------------------------------------------------------
/src/CommonLib/Enums/UAC.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Enums
4 | {
5 | [Flags]
6 | public enum UacFlags
7 | {
8 | Script = 0x1,
9 | AccountDisable = 0x2,
10 | HomeDirRequired = 0x8,
11 | Lockout = 0x10,
12 | PasswordNotRequired = 0x20,
13 | PasswordCantChange = 0x40,
14 | EncryptedTextPwdAllowed = 0x80,
15 | TempDuplicateAccount = 0x100,
16 | NormalAccount = 0x200,
17 | InterdomainTrustAccount = 0x800,
18 | WorkstationTrustAccount = 0x1000,
19 | ServerTrustAccount = 0x2000,
20 | DontExpirePassword = 0x10000,
21 | MnsLogonAccount = 0x20000,
22 | SmartcardRequired = 0x40000,
23 | TrustedForDelegation = 0x80000,
24 | NotDelegated = 0x100000,
25 | UseDesKeyOnly = 0x200000,
26 | DontReqPreauth = 0x400000,
27 | PasswordExpired = 0x800000,
28 | TrustedToAuthForDelegation = 0x1000000,
29 | PartialSecretsAccount = 0x04000000
30 | }
31 | }
--------------------------------------------------------------------------------
/src/CommonLib/Exceptions/LdapAuthenticationException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.DirectoryServices.Protocols;
3 |
4 | namespace SharpHoundCommonLib.Exceptions
5 | {
6 | internal class LdapAuthenticationException : Exception
7 | {
8 | public readonly LdapException LdapException;
9 | public LdapAuthenticationException(LdapException exception) : base("Error authenticating to LDAP", exception)
10 | {
11 | LdapException = exception;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/CommonLib/Exceptions/LdapConnectionException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.DirectoryServices.Protocols;
3 |
4 | namespace SharpHoundCommonLib.Exceptions
5 | {
6 | internal class LdapConnectionException : Exception
7 | {
8 | public int ErrorCode { get; }
9 | public LdapConnectionException(LdapException innerException) : base("Failed during ldap connection tests", innerException)
10 | {
11 | ErrorCode = innerException.ErrorCode;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/CommonLib/Exceptions/NoLdapDataException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Exceptions
4 | {
5 | internal class NoLdapDataException : Exception
6 | {
7 | public NoLdapDataException()
8 | {
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/CommonLib/IRegistryKey.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 |
3 | namespace SharpHoundCommonLib
4 | {
5 | public interface IRegistryKey
6 | {
7 | public object GetValue(string subkey, string name);
8 | }
9 |
10 | public class SHRegistryKey : IRegistryKey
11 | {
12 | private RegistryKey _currentKey;
13 |
14 | public SHRegistryKey(RegistryHive hive, string machineName)
15 | {
16 | var remoteKey = RegistryKey.OpenRemoteBaseKey(hive, machineName);
17 | _currentKey = remoteKey;
18 | }
19 |
20 | public object GetValue(string subkey, string name)
21 | {
22 | var key = _currentKey.OpenSubKey(subkey);
23 | return key?.GetValue(name);
24 | }
25 | }
26 |
27 | public class MockRegistryKey : IRegistryKey
28 | {
29 | public virtual object GetValue(string subkey, string name) {
30 | //Unimplemented
31 | return default;
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/CommonLib/LdapConfig.cs:
--------------------------------------------------------------------------------
1 | using System.DirectoryServices.Protocols;
2 | using System.Text;
3 |
4 | namespace SharpHoundCommonLib
5 | {
6 | public class LdapConfig
7 | {
8 | public string Username { get; set; } = null;
9 | public string Password { get; set; } = null;
10 | public string Server { get; set; } = null;
11 | public int Port { get; set; } = 0;
12 | public int SSLPort { get; set; } = 0;
13 | public bool ForceSSL { get; set; } = false;
14 | public bool DisableSigning { get; set; } = false;
15 | public bool DisableCertVerification { get; set; } = false;
16 | public AuthType AuthType { get; set; } = AuthType.Kerberos;
17 | public int MaxConcurrentQueries { get; set; } = 15;
18 |
19 | //Returns the port for connecting to LDAP. Will always respect a user's overridden config over anything else
20 | public int GetPort(bool ssl)
21 | {
22 | if (ssl && SSLPort != 0) {
23 | return SSLPort;
24 | }
25 | if (!ssl && Port != 0)
26 | {
27 | return Port;
28 | }
29 |
30 | return ssl ? 636 : 389;
31 | }
32 |
33 | public int GetGCPort(bool ssl)
34 | {
35 | return ssl ? 3269 : 3268;
36 | }
37 |
38 | public override string ToString() {
39 | var sb = new StringBuilder();
40 | sb.AppendLine($"Server: {Server}");
41 | sb.AppendLine($"LdapPort: {GetPort(false)}");
42 | sb.AppendLine($"LdapSSLPort: {GetPort(true)}");
43 | sb.AppendLine($"ForceSSL: {ForceSSL}");
44 | sb.AppendLine($"AuthType: {AuthType.ToString()}");
45 | sb.AppendLine($"MaxConcurrentQueries: {MaxConcurrentQueries}");
46 | if (!string.IsNullOrWhiteSpace(Username)) {
47 | sb.AppendLine($"Username: {Username}");
48 | }
49 |
50 | if (!string.IsNullOrWhiteSpace(Password)) {
51 | sb.AppendLine($"Password: {new string('*', Password.Length)}");
52 | }
53 | return sb.ToString();
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/CommonLib/LdapQueries/CommonFilters.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.LDAPQueries
2 | {
3 | public static class CommonFilters
4 | {
5 | public static string EnabledOnly => "(!(UserAccountControl:1.2.840.113556.1.4.803:=2))";
6 |
7 | public static string NeedsGPCFilePath => "(gpcfilesyspath=*)";
8 |
9 | public static string NeedsSPN => "(serviceprincipalname=*)";
10 |
11 | public static string ExcludeDomainControllers => "(!(userAccountControl:1.2.840.113556.1.4.803:=8192))";
12 |
13 | public static string DomainControllers => "(userAccountControl:1.2.840.113556.1.4.803:=8192)";
14 |
15 | public static string TrustedDomains => "(objectclass=trusteddomain)";
16 |
17 | public static string SpecificSID(string sid)
18 | {
19 | var hSid = Helpers.ConvertSidToHexSid(sid);
20 | return $"(objectsid={hSid})";
21 | }
22 |
23 | public static string SpecificGUID(string guid)
24 | {
25 | var hGuid = Helpers.ConvertGuidToHexGuid(guid);
26 | return $"(objectguid={hGuid})";
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/CommonLib/LdapQueries/CommonPaths.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.LDAPQueries
2 | {
3 | public static class CommonPaths
4 | {
5 | public const string QueryPolicyPath =
6 | "CN=Default Query Policy,CN=Query-Policies,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration";
7 |
8 | public const string DirectoryServicePath =
9 | "CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration";
10 |
11 | public const string ConfigurationPath = "CN=Configuration";
12 |
13 | public static string CreateDNPath(string prePath, string baseDomainDN)
14 | {
15 | return $"{prePath},{baseDomainDN}";
16 | }
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/CommonLib/LdapQueryParameters.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.DirectoryServices.Protocols;
3 | using System.Threading;
4 | using SharpHoundCommonLib.Enums;
5 |
6 | namespace SharpHoundCommonLib {
7 | public class LdapQueryParameters {
8 | private static int _queryIDIndex;
9 | private string _searchBase;
10 | private string _relativeSearchBase;
11 | public string LDAPFilter { get; set; }
12 | public SearchScope SearchScope { get; set; } = SearchScope.Subtree;
13 | public string[] Attributes { get; set; } = Array.Empty();
14 | public string DomainName { get; set; }
15 | public bool GlobalCatalog { get; set; }
16 | public bool IncludeSecurityDescriptor { get; set; } = false;
17 | public bool IncludeDeleted { get; set; } = false;
18 | private int QueryID { get; }
19 |
20 | public LdapQueryParameters() {
21 | QueryID = _queryIDIndex;
22 | Interlocked.Increment(ref _queryIDIndex);
23 | }
24 |
25 | public string SearchBase {
26 | get => _searchBase;
27 | set {
28 | _relativeSearchBase = null;
29 | _searchBase = value;
30 | }
31 | }
32 |
33 | public string RelativeSearchBase {
34 | get => _relativeSearchBase;
35 | set {
36 | _relativeSearchBase = value;
37 | _searchBase = null;
38 | }
39 | }
40 |
41 | public NamingContext NamingContext { get; set; } = NamingContext.Default;
42 |
43 | public string GetQueryInfo()
44 | {
45 | return $"Query Information - Filter: {LDAPFilter}, Domain: {DomainName}, GlobalCatalog: {GlobalCatalog}, ADSPath: {SearchBase}, ID: {QueryID}";
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/CommonLib/LdapQuerySetupResult.cs:
--------------------------------------------------------------------------------
1 | using System.DirectoryServices;
2 | using System.DirectoryServices.Protocols;
3 |
4 | namespace SharpHoundCommonLib {
5 | public class LdapQuerySetupResult {
6 | public LdapConnectionWrapper ConnectionWrapper { get; set; }
7 | public SearchRequest SearchRequest { get; set; }
8 | public string Server { get; set; }
9 | public bool Success { get; set; }
10 | public string Message { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/CommonLib/LdapResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib {
4 | public class LdapResult : Result
5 | {
6 | public string QueryInfo { get; set; }
7 | public int ErrorCode { get; set; }
8 |
9 | protected LdapResult(T value, bool success, string error, string queryInfo, int errorCode) : base(value, success, error) {
10 | QueryInfo = queryInfo;
11 | ErrorCode = errorCode;
12 | }
13 |
14 | public new static LdapResult Ok(T value) {
15 | return new LdapResult(value, true, string.Empty, null, 0);
16 | }
17 |
18 | public new static LdapResult Fail() {
19 | return new LdapResult(default, false, string.Empty, null, 0);
20 | }
21 |
22 | public static LdapResult Fail(string message, LdapQueryParameters queryInfo) {
23 | return new LdapResult(default, false, message, queryInfo.GetQueryInfo(), 0);
24 | }
25 |
26 | public static LdapResult Fail(string message, LdapQueryParameters queryInfo, int errorCode) {
27 | return new LdapResult(default, false, message, queryInfo.GetQueryInfo(), errorCode);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/CommonLib/Logging/Logging.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Concurrent;
3 | using Microsoft.Extensions.Logging;
4 |
5 | namespace SharpHoundCommonLib
6 | {
7 | internal static class Logging
8 | {
9 | internal static readonly ILoggerProvider LogProvider = new LogProvider();
10 | internal static ILogger Logger { get; set; } = new NoOpLogger();
11 |
12 | ///
13 | /// Configures logging for the common library using an ILogger interface
14 | ///
15 | /// ILogger interface desired for logging
16 | internal static void ConfigureLogging(ILogger logger)
17 | {
18 | Logger = logger;
19 | }
20 | }
21 |
22 | internal class LogProvider : ILoggerProvider
23 | {
24 | private readonly ConcurrentDictionary _loggers = new();
25 |
26 | public void Dispose()
27 | {
28 | _loggers.Clear();
29 | }
30 |
31 | public ILogger CreateLogger(string categoryName)
32 | {
33 | return _loggers.GetOrAdd(categoryName, name => new PassThroughLogger(name));
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/CommonLib/Logging/NoOpLogger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Extensions.Logging;
3 |
4 | namespace SharpHoundCommonLib
5 | {
6 | ///
7 | /// An ILogger interface that does nothing
8 | ///
9 | public class NoOpLogger : ILogger
10 | {
11 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception,
12 | Func formatter)
13 | {
14 | }
15 |
16 | public bool IsEnabled(LogLevel logLevel)
17 | {
18 | return false;
19 | }
20 |
21 | public IDisposable BeginScope(TState state)
22 | {
23 | return default;
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/CommonLib/Logging/PassThroughLogger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Extensions.Logging;
3 |
4 | namespace SharpHoundCommonLib
5 | {
6 | ///
7 | /// ILogger implementation that passes log entries through to the configured ILogger and prepends an identification
8 | /// string
9 | ///
10 | internal class PassThroughLogger : ILogger
11 | {
12 | private readonly string _name;
13 |
14 | public PassThroughLogger(string name)
15 | {
16 | _name = name;
17 | }
18 |
19 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception,
20 | Func formatter)
21 | {
22 | var newLog = FormatLog(formatter(state, exception), exception);
23 | Logging.Logger.Log(logLevel, newLog);
24 | }
25 |
26 | public bool IsEnabled(LogLevel logLevel)
27 | {
28 | return true;
29 | }
30 |
31 | public IDisposable BeginScope(TState state)
32 | {
33 | return default;
34 | }
35 |
36 | private string FormatLog(string message, Exception e)
37 | {
38 | return $"[CommonLib {_name}]{message}{(e != null ? $"\n{e}" : "")}";
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/CommonLib/NativeMethods.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics.CodeAnalysis;
3 | using Microsoft.Extensions.Logging;
4 | using SharpHoundRPC.NetAPINative;
5 |
6 | namespace SharpHoundCommonLib
7 | {
8 | [ExcludeFromCodeCoverage]
9 | // This class exists entirely as a shim for testing
10 | public class NativeMethods
11 | {
12 | private readonly ILogger _log;
13 |
14 | public NativeMethods(ILogger log = null)
15 | {
16 | _log = log ?? Logging.LogProvider.CreateLogger("NativeMethods");
17 | }
18 |
19 | public NativeMethods()
20 | {
21 | _log = Logging.LogProvider.CreateLogger("NativeMethods");
22 | }
23 |
24 | public virtual NetAPIResult> NetSessionEnum(string serverName)
25 | {
26 | return NetAPIMethods.NetSessionEnum(serverName);
27 | }
28 |
29 | public virtual NetAPIResult> NetWkstaUserEnum(string servername)
30 | {
31 | return NetAPIMethods.NetWkstaUserEnum(servername);
32 | }
33 |
34 | public virtual NetAPIResult CallDsGetDcName(string computerName,
35 | string domainName, uint flags)
36 | {
37 | return NetAPIMethods.DsGetDcName(computerName, domainName, flags);
38 | }
39 |
40 | public virtual NetAPIResult CallNetWkstaGetInfo(string serverName) {
41 | return NetAPIMethods.NetWkstaGetInfo(serverName);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/src/CommonLib/Ntlm/HttpClientFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Http;
4 |
5 | namespace SharpHoundCommonLib.Ntlm;
6 |
7 | public interface IHttpClientFactory {
8 | HttpClient CreateUnauthenticatedClient();
9 | HttpClient CreateAuthenticatedHttpClient(Uri Url, string authPackage = "Kerberos");
10 | }
11 |
12 | public class HttpClientFactory : IHttpClientFactory {
13 | public HttpClient CreateUnauthenticatedClient() {
14 | var handler = new HttpClientHandler {
15 | ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true,
16 | UseDefaultCredentials = false
17 | };
18 |
19 | return new HttpClient(handler);
20 | }
21 |
22 | public HttpClient CreateAuthenticatedHttpClient(Uri Url, string authPackage = "Kerberos") {
23 | var handler = new HttpClientHandler {
24 | Credentials = new CredentialCache() {
25 | { Url, authPackage, CredentialCache.DefaultNetworkCredentials }
26 | },
27 |
28 | PreAuthenticate = true,
29 | ServerCertificateCustomValidationCallback =
30 | (httpRequestMessage, cert, cetChain, policyErrors) => { return true; },
31 | };
32 |
33 | return new HttpClient(handler);
34 | }
35 | }
--------------------------------------------------------------------------------
/src/CommonLib/Ntlm/INtlmTransport.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace SharpHoundCommonLib.Ntlm;
5 |
6 | public interface INtlmTransport {
7 | Task NegotiateAsync(byte[] negotiateMessage);
8 | Task AuthenticateAsync(byte[] authenticateMessage);
9 | }
--------------------------------------------------------------------------------
/src/CommonLib/Ntlm/LdapNativeException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.Ntlm;
4 |
5 | public class LdapNativeException : Exception {
6 | public int ErrorCode { get; }
7 | public string ServerErrorMessage { get; }
8 |
9 | public LdapNativeException(string message, int errorCode, string serverErrorMessage = null)
10 | : base(
11 | $"{message}. LDAP error code: {errorCode}{(string.IsNullOrEmpty(serverErrorMessage) ? "" : $". Server error: {serverErrorMessage}")}") {
12 | ErrorCode = errorCode;
13 | ServerErrorMessage = serverErrorMessage;
14 | }
15 | }
--------------------------------------------------------------------------------
/src/CommonLib/Ntlm/NtlmAuthenticationHandler.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using SharpHoundCommonLib.Processors;
3 | using SharpHoundCommonLib.ThirdParty.PSOpenAD;
4 | using System;
5 | using System.Threading.Tasks;
6 |
7 | namespace SharpHoundCommonLib.Ntlm;
8 |
9 | interface INtlmAuthenticationHandler {
10 | Task PerformNtlmAuthenticationAsync(INtlmTransport transport);
11 | }
12 |
13 | ///
14 | /// Uses an implementation of transports to actually perform the NTLM authentication.
15 | ///
16 | public class NtlmAuthenticationHandler : INtlmAuthenticationHandler {
17 | private readonly ILogger _logger;
18 | private readonly string _targetService;
19 | public LdapAuthOptions Options { get; set; }
20 |
21 | public NtlmAuthenticationHandler(string targetService, ILogger logger = null) {
22 | _logger = logger ?? Logging.LogProvider.CreateLogger("NtlmAuthenticationHandler");
23 | _targetService = targetService;
24 |
25 | Options = new LdapAuthOptions {
26 | Signing = false,
27 | Bindings = null
28 | };
29 | }
30 |
31 | public virtual async Task PerformNtlmAuthenticationAsync(INtlmTransport transport) {
32 | using var context = new SspiContext(
33 | null,
34 | null,
35 | AuthenticationMethod.NTLM,
36 | _targetService,
37 | Options.Bindings,
38 | Options.Signing,
39 | Options.Signing
40 | );
41 |
42 | // NEGOTIATE
43 | var negotiateMsgBytes = context.Step();
44 |
45 | // CHALLENGE
46 | var challengeMessageBytes = await transport.NegotiateAsync(negotiateMsgBytes);
47 |
48 | // AUTHENTICATE
49 | var authenticateMsgBytes = context.Step(challengeMessageBytes);
50 |
51 | // Perform final authentication
52 | var response = await transport.AuthenticateAsync(authenticateMsgBytes);
53 |
54 | return response;
55 | }
56 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/ACE.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.Enums;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes {
4 | public class ACE {
5 | public string PrincipalSID { get; set; }
6 | public Label PrincipalType { get; set; }
7 | public string RightName { get; set; }
8 | public bool IsInherited { get; set; }
9 | public string InheritanceHash { get; set; }
10 |
11 | public override string ToString() {
12 | return $"{PrincipalType} {PrincipalSID} - {RightName} {(IsInherited ? "" : "Not")} Inherited";
13 | }
14 |
15 | protected bool Equals(ACE other) {
16 | return PrincipalSID == other.PrincipalSID && PrincipalType == other.PrincipalType &&
17 | RightName == other.RightName && IsInherited == other.IsInherited;
18 | }
19 |
20 | public override bool Equals(object obj) {
21 | if (ReferenceEquals(null, obj)) return false;
22 | if (ReferenceEquals(this, obj)) return true;
23 | if (obj.GetType() != GetType()) return false;
24 | return Equals((ACE)obj);
25 | }
26 |
27 | public override int GetHashCode() {
28 | unchecked {
29 | var hashCode = PrincipalSID != null ? PrincipalSID.GetHashCode() : 0;
30 | hashCode = (hashCode * 397) ^ (int)PrincipalType;
31 | hashCode = (hashCode * 397) ^ (RightName != null ? RightName.GetHashCode() : 0);
32 | hashCode = (hashCode * 397) ^ IsInherited.GetHashCode();
33 | return hashCode;
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/AIACA.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class AIACA : OutputBase
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResult.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes {
2 | public class APIResult {
3 | public bool Collected { get; set; }
4 | public string FailureReason { get; set; }
5 | }
6 |
7 | public class APIResult : APIResult {
8 | public T Result { get; set; }
9 |
10 | public static APIResult Success(T result) {
11 | return new APIResult {
12 | Result = result,
13 | Collected = true
14 | };
15 | }
16 |
17 | public static APIResult Failure(string failureReason) {
18 | return new APIResult {
19 | Collected = false,
20 | FailureReason = failureReason
21 | };
22 | }
23 |
24 | public static implicit operator APIResult(T input)
25 | {
26 | return Success(input);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/AceRegistryAPIResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class AceRegistryAPIResult : APIResult
6 | {
7 | public ACE[] Data { get; set; } = Array.Empty();
8 | }
9 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/BoolRegistryAPIResult.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class BoolRegistryAPIResult : APIResult
4 | {
5 | public bool Value { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/EnrollmentAgentRegistryAPIResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SharpHoundCommonLib.Processors;
3 |
4 | namespace SharpHoundCommonLib.OutputTypes
5 | {
6 | public class EnrollmentAgentRegistryAPIResult : APIResult
7 | {
8 | public EnrollmentAgentRestriction[] Restrictions { get; set; } = Array.Empty();
9 | }
10 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/IntRegistryAPIResult.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class IntRegistryAPIResult : APIResult
4 | {
5 | public int Value { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/LSAPrivilegeAPIResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class LSAPrivilegeAPIResult : APIResult
6 | {
7 | public TypedPrincipal[] Results { get; set; } = Array.Empty();
8 | }
9 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/LocalGroupAPIResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace SharpHoundCommonLib.OutputTypes
5 | {
6 | public class LocalGroupAPIResult : APIResult
7 | {
8 | public string ObjectIdentifier { get; set; }
9 | public string Name { get; set; }
10 | public TypedPrincipal[] Results { get; set; } = Array.Empty();
11 | public NamedPrincipal[] LocalNames { get; set; } = Array.Empty();
12 |
13 | public override string ToString()
14 | {
15 | var builder = new StringBuilder();
16 | builder.AppendLine($"Local group {Name} ({ObjectIdentifier})");
17 | foreach (var x in Results) builder.AppendLine(x.ToString());
18 |
19 | builder.AppendLine("Extra Names:");
20 |
21 | foreach (var x in LocalNames) builder.AppendLine(x.ToString());
22 | return builder.ToString();
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/SessionAPIResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class SessionAPIResult : APIResult
6 | {
7 | public Session[] Results { get; set; } = Array.Empty();
8 | }
9 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/APIResults/UserRightsAssignmentAPIResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace SharpHoundCommonLib.OutputTypes
5 | {
6 | public class UserRightsAssignmentAPIResult : APIResult
7 | {
8 | public string Privilege { get; set; }
9 | public TypedPrincipal[] Results { get; set; } = Array.Empty();
10 | public NamedPrincipal[] LocalNames { get; set; } = Array.Empty();
11 |
12 | public override string ToString()
13 | {
14 | var builder = new StringBuilder();
15 | builder.AppendLine($"Privilege {Privilege}");
16 | foreach (var x in Results) builder.AppendLine(x.ToString());
17 |
18 | builder.AppendLine("Extra Names:");
19 |
20 | foreach (var x in LocalNames) builder.AppendLine(x.ToString());
21 | return builder.ToString();
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/CARegistryData.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.Processors;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class CARegistryData
6 | {
7 | public AceRegistryAPIResult CASecurity { get; set; }
8 | public EnrollmentAgentRegistryAPIResult EnrollmentAgentRestrictions { get; set; }
9 | public BoolRegistryAPIResult IsUserSpecifiesSanEnabled { get; set; }
10 | public BoolRegistryAPIResult RoleSeparationEnabled { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/CertTemplate.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.Processors;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class CertTemplate : OutputBase
6 | {
7 | }
8 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/CertificateExtension.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Cryptography;
2 | using System.Security.Cryptography.X509Certificates;
3 |
4 | namespace SharpHoundCommonLib.OutputTypes
5 | {
6 | public class CertificateExtension
7 | {
8 | public Oid Oid { get; set; }
9 | public bool Critical { get; set; }
10 |
11 | public CertificateExtension(X509Extension extension)
12 | {
13 | Oid = new Oid(extension.Oid);
14 | Critical = extension.Critical;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/Container.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class Container : OutputBase
6 | {
7 | public TypedPrincipal[] ChildObjects { get; set; } = Array.Empty();
8 | public string[] InheritanceHashes { get; set; } = Array.Empty();
9 | }
10 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/Domain.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class Domain : OutputBase
6 | {
7 | public ResultingGPOChanges GPOChanges = new();
8 | public TypedPrincipal[] ChildObjects { get; set; } = Array.Empty();
9 | public DomainTrust[] Trusts { get; set; } = Array.Empty();
10 | public GPLink[] Links { get; set; } = Array.Empty();
11 | public string[] InheritanceHashes { get; set; } = Array.Empty();
12 | public string ForestRootIdentifier { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/DomainController.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SpecterOps/SharpHoundCommon/367fc765656a347ec7b6d0350123045f52bb7c17/src/CommonLib/OutputTypes/DomainController.cs
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/DomainTrust.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.Enums;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class DomainTrust
6 | {
7 | public string TargetDomainSid { get; set; }
8 | public string TargetDomainName { get; set; }
9 | public bool IsTransitive { get; set; }
10 | public bool SidFilteringEnabled { get; set; }
11 | public bool TGTDelegationEnabled { get; set; }
12 | public long TrustAttributes { get; set; }
13 | public TrustDirection TrustDirection { get; set; }
14 | public TrustType TrustType { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/EnterpriseCA.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class EnterpriseCA : OutputBase
4 | {
5 | public string HostingComputer { get; set; }
6 | public CARegistryData CARegistryData { get; set; }
7 | public TypedPrincipal[] EnabledCertTemplates { get; set; }
8 | public APIResult[] HttpEnrollmentEndpoints { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/GPLink.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class GPLink
4 | {
5 | private string _guid;
6 |
7 | public bool IsEnforced { get; set; }
8 |
9 | public string GUID
10 | {
11 | get => _guid;
12 | set => _guid = value?.ToUpper();
13 | }
14 |
15 | protected bool Equals(GPLink other)
16 | {
17 | return _guid == other._guid && IsEnforced == other.IsEnforced;
18 | }
19 |
20 | public override bool Equals(object obj)
21 | {
22 | if (ReferenceEquals(null, obj)) return false;
23 | if (ReferenceEquals(this, obj)) return true;
24 | if (obj.GetType() != GetType()) return false;
25 | return Equals((GPLink) obj);
26 | }
27 |
28 | public override int GetHashCode()
29 | {
30 | unchecked
31 | {
32 | return ((_guid != null ? _guid.GetHashCode() : 0) * 397) ^ IsEnforced.GetHashCode();
33 | }
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/GPO.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class GPO : OutputBase
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/Group.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class Group : OutputBase
6 | {
7 | public TypedPrincipal[] Members { get; set; } = Array.Empty();
8 | }
9 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/IssuancePolicy.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class IssuancePolicy : OutputBase
4 | {
5 | public TypedPrincipal GroupLink { get; set; } = new();
6 | }
7 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/LocalGroup.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class LocalGroup
4 | {
5 | public string Name { get; set; }
6 | public int Rid { get; set; }
7 | public string ObjectID { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/MetaTag.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | [DataContract]
6 | public class MetaTag
7 | {
8 | [DataMember(Name = "methods")] public long CollectionMethods { get; set; }
9 | [DataMember(Name = "type")] public string DataType { get; set; }
10 | [DataMember(Name = "count")] public long Count { get; set; }
11 | [DataMember(Name = "version")] public int Version { get; set; }
12 | [DataMember(Name = "collectorversion")] public string CollectorVersion { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/NTAuthStore.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class NTAuthStore : OutputBase
4 | {
5 | public string DomainSID { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/NamedPrincipal.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class NamedPrincipal
4 | {
5 | public NamedPrincipal()
6 | {
7 | }
8 |
9 | public NamedPrincipal(string principalName, string objectId)
10 | {
11 | PrincipalName = principalName;
12 | ObjectId = objectId;
13 | }
14 |
15 | public string PrincipalName { get; set; }
16 | public string ObjectId { get; set; }
17 |
18 | public override string ToString()
19 | {
20 | return $"{PrincipalName} - {ObjectId}";
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/OU.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class OU : OutputBase
6 | {
7 | public ResultingGPOChanges GPOChanges = new();
8 | public GPLink[] Links { get; set; } = Array.Empty();
9 | public TypedPrincipal[] ChildObjects { get; set; } = Array.Empty();
10 | public string[] InheritanceHashes { get; set; } = Array.Empty();
11 | }
12 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/OutputBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace SharpHoundCommonLib.OutputTypes
5 | {
6 | ///
7 | /// Represents a base JSON object which other objects will inherit from.
8 | ///
9 | public class OutputBase
10 | {
11 | public Dictionary Properties = new();
12 | public ACE[] Aces { get; set; } = Array.Empty();
13 | public string ObjectIdentifier { get; set; }
14 | public bool IsDeleted { get; set; }
15 | public bool IsACLProtected { get; set; }
16 | public TypedPrincipal ContainedBy { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/OutputWrapper.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Runtime.Serialization;
3 |
4 | namespace SharpHoundCommonLib.OutputTypes
5 | {
6 | [DataContract]
7 | public class OutputWrapper
8 | {
9 | [DataMember(Name = "meta")] public MetaTag Meta { get; set; }
10 | [DataMember(Name = "data")] public List Data { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/RegistryData.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using SharpHoundRPC.Registry;
3 |
4 | namespace SharpHoundCommonLib.OutputTypes;
5 |
6 | public class RegistryData {
7 | public uint? RestrictSendingNtlmTraffic { get; set; } = null;
8 | public uint? RestrictReceivingNtlmTraffic { get; set; } = null;
9 | public uint? NtlmMinServerSec { get; set; } = null;
10 | public uint? NtlmMinClientSec { get; set; } = null;
11 | public uint? LmCompatibilityLevel { get; set; } = null;
12 | public uint? UseMachineId { get; set; } = null;
13 | public uint? RequireSecuritySignature { get; set; } = null;
14 | public uint? EnableSecuritySignature { get; set; } = null;
15 | public string[]? ClientAllowedNTLMServers { get; set; } = null;
16 | }
17 | #nullable disable
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/ResultingGPOChanges.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class ResultingGPOChanges
6 | {
7 | public TypedPrincipal[] LocalAdmins { get; set; } = Array.Empty();
8 | public TypedPrincipal[] RemoteDesktopUsers { get; set; } = Array.Empty();
9 | public TypedPrincipal[] DcomUsers { get; set; } = Array.Empty();
10 | public TypedPrincipal[] PSRemoteUsers { get; set; } = Array.Empty();
11 | public TypedPrincipal[] AffectedComputers { get; set; } = Array.Empty();
12 | }
13 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/RootCA.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class RootCA : OutputBase
4 | {
5 | public string DomainSID { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/SPNPrivilege.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class SPNPrivilege
4 | {
5 | public string ComputerSID { get; set; }
6 | public int Port { get; set; }
7 | public string Service { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/Session.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.OutputTypes
2 | {
3 | public class Session
4 | {
5 | private string _computerSID;
6 | private string _userSID;
7 |
8 | public string UserSID
9 | {
10 | get => _userSID;
11 | set => _userSID = value?.ToUpper();
12 | }
13 |
14 | public string ComputerSID
15 | {
16 | get => _computerSID;
17 | set => _computerSID = value?.ToUpper();
18 | }
19 |
20 | protected bool Equals(Session other)
21 | {
22 | return _computerSID == other._computerSID && _userSID == other._userSID;
23 | }
24 |
25 | public override bool Equals(object obj)
26 | {
27 | if (ReferenceEquals(null, obj)) return false;
28 | if (ReferenceEquals(this, obj)) return true;
29 | if (obj.GetType() != GetType()) return false;
30 | return Equals((Session) obj);
31 | }
32 |
33 | public override int GetHashCode()
34 | {
35 | unchecked
36 | {
37 | return ((_computerSID != null ? _computerSID.GetHashCode() : 0) * 397) ^
38 | (_userSID != null ? _userSID.GetHashCode() : 0);
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/TypedPrincipal.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.Enums;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class TypedPrincipal
6 | {
7 | public TypedPrincipal()
8 | {
9 | }
10 |
11 | public TypedPrincipal(string objectIdentifier, Label type)
12 | {
13 | ObjectIdentifier = objectIdentifier;
14 | ObjectType = type;
15 | }
16 |
17 | public string ObjectIdentifier { get; set; }
18 | public Label ObjectType { get; set; }
19 |
20 | public override string ToString()
21 | {
22 | return $"{ObjectIdentifier} - {ObjectType}";
23 | }
24 |
25 | protected bool Equals(TypedPrincipal other)
26 | {
27 | return ObjectIdentifier == other.ObjectIdentifier && ObjectType == other.ObjectType;
28 | }
29 |
30 | public override bool Equals(object obj)
31 | {
32 | if (ReferenceEquals(null, obj)) return false;
33 | if (ReferenceEquals(this, obj)) return true;
34 | if (obj.GetType() != GetType()) return false;
35 | return Equals((TypedPrincipal) obj);
36 | }
37 |
38 | public override int GetHashCode()
39 | {
40 | unchecked
41 | {
42 | return ((ObjectIdentifier != null ? ObjectIdentifier.GetHashCode() : 0) * 397) ^ (int) ObjectType;
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/CommonLib/OutputTypes/User.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.OutputTypes
4 | {
5 | public class User : OutputBase
6 | {
7 | public TypedPrincipal[] AllowedToDelegate { get; set; } = Array.Empty();
8 | public string PrimaryGroupSID { get; set; }
9 | public TypedPrincipal[] HasSIDHistory { get; set; } = Array.Empty();
10 | public SPNPrivilege[] SPNTargets { get; set; } = Array.Empty();
11 | public bool UnconstrainedDelegation { get; set; }
12 | public string DomainSID { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/CommonLib/Processors/ACEGuids.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.Processors
2 | {
3 | public class ACEGuids
4 | {
5 | public const string DSReplicationGetChanges = "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2";
6 | public const string DSReplicationGetChangesAll = "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2";
7 | public const string DSReplicationGetChangesInFilteredSet = "89e95b76-444d-4c62-991a-0facbeda640c";
8 | public const string UserForceChangePassword = "00299570-246d-11d0-a768-00aa006e0529";
9 | public const string AllGuid = "00000000-0000-0000-0000-000000000000";
10 | public const string WriteMember = "bf9679c0-0de6-11d0-a285-00aa003049e2";
11 | public const string WriteAllowedToAct = "3f78c3e5-f79a-46bd-a0b8-9d18116ddc79";
12 | public const string WriteSPN = "f3a64788-5306-11d1-a9c5-0000f80367c1";
13 | public const string AddKeyPrincipal = "5b47d60f-6090-40b2-9f37-2a4de88f3063";
14 | public const string UserAccountRestrictions = "4c164200-20c0-11d0-a768-00aa006e0529";
15 | public const string WriteGPLink = "f30e3bbe-9ff0-11d1-b603-0000f80367c1";
16 | public const string WriteTitle = "bf967a55-0de6-11d0-a285-00aa003049e2"; // Not an edge, just used for testing
17 |
18 |
19 | //Cert abuse ACEs
20 | public const string PKINameFlag = "ea1dddc4-60ff-416e-8cc0-17cee534bce7";
21 | public const string PKIEnrollmentFlag = "d15ef7d8-f226-46db-ae79-b34e560bd12c";
22 | public const string Enroll = "0e10c968-78fb-11d2-90d4-00c04f79dc55";
23 | public const string AutoEnroll = "a05b8cc2-17bc-4802-a710-e7c15ab866a2"; //TODO: Add this if it becomes abusable
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/CommonLib/Processors/CachedLocalItem.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.Enums;
2 |
3 | namespace SharpHoundCommonLib.Processors
4 | {
5 | internal class CachedLocalItem
6 | {
7 | public CachedLocalItem(string name, Label type)
8 | {
9 | Name = name;
10 | Type = type;
11 | }
12 |
13 | public string Name { get; set; }
14 | public Label Type { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/CommonLib/Processors/RegistryResult.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.OutputTypes;
2 |
3 | namespace SharpHoundCommonLib.Processors {
4 | public class RegistryResult : APIResult {
5 | public object Value { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/CommonLib/ResolvedSearchResult.cs:
--------------------------------------------------------------------------------
1 | using SharpHoundCommonLib.Enums;
2 |
3 | namespace SharpHoundCommonLib
4 | {
5 | public class ResolvedSearchResult
6 | {
7 | private string _displayName;
8 | private string _objectID;
9 |
10 | public string DisplayName
11 | {
12 | get => _displayName?.ToUpper();
13 | set => _displayName = value;
14 | }
15 |
16 | public Label ObjectType { get; set; }
17 |
18 | public string ObjectId
19 | {
20 | get => _objectID;
21 | set => _objectID = value.ToUpper();
22 | }
23 |
24 | public bool Deleted { get; set; }
25 |
26 | public string Domain { get; set; }
27 | public string DomainSid { get; set; }
28 | public bool IsDomainController { get; set; }
29 |
30 | public override string ToString()
31 | {
32 | return $"{DisplayName} - {ObjectType}";
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/CommonLib/Result.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib {
2 | public class Result : Result {
3 | public T Value { get; set; }
4 |
5 | protected Result(T value, bool success, string error) : base(success, error) {
6 | Value = value;
7 | }
8 |
9 | public new static Result Fail(string message) {
10 | return new Result(default, false, message);
11 | }
12 |
13 | public static Result Fail() {
14 | return new Result(default, false, string.Empty);
15 | }
16 |
17 | public static Result Ok(T value) {
18 | return new Result(value, true, string.Empty);
19 | }
20 | }
21 |
22 | public class Result {
23 |
24 | public string Error { get; set; }
25 | public bool IsSuccess => string.IsNullOrWhiteSpace(Error) && Success;
26 | private bool Success { get; set; }
27 |
28 | protected Result(bool success, string error) {
29 | Success = success;
30 | Error = error;
31 | }
32 |
33 | public static Result Fail(string message) {
34 | return new Result(false, message);
35 | }
36 |
37 | public static Result Ok() {
38 | return new Result(true, string.Empty);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB1/SMB1Command.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SharpHoundCommonLib.SMB.SMB1
8 | {
9 | ///
10 | /// SMB1 command codes.
11 | /// Place holder class for future commands that may be used.
12 | ///
13 | ///
14 | /// For more information, see:
15 | ///
16 | /// MS-CIFS 2.2.4 SMB Commands
17 | ///
18 | ///
19 | public class SMB1Command
20 | {
21 | ///
22 | /// SMB_COM_NEGOTIATE (0x72).
23 | /// This command is used to initiate an SMB connection between the client and the server.
24 | ///
25 | public static byte Negotiate = 0x72;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB1/SMB1Flags.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundCommonLib.SMB.SMB1
4 | {
5 | ///
6 | /// Flags defined in the SMB1 Header.
7 | ///
8 | ///
9 | /// For more information, see:
10 | /// MS-CIFS 2.2.3.1 The SMB Header
11 | ///
12 | [Flags]
13 | public enum SMB1Flags : byte
14 | {
15 | ///
16 | /// No flags set
17 | ///
18 | None = 0x00,
19 |
20 | ///
21 | /// Client can support LOCK_AND_READ commands.
22 | ///
23 | ///
24 | /// Corresponds to SMB_FLAGS_LOCK_AND_READ_OK in the specification.
25 | ///
26 | LockAndRead = 0x01,
27 |
28 | ///
29 | /// Client has posted a big buffer.
30 | ///
31 | ///
32 | /// Corresponds to SMB_FLAGS_BUF_AVAIL in the specification.
33 | ///
34 | ReceiveBufferPosted = 0x02,
35 |
36 | ///
37 | /// Reserved - must not be set.
38 | ///
39 | Reserved = 0x04,
40 |
41 | ///
42 | /// Path names should be treated as case insensitive.
43 | ///
44 | ///
45 | /// Corresponds to SMB_FLAGS_CASE_INSENSITIVE in the specification.
46 | ///
47 | CaseSensitive = 0x08,
48 |
49 | ///
50 | /// Pathnames are canonicalized.
51 | ///
52 | ///
53 | /// Corresponds to SMB_FLAGS_CANONICALIZED_PATHS in the specification.
54 | ///
55 | CanonicalizedPaths = 0x10,
56 |
57 | ///
58 | /// Opportunistic lock on file has been granted.
59 | ///
60 | ///
61 | /// Corresponds to SMB_FLAGS_OPLOCK in the specification.
62 | ///
63 | OpLock = 0x20,
64 |
65 | ///
66 | /// Batch opportunistic lock on file has been granted.
67 | ///
68 | ///
69 | /// Corresponds to SMB_FLAGS_OPBATCH in the specification.
70 | ///
71 | OpLockBatch = 0x40,
72 |
73 | ///
74 | /// Message is a response, not a request.
75 | ///
76 | ///
77 | /// Corresponds to SMB_FLAGS_REPLY in the specification.
78 | ///
79 | Reply = 0x80
80 | }
81 |
82 | }
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB2/SMB2CompressionAlgorithm.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.SMB.SMB2
2 | {
3 | ///
4 | /// SMB2 Compression Algorithms
5 | ///
6 | public enum SMB2CompressionAlgorithm : ushort
7 | {
8 | None = 0x0000,
9 | Lznt1 = 0x0001,
10 | Lz77 = 0x0002,
11 | Lz77Huffman = 0x0003,
12 | PatternV1 = 0x0004,
13 | Lz4 = 0x0005
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB2/SMB2Constants.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.SMB.SMB2
2 | {
3 | ///
4 | /// Common constant used in the SMB2 protocol
5 | ///
6 | public static class SMB2Constants
7 | {
8 | // Protocol identifiers
9 |
10 | // Commands
11 | public const ushort NegotiateCommand = 0x0000;
12 |
13 | // Structure sizes
14 | public const ushort NegotiateRequestSize = 36;
15 |
16 | // Status codes
17 | public const uint StatusSuccess = 0x00000000;
18 | public const uint StatusInvalidParameter = 0xC000000D;
19 |
20 | // Security modes
21 | public const ushort SigningEnabled = 0x0001;
22 | public const ushort SigningRequired = 0x0002;
23 |
24 | // Expected response structure sizes
25 | public const ushort ExpectedNegotiateStructureSizeA = 0x41;
26 | public const ushort ExpectedNegotiateStructureSizeB = 0x65;
27 |
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB2/SMB2Dialect.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.SMB.SMB2
2 | {
3 | ///
4 | /// SMB2 Protocol dialects
5 | ///
6 | ///
7 | /// These dialects select the type of SMB that's used (e.g. SMB 2.x or SMB3.x). For definition, see:
8 | /// MS-SMB2 1.7 Versioning and Capability Negotiation
9 | ///
10 | public enum SMB2Dialect : ushort
11 | {
12 | Smb202 = 0x0202,
13 | Smb21 = 0x0210,
14 | Smb30 = 0x0300,
15 | Smb302 = 0x0302,
16 | Smb311 = 0x0311
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB2/SMB2EncryptionAlgorithm.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.SMB.SMB2
2 | {
3 | ///
4 | /// SMB2 Encryption Algorithms
5 | ///
6 | public enum SMB2EncryptionAlgorithm : ushort
7 | {
8 | Aes128Ccm = 0x0001,
9 | Aes128Gcm = 0x0002,
10 | Aes256Ccm = 0x0003,
11 | Aes256Gcm = 0x0004
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB2/SMB2HashAlgorithm.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundCommonLib.SMB.SMB2
2 | {
3 | ///
4 | /// SMB2 Hash Algorithms for Preauth Integrity
5 | ///
6 | /// For definition, see:
7 | /// MS-SMB2 2.2.3.1.1 SMB2_PREAUTH_INTEGRITY_CAPABILITIES
8 | ///
9 | ///
10 | public enum SMB2HashAlgorithm : ushort
11 | {
12 | Sha512 = 0x0001
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB2/SMB2RdmaTransformType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SharpHoundCommonLib.SMB.SMB2
8 | {
9 | ///
10 | /// SMB2 RDMA Transform Types
11 | ///
12 | public enum SMB2RdmaTransformType : ushort
13 | {
14 | None = 0x0000,
15 | Encryption = 0x0001,
16 | Signing = 0x0002
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/CommonLib/SMB/SMB2/SMB2SigningAlgorithm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SharpHoundCommonLib.SMB.SMB2
8 | {
9 | ///
10 | /// SMB2 Signing Algorithms
11 | ///
12 | public enum SMB2SigningAlgorithm : ushort
13 | {
14 | HmacSha256 = 0x0000,
15 | AesCmac = 0x0001,
16 | AesGmac = 0x0002
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/CommonLib/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Handles/BasePointer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Principal;
5 | using Microsoft.Win32.SafeHandles;
6 |
7 | namespace SharpHoundRPC.Handles
8 | {
9 | public abstract class BasePointer : SafeHandleZeroOrMinusOneIsInvalid
10 | {
11 | protected BasePointer() : base(true)
12 | {
13 | }
14 |
15 | protected BasePointer(bool ownsHandle) : base(ownsHandle)
16 | {
17 | }
18 |
19 | protected BasePointer(IntPtr handle) : base(true)
20 | {
21 | SetHandle(handle);
22 | }
23 |
24 | protected BasePointer(IntPtr handle, bool ownsHandle) : base(ownsHandle)
25 | {
26 | SetHandle(handle);
27 | }
28 |
29 | public IEnumerable GetEnumerable(int count)
30 | {
31 | for (var i = 0; i < count; i++)
32 | if (typeof(T) == typeof(int))
33 | yield return (T) (object) ReadInt32(i);
34 | else if (typeof(T) == typeof(long))
35 | yield return (T) (object) ReadInt64(i);
36 | else if (typeof(T) == typeof(SecurityIdentifier))
37 | yield return (T) (object) new SecurityIdentifier(ReadIntPtr(i));
38 | else
39 | yield return Marshal.PtrToStructure(handle + Marshal.SizeOf() * i);
40 | }
41 |
42 | public T GetData()
43 | {
44 | if (typeof(T) == typeof(int)) return (T) (object) ReadInt32();
45 |
46 | if (typeof(T) == typeof(long)) return (T) (object) ReadInt64();
47 |
48 | if (typeof(T) == typeof(SecurityIdentifier)) return (T) (object) new SecurityIdentifier(handle);
49 |
50 | return Marshal.PtrToStructure(handle);
51 | }
52 |
53 | private int ReadInt32(int offset = 0)
54 | {
55 | return Marshal.ReadInt32(handle + offset * Marshal.SizeOf());
56 | }
57 |
58 | private long ReadInt64(int offset = 0)
59 | {
60 | return Marshal.ReadInt64(handle + offset * Marshal.SizeOf());
61 | }
62 |
63 | private IntPtr ReadIntPtr(int offset = 0)
64 | {
65 | return Marshal.ReadIntPtr(handle + offset * Marshal.SizeOf());
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Handles/LSAHandle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Win32.SafeHandles;
3 | using SharpHoundRPC.LSANative;
4 |
5 | namespace SharpHoundRPC.Handles
6 | {
7 | public class LSAHandle : SafeHandleZeroOrMinusOneIsInvalid
8 | {
9 | public LSAHandle() : base(true)
10 | {
11 | }
12 |
13 | public LSAHandle(IntPtr handle, bool ownsHandle) : base(ownsHandle)
14 | {
15 | SetHandle(handle);
16 | }
17 |
18 | public LSAHandle(bool ownsHandle) : base(true)
19 | {
20 | }
21 |
22 | protected override bool ReleaseHandle()
23 | {
24 | if (handle == IntPtr.Zero) return true;
25 | return LSAMethods.LsaClose(handle) == NtStatus.StatusSuccess;
26 | }
27 |
28 | ~LSAHandle()
29 | {
30 | Dispose();
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Handles/LSAPointer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SharpHoundRPC.LSANative;
3 |
4 | namespace SharpHoundRPC.Handles
5 | {
6 | public class LSAPointer : BasePointer
7 | {
8 | public LSAPointer() : base(true)
9 | {
10 | }
11 |
12 | public LSAPointer(IntPtr handle) : base(handle, true)
13 | {
14 | }
15 |
16 | public LSAPointer(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle)
17 | {
18 | }
19 |
20 | protected override bool ReleaseHandle()
21 | {
22 | if (handle == IntPtr.Zero) return true;
23 | return LSAMethods.LsaFreeMemory(handle) == NtStatus.StatusSuccess;
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Handles/NetAPIPointer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SharpHoundRPC.NetAPINative;
3 |
4 | namespace SharpHoundRPC.Handles
5 | {
6 | public class NetAPIPointer : BasePointer
7 | {
8 | public NetAPIPointer() : base(true)
9 | {
10 | }
11 |
12 | public NetAPIPointer(IntPtr handle) : base(handle, true)
13 | {
14 | }
15 |
16 | public NetAPIPointer(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle)
17 | {
18 | }
19 |
20 | protected override bool ReleaseHandle()
21 | {
22 | if (handle == IntPtr.Zero) return true;
23 | return NetAPIMethods.NetApiBufferFree(handle) == NetAPIEnums.NetAPIStatus.Success;
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Handles/SAMHandle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Win32.SafeHandles;
3 | using SharpHoundRPC.SAMRPCNative;
4 |
5 | namespace SharpHoundRPC.Handles
6 | {
7 | public class SAMHandle : SafeHandleZeroOrMinusOneIsInvalid
8 | {
9 | public SAMHandle() : base(true)
10 | {
11 | }
12 |
13 | public SAMHandle(IntPtr handle) : base(true)
14 | {
15 | SetHandle(handle);
16 | }
17 |
18 | public SAMHandle(IntPtr handle, bool ownsHandle) : base(ownsHandle)
19 | {
20 | SetHandle(handle);
21 | }
22 |
23 | protected override bool ReleaseHandle()
24 | {
25 | if (handle == IntPtr.Zero) return true;
26 | return SAMMethods.SamCloseHandle(handle) == NtStatus.StatusSuccess;
27 | }
28 |
29 | ~SAMHandle()
30 | {
31 | Dispose();
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Handles/SAMPointer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SharpHoundRPC.SAMRPCNative;
3 |
4 | namespace SharpHoundRPC.Handles
5 | {
6 | public class SAMPointer : BasePointer
7 | {
8 | public SAMPointer() : base(true)
9 | {
10 | }
11 |
12 | public SAMPointer(IntPtr handle) : base(handle, true)
13 | {
14 | }
15 |
16 | public SAMPointer(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle)
17 | {
18 | }
19 |
20 | protected override bool ReleaseHandle()
21 | {
22 | return SAMMethods.SamFreeMemory(handle) == NtStatus.StatusSuccess;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Handles/SAMSidArray.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Principal;
5 |
6 | namespace SharpHoundRPC.Handles
7 | {
8 | public class SAMSidArray : SAMPointer
9 | {
10 | public SAMSidArray()
11 | {
12 | }
13 |
14 | public SAMSidArray(IntPtr handle) : base(handle)
15 | {
16 | }
17 |
18 | public SAMSidArray(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle)
19 | {
20 | }
21 |
22 | public IEnumerable GetData(int count)
23 | {
24 | for (var i = 0; i < count; i++)
25 | {
26 | var rawPtr = Marshal.ReadIntPtr(handle, Marshal.SizeOf() * i);
27 | var sid = new SecurityIdentifier(rawPtr);
28 | yield return sid;
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/LSANative/LSAEnums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundRPC.LSANative
4 | {
5 | public class LSAEnums
6 | {
7 | [Flags]
8 | public enum LsaOpenMask
9 | {
10 | ViewLocalInfo = 0x1,
11 | ViewAuditInfo = 0x2,
12 | GetPrivateInfo = 0x4,
13 | TrustAdmin = 0x8,
14 | CreateAccount = 0x10,
15 | CreateSecret = 0x20,
16 | CreatePrivilege = 0x40,
17 | SetDefaultQuotaLimits = 0x80,
18 | SetAuditRequirements = 0x100,
19 | AuditLogAdmin = 0x200,
20 | ServerAdmin = 0x400,
21 | LookupNames = 0x800,
22 | Notification = 0x1000,
23 | POLICY_READ = 0x20006,
24 | POLICY_ALL_ACCESS = 0x00F0FFF,
25 | POLICY_EXECUTE = 0X20801,
26 | POLICY_WRITE = 0X207F8
27 | }
28 |
29 | public enum LSAPolicyInformation
30 | {
31 | PolicyAuditLogInformation = 1,
32 | PolicyAuditEventsInformation,
33 | PolicyPrimaryDomainInformation,
34 | PolicyPdAccountInformation,
35 | PolicyAccountDomainInformation,
36 | PolicyLsaServerRoleInformation,
37 | PolicyReplicaSourceInformation,
38 | PolicyDefaultQuotaInformation,
39 | PolicyModificationInformation,
40 | PolicyAuditFullSetInformation,
41 | PolicyAuditFullQueryInformation,
42 | PolicyDnsDomainInformation
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/LSANative/LSAStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using SharpHoundRPC.Shared;
4 |
5 | namespace SharpHoundRPC.LSANative
6 | {
7 | public class LSAStructs
8 | {
9 | [StructLayout(LayoutKind.Sequential)]
10 | public struct ObjectAttributes
11 | {
12 | public int Length;
13 | public IntPtr RootDirectory;
14 | public IntPtr ObjectName;
15 | public int Attributes;
16 | public IntPtr SecurityDescriptor;
17 | public IntPtr SecurityQualityOfService;
18 |
19 | public void Dispose()
20 | {
21 | if (ObjectName == IntPtr.Zero) return;
22 | Marshal.DestroyStructure(ObjectName, typeof(SharedStructs.UnicodeString));
23 | Marshal.FreeHGlobal(ObjectName);
24 | ObjectName = IntPtr.Zero;
25 | }
26 | }
27 |
28 | [StructLayout(LayoutKind.Sequential)]
29 | public struct PolicyAccountDomainInfo
30 | {
31 | public SharedStructs.UnicodeString DomainName;
32 | public IntPtr DomainSid;
33 | }
34 |
35 | [StructLayout(LayoutKind.Sequential)]
36 | public struct LSATranslatedNames
37 | {
38 | public SharedEnums.SidNameUse Use;
39 | public SharedStructs.UnicodeString Name;
40 | public int DomainIndex;
41 | }
42 |
43 | [StructLayout(LayoutKind.Sequential)]
44 | public struct LSAReferencedDomains
45 | {
46 | public int Entries;
47 | public IntPtr Domains;
48 | }
49 |
50 | [StructLayout(LayoutKind.Sequential)]
51 | public struct LSATrustInformation
52 | {
53 | public SharedStructs.UnicodeString Name;
54 | public IntPtr Sid;
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/NTStatus.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundRPC
2 | {
3 | public enum NtStatus
4 | {
5 | StatusSuccess = 0x0,
6 | StatusMoreEntries = 0x105,
7 | StatusSomeMapped = 0x107,
8 | StatusInvalidHandle = unchecked((int) 0xC0000008),
9 | StatusInvalidParameter = unchecked((int) 0xC000000D),
10 | StatusAccessDenied = unchecked((int) 0xC0000022),
11 | StatusObjectTypeMismatch = unchecked((int) 0xC0000024),
12 | StatusNoSuchDomain = unchecked((int) 0xC00000DF),
13 | StatusRpcServerUnavailable = unchecked((int) 0xC0020017),
14 | StatusNoSuchAlias = unchecked((int) 0xC0000151),
15 | StatusNoMoreEntries = unchecked((int) 0x8000001A)
16 | }
17 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/NetAPINative/NetAPIResult.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundRPC.NetAPINative
2 | {
3 | public class NetAPIResult
4 | {
5 | public bool IsSuccess { get; private set; }
6 | public NetAPIEnums.NetAPIStatus Status { get; private set; }
7 | public T Value { get; private set; }
8 | public string Error { get; private set; }
9 | public bool IsFailed => !IsSuccess;
10 |
11 | public static NetAPIResult Ok(T value)
12 | {
13 | return new NetAPIResult {IsSuccess = true, Value = value};
14 | }
15 |
16 | public static NetAPIResult Fail(NetAPIEnums.NetAPIStatus status)
17 | {
18 | return new NetAPIResult {Status = status};
19 | }
20 |
21 | public static NetAPIResult Fail(string error)
22 | {
23 | return new NetAPIResult {Error = error};
24 | }
25 |
26 | public static implicit operator NetAPIResult(T input)
27 | {
28 | return Ok(input);
29 | }
30 |
31 | public static implicit operator NetAPIResult(NetAPIEnums.NetAPIStatus status)
32 | {
33 | return Fail(status);
34 | }
35 |
36 | public static implicit operator NetAPIResult(string error)
37 | {
38 | return Fail(error);
39 | }
40 |
41 | public string GetErrorStatus() {
42 | if (!string.IsNullOrEmpty(Error)) {
43 | return Error;
44 | }
45 |
46 | return Status.ToString();
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/NetAPINative/NetAPIReturns.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundRPC.NetAPINative
2 | {
3 | public class NetWkstaUserEnumResults
4 | {
5 | public NetWkstaUserEnumResults(string username, string domain)
6 | {
7 | LogonDomain = domain;
8 | Username = username;
9 | }
10 |
11 | public string LogonDomain { get; }
12 | public string Username { get; }
13 | }
14 |
15 | public class NetSessionEnumResults
16 | {
17 | public NetSessionEnumResults(string username, string cname)
18 | {
19 | Username = username;
20 | ComputerName = cname;
21 | }
22 |
23 | public string Username { get; }
24 | public string ComputerName { get; }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/NetAPINative/NetAPIStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace SharpHoundRPC.NetAPINative
5 | {
6 | public class NetAPIStructs
7 | {
8 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
9 | public struct WkstaUserInfo1
10 | {
11 | public string Username;
12 | public string LogonDomain;
13 | public string OtherDomains;
14 | public string LogonServer;
15 | }
16 |
17 | [StructLayout(LayoutKind.Sequential)]
18 | public struct SessionInfo10
19 | {
20 | [MarshalAs(UnmanagedType.LPWStr)] public string CName;
21 | [MarshalAs(UnmanagedType.LPWStr)] public string Username;
22 | public uint Time;
23 | public uint IdleTIme;
24 | }
25 |
26 | [StructLayout(LayoutKind.Sequential)]
27 | public struct WorkstationInfo100
28 | {
29 | public int PlatformId;
30 | [MarshalAs(UnmanagedType.LPWStr)] public string ComputerName;
31 | [MarshalAs(UnmanagedType.LPWStr)] public string LanGroup;
32 | public int MajorVersion;
33 | public int MinorVersion;
34 | }
35 |
36 | [StructLayout(LayoutKind.Sequential)]
37 | public class GuidClass
38 | {
39 | public Guid TheGuid;
40 | }
41 |
42 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
43 | public struct DomainControllerInfo
44 | {
45 | [MarshalAs(UnmanagedType.LPTStr)] public string DomainControllerName;
46 | [MarshalAs(UnmanagedType.LPTStr)] public string DomainControllerAddress;
47 | public uint DomainControllerAddressType;
48 | public Guid DomainGuid;
49 | [MarshalAs(UnmanagedType.LPTStr)] public string DomainName;
50 | [MarshalAs(UnmanagedType.LPTStr)] public string DnsForestName;
51 | public uint Flags;
52 | [MarshalAs(UnmanagedType.LPTStr)] public string DcSiteName;
53 | [MarshalAs(UnmanagedType.LPTStr)] public string ClientSiteName;
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/PortScanner/IPortScanner.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace SharpHoundRPC.PortScanner {
4 | public interface IPortScanner {
5 | Task CheckPort(string hostname, int port = 445, int timeout = 10000, bool throwError = false);
6 | }
7 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/RPCException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpHoundRPC
4 | {
5 | public class RPCException : Exception
6 | {
7 | public const string Connect = "SamConnect";
8 | public const string EnumerateDomains = "SamEnumerateDomainsInSamServer";
9 | public const string ServerNotInitialized = "Server Not Initialized";
10 | public const string OpenAlias = "SamOpenAlias";
11 | public const string OpenDomain = "SamOpenDomain";
12 | public const string AliasNotFound = "Alias Not Found";
13 | public const string DomainNotFound = "Domain Not Found";
14 | public const string LookupIds = "SamLookupIdsInDomain";
15 | public const string EnumerateAliases = "SamEnumerateAliasesInDomain";
16 | public const string GetAliasMembers = "SamGetMembersinAlias";
17 | public const string LookupDomain = "SamLookupDomainInSamServer";
18 | public const string GetMachineSid = "GetMachineSid";
19 | private readonly string APICall;
20 | private readonly string Status;
21 |
22 | public RPCException(string apiCall, NtStatus status)
23 | {
24 | APICall = apiCall;
25 | Status = status.ToString();
26 | }
27 |
28 | public RPCException(string apiCall, string status)
29 | {
30 | APICall = apiCall;
31 | Status = status;
32 | }
33 |
34 | public override string ToString()
35 | {
36 | return $"Call to {APICall} returned {Status}";
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Registry/ICollectionStrategy.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace SharpHoundRPC.Registry {
6 | ///
7 | /// Strategy for collecting data of type using queries of type .
8 | ///
9 | /// The type of data to collect
10 | /// The type of query used to collect the data
11 | public interface ICollectionStrategy {
12 | ///
13 | /// Checks if this strategy can be executed against the target machine.
14 | ///
15 | /// Target machine name or IP
16 | /// Whether the strategy can execute and reason if it cannot
17 | Task<(bool canExecute, string reason)> CanExecute(string targetMachine);
18 |
19 | ///
20 | /// Executes the strategy to collect data from the target machine.
21 | ///
22 | /// Target machine name or IP
23 | /// Queries specifying what data to collect
24 | /// Collection of results
25 | Task> ExecuteAsync(string targetMachine, IEnumerable queries);
26 | }
27 | #nullable disable
28 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Registry/RegistryQuery.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using Microsoft.Win32;
3 | using System.Collections.Generic;
4 |
5 | namespace SharpHoundRPC.Registry {
6 | public class RegistryQuery {
7 | public RegistryQuery(RegistryHive hive, string keyPath) {
8 | Hive = hive;
9 | KeyPath = keyPath;
10 | }
11 |
12 | public RegistryHive Hive { get; set; }
13 | public string KeyPath { get; set; }
14 |
15 | // If not set, returns all values in the key
16 | public IEnumerable? ValueNames { get; set; }
17 |
18 |
19 | // Helper methods for fluent configuration
20 | public static RegistryQuery ForKey(RegistryHive hive, string keyPath) {
21 | return new RegistryQuery(hive, keyPath);
22 | }
23 |
24 | public RegistryQuery WithValues(params string[] valueNames) {
25 | ValueNames = valueNames;
26 | return this;
27 | }
28 | }
29 | #nullable disable
30 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Registry/RegistryQueryResult.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace SharpHoundRPC.Registry {
3 | using Microsoft.Win32;
4 |
5 |
6 | public class RegistryQueryResult {
7 | public RegistryQueryResult(string keyPath, string valueName, object? value, RegistryValueKind? valueKind,
8 | bool valueExists) {
9 | KeyPath = keyPath;
10 | ValueName = valueName;
11 | Value = value;
12 | ValueKind = valueKind;
13 | ValueExists = valueExists;
14 | }
15 |
16 | public string KeyPath { get; set; }
17 | public string ValueName { get; set; }
18 | public object? Value { get; set; }
19 | public RegistryValueKind? ValueKind { get; set; }
20 | public bool ValueExists { get; set; }
21 | }
22 | #nullable disable
23 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Registry/StrategyExecutor.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace SharpHoundRPC.Registry {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 |
8 | public class StrategyExecutor {
9 | public async Task> CollectAsync(
10 | string targetMachine,
11 | IEnumerable queries,
12 | IEnumerable> strategies) {
13 | var attempts = new List>();
14 |
15 | foreach (var strategy in strategies) {
16 | var attempt = new StrategyResult(strategy.GetType());
17 | var (canExecute, reason) = await strategy.CanExecute(targetMachine).ConfigureAwait(false);
18 |
19 | if (!canExecute) {
20 | attempt.FailureReason = reason;
21 | attempts.Add(attempt);
22 | continue;
23 | }
24 |
25 | try {
26 | var results = await strategy.ExecuteAsync(targetMachine, queries).ConfigureAwait(false);
27 |
28 | attempt.WasSuccessful = true;
29 | attempt.Results = results;
30 |
31 | return new StrategyExecutorResult {
32 | Results = results,
33 | FailureAttempts = attempts,
34 | WasSuccessful = true
35 | };
36 | } catch (Exception ex) {
37 | attempt.FailureReason = $"Collector failed: {ex.Message}.\nInner Exception: {ex.InnerException}";
38 | }
39 |
40 | attempts.Add(attempt);
41 | }
42 |
43 | return new StrategyExecutorResult {
44 | Results = null,
45 | FailureAttempts = attempts
46 | };
47 | }
48 | }
49 | #nullable disable
50 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Registry/StrategyExecutorResult.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | namespace SharpHoundRPC.Registry {
3 | using System.Collections.Generic;
4 |
5 |
6 | public class StrategyExecutorResult {
7 | public IEnumerable? Results { get; set; } = null;
8 | public IEnumerable>? FailureAttempts { get; set; } = null;
9 | public bool WasSuccessful = false;
10 | }
11 | #nullable disable
12 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Registry/StrategyResult.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 |
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace SharpHoundRPC.Registry {
7 | ///
8 | /// Represents the result of attempting to execute an enumeration strategy
9 | ///
10 | /// The type of data being enumerated
11 | public class StrategyResult {
12 | ///
13 | /// The type of strategy that was attempted
14 | ///
15 | public Type StrategyType { get; set; }
16 |
17 | ///
18 | /// Indicates whether the strategy executed successfully.
19 | /// Only meaningful if WasAttempted is true.
20 | ///
21 | public bool WasSuccessful { get; set; } = false;
22 |
23 | ///
24 | /// A human-readable description of why the strategy failed.
25 | /// May include details about port availability, access denied, etc.
26 | ///
27 | public string? FailureReason { get; set; } = null;
28 |
29 | ///
30 | /// The results returned by the strategy if it executed successfully.
31 | /// Will be null or empty if strategy failed or wasn't attempted.
32 | ///
33 | public IEnumerable? Results { get; set; }
34 |
35 | ///
36 | /// Creates a new instance of StrategyAttemptResult with default values
37 | ///
38 | public StrategyResult(Type strategyType) {
39 | StrategyType = strategyType;
40 | }
41 |
42 | ///
43 | /// Returns a string representation of the attempt result for logging/debugging
44 | ///
45 | public override string ToString() {
46 | return $"Strategy: {StrategyType?.Name ?? "Unknown"}, " +
47 | $"Successful: {WasSuccessful}, " +
48 | (!string.IsNullOrEmpty(FailureReason) ? $", Reason: {FailureReason}" : "");
49 | }
50 | }
51 | #nullable disable
52 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Result.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundRPC
2 | {
3 | public class Result
4 | {
5 | public bool IsSuccess { get; private set; }
6 | public NtStatus Status { get; private set; }
7 | public T Value { get; private set; }
8 | public string Error { get; private set; }
9 | public bool IsFailed => !IsSuccess;
10 | public bool IsTimeout { get; set; }
11 |
12 | public static Result Ok(T value)
13 | {
14 | return new() {IsSuccess = true, Value = value};
15 | }
16 |
17 | public static Result Fail(NtStatus status)
18 | {
19 | return new() {Status = status};
20 | }
21 |
22 | public static Result Fail(string error)
23 | {
24 | return new() {Error = error};
25 | }
26 |
27 | public string SError
28 | {
29 | get
30 | {
31 | if (!string.IsNullOrEmpty(Error))
32 | {
33 | return Error;
34 | }
35 |
36 | return Status.ToString();
37 | }
38 | }
39 |
40 | public static implicit operator Result(T input)
41 | {
42 | return Ok(input);
43 | }
44 |
45 | public static implicit operator Result(NtStatus status)
46 | {
47 | return Fail(status);
48 | }
49 |
50 | public static implicit operator Result(string error)
51 | {
52 | return Fail(error);
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/SAMRPCNative/SAMEnums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 |
4 | namespace SharpHoundRPC.SAMRPCNative
5 | {
6 | public class SAMEnums
7 | {
8 | [Flags]
9 | [SuppressMessage("ReSharper", "UnusedMember.Local")]
10 | public enum AliasOpenFlags
11 | {
12 | AddMember = 0x1,
13 | RemoveMember = 0x2,
14 | ListMembers = 0x4,
15 | ReadInfo = 0x8,
16 | WriteAccount = 0x10,
17 | AllAccess = 0xf001f,
18 | Read = 0x20004,
19 | Write = 0x20013,
20 | Execute = 0x20008
21 | }
22 |
23 | [Flags]
24 | [SuppressMessage("ReSharper", "UnusedMember.Local")]
25 | public enum DomainAccessMask
26 | {
27 | ReadPasswordParameters = 0x1,
28 | WritePasswordParameters = 0x2,
29 | ReadOtherParameters = 0x4,
30 | WriteOtherParameters = 0x8,
31 | CreateUser = 0x10,
32 | CreateGroup = 0x20,
33 | CreateAlias = 0x40,
34 | GetAliasMembership = 0x80,
35 | ListAccounts = 0x100,
36 | Lookup = 0x200,
37 | AdministerServer = 0x400,
38 | AllAccess = 0xf07ff,
39 | Read = 0x20084,
40 | Write = 0x2047A,
41 | Execute = 0x20301
42 | }
43 |
44 | [Flags]
45 | [SuppressMessage("ReSharper", "UnusedMember.Local")]
46 | public enum SamAccessMasks
47 | {
48 | SamServerConnect = 0x1,
49 | SamServerShutdown = 0x2,
50 | SamServerInitialize = 0x4,
51 | SamServerCreateDomains = 0x8,
52 | SamServerEnumerateDomains = 0x10,
53 | SamServerLookupDomain = 0x20,
54 | SamServerAllAccess = 0xf003f,
55 | SamServerRead = 0x20010,
56 | SamServerWrite = 0x2000e,
57 | SamServerExecute = 0x20021
58 | }
59 |
60 | [Flags]
61 | [SuppressMessage("ReSharper", "UnusedMember.Local")]
62 | internal enum SamAliasFlags
63 | {
64 | AddMembers = 0x1,
65 | RemoveMembers = 0x2,
66 | ListMembers = 0x4,
67 | ReadInfo = 0x8,
68 | WriteAccount = 0x10,
69 | AllAccess = 0xf001f,
70 | Read = 0x20004,
71 | Write = 0x20013,
72 | Execute = 0x20008
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/SAMRPCNative/SAMStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using SharpHoundRPC.Shared;
4 |
5 | namespace SharpHoundRPC.SAMRPCNative
6 | {
7 | public static class SAMStructs
8 | {
9 | public struct ObjectAttributes : IDisposable
10 | {
11 | public void Dispose()
12 | {
13 | if (_objectName == IntPtr.Zero) return;
14 | Marshal.DestroyStructure(_objectName, typeof(SharedStructs.UnicodeString));
15 | Marshal.FreeHGlobal(_objectName);
16 | _objectName = IntPtr.Zero;
17 | }
18 |
19 | public int Length;
20 | public IntPtr RootDirectory;
21 | public uint Attributes;
22 | public IntPtr SID;
23 | public IntPtr Qos;
24 | private IntPtr _objectName;
25 | public SharedStructs.UnicodeString ObjectName;
26 | }
27 |
28 | [StructLayout(LayoutKind.Sequential)]
29 | public struct SamRidEnumeration
30 | {
31 | public int Rid;
32 | public SharedStructs.UnicodeString Name;
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Shared/SharedEnums.cs:
--------------------------------------------------------------------------------
1 | namespace SharpHoundRPC.Shared
2 | {
3 | public class SharedEnums
4 | {
5 | public enum SidNameUse
6 | {
7 | User = 1,
8 | Group,
9 | Domain,
10 | Alias,
11 | WellKnownGroup,
12 | DeletedAccount,
13 | Invalid,
14 | Unknown,
15 | Computer,
16 | Label,
17 | LogonSession
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Shared/SharedStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace SharpHoundRPC.Shared
5 | {
6 | public class SharedStructs
7 | {
8 | [StructLayout(LayoutKind.Sequential)]
9 | public struct UnicodeString : IDisposable
10 | {
11 | private readonly ushort Length;
12 | private readonly ushort MaximumLength;
13 | private IntPtr Buffer;
14 |
15 | public UnicodeString(string s)
16 | : this()
17 | {
18 | if (s == null) return;
19 | Length = (ushort) (s.Length * 2);
20 | MaximumLength = (ushort) (Length + 2);
21 | Buffer = Marshal.StringToHGlobalUni(s);
22 | }
23 |
24 | public void Dispose()
25 | {
26 | if (Buffer == IntPtr.Zero) return;
27 | Marshal.FreeHGlobal(Buffer);
28 | Buffer = IntPtr.Zero;
29 | }
30 |
31 | public override string ToString()
32 | {
33 | return (Buffer != IntPtr.Zero ? Marshal.PtrToStringUni(Buffer, Length / 2) : null) ??
34 | throw new InvalidOperationException();
35 | }
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/SharpHoundRPC.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net472
4 | library
5 | SharpHoundRPC
6 | default
7 | Rohan Vazarkar
8 | SpecterOps
9 | SAM/LSA Wrapper for C# BloodHound tasks
10 | GPL-3.0-only
11 | 4.2.1
12 | SharpHoundRPC
13 | SharpHoundRPC
14 |
15 |
16 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
17 | full
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/ILSAPolicy.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Security.Principal;
3 | using SharpHoundRPC.Shared;
4 |
5 | namespace SharpHoundRPC.Wrappers
6 | {
7 | public interface ILSAPolicy
8 | {
9 | Result<(string Name, string Sid)> GetLocalDomainInformation();
10 | Result> GetPrincipalsWithPrivilege(string userRight);
11 |
12 | Result>
13 | GetResolvedPrincipalsWithPrivilege(string userRight);
14 |
15 | Result<(string Name, SharedEnums.SidNameUse Use, string Domains)> LookupSid(SecurityIdentifier sid);
16 |
17 | Result>
18 | LookupSids(
19 | SecurityIdentifier[] sids);
20 | }
21 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/ISAMAlias.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Security.Principal;
3 |
4 | namespace SharpHoundRPC.Wrappers
5 | {
6 | public interface ISAMAlias
7 | {
8 | Result> GetMembers();
9 | }
10 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/ISAMDomain.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using SharpHoundRPC.SAMRPCNative;
3 | using SharpHoundRPC.Shared;
4 |
5 | namespace SharpHoundRPC.Wrappers
6 | {
7 | public interface ISAMDomain
8 | {
9 | Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid);
10 | Result> GetAliases();
11 |
12 | Result OpenAlias(int rid,
13 | SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers);
14 |
15 | Result OpenAlias(string name);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/ISAMServer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Security.Principal;
3 | using SharpHoundRPC.SAMRPCNative;
4 | using SharpHoundRPC.Shared;
5 |
6 | namespace SharpHoundRPC.Wrappers
7 | {
8 | public interface ISAMServer
9 | {
10 | Result> GetDomains();
11 | Result LookupDomain(string name);
12 | Result GetMachineSid(string testName = null);
13 |
14 | Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalBySid(
15 | SecurityIdentifier securityIdentifier);
16 |
17 | Result OpenDomain(string domainName, SAMEnums.DomainAccessMask requestedDomainAccess =
18 | SAMEnums.DomainAccessMask.Lookup |
19 | SAMEnums.DomainAccessMask.ListAccounts);
20 |
21 | Result OpenDomain(SecurityIdentifier securityIdentifier,
22 | SAMEnums.DomainAccessMask requestedDomainAccess =
23 | SAMEnums.DomainAccessMask.Lookup |
24 | SAMEnums.DomainAccessMask.ListAccounts);
25 | }
26 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/LSABase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SharpHoundRPC.Handles;
3 |
4 | namespace SharpHoundRPC.Wrappers
5 | {
6 | public class LSABase : IDisposable
7 | {
8 | protected LSAHandle Handle;
9 |
10 | protected LSABase(LSAHandle handle)
11 | {
12 | Handle = handle;
13 | }
14 |
15 | public void Dispose()
16 | {
17 | Dispose(true);
18 | }
19 |
20 | protected virtual void Dispose(bool disposing)
21 | {
22 | if (disposing) ReleaseHandle();
23 | }
24 |
25 | protected virtual void ReleaseHandle()
26 | {
27 | Handle?.Dispose();
28 | Handle = null;
29 | //Call suppressfinalize to prevent finalization, since we've already cleaned up our own stuff
30 | GC.SuppressFinalize(this);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/SAMAlias.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Security.Principal;
3 | using SharpHoundRPC.Handles;
4 | using SharpHoundRPC.SAMRPCNative;
5 |
6 | namespace SharpHoundRPC.Wrappers
7 | {
8 | public class SAMAlias : SAMBase, ISAMAlias
9 | {
10 | public SAMAlias(SAMHandle handle) : base(handle)
11 | {
12 | }
13 |
14 | public string Name { get; set; }
15 | public int Rid { get; set; }
16 |
17 | public Result> GetMembers()
18 | {
19 | var (status, members, count) = SAMMethods.SamGetMembersInAlias(Handle);
20 |
21 | if (status.IsError())
22 | {
23 | return status;
24 | }
25 |
26 | return Result>.Ok(members.GetData(count));
27 |
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/SAMBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SharpHoundRPC.Handles;
3 |
4 | namespace SharpHoundRPC.Wrappers
5 | {
6 | public class SAMBase : IDisposable
7 | {
8 | protected SAMHandle Handle;
9 |
10 | protected SAMBase(SAMHandle handle)
11 | {
12 | Handle = handle;
13 | }
14 |
15 | public void Dispose()
16 | {
17 | Dispose(true);
18 | }
19 |
20 | protected virtual void Dispose(bool disposing)
21 | {
22 | if (disposing) ReleaseHandle();
23 | }
24 |
25 | protected virtual void ReleaseHandle()
26 | {
27 | Handle?.Dispose();
28 | Handle = null;
29 | //Call suppressfinalize to prevent finalization, since we've already cleaned up our own stuff
30 | GC.SuppressFinalize(this);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/SharpHoundRPC/Wrappers/SAMDomain.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using SharpHoundRPC.Handles;
5 | using SharpHoundRPC.SAMRPCNative;
6 | using SharpHoundRPC.Shared;
7 |
8 | namespace SharpHoundRPC.Wrappers
9 | {
10 | public class SAMDomain : SAMBase, ISAMDomain
11 | {
12 | public SAMDomain(SAMHandle handle) : base(handle)
13 | {
14 | }
15 |
16 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid)
17 | {
18 | var (status, namePointer, usePointer) = SAMMethods.SamLookupIdsInDomain(Handle, rid);
19 |
20 | if (status.IsError()) return status;
21 |
22 | return (namePointer.GetData().ToString(),
23 | (SharedEnums.SidNameUse) usePointer.GetData());
24 | }
25 |
26 | public Result> GetAliases()
27 | {
28 | var (status, ridPointer, count) = SAMMethods.SamEnumerateAliasesInDomain(Handle);
29 |
30 | if (status.IsError())
31 | {
32 | return status;
33 | }
34 |
35 | var ret = Result>.Ok(ridPointer
36 | .GetEnumerable(count)
37 | .Select(x => (x.Name.ToString(), x.Rid)));
38 |
39 | return ret;
40 | }
41 |
42 | public Result OpenAlias(int rid,
43 | SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers)
44 | {
45 | var (status, aliasHandle) = SAMMethods.SamOpenAlias(Handle, desiredAccess, rid);
46 | if (status.IsError()) return status;
47 |
48 | return new SAMAlias(aliasHandle);
49 | }
50 |
51 | public Result OpenAlias(string name)
52 | {
53 | var getAliasesResult = GetAliases();
54 | if (getAliasesResult.IsFailed) return getAliasesResult.Status;
55 |
56 | foreach (var alias in getAliasesResult.Value)
57 | if (alias.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
58 | return OpenAlias(alias.Rid);
59 |
60 | return $"Alias {name} was not found";
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/test/unit/.gitignore:
--------------------------------------------------------------------------------
1 | coverage.json
--------------------------------------------------------------------------------
/test/unit/CAEnrollmentProcessorTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using Moq;
10 | using SharpHoundCommonLib;
11 | using SharpHoundCommonLib.OutputTypes;
12 | using SharpHoundCommonLib.Processors;
13 | using SharpHoundRPC;
14 | using Xunit;
15 | using Xunit.Abstractions;
16 |
17 | namespace CommonLibTest {
18 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
19 | public class CAEnrollmentProcessorTest : IDisposable {
20 |
21 | private readonly ITestOutputHelper _testOutputHelper;
22 |
23 | public CAEnrollmentProcessorTest(ITestOutputHelper testOutputHelper) {
24 | _testOutputHelper = testOutputHelper;
25 | }
26 |
27 | public void Dispose() {
28 | }
29 |
30 | // TODO: Has error "The requested security protocol is not supported
31 | // [Theory]
32 | // [MemberData(nameof(BuildEnrollmentUrlsData))]
33 | // public async Task CAEnrollmentProcessor_BuildEnrollmentUrls(CAEnrollmentEndpointType type, Uri expectedhttpUrl, Uri expectedhttpsUrl)
34 | // {
35 | // var processor = new CAEnrollmentProcessor("primary.testlab.local", "primary-dc-ca");
36 | // (Uri httpUrl, Uri httpsUrl) = processor.BuildEnrollmentUrls(type);
37 | //
38 | // Assert.Equal(httpUrl, expectedhttpUrl);
39 | // Assert.Equal(httpsUrl, expectedhttpsUrl);
40 | // }
41 | //
42 | // public static IEnumerable BuildEnrollmentUrlsData =>
43 | // new List
44 | // {
45 | // new object[]
46 | // {
47 | // CAEnrollmentEndpointType.WebEnrollmentApplication,
48 | // new Uri("http://primary.testlab.local/certsrv/"),
49 | // new Uri("https://primary.testlab.local/certsrv/")
50 | // },
51 | // new object[]
52 | // {
53 | // CAEnrollmentEndpointType.EnrollmentWebService,
54 | // new Uri("http://primary.testlab.local/primary-dc-ca_CES_Kerberos/service.svc"),
55 | // new Uri("https://primary.testlab.local/primary-dc-ca_CES_Kerberos/service.svc")
56 | // }
57 | // };
58 | }
59 | }
--------------------------------------------------------------------------------
/test/unit/CacheTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 | using SharpHoundCommonLib;
4 | using Xunit;
5 | using Xunit.Abstractions;
6 |
7 | namespace CommonLibTest
8 | {
9 | public class CacheTest
10 | {
11 | private ITestOutputHelper _testOutputHelper;
12 | public CacheTest(ITestOutputHelper testOutputHelper)
13 | {
14 | _testOutputHelper = testOutputHelper;
15 | }
16 |
17 | [Fact]
18 | public void Cache_TestNewCache()
19 | {
20 | var cache = Cache.CreateNewCache();
21 | Assert.Equal(cache.CacheCreationVersion, new Version(1,0,0));
22 | var version = new Version(1, 0, 1);
23 | cache = Cache.CreateNewCache(version);
24 | var time = DateTime.Now.Date;
25 | Assert.Equal(cache.CacheCreationVersion, version);
26 | Assert.Equal(cache.CacheCreationDate, time);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/test/unit/Facades/Consts.cs:
--------------------------------------------------------------------------------
1 | namespace CommonLibTest.Facades
2 | {
3 | public class Consts
4 | {
5 | public const string MockDomainSid = "S-1-5-21-3130019616-2776909439-2417379446";
6 | public const string MockDCMachineSid = "S-1-5-21-4243161961-3815211218-2888324771";
7 | public const string MockWorkstationMachineSid = "S-1-5-21-321011808-3761883066-353627080";
8 | }
9 | }
--------------------------------------------------------------------------------
/test/unit/Facades/FacadeHelpers.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.Serialization;
3 |
4 | namespace CommonLibTest.Facades
5 | {
6 | public class FacadeHelpers
7 | {
8 | private const BindingFlags nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
9 | private const BindingFlags publicInstance = BindingFlags.Public | BindingFlags.Instance;
10 |
11 | internal static T GetUninitializedObject()
12 | {
13 | return (T) FormatterServices.GetUninitializedObject(typeof(T));
14 | }
15 |
16 | internal static void SetField(T1 obj, string propertyName, T2 propertyValue)
17 | {
18 | var set = typeof(T1).GetField(propertyName, nonPublicInstance);
19 | if (set != null) set.SetValue(obj, propertyValue);
20 | }
21 |
22 | internal static void SetProperty(T1 obj, string propertyName, T2 propertyValue)
23 | {
24 | var set = typeof(T1).GetProperty(propertyName, nonPublicInstance);
25 | if (set != null) set.SetValue(obj, propertyValue);
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/test/unit/Facades/LSAMocks/DCMocks/MockDCLSAPolicy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.Shared;
7 | using SharpHoundRPC.Wrappers;
8 |
9 | namespace CommonLibTest.Facades.LSAMocks.DCMocks
10 | {
11 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
12 | public class MockDCLSAPolicy : ILSAPolicy
13 | {
14 | public Result<(string Name, string Sid)> GetLocalDomainInformation()
15 | {
16 | return ("TESTLAB", Consts.MockDCMachineSid);
17 | }
18 |
19 | public Result> GetPrincipalsWithPrivilege(string userRight)
20 | {
21 | throw new NotImplementedException();
22 | }
23 |
24 | public Result>
25 | GetResolvedPrincipalsWithPrivilege(string userRight)
26 | {
27 | return new List<(SecurityIdentifier sid, string Name, SharedEnums.SidNameUse Use, string Domain)>
28 | {
29 | (new SecurityIdentifier("S-1-5-32-544"), "Administrators", SharedEnums.SidNameUse.Alias, "abc")
30 | };
31 | }
32 |
33 | public Result<(string Name, SharedEnums.SidNameUse Use, string Domains)> LookupSid(SecurityIdentifier sid)
34 | {
35 | throw new NotImplementedException();
36 | }
37 |
38 | public Result>
39 | LookupSids(SecurityIdentifier[] sids)
40 | {
41 | throw new NotImplementedException();
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/test/unit/Facades/LSAMocks/ErrorCaseMocks/MockFailLSAPolicy_GetLocalDomainInformation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.Shared;
7 | using SharpHoundRPC.Wrappers;
8 |
9 | namespace CommonLibTest.Facades.LSAMocks.WorkstationMocks
10 | {
11 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
12 | public class MockFailLSAPolicy_GetLocalDomainInformation : ILSAPolicy
13 | {
14 | public Result<(string Name, string Sid)> GetLocalDomainInformation()
15 | {
16 | return NtStatus.StatusAccessDenied;
17 | }
18 |
19 | public Result> GetPrincipalsWithPrivilege(string userRight)
20 | {
21 | throw new NotImplementedException();
22 | }
23 |
24 | public Result>
25 | GetResolvedPrincipalsWithPrivilege(string userRight)
26 | {
27 | return new List<(SecurityIdentifier sid, string Name, SharedEnums.SidNameUse Use, string Domain)>
28 | {
29 | (new SecurityIdentifier("S-1-5-32-555"), "Remote Desktop Users", SharedEnums.SidNameUse.Alias, "abc"),
30 | (new SecurityIdentifier("S-1-5-32-544"), "Administrators", SharedEnums.SidNameUse.Alias, "abc"),
31 | (new SecurityIdentifier($"{Consts.MockWorkstationMachineSid}-1000"), "John", SharedEnums.SidNameUse.User, "abc"),
32 | (new SecurityIdentifier($"{Consts.MockWorkstationMachineSid}-1001"), "TestGroup", SharedEnums.SidNameUse.Alias, "abc"),
33 | };
34 | }
35 |
36 | public Result<(string Name, SharedEnums.SidNameUse Use, string Domains)> LookupSid(SecurityIdentifier sid)
37 | {
38 | throw new NotImplementedException();
39 | }
40 |
41 | public Result>
42 | LookupSids(SecurityIdentifier[] sids)
43 | {
44 | throw new NotImplementedException();
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/test/unit/Facades/LSAMocks/ErrorCaseMocks/MockFailLSAPolicy_GetResolvedPrincipalsWithPrivilege.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.Shared;
7 | using SharpHoundRPC.Wrappers;
8 |
9 | namespace CommonLibTest.Facades.LSAMocks.WorkstationMocks
10 | {
11 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
12 | public class MockFailLSAPolicy_GetResolvedPrincipalsWithPrivilege : ILSAPolicy
13 | {
14 | public Result<(string Name, string Sid)> GetLocalDomainInformation()
15 | {
16 | return ("WIN10", Consts.MockWorkstationMachineSid);
17 | }
18 |
19 | public Result> GetPrincipalsWithPrivilege(string userRight)
20 | {
21 | throw new NotImplementedException();
22 | }
23 |
24 | public Result>
25 | GetResolvedPrincipalsWithPrivilege(string userRight)
26 | {
27 | return NtStatus.StatusAccessDenied;
28 | }
29 |
30 | public Result<(string Name, SharedEnums.SidNameUse Use, string Domains)> LookupSid(SecurityIdentifier sid)
31 | {
32 | throw new NotImplementedException();
33 | }
34 |
35 | public Result>
36 | LookupSids(SecurityIdentifier[] sids)
37 | {
38 | throw new NotImplementedException();
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/test/unit/Facades/LSAMocks/WorkstationMocks/MockWorkstationLSAPolicy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.Shared;
7 | using SharpHoundRPC.Wrappers;
8 |
9 | namespace CommonLibTest.Facades.LSAMocks.WorkstationMocks
10 | {
11 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
12 | public class MockWorkstationLSAPolicy : ILSAPolicy
13 | {
14 | public Result<(string Name, string Sid)> GetLocalDomainInformation()
15 | {
16 | return ("WIN10", Consts.MockWorkstationMachineSid);
17 | }
18 |
19 | public Result> GetPrincipalsWithPrivilege(string userRight)
20 | {
21 | throw new NotImplementedException();
22 | }
23 |
24 | public Result>
25 | GetResolvedPrincipalsWithPrivilege(string userRight)
26 | {
27 | return new List<(SecurityIdentifier sid, string Name, SharedEnums.SidNameUse Use, string Domain)>
28 | {
29 | (new SecurityIdentifier("S-1-5-32-555"), "Remote Desktop Users", SharedEnums.SidNameUse.Alias, "abc"),
30 | (new SecurityIdentifier("S-1-5-32-544"), "Administrators", SharedEnums.SidNameUse.Alias, "abc"),
31 | (new SecurityIdentifier($"{Consts.MockWorkstationMachineSid}-1000"), "John", SharedEnums.SidNameUse.User, "abc"),
32 | (new SecurityIdentifier($"{Consts.MockWorkstationMachineSid}-1001"), "TestGroup", SharedEnums.SidNameUse.Alias, "abc"),
33 | };
34 | }
35 |
36 | public Result<(string Name, SharedEnums.SidNameUse Use, string Domains)> LookupSid(SecurityIdentifier sid)
37 | {
38 | throw new NotImplementedException();
39 | }
40 |
41 | public Result>
42 | LookupSids(SecurityIdentifier[] sids)
43 | {
44 | throw new NotImplementedException();
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/test/unit/Facades/MockExtentions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Microsoft.Extensions.Logging;
4 | using Moq;
5 |
6 | namespace CommonLibTest.Facades;
7 |
8 | public static class MockExtentions
9 | {
10 | public static void VerifyLogContains(this Mock> mockLogger, LogLevel logLevel, params string[] expected)
11 | {
12 | mockLogger.Verify(
13 | x => x.Log(
14 | logLevel,
15 | It.IsAny(),
16 | It.Is((o, t) =>
17 | expected.All(s => o.ToString().Contains(s, StringComparison.OrdinalIgnoreCase))),
18 | It.IsAny(),
19 | It.IsAny>()),
20 | Times.Once);
21 | }
22 |
23 | public static void VerifyLog(this Mock> mockLogger, LogLevel logLevel, string expectedMessage)
24 | {
25 | mockLogger.Verify(
26 | x => x.Log(
27 | logLevel,
28 | It.IsAny(),
29 | It.Is((o, t) =>
30 | string.Equals(expectedMessage, o.ToString(), StringComparison.InvariantCultureIgnoreCase)),
31 | It.IsAny(),
32 | It.IsAny>()),
33 | Times.Once);
34 | }
35 | }
--------------------------------------------------------------------------------
/test/unit/Facades/MockSAMDomain.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using SharpHoundRPC;
3 | using SharpHoundRPC.SAMRPCNative;
4 | using SharpHoundRPC.Shared;
5 | using SharpHoundRPC.Wrappers;
6 |
7 | namespace CommonLibTest.Facades
8 | {
9 | public class MockSAMDomain : ISAMDomain
10 | {
11 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid)
12 | {
13 | throw new System.NotImplementedException();
14 | }
15 |
16 | public Result> GetAliases()
17 | {
18 | throw new System.NotImplementedException();
19 | }
20 |
21 | public Result OpenAlias(int rid, SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers)
22 | {
23 | throw new System.NotImplementedException();
24 | }
25 |
26 | public Result OpenAlias(string name)
27 | {
28 | throw new System.NotImplementedException();
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/test/unit/Facades/MockableDomain.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 | using System.DirectoryServices.ActiveDirectory;
3 |
4 | namespace CommonLibTest.Facades
5 | {
6 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
7 | public class MockableDomain
8 | {
9 | public static Domain Construct(string domainName)
10 | {
11 | var domain = FacadeHelpers.GetUninitializedObject();
12 | FacadeHelpers.SetField(domain, "partitionName", domainName);
13 |
14 | return domain;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/test/unit/Facades/MockableForest.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 | using System.DirectoryServices.ActiveDirectory;
3 |
4 | namespace CommonLibTest.Facades
5 | {
6 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
7 | public class MockableForest
8 | {
9 | public static Forest Construct(string forestDnsName)
10 | {
11 | var forest = FacadeHelpers.GetUninitializedObject();
12 | FacadeHelpers.SetField(forest, "_forestDnsName", forestDnsName);
13 |
14 | return forest;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/test/unit/Facades/MockableSearchResultEntry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.DirectoryServices.Protocols;
5 | using SharpHoundCommonLib;
6 | using BindingFlags = System.Reflection.BindingFlags;
7 |
8 | namespace CommonLibTest.Facades
9 | {
10 | public class MockableSearchResultEntry
11 | {
12 | public static SearchResultEntry Construct(Dictionary values, string distinguishedName)
13 | {
14 | var attributes = CreateAttributes(values);
15 |
16 | return CreateSearchResultEntry(attributes, distinguishedName);
17 | }
18 |
19 |
20 | private static SearchResultAttributeCollection CreateAttributes(Dictionary values)
21 | {
22 | var coll =
23 | (SearchResultAttributeCollection)typeof(SearchResultAttributeCollection)
24 | .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null)
25 | .Invoke(null);
26 |
27 | var dict = (IDictionary) typeof(SearchResultAttributeCollection).GetProperty("Dictionary",
28 | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(coll);
29 |
30 | foreach (var v in values)
31 | {
32 | dict.Add(v.Key, new DirectoryAttribute(v.Key, v.Value));
33 | }
34 | return coll;
35 | }
36 |
37 | private static SearchResultEntry CreateSearchResultEntry(SearchResultAttributeCollection attributes,
38 | string distinguishedName)
39 | {
40 | var types = new[]
41 | {
42 | typeof(string),
43 | typeof(SearchResultAttributeCollection),
44 | };
45 |
46 | var sre = (SearchResultEntry)typeof(SearchResultEntry)
47 | .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, types, null)
48 | .Invoke(new object[]{ distinguishedName, attributes});
49 |
50 | return sre;
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/DCMocks/MockDCAliasAdministrators.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Security.Principal;
4 | using SharpHoundRPC;
5 | using SharpHoundRPC.Wrappers;
6 |
7 | namespace CommonLibTest.Facades
8 | {
9 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
10 | public class MockDCAliasAdministrators : ISAMAlias
11 | {
12 | public Result> GetMembers()
13 | {
14 | return new List
15 | {
16 | new("S-1-5-21-4243161961-3815211218-2888324771-500"),
17 | new("S-1-5-21-4243161961-3815211218-2888324771-519"),
18 | new("S-1-5-21-4243161961-3815211218-2888324771-512")
19 | };
20 | }
21 |
22 | public void Dispose()
23 | {
24 | throw new System.NotImplementedException();
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/DCMocks/MockDCAliasUsers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Security.Principal;
4 | using SharpHoundRPC;
5 | using SharpHoundRPC.Wrappers;
6 |
7 | namespace CommonLibTest.Facades
8 | {
9 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
10 | public class MockDCAliasUsers : ISAMAlias
11 | {
12 | public Result> GetMembers()
13 | {
14 | return new List
15 | {
16 | new("S-1-5-4"),
17 | new("S-1-5-11"),
18 | new("S-1-5-21-4243161961-3815211218-2888324771-513"),
19 | };
20 | }
21 |
22 | public void Dispose()
23 | {
24 | throw new System.NotImplementedException();
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/DCMocks/MockDCDomainBuiltIn.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using SharpHoundRPC;
4 | using SharpHoundRPC.SAMRPCNative;
5 | using SharpHoundRPC.Shared;
6 | using SharpHoundRPC.Wrappers;
7 |
8 | namespace CommonLibTest.Facades
9 | {
10 | public class MockDCDomainBuiltIn : ISAMDomain
11 | {
12 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid)
13 | {
14 | throw new System.NotImplementedException();
15 | }
16 |
17 | public Result> GetAliases()
18 | {
19 | var results = new List<(string, int)>
20 | {
21 | ("Administrators", 544),
22 | ("Users", 545)
23 | };
24 | return results;
25 | }
26 |
27 | public Result OpenAlias(int rid, SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers)
28 | {
29 | switch (rid)
30 | {
31 | case 544:
32 | return new MockDCAliasAdministrators();
33 | case 545:
34 | return new MockDCAliasUsers();
35 | default:
36 | throw new IndexOutOfRangeException();
37 | }
38 | }
39 |
40 | public Result OpenAlias(string name)
41 | {
42 | throw new System.NotImplementedException();
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/DCMocks/MockDCSAMServer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.SAMRPCNative;
7 | using SharpHoundRPC.Shared;
8 | using SharpHoundRPC.Wrappers;
9 |
10 | namespace CommonLibTest.Facades
11 | {
12 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
13 | public class MockDCSAMServer : ISAMServer
14 | {
15 | public bool IsNull { get; }
16 | public Result> GetDomains()
17 | {
18 | var domains = new List<(string, int)>
19 | {
20 | ("BUILTIN", 1)
21 | };
22 | return domains;
23 | }
24 |
25 | public virtual Result LookupDomain(string name)
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public Result GetMachineSid(string testName = null)
31 | {
32 | var securityIdentifier = new SecurityIdentifier(Consts.MockDCMachineSid);
33 | return Result.Ok(securityIdentifier);
34 | }
35 |
36 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalBySid(SecurityIdentifier securityIdentifier)
37 | {
38 | throw new System.NotImplementedException();
39 | }
40 |
41 | public Result OpenDomain(string domainName,
42 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
43 | {
44 | if (domainName.Equals("builtin", StringComparison.OrdinalIgnoreCase))
45 | {
46 | return new MockDCDomainBuiltIn();
47 | }
48 |
49 | throw new NotImplementedException();
50 | }
51 |
52 | public Result OpenDomain(SecurityIdentifier securityIdentifier,
53 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
54 | {
55 | throw new System.NotImplementedException();
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailAliasAdministrators_PreviouslyCached.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Security.Principal;
4 | using SharpHoundRPC;
5 | using SharpHoundRPC.Wrappers;
6 |
7 | namespace CommonLibTest.Facades
8 | {
9 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
10 | public class MockFailAliasAdministrators_PreviouslyCached : ISAMAlias
11 | {
12 | public Result> GetMembers()
13 | {
14 | return new List()
15 | {
16 | new("S-1-5-21-321011808-3761883066-353627080-1000"),
17 | new("S-1-5-21-321011808-3761883066-353627080-1000"),
18 | new("S-1-5-21-4243161961-3815211218-2888324771-512"),
19 | };
20 | }
21 |
22 | public void Dispose()
23 | {
24 | throw new System.NotImplementedException();
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailAlias_PreviouslyCached.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Security.Principal;
4 | using SharpHoundRPC;
5 | using SharpHoundRPC.Wrappers;
6 |
7 | namespace CommonLibTest.Facades
8 | {
9 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
10 | public class MockFailAlias_PreviouslyCached : ISAMAlias
11 | {
12 | public Result> GetMembers()
13 | {
14 | return new List()
15 | {
16 | new("S-1-5-21-321011808-3761883066-353627080-1003"),
17 | new("S-1-5-21-321011808-3761883066-353627080-1003"),
18 | new("S-1-5-32-544"),
19 | };
20 | }
21 |
22 | public void Dispose()
23 | {
24 | throw new System.NotImplementedException();
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailDomainBuiltIn_GetAliases.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using SharpHoundRPC;
4 | using SharpHoundRPC.SAMRPCNative;
5 | using SharpHoundRPC.Shared;
6 | using SharpHoundRPC.Wrappers;
7 |
8 | namespace CommonLibTest.Facades
9 | {
10 | public class MockFailDomainBuiltIn_GetAliases : ISAMDomain
11 | {
12 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid)
13 | {
14 | throw new System.NotImplementedException();
15 | }
16 |
17 | public Result> GetAliases()
18 | {
19 | // var results = new List<(string, int)>
20 | // {
21 | // ("Administrators", 544),
22 | // ("Users", 545)
23 | // };
24 | // return results;
25 | return NtStatus.StatusAccessDenied;
26 | }
27 |
28 | public Result OpenAlias(int rid, SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers)
29 | {
30 | switch (rid)
31 | {
32 | case 544:
33 | return new MockDCAliasAdministrators();
34 | case 545:
35 | return new MockDCAliasUsers();
36 | default:
37 | throw new IndexOutOfRangeException();
38 | }
39 | }
40 |
41 | public Result OpenAlias(string name)
42 | {
43 | throw new System.NotImplementedException();
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailDomainBuiltIn_GetMembers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using SharpHoundRPC;
4 | using SharpHoundRPC.SAMRPCNative;
5 | using SharpHoundRPC.Shared;
6 | using SharpHoundRPC.Wrappers;
7 |
8 | namespace CommonLibTest.Facades
9 | {
10 | public class MockFailDomainBuiltIn_GetMembers : ISAMDomain
11 | {
12 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid)
13 | {
14 | throw new System.NotImplementedException();
15 | }
16 |
17 | public Result> GetAliases()
18 | {
19 | var results = new List<(string, int)>
20 | {
21 | ("Users", 545)
22 | };
23 | return results;
24 | }
25 |
26 | public Result OpenAlias(int rid, SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers)
27 | {
28 | switch (rid)
29 | {
30 | case 545:
31 | return new MockFailSAMAliasUsers_GetMembers();
32 | default:
33 | throw new IndexOutOfRangeException();
34 | }
35 | }
36 |
37 | public Result OpenAlias(string name)
38 | {
39 | throw new System.NotImplementedException();
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailDomainBuiltIn_OpenAlias.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using SharpHoundRPC;
4 | using SharpHoundRPC.SAMRPCNative;
5 | using SharpHoundRPC.Shared;
6 | using SharpHoundRPC.Wrappers;
7 |
8 | namespace CommonLibTest.Facades
9 | {
10 | public class MockFailDomainBuiltIn_OpenAlias : ISAMDomain
11 | {
12 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid)
13 | {
14 | throw new System.NotImplementedException();
15 | }
16 |
17 | public Result> GetAliases()
18 | {
19 | var results = new List<(string, int)>
20 | {
21 | ("Administrators", 544)
22 | };
23 | return results;
24 | }
25 |
26 | public Result OpenAlias(int rid, SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers)
27 | {
28 | // switch (rid)
29 | // {
30 | // case 544:
31 | // return new MockDCAliasAdministrators();
32 | // case 545:
33 | // return new MockDCAliasUsers();
34 | // default:
35 | // throw new IndexOutOfRangeException();
36 | // }
37 | return NtStatus.StatusAccessDenied;
38 | }
39 |
40 | public Result OpenAlias(string name)
41 | {
42 | throw new System.NotImplementedException();
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailDomainBuiltIn_PreviouslyCached.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using SharpHoundRPC;
4 | using SharpHoundRPC.SAMRPCNative;
5 | using SharpHoundRPC.Shared;
6 | using SharpHoundRPC.Wrappers;
7 |
8 | namespace CommonLibTest.Facades
9 | {
10 | public class MockFailDomainBuiltIn_PreviouslyCached : ISAMDomain
11 | {
12 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalByRid(int rid)
13 | {
14 | throw new System.NotImplementedException();
15 | }
16 |
17 | public Result> GetAliases()
18 | {
19 | var result = new List<(string, int)>
20 | {
21 | ("administrators", 544),
22 | ("remote desktop users", 555)
23 | };
24 | return result;
25 | }
26 |
27 | public Result OpenAlias(int rid, SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers)
28 | {
29 | if (rid == 544)
30 | {
31 | return new MockFailAliasAdministrators_PreviouslyCached();
32 | }
33 | if (rid == 555)
34 | {
35 | return new MockFailAlias_PreviouslyCached();
36 | }
37 |
38 | throw new NotImplementedException();
39 | }
40 |
41 | public Result OpenAlias(string name)
42 | {
43 | throw new System.NotImplementedException();
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailSAMAliasUsers_GetMembers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using SharpHoundRPC;
3 | using SharpHoundRPC.Wrappers;
4 | using System.Security.Principal;
5 |
6 | namespace CommonLibTest.Facades
7 | {
8 | public class MockFailSAMAliasUsers_GetMembers : ISAMAlias
9 | {
10 | public Result> GetMembers()
11 | {
12 | return NtStatus.StatusAccessDenied;
13 | }
14 | }
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailSAMServer_GetAliases.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.SAMRPCNative;
7 | using SharpHoundRPC.Shared;
8 | using SharpHoundRPC.Wrappers;
9 |
10 | namespace CommonLibTest.Facades
11 | {
12 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
13 | public class MockFailSAMServer_GetAliases : ISAMServer
14 | {
15 | public bool IsNull { get; }
16 | public Result> GetDomains()
17 | {
18 | var domains = new List<(string, int)>
19 | {
20 | ("BUILTIN", 1)
21 | };
22 | return domains;
23 | }
24 |
25 | public virtual Result LookupDomain(string name)
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public Result GetMachineSid(string testName = null)
31 | {
32 | var securityIdentifier = new SecurityIdentifier(Consts.MockWorkstationMachineSid);
33 | return Result.Ok(securityIdentifier);
34 | }
35 |
36 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalBySid(SecurityIdentifier securityIdentifier)
37 | {
38 | throw new System.NotImplementedException();
39 | }
40 |
41 | public Result OpenDomain(string domainName,
42 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
43 | {
44 | if (domainName.Equals("builtin", StringComparison.OrdinalIgnoreCase))
45 | {
46 | return new MockFailDomainBuiltIn_GetAliases();
47 | }
48 |
49 | throw new NotImplementedException();
50 | }
51 |
52 | public Result OpenDomain(SecurityIdentifier securityIdentifier,
53 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
54 | {
55 | throw new System.NotImplementedException();
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailSAMServer_GetDomains.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.SAMRPCNative;
7 | using SharpHoundRPC.Shared;
8 | using SharpHoundRPC.Wrappers;
9 |
10 | namespace CommonLibTest.Facades
11 | {
12 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
13 | public class MockFailSAMServer_GetDomains : ISAMServer
14 | {
15 | public bool IsNull { get; }
16 | public Result> GetDomains()
17 | {
18 | // var domains = new List<(string, int)>
19 | // {
20 | // ("BUILTIN", 1)
21 | // };
22 | // return domains;
23 |
24 | return Result>.Fail(NtStatus.StatusAccessDenied);
25 | }
26 |
27 | public virtual Result LookupDomain(string name)
28 | {
29 | throw new System.NotImplementedException();
30 | }
31 |
32 | public Result GetMachineSid(string testName = null)
33 | {
34 | var securityIdentifier = new SecurityIdentifier(Consts.MockWorkstationMachineSid);
35 | return Result.Ok(securityIdentifier);
36 | }
37 |
38 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalBySid(SecurityIdentifier securityIdentifier)
39 | {
40 | throw new System.NotImplementedException();
41 | }
42 |
43 | public Result OpenDomain(string domainName,
44 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
45 | {
46 | if (domainName.Equals("builtin", StringComparison.OrdinalIgnoreCase))
47 | {
48 | return new MockDCDomainBuiltIn();
49 | }
50 |
51 | throw new NotImplementedException();
52 | }
53 |
54 | public Result OpenDomain(SecurityIdentifier securityIdentifier,
55 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
56 | {
57 | throw new System.NotImplementedException();
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailSAMServer_GetMachineSid.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.SAMRPCNative;
7 | using SharpHoundRPC.Shared;
8 | using SharpHoundRPC.Wrappers;
9 |
10 | namespace CommonLibTest.Facades
11 | {
12 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
13 | public class MockFailSAMServer_GetMachineSid : ISAMServer
14 | {
15 | public bool IsNull { get; }
16 | public Result> GetDomains()
17 | {
18 | var domains = new List<(string, int)>
19 | {
20 | ("BUILTIN", 1)
21 | };
22 | return domains;
23 | }
24 |
25 | public virtual Result LookupDomain(string name)
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public Result GetMachineSid(string testName = null)
31 | {
32 | // var securityIdentifier = new SecurityIdentifier(Consts.MockWorkstationMachineSid);
33 | // return Result.Ok(securityIdentifier);
34 |
35 | return Result.Fail(NtStatus.StatusAccessDenied);
36 | }
37 |
38 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalBySid(SecurityIdentifier securityIdentifier)
39 | {
40 | throw new System.NotImplementedException();
41 | }
42 |
43 | public Result OpenDomain(string domainName,
44 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
45 | {
46 | if (domainName.Equals("builtin", StringComparison.OrdinalIgnoreCase))
47 | {
48 | return new MockDCDomainBuiltIn();
49 | }
50 |
51 | throw new NotImplementedException();
52 | }
53 |
54 | public Result OpenDomain(SecurityIdentifier securityIdentifier,
55 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
56 | {
57 | throw new System.NotImplementedException();
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailSAMServer_GetMembers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.SAMRPCNative;
7 | using SharpHoundRPC.Shared;
8 | using SharpHoundRPC.Wrappers;
9 |
10 | namespace CommonLibTest.Facades
11 | {
12 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
13 | public class MockFailSAMServer_GetMembers : ISAMServer
14 | {
15 | public bool IsNull { get; }
16 | public Result> GetDomains()
17 | {
18 | var domains = new List<(string, int)>
19 | {
20 | ("BUILTIN", 1)
21 | };
22 | return domains;
23 | }
24 |
25 | public virtual Result LookupDomain(string name)
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public Result GetMachineSid(string testName = null)
31 | {
32 | var securityIdentifier = new SecurityIdentifier(Consts.MockWorkstationMachineSid);
33 | return Result.Ok(securityIdentifier);
34 | }
35 |
36 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalBySid(SecurityIdentifier securityIdentifier)
37 | {
38 | throw new System.NotImplementedException();
39 | }
40 |
41 | public Result OpenDomain(string domainName,
42 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
43 | {
44 | if (domainName.Equals("builtin", StringComparison.OrdinalIgnoreCase))
45 | {
46 | return new MockFailDomainBuiltIn_GetMembers();
47 | }
48 |
49 | throw new NotImplementedException();
50 | }
51 |
52 | public Result OpenDomain(SecurityIdentifier securityIdentifier,
53 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
54 | {
55 | throw new System.NotImplementedException();
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailSAMServer_OpenAlias.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.SAMRPCNative;
7 | using SharpHoundRPC.Shared;
8 | using SharpHoundRPC.Wrappers;
9 |
10 | namespace CommonLibTest.Facades
11 | {
12 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
13 | public class MockFailSAMServer_OpenAlias : ISAMServer
14 | {
15 | public bool IsNull { get; }
16 | public Result> GetDomains()
17 | {
18 | var domains = new List<(string, int)>
19 | {
20 | ("BUILTIN", 1)
21 | };
22 | return domains;
23 | }
24 |
25 | public virtual Result LookupDomain(string name)
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public Result GetMachineSid(string testName = null)
31 | {
32 | var securityIdentifier = new SecurityIdentifier(Consts.MockWorkstationMachineSid);
33 | return Result.Ok(securityIdentifier);
34 | }
35 |
36 | public Result<(string Name, SharedEnums.SidNameUse Type)> LookupPrincipalBySid(SecurityIdentifier securityIdentifier)
37 | {
38 | throw new System.NotImplementedException();
39 | }
40 |
41 | public Result OpenDomain(string domainName,
42 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
43 | {
44 | if (domainName.Equals("builtin", StringComparison.OrdinalIgnoreCase))
45 | {
46 | return new MockFailDomainBuiltIn_OpenAlias();
47 | }
48 |
49 | throw new NotImplementedException();
50 | }
51 |
52 | public Result OpenDomain(SecurityIdentifier securityIdentifier,
53 | SAMEnums.DomainAccessMask requestedDomainAccess = SAMEnums.DomainAccessMask.ListAccounts | SAMEnums.DomainAccessMask.Lookup)
54 | {
55 | throw new System.NotImplementedException();
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/test/unit/Facades/SAMMocks/ErrorCaseMocks/LocalGroupProcessorErrorCases/MockFailSAMServer_OpenDomain.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Security.Principal;
5 | using SharpHoundRPC;
6 | using SharpHoundRPC.SAMRPCNative;
7 | using SharpHoundRPC.Shared;
8 | using SharpHoundRPC.Wrappers;
9 |
10 | namespace CommonLibTest.Facades
11 | {
12 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
13 | public class MockFailSAMServer_OpenDomain : ISAMServer
14 | {
15 | public bool IsNull { get; }
16 | public Result> GetDomains()
17 | {
18 | var domains = new List<(string, int)>
19 | {
20 | ("BUILTIN", 1)
21 | };
22 | return domains;
23 | }
24 |
25 | public virtual Result