Created
February 22, 2014 09:55
-
-
Save altrive/9151365 to your computer and use it in GitHub Desktop.
Sample code to set LSA account previlage via P/Invoke(LsaAddAccountRights).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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