├── .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 | ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/BloodHoundAD/SharpHoundCommon/Build) 5 | [![Version](https://img.shields.io/nuget/v/SharpHoundCommon?label=version&logo=nuget)](https://www.nuget.org/packages/SharpHoundCommon) 6 | ![Downloads](https://img.shields.io/nuget/dt/SharpHoundCommon) 7 | [![Coverage](https://bloodhoundad.github.io/SharpHoundCommon/coverage/report/badge_combined.svg)](https://bloodhoundad.github.io/SharpHoundCommon/coverage/report/index.html) 8 | [![Documentation](https://img.shields.io/static/v1?label=&message=documentation&color=blue)](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 |
31 | 32 |
33 | 34 | {{>partials/navbar}} 35 | 36 |
37 | 38 | {{^_disableToc}} 39 | {{>partials/toc}} 40 | {{/_disableToc}} 41 | 42 |
43 | 44 | {{>partials/footer}} 45 | 46 |
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 |
2 | {{{_appFooter}}} 3 | {{^_appFooter}}Generated by DocFX{{/_appFooter}} 4 |
-------------------------------------------------------------------------------- /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 | {{name}} 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 |
      26 | {{>partials/dd-li}} 27 |
    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 |
4 |
5 |
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 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 MockDCDomainBuiltIn(); 47 | // } 48 | 49 | return NtStatus.StatusAccessDenied; 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/WorkstationMocks/MockWorkstationAliasAdministrators.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 MockWorkstationAliasAdministrators : ISAMAlias 11 | { 12 | public Result> GetMembers() 13 | { 14 | return new List() 15 | { 16 | new("S-1-5-21-321011808-3761883066-353627080-500"), 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/WorkstationMocks/MockWorkstationAliasRDP.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 MockWorkstationAliasRDP : 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-32-544"), 18 | }; 19 | } 20 | 21 | public void Dispose() 22 | { 23 | throw new System.NotImplementedException(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /test/unit/Facades/SAMMocks/WorkstationMocks/MockWorkstationAliasTestGroup.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 MockWorkstationAliasTestGroup : ISAMAlias 11 | { 12 | public Result> GetMembers() 13 | { 14 | return new List(); 15 | } 16 | 17 | public void Dispose() 18 | { 19 | throw new System.NotImplementedException(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /test/unit/Facades/SAMMocks/WorkstationMocks/MockWorkstationDomainBuiltIn.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 MockWorkstationDomainBuiltIn : 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 MockWorkstationAliasAdministrators(); 32 | } 33 | if (rid == 555) 34 | { 35 | return new MockWorkstationAliasRDP(); 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/WorkstationMocks/MockWorkstationDomainWIN10.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 MockWorkstationDomainWIN10 : 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 | ("testgroup", 1003) 22 | }; 23 | return result; 24 | } 25 | 26 | public Result OpenAlias(int rid, SAMEnums.AliasOpenFlags desiredAccess = SAMEnums.AliasOpenFlags.ListMembers) 27 | { 28 | if (rid == 1003) 29 | { 30 | return new MockWorkstationAliasTestGroup(); 31 | } 32 | 33 | throw new NotImplementedException(); 34 | } 35 | 36 | public Result OpenAlias(string name) 37 | { 38 | throw new System.NotImplementedException(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /test/unit/LdapConnectionPoolTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Threading.Tasks; 3 | using Microsoft.Extensions.Logging; 4 | using Moq; 5 | using SharpHoundCommonLib; 6 | using Xunit; 7 | 8 | public class LdapConnectionPoolTest 9 | { 10 | private static void AddExclusionDomain(string identifier) { 11 | var excludedDomainsField = typeof(LdapConnectionPool) 12 | .GetField("_excludedDomains", BindingFlags.Static | BindingFlags.NonPublic); 13 | 14 | var excludedDomains = (ConcurrentHashSet)excludedDomainsField.GetValue(null); 15 | 16 | excludedDomains.Add(identifier); 17 | } 18 | 19 | [Fact] 20 | public async Task LdapConnectionPool_ExcludedDomains_ShouldExitEarly() 21 | { 22 | var mockLogger = new Mock(); 23 | var ldapConfig = new LdapConfig(); 24 | var connectionPool = new ConnectionPoolManager(ldapConfig, mockLogger.Object); 25 | 26 | AddExclusionDomain("excludedDomain.com"); 27 | var connectAttempt = await connectionPool.TestDomainConnection("excludedDomain.com", false); 28 | 29 | Assert.False(connectAttempt.Success); 30 | Assert.Contains("excluded for connection attempt", connectAttempt.Message); 31 | } 32 | 33 | [Fact] 34 | public async Task LdapConnectionPool_ExcludedDomains_NonExcludedShouldntExit() 35 | { 36 | var mockLogger = new Mock(); 37 | var ldapConfig = new LdapConfig(); 38 | var connectionPool = new ConnectionPoolManager(ldapConfig, mockLogger.Object); 39 | 40 | AddExclusionDomain("excludedDomain.com"); 41 | var connectAttempt = await connectionPool.TestDomainConnection("perfectlyValidDomain.com", false); 42 | 43 | Assert.DoesNotContain("excluded for connection attempt", connectAttempt.Message); 44 | } 45 | } -------------------------------------------------------------------------------- /test/unit/SmbProcessorTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Threading.Tasks; 5 | using Moq; 6 | using SharpHoundCommonLib; 7 | using SharpHoundCommonLib.Processors; 8 | using SharpHoundCommonLib.SMB; 9 | using SharpHoundRPC; 10 | using Xunit; 11 | using Xunit.Abstractions; 12 | 13 | namespace CommonLibTest { 14 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")] 15 | public class SMBProcessorTest : IDisposable { 16 | 17 | private readonly ITestOutputHelper _testOutputHelper; 18 | 19 | public SMBProcessorTest(ITestOutputHelper testOutputHelper) { 20 | _testOutputHelper = testOutputHelper; 21 | } 22 | 23 | public void Dispose() { 24 | } 25 | 26 | [Fact] 27 | public async Task SmbProcessor_TestTimeout() { 28 | 29 | var mockSmbScanner = new Mock(); 30 | mockSmbScanner 31 | .Setup(x => x.ScanHost(It.IsAny(), It.IsAny())) 32 | .Returns(async () => { 33 | await Task.Delay(100); 34 | return NtStatus.StatusAccessDenied; 35 | }); 36 | 37 | var mockProcessor = new SmbProcessor(2, mockSmbScanner.Object); 38 | var receivedStatus = new List(); 39 | mockProcessor.ComputerStatusEvent += async status => receivedStatus.Add(status); 40 | var results = await mockProcessor.Scan("primary.testlab.local",TimeSpan.FromMilliseconds(1)); 41 | 42 | Assert.Single(receivedStatus); 43 | var status = receivedStatus[0]; 44 | Assert.Equal("Timeout", status.Status); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /test/unit/SmokeTest.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xbehave; 3 | using Xunit; 4 | 5 | namespace CommonLibTest 6 | { 7 | public class SmokeTest 8 | { 9 | [Fact] 10 | public void Show_FluentAssertions_TestWorks() 11 | { 12 | var actual = "ABCDEFGHI"; 13 | actual.Should().StartWith("AB").And.EndWith("HI").And.Contain("EF").And.HaveLength(9); 14 | } 15 | 16 | [Scenario] 17 | public void Show_xBehave_TestWorks() 18 | { 19 | int x = 0, 20 | y = 0, 21 | answer = 0; 22 | 23 | "Given the number 1" 24 | .x(() => x = 1); 25 | 26 | "And the number 2" 27 | .x(() => y = 2); 28 | 29 | "When I add the numbers together" 30 | .x(() => answer = x + y); 31 | 32 | "Then the answer is 3" 33 | .x(() => Assert.Equal(3, answer)); 34 | } 35 | 36 | #region xUnit [Classic] 37 | 38 | [Fact] 39 | public void SanityCheck() 40 | { 41 | Assert.True(true); 42 | } 43 | 44 | [Fact] 45 | public void Throw_FileExistsException_ExceptionIsThrown() 46 | { 47 | Assert.True(true); 48 | } 49 | 50 | #endregion 51 | } 52 | } -------------------------------------------------------------------------------- /test/unit/TestLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Microsoft.Extensions.Logging; 4 | using Xunit.Abstractions; 5 | 6 | namespace CommonLibTest 7 | { 8 | [ExcludeFromCodeCoverage] 9 | public class TestLogger : ILogger 10 | { 11 | private readonly LogLevel _level; 12 | private readonly ITestOutputHelper _output; 13 | 14 | public TestLogger(ITestOutputHelper output, LogLevel level) 15 | { 16 | _output = output; 17 | _level = level; 18 | } 19 | 20 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, 21 | Func formatter) 22 | { 23 | if (IsEnabled(logLevel)) 24 | _output.WriteLine(formatter(state, exception)); 25 | } 26 | 27 | public bool IsEnabled(LogLevel logLevel) 28 | { 29 | return logLevel >= _level; 30 | } 31 | 32 | public IDisposable BeginScope(TState state) 33 | { 34 | return default; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /test/unit/TestPrivateMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | namespace CommonLibTest 6 | { 7 | //Class taken from https://stackoverflow.com/questions/41462468/net-core-library-how-to-test-private-methods-using-xunit 8 | public static class TestPrivateMethod 9 | { 10 | public static T StaticMethod(Type classType, string methodName, object[] callParams) 11 | { 12 | var methodList = classType 13 | .GetMethods(BindingFlags.NonPublic | BindingFlags.Static); 14 | 15 | if (methodList is null || !methodList.Any()) 16 | throw new EntryPointNotFoundException(); 17 | 18 | var method = methodList.First(x => x.Name == methodName && !x.IsPublic && x.GetParameters().Length == callParams.Length); 19 | 20 | var output = (T)method.Invoke(null, callParams); 21 | 22 | return output; 23 | } 24 | 25 | public static T InstanceMethod(object instance, string methodName, object[] callParams) 26 | { 27 | var classType = instance.GetType(); 28 | var methodList = classType 29 | .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance); 30 | 31 | if (methodList is null || !methodList.Any()) 32 | throw new EntryPointNotFoundException(); 33 | 34 | var method = methodList.First(x => x.Name == methodName && !x.IsPublic && x.GetParameters().Length == callParams.Length); 35 | 36 | var output = (T)method.Invoke(instance, callParams); 37 | 38 | return output; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /test/unit/WebClientServiceProcessorTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.IO; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Moq; 9 | using SharpHoundCommonLib; 10 | using SharpHoundCommonLib.OutputTypes; 11 | using SharpHoundCommonLib.Processors; 12 | using SharpHoundRPC; 13 | using Xunit; 14 | using Xunit.Abstractions; 15 | 16 | namespace CommonLibTest { 17 | [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")] 18 | public class WebClientServiceProcessorTest : IDisposable { 19 | 20 | private readonly ITestOutputHelper _testOutputHelper; 21 | 22 | public WebClientServiceProcessorTest(ITestOutputHelper testOutputHelper) { 23 | _testOutputHelper = testOutputHelper; 24 | } 25 | 26 | public void Dispose() { 27 | } 28 | 29 | [Fact] 30 | public async Task WebClientServiceProcessorTest_TestPathExists() 31 | { 32 | var processor = new WebClientServiceProcessor(); 33 | 34 | var result = await processor.IsWebClientRunning("primary.testlab.local"); 35 | 36 | Assert.True(result.Collected); 37 | Assert.False(result.Result); 38 | } 39 | 40 | } 41 | } --------------------------------------------------------------------------------