Description
In this article, I am going to explain about how to set or grant Logon as batch job
rights/permission/privilege using Local Security Policy, Powershell, C# and Command Line tool.
Summary
- Set Logon as batch job rights to user using Local Security Policy
- Grant User Logon as a batch job privilege via Powershell
- Set User Logon as a batch job permission using C#
- Set User Logon as batch job right via Command Line
Set Logon as batch job rights to user using Local Security Policy GUI
Follow the below steps to set Logon as batch job rights via Local Security Policy
1. Open the Run window by pressing ‘Windows’ + ‘R’ keys.
2. Type the command secpol.msc in the text box and click OK.
3. Now the Local Security Policy window will be open, in that window navigate to the node User Rights Assignment (Security Settings -> Local Polices ->User Rights Assignment). In right side pane, search and select the policy Log on as batch job.
4. Double-click on the policy Log on as batch job, in the opened window click the button Add User or Group, select the user account you want to set logon as a batch job rights and click OK, and click Apply button to finish.
Set or Grant User Logon as batch job rights via Powershell
We can set the Logon as a batch job right to user in Powershell by importing the third party DLL ( Carbon ). Before you run the below script you need to the download latest Carbon files from here Download Carbon DLL.
Steps to follow to set Logon as batch job rights via Powershell :
1. Download latest Carbon files from here Download Carbon DLL.
2. If you have downloaded the files, extract the zip file and you could see the Carbon DLL inside bin folder (In my case: C:UsersAdministratorDownloadsCarbonbinCarbon.dll).
3. Copy the below Powershell script commands and place it notepad or textfile.
4. Now you can replace your Carbon DLL path in following script for the variable $CarbonDllPath
5. You can also replace the user identity that you are going to set log on as batch job rights in the variable $Identity
6. Now run as Powershell window with Admin Privilege (Run as Administrator)
7. Copy the edited Powershell script and Run it in Powershell to set log on as batch job rights.
$Identity = "DomainNameSvc_User_account" $privilege = "SeBatchLogonRight" $CarbonDllPath = "C:\UsersAdministratorDownloadsCarbonbinCarbon.dll" [Reflection.Assembly]::LoadFile($CarbonDllPath) [Carbon.Lsa]::GrantPrivileges( $Identity , $privilege )
Powershell output:
Other web site links for Carbon DLL:
https://bitbucket.org/splatteredbits/carbon/downloads
http://pshdo.com/
http://get-carbon.org/help/Grant-Privilege.html
Set or Grant User Logon as a batch job right/permission to user using C#
You can use the function GrantUserLogonAsBatchJob to set logon as a batch job right to user using C# code. This function uses the class LsaWrapper.
static void GrantUserLogonAsBatchJob(string userName) { try { LsaWrapper lsaUtility = new LsaWrapper(); lsaUtility.SetRight(userName, "SeBatchLogonRight"); Console.WriteLine("Logon as batch job right is granted successfully to " + userName); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
LsaWrapper class file
public class LsaWrapper { // Import the LSA functions [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")] public static extern void FreeSid(IntPtr pSid); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)] private static extern bool LookupAccountName( string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName, ref int cbdomainLength, ref int use); [DllImport("advapi32.dll")] private static extern bool IsValidSid(IntPtr pSid); [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); // define the structures 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 } [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; } /// //Adds a privilege to an account /// Name of an account - "domainaccount" or only "account" /// Name ofthe privilege /// The windows error code returned by LsaAddAccountRights public long SetRight(String accountName, String privilegeName) { long winErrorCode = 0; //contains the last error //pointer an size for the SID IntPtr sid = IntPtr.Zero; int sidSize = 0; //StringBuilder and size for the domain name var domainName = new StringBuilder(); int nameSize = 0; //account-type variable for lookup int accountType = 0; //get required buffer size LookupAccountName(String.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType); //allocate buffers domainName = new StringBuilder(nameSize); sid = Marshal.AllocHGlobal(sidSize); //lookup the SID for the account bool result = LookupAccountName(String.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, ref accountType); //say what you're doing Console.WriteLine("LookupAccountName result = " + result); Console.WriteLine("IsValidSid: " + IsValidSid(sid)); Console.WriteLine("LookupAccountName domainName: " + domainName); if (!result) { winErrorCode = GetLastError(); Console.WriteLine("LookupAccountName failed: " + winErrorCode); } else { //initialize an empty unicode-string var systemName = new LSA_UNICODE_STRING(); //combine all policies var 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 ); //initialize a pointer for the policy handle IntPtr policyHandle = IntPtr.Zero; //these attributes are not used, but LsaOpenPolicy wants them to exists var ObjectAttributes = new LSA_OBJECT_ATTRIBUTES(); ObjectAttributes.Length = 0; ObjectAttributes.RootDirectory = IntPtr.Zero; ObjectAttributes.Attributes = 0; ObjectAttributes.SecurityDescriptor = IntPtr.Zero; ObjectAttributes.SecurityQualityOfService = IntPtr.Zero; //get a policy handle uint resultPolicy = LsaOpenPolicy(ref systemName, ref ObjectAttributes, access, out policyHandle); winErrorCode = LsaNtStatusToWinError(resultPolicy); if (winErrorCode != 0) { Console.WriteLine("OpenPolicy failed: " + winErrorCode); } else { //Now that we have the SID an the policy, //we can add rights to the account. //initialize an unicode-string for the privilege name var userRights = new LSA_UNICODE_STRING[1]; userRights[0] = new LSA_UNICODE_STRING(); userRights[0].Buffer = Marshal.StringToHGlobalUni(privilegeName); userRights[0].Length = (UInt16) (privilegeName.Length*UnicodeEncoding.CharSize); userRights[0].MaximumLength = (UInt16) ((privilegeName.Length + 1)*UnicodeEncoding.CharSize); //add the right to the account long res = LsaAddAccountRights(policyHandle, sid, userRights, 1); winErrorCode = LsaNtStatusToWinError(res); if (winErrorCode != 0) { Console.WriteLine("LsaAddAccountRights failed: " + winErrorCode); } LsaClose(policyHandle); } FreeSid(sid); } return winErrorCode; } }
Grant Logon as a batch job right to user via Command Line
You can use the NTRights.exe utility to grant or deny user rights to users and groups from a command line or a batch file. The NTRights.exe utility is included in the Windows NT Server 4.0 Resource Kit Supplement 3.
Refer: http://support.microsoft.com/kb/266280
Set Logon As Batch Job right
ntrights +r SeBatchLogonRight -u "DomainSvc_Test_user"
Revoke Logon As Batch Job right
ntrights -r SeBatchLogonRight -u "DomainSvc_Test_user"
Thanks,
Morgan
Software Developer
———————
This is great for the local computer, but not for batch processing. Is there any technique to add user rights for a batch of computers?
This is great for the local computer, but not for batch processing. Is there any technique to add user rights for a batch of computers?
Thank you very much
Managed Debugging Assistant ‘PInvokeStackImbalance’ has detected a problem in ‘C:\Users\DR\source\repos\EdgeboxThreatModel\bin\Debug\EdgeboxThreatModel.exe’.
Additional Information: A call to PInvoke function ‘EdgeboxThreatModel!EdgeboxThreatModel.LsaWrapper::LsaNtStatusToWinError’ has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
occurring at winErrorCode = LsaNtStatusToWinError(resultPolicy);
I get the same can anybody help?
For those who come after.. this works as a powershell Script – I wanted a local account on the machine that I had created called DNS to be given the right, so you can change the user to one of your choice :
$UserOrGroup = “DNS”
try {
# Check if the user account exists.
$null = ([System.Security.Principal.NTAccount]::new($UserOrGroup)).Translate([System.Security.Principal.SecurityIdentifier]).Value
}
catch {
# Exit the script if the user account does not exist.
“The account [$UserOrGroup] does not exist.” | Out-Default
return $null
}
$tempConfigFile = “$env:TEMP\tempCfg.ini”
$tempDatabaseFile = “$env:TEMP\tempSdb.sdb”
$null = $(secedit /export /cfg $tempConfigFile)
$null = $(secedit /import /cfg $tempDatabaseFile /db $tempDatabaseFile)
$configIni = Get-Content $tempConfigFile
$originalString = ($configIni | Select-String “SeBatchLogonRight”).ToString()
$replacementString = $originalString + ‘,’ + $UserOrGroup
$configIni = $configIni.Replace($originalString, $replacementString)
$configIni | Out-File $tempConfigFile
secedit /configure /db $tempDatabaseFile /cfg $tempConfigFile /areas USER_RIGHTS
# Clean up
$tempConfigFile, $tempDatabaseFile | ForEach-Object {
if (Test-Path $_) {
Remove-Item -Path $_ -Force -Confirm:$false
}
}
The majority of this code is courtesy of this guy – thanks
https://github.com/junecastillote/PS-Manage-Log-On-As-A-Service/blob/main/Add-ServiceLogonRight.ps1