DSInternals icon indicating copy to clipboard operation
DSInternals copied to clipboard

Online SIDHistory synchronization

Open Stanvy opened this issue 9 years ago • 3 comments

It would be very helpful to have ability of online SIDHistory synchronization. At least via legitimate "DsAddSidHistory" API.

Stanvy avatar Jul 14 '16 21:07 Stanvy

Below is a simple concept code in PowerShell that makes it:

Add-Type -Language "CSharp" -TypeDefinition @"
using System;
using System.Text;
using System.Runtime.InteropServices;

namespace PInvoke
{
	public class ntdsapi
	{
		[DllImport("ntdsapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern UInt32 DsMakePasswordCredentials(
			[MarshalAs(UnmanagedType.LPWStr)] String User,
			[MarshalAs(UnmanagedType.LPWStr)] String Domain,
			[MarshalAs(UnmanagedType.LPWStr)] String Password,
			out IntPtr pAuthIdentity
		);

		[DllImport("ntdsapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern void DsFreePasswordCredentials(
			IntPtr AuthIdentity
		);

		[DllImport("ntdsapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern UInt32 DsBindWithCred(
			[MarshalAs(UnmanagedType.LPWStr)] String DomainControllerName,
			[MarshalAs(UnmanagedType.LPWStr)] String DnsDomainName,
			IntPtr AuthIdentity,
			out IntPtr phDS
		);

		[DllImport("ntdsapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern UInt32 DsUnBind(
			IntPtr phDS
		);

		[DllImport("ntdsapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
		public static extern UInt32 DsAddSidHistory(
			IntPtr hDS,
			UInt32 Flags,
			[MarshalAs(UnmanagedType.LPWStr)] String SrcDomain,
			[MarshalAs(UnmanagedType.LPWStr)] String SrcPrincipal,
			[MarshalAs(UnmanagedType.LPWStr)] String SrcDomainController,
			IntPtr SrcDomainCreds,
			[MarshalAs(UnmanagedType.LPWStr)] String DstDomain,
			[MarshalAs(UnmanagedType.LPWStr)] String DstPrincipal
		);
	}
}
"@



[System.UInt32] $uiErrorCode = 0
[System.ComponentModel.Win32Exception] $objException = $null


[System.String] $strSourceUserName = "AdministratorUserName"
[System.String] $strSourceUserPassword = "AdministratorPassword"
[System.String] $strSourceUserDomainName = "DOMAIN"
[System.IntPtr] $hSourceAuthenticationIdentity = 0


[System.String] $strTargetUserName = $null
[System.String] $strTargetUserPassword = $null
[System.String] $strTargetUserDomainName = $null
[System.IntPtr] $hTargetAuthenticationIdentity = 0


[System.String] $strSourceDomainControllerFQDN = "PDC.source.com"
[System.String] $strSourceDomainFQDN = "source.com"
[System.IntPtr] $hSourceDirectoryService = 0


[System.String] $strTargetDomainControllerFQDN = $null
[System.String] $strTargetDomainFQDN = "target.com"
[System.IntPtr] $hTargetDirectoryService = 0


[System.String] $strSourcePrincipalUserName = "SAMAccountName"
[System.String] $strTargetPrincipalUserName = "SAMAccountName"


if ($strSourceUserName.Length) {
	$uiErrorCode = [PInvoke.ntdsapi]::DsMakePasswordCredentials(
		$strSourceUserName,
		$strSourceUserDomainName,
		$strSourceUserPassword,
		[ref] $hSourceAuthenticationIdentity
	)
} else {
	$hSourceAuthenticationIdentity = 0
}


if ($strTargetUserName.Length) {
	$uiErrorCode = [PInvoke.ntdsapi]::DsMakePasswordCredentials(
		$strTargetUserName,
		$strTargetUserDomainName,
		$strTargetUserPassword,
		[ref] $hTargetAuthenticationIdentity
	)
} else {
	$hTargetAuthenticationIdentity = 0
}


$uiErrorCode = [PInvoke.ntdsapi]::DsBindWithCred(
	$strTargetDomainControllerFQDN,
	$strTargetDomainFQDN,
	$hTargetAuthenticationIdentity,
	[ref] $hTargetDirectoryService
)


$uiErrorCode = [PInvoke.ntdsapi]::DsAddSidHistory(
	$hTargetDirectoryService,
	0,
	$strSourceDomainFQDN,
	$strSourcePrincipalUserName,
	$strSourceDomainControllerFQDN,
	$hSourceAuthenticationIdentity,
	$strTargetDomainFQDN,
	$strTargetPrincipalUserName
)

$objException = New-Object -TypeName System.ComponentModel.Win32Exception([System.Int32] $uiErrorCode)
$objException.Message


$uiErrorCode = [PInvoke.ntdsapi]::DsUnBind($hSourceDirectoryService)
[PInvoke.ntdsapi]::DsFreePasswordCredentials($hSourceAuthenticationIdentity)

$uiErrorCode = [PInvoke.ntdsapi]::DsUnBind($hTargetDirectoryService)
[PInvoke.ntdsapi]::DsFreePasswordCredentials($hTargetAuthenticationIdentity)

Stanvy avatar Apr 21 '20 19:04 Stanvy

Thanks. DSInternals actually uses direct MS-DRSR RPC calls instead of utilizing ntdsapi.dll. The code would thus need to be implemented in C++ in the DRSConnection class and by calling IDL_DRSAddSidHistory.

MichaelGrafnetter avatar Apr 21 '20 20:04 MichaelGrafnetter

Initial point of this issue was to write values into "sIDHistory" attribute of target objects without taking AD database offline, like "Add-ADDBSidHistory" requires. Replication protocol allows to read everything, including password hashes, but it doesn't allow to perform writes. Am I wrong about it?

Stanvy avatar Apr 21 '20 22:04 Stanvy