Skip to content

Instantly share code, notes, and snippets.

@altrive
Created February 22, 2014 09:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save altrive/9151365 to your computer and use it in GitHub Desktop.
Save altrive/9151365 to your computer and use it in GitHub Desktop.
Sample code to set LSA account previlage via P/Invoke(LsaAddAccountRights).
#Requires -RunAsAdministrator
function Main
{
$ErrorActionPreference = "Stop"
$VerbosePreference = "Continue"
#Target account to assign previlage
$svcAccount = "TestSvc"
#サービスとしてログオン
Write-Verbose ("Set account previlage({0}) to '{1}'" -f "SeServiceLogonRight", $svcAccount)
[LsaWrapper]::SetRight($svcAccount, "SeServiceLogonRight")
#バッチジョブとしてログオン
Write-Verbose ("Set account previlage({0}) to '{1}'" -f "SeBatchLogonRight", $svcAccount)
[LsaWrapper]::SetRight($svcAccount, "SeBatchLogonRight")
#ボリュームの保守タスクを実行
Write-Verbose ("Set account previlage({0}) to '{1}'" -f "SeManageVolumePrivilege", $svcAccount)
[LsaWrapper]::SetRight($svcAccount, "SeManageVolumePrivilege")
#メモリ内のページのロック
Write-Verbose ("Set account previlage({0}) to '{1}'" -f "SeLockMemoryPrivilege", $svcAccount)
[LsaWrapper]::SetRight($svcAccount, "SeLockMemoryPrivilege")
#ローカルログオンを拒否
Write-Verbose ("Set account previlage({0}) to '{1}'" -f "SeDenyInteractiveLogonRight", $svcAccount)
[LsaWrapper]::SetRight($svcAccount, "SeDenyInteractiveLogonRight")
}
Add-Type -TypeDefinition @'
using System;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;
public static class LSAWrapper
{
[DllImport("advapi32.dll", PreserveSig = true)]
private static extern UInt32 LsaOpenPolicy(
ref LSA_UNICODE_STRING SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
Int32 DesiredAccess,
out IntPtr PolicyHandle
);
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
private static extern long LsaAddAccountRights(
IntPtr PolicyHandle,
IntPtr AccountSid,
LSA_UNICODE_STRING[] UserRights,
long CountOfRights);
[DllImport("advapi32.dll")]
private static extern long LsaClose(IntPtr objectHandle);
[DllImport("kernel32.dll")]
private static extern int GetLastError();
[DllImport("advapi32.dll")]
private static extern long LsaNtStatusToWinError(long status);
[StructLayout(LayoutKind.Sequential)]
private struct LSA_OBJECT_ATTRIBUTES
{
public int Length;
public IntPtr RootDirectory;
public readonly LSA_UNICODE_STRING ObjectName;
public UInt32 Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential)]
private struct LSA_UNICODE_STRING
{
public UInt16 Length;
public UInt16 MaximumLength;
public IntPtr Buffer;
}
[Flags]
private enum LSA_AccessPolicy : long
{
POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L,
POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L,
POLICY_GET_PRIVATE_INFORMATION = 0x00000004L,
POLICY_TRUST_ADMIN = 0x00000008L,
POLICY_CREATE_ACCOUNT = 0x00000010L,
POLICY_CREATE_SECRET = 0x00000020L,
POLICY_CREATE_PRIVILEGE = 0x00000040L,
POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L,
POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L,
POLICY_AUDIT_LOG_ADMIN = 0x00000200L,
POLICY_SERVER_ADMIN = 0x00000400L,
POLICY_LOOKUP_NAMES = 0x00000800L,
POLICY_NOTIFICATION = 0x00001000L
}
//POLICY_ALL_ACCESS mask <http://msdn.microsoft.com/en-us/library/windows/desktop/ms721916%28v=vs.85%29.aspx>
private const int POLICY_ALL_ACCESS = (int)(
LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN |
LSA_AccessPolicy.POLICY_CREATE_ACCOUNT |
LSA_AccessPolicy.POLICY_CREATE_PRIVILEGE |
LSA_AccessPolicy.POLICY_CREATE_SECRET |
LSA_AccessPolicy.POLICY_GET_PRIVATE_INFORMATION |
LSA_AccessPolicy.POLICY_LOOKUP_NAMES |
LSA_AccessPolicy.POLICY_NOTIFICATION |
LSA_AccessPolicy.POLICY_SERVER_ADMIN |
LSA_AccessPolicy.POLICY_SET_AUDIT_REQUIREMENTS |
LSA_AccessPolicy.POLICY_SET_DEFAULT_QUOTA_LIMITS |
LSA_AccessPolicy.POLICY_TRUST_ADMIN |
LSA_AccessPolicy.POLICY_VIEW_AUDIT_INFORMATION |
LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION
);
public static void SetRight(string accountName, string privilegeName)
{
//Convert assigned privilege to LSA_UNICODE_STRING[] object
var userRights = GetUserRightsObject(privilegeName);
//Get account SID and pin object for P/Invoke
var sid = GetBinarySID(accountName);
var handle = GCHandle.Alloc(sid, GCHandleType.Pinned);
//Open LSA policy
IntPtr policyHandle = OpenPolicyHandle();
try
{
//add the right to the account
long status = LsaAddAccountRights(policyHandle, handle.AddrOfPinnedObject(), userRights, userRights.Length);
var winErrorCode = LsaNtStatusToWinError(status);
if (winErrorCode != 0)
{
throw new Win32Exception((int)winErrorCode, "LsaAddAccountRights failed");
}
}
finally
{
handle.Free();
Marshal.FreeHGlobal(userRights[0].Buffer); //Can use LsaFreeMemory instead?
LsaClose(policyHandle);
}
}
private static LSA_UNICODE_STRING[] GetUserRightsObject(string privilegeName)
{
//initialize userRights objects
return new[]
{
new LSA_UNICODE_STRING
{
Buffer = Marshal.StringToHGlobalUni(privilegeName),
Length = (UInt16)(privilegeName.Length * UnicodeEncoding.CharSize),
MaximumLength = (UInt16)((privilegeName.Length + 1) * UnicodeEncoding.CharSize)
}
};
}
private static byte[] GetBinarySID(string accountName)
{
//Get account SID
NTAccount account;
try
{
account = new NTAccount(accountName);
}
catch(IdentityNotMappedException)
{
throw; //TODO:ErrorHandling
}
//Convert SID to byte[]
var identity = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
var buffer = new byte[identity.BinaryLength];
identity.GetBinaryForm(buffer, 0);
return buffer;
}
private static IntPtr OpenPolicyHandle()
{
//dummy variables
var systemName = new LSA_UNICODE_STRING();
var objectAttributes = new LSA_OBJECT_ATTRIBUTES
{
Length = 0,
RootDirectory = IntPtr.Zero,
Attributes = 0,
SecurityDescriptor = IntPtr.Zero,
SecurityQualityOfService = IntPtr.Zero
};
IntPtr policyHandle;
uint status = LsaOpenPolicy(ref systemName, ref objectAttributes, POLICY_ALL_ACCESS, out policyHandle);
var winErrorCode = LsaNtStatusToWinError(status);
if (winErrorCode != 0)
{
throw new Win32Exception((int)winErrorCode, "LsaOpenPolicy failed");
}
return policyHandle;
}
}
'@
Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment