منذ عدة سنوات وأنا أعمل في الجامعة لدعم 10 محطات عمل تعمل بنظام التشغيل Microsoft Windows 8.1. يتكون الدعم بشكل أساسي من تثبيت البرامج اللازمة للعملية التعليمية وضمان الأداء العام.
كل محطة بها مستخدمان: المسؤول والطالب. يمتلك المسؤول التحكم الكامل ، ولا يمتلك الطالب القدرة على تثبيت البرنامج. حتى لا تتعب نفسك عناء تنظيف مستخدم الطالب ، يتم ببساطة حذف هذا الحساب بالكامل وإنشاءه من جديد. هذا يستلزم بعض حركات الجسم التي يجب القيام بها في كل محطة.
قررت هذا العام أتمتة معظم حركات الجسم باستخدام PowerShell بدون ActiveDirectory وجمعت في هذا المنشور بعض الوصفات التي وجدتها على الشبكة.
تدريب
لقد صادفت على الفور حقيقة أن PS 4 تم تثبيته في المحطات وأن بعض الأمثلة من الإنترنت الذي يعرف كل شيء لم تنجح. لذلك ، قبل تشغيل البرامج النصية الناتجة ، عليك القيام ببعض الإجراءات:
- قم بتثبيت Windows Management Framework 5.1
- قم بتثبيت أحدث إصدار من PowerShell
الإجراءات الآلية
- حذف / إنشاء حساب مستخدم
- تسجيل الدخول التلقائي لمستخدم معين
- تشغيل البرنامج النصي عند تسجيل دخول المستخدم لأول مرة
حذف / إنشاء حساب مستخدم
بدأ بالخلق. في هذه الحالة ، تحتاج إلى تنفيذ إجراءين: إنشاء مستخدم ( New-LocalUser ) وإضافته إلى المجموعة ( Add-LocalGroupMember) . للراحة ، جمعت هذه الأوامر في وظيفة:
Function New-User {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#New-User "Student" "Student"
.PARAMETER Name
( )
.PARAMETER Password
( )
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Name,
[PARAMETER(Mandatory=$True)][String]$Password
)
$Pwd = convertto-securestring $Password -asplaintext -force
$GroupSID = "S-1-5-32-545"
New-LocalUser -User $Name -AccountNeverExpires:$true -FullName $Name -Password $Pwd -PasswordNeverExpires:$true
Add-LocalGroupMember -SID $GroupSID -Member $Name
Write-Host "-- $Name $Password" -foregroundcolor Green
}
أضفت إلى المجموعة بواسطة SID ، لأنه في إحدى المقالات التي التقيت بها أن SID الخاص بمجموعة المستخدمين هو نفسه في كل مكان - S-1-5-32-545.
لقد قمت بتنظيم الحذف وفقًا للمبدأ التالي: حذف جميع الحسابات التي تم إنشاؤها بواسطة المسؤول. للقيام بذلك ، باستخدام كائن WMI لفئة Win32_UserProfile ، أقوم بتعريف كافة المستخدمين غير النشطين حاليًا وغير المميزين.
Function Remove-Users {
<#
.SYNOPSIS
.DESCRIPTION
,
.EXAMPLE
#Remove-Users
#>
[CmdletBinding()]
$UsersProfiles = Get-WMIObject -class Win32_UserProfile -ComputerName $env:COMPUTERNAME | Where {!($_.Loaded) -and !($_.Special)}
foreach($Usr in $UsersProfiles) {
$UsrName = $Usr.LocalPath.Split("\")[2]
Write-Host "-- $UsrName ..." -foregroundcolor Green
Remove-LocalUser -Name $UsrName
Remove-WmiObject -Path $Usr.__PATH
Write-Host "-- $UsrName " -foregroundcolor Green
}
}
تسجيل الدخول التلقائي (تسجيل الدخول التلقائي) للمستخدم المحدد
كان كل شيء هنا مقصورًا على تغيير سجل HKEY_LOCAL_MACHINE. يتم أيضًا دمج هذه الإجراءات في وظيفة صغيرة:
Function Set-AutoLogon {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-AutoLogon "Student" "Student"
.PARAMETER Name
( )
.PARAMETER Password
( )
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Name,
[PARAMETER(Mandatory=$True)][String]$Password
)
$PathToWinlogon = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
New-ItemProperty -Path $PathToWinlogon -Name AutoAdminLogon -Value 1 -PropertyType "String"
New-ItemProperty -Path $PathToWinlogon -Name DefaultUserName -Value $Name -PropertyType "String"
New-ItemProperty -Path $PathToWinlogon -Name DefaultPassword -Value $Password -PropertyType "String"
}
تشغيل البرنامج النصي عند تسجيل دخول المستخدم لأول مرة
اتضح أنه لا يمكن تكوين كل شيء قبل تسجيل الدخول الأول لمستخدم جديد (والذي كان مفاجئًا إلى حد ما بالنسبة لي). لذلك ، كانت هناك حاجة لتشغيل برنامج نصي يقوم ببعض الإجراءات بعد تسجيل الدخول الأول:
- إعدادات الوكيل
- منع إنشاء الملفات على سطح المكتب
- تخصيص لوحة تحكم المستخدم
لقد جربت عدة طرق ، ولكن تبين لي أن الطريقة التالية تناسبني: تثبيت المهمة. لكن لم أتمكن من الحصول على المهمة عن طريق PS. لذلك اتخذت طريقًا طويلاً:
schtasks /create /tn LogonUserSettings /tr "pwsh C:\Scripts\Settings.ps1" /sc onlogon /ru $env:USERDOMAIN\$UserName /rp $Password /f
لكن هذا لم يكن كافيًا - طلب Windows السماح بتسجيل الدخول كوظيفة مجمعة (SeBatchLogonRight). أدى البحث عن إجابة لسؤال كيفية القيام بذلك إلى النتيجة التالية :
LsaWrapper
$Source = @'
using System;
using System.Collections.Generic;
using System.Text;
namespace MyLsaWrapper
{
using System.Runtime.InteropServices;
using System.Security;
using System.Management;
using System.Runtime.CompilerServices;
using System.ComponentModel;
using LSA_HANDLE = IntPtr;
[StructLayout(LayoutKind.Sequential)]
struct LSA_OBJECT_ATTRIBUTES
{
internal int Length;
internal IntPtr RootDirectory;
internal IntPtr ObjectName;
internal int Attributes;
internal IntPtr SecurityDescriptor;
internal IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct LSA_UNICODE_STRING
{
internal ushort Length;
internal ushort MaximumLength;
[MarshalAs(UnmanagedType.LPWStr)]
internal string Buffer;
}
sealed class Win32Sec
{
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaOpenPolicy(
LSA_UNICODE_STRING[] SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
int AccessMask,
out IntPtr PolicyHandle
);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaAddAccountRights(
LSA_HANDLE PolicyHandle,
IntPtr pSID,
LSA_UNICODE_STRING[] UserRights,
int CountOfRights
);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern int LsaLookupNames2(
LSA_HANDLE PolicyHandle,
uint Flags,
uint Count,
LSA_UNICODE_STRING[] Names,
ref IntPtr ReferencedDomains,
ref IntPtr Sids
);
[DllImport("advapi32")]
internal static extern int LsaNtStatusToWinError(int NTSTATUS);
[DllImport("advapi32")]
internal static extern int LsaClose(IntPtr PolicyHandle);
[DllImport("advapi32")]
internal static extern int LsaFreeMemory(IntPtr Buffer);
}
/// <summary>
/// This class is used to grant "Log on as a service", "Log on as a batchjob", "Log on localy" etc.
/// to a user.
/// </summary>
public sealed class LsaWrapper : IDisposable
{
[StructLayout(LayoutKind.Sequential)]
struct LSA_TRUST_INFORMATION
{
internal LSA_UNICODE_STRING Name;
internal IntPtr Sid;
}
[StructLayout(LayoutKind.Sequential)]
struct LSA_TRANSLATED_SID2
{
internal SidNameUse Use;
internal IntPtr Sid;
internal int DomainIndex;
uint Flags;
}
[StructLayout(LayoutKind.Sequential)]
struct LSA_REFERENCED_DOMAIN_LIST
{
internal uint Entries;
internal LSA_TRUST_INFORMATION Domains;
}
enum SidNameUse : int
{
User = 1,
Group = 2,
Domain = 3,
Alias = 4,
KnownGroup = 5,
DeletedAccount = 6,
Invalid = 7,
Unknown = 8,
Computer = 9
}
enum Access : int
{
POLICY_READ = 0x20006,
POLICY_ALL_ACCESS = 0x00F0FFF,
POLICY_EXECUTE = 0X20801,
POLICY_WRITE = 0X207F8
}
const uint STATUS_ACCESS_DENIED = 0xc0000022;
const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a;
const uint STATUS_NO_MEMORY = 0xc0000017;
IntPtr lsaHandle;
public LsaWrapper()
: this(null)
{ }
// // local system if systemName is null
public LsaWrapper(string systemName)
{
LSA_OBJECT_ATTRIBUTES lsaAttr;
lsaAttr.RootDirectory = IntPtr.Zero;
lsaAttr.ObjectName = IntPtr.Zero;
lsaAttr.Attributes = 0;
lsaAttr.SecurityDescriptor = IntPtr.Zero;
lsaAttr.SecurityQualityOfService = IntPtr.Zero;
lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
lsaHandle = IntPtr.Zero;
LSA_UNICODE_STRING[] system = null;
if (systemName != null)
{
system = new LSA_UNICODE_STRING[1];
system[0] = InitLsaString(systemName);
}
uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr,
(int)Access.POLICY_ALL_ACCESS, out lsaHandle);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
public void AddPrivileges(string account, string privilege)
{
IntPtr pSid = GetSIDInformation(account);
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
privileges[0] = InitLsaString(privilege);
uint ret = Win32Sec.LsaAddAccountRights(lsaHandle, pSid, privileges, 1);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
public void Dispose()
{
if (lsaHandle != IntPtr.Zero)
{
Win32Sec.LsaClose(lsaHandle);
lsaHandle = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
~LsaWrapper()
{
Dispose();
}
// helper functions
IntPtr GetSIDInformation(string account)
{
LSA_UNICODE_STRING[] names = new LSA_UNICODE_STRING[1];
LSA_TRANSLATED_SID2 lts;
IntPtr tsids = IntPtr.Zero;
IntPtr tdom = IntPtr.Zero;
names[0] = InitLsaString(account);
lts.Sid = IntPtr.Zero;
//Console.WriteLine("String account: {0}", names[0].Length);
int ret = Win32Sec.LsaLookupNames2(lsaHandle, 0, 1, names, ref tdom, ref tsids);
if (ret != 0)
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError(ret));
lts = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(tsids,
typeof(LSA_TRANSLATED_SID2));
Win32Sec.LsaFreeMemory(tsids);
Win32Sec.LsaFreeMemory(tdom);
return lts.Sid;
}
static LSA_UNICODE_STRING InitLsaString(string s)
{
// Unicode strings max. 32KB
if (s.Length > 0x7ffe)
throw new ArgumentException("String too long");
LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
lus.Buffer = s;
lus.Length = (ushort)(s.Length * sizeof(char));
lus.MaximumLength = (ushort)(lus.Length + sizeof(char));
return lus;
}
}
public class LsaWrapperCaller
{
public static void AddPrivileges(string account, string privilege)
{
using (LsaWrapper lsaWrapper = new LsaWrapper())
{
lsaWrapper.AddPrivileges(account, privilege);
}
}
}
}
'@
Add-Type -TypeDefinition $Source
[MyLsaWrapper.LsaWrapperCaller]::AddPrivileges($Identity, "SeBatchLogonRight")
سمح لنا السماح بتسجيل الدخول كوظيفة مجمعة بالانتقال إلى كتابة برنامج نصي يتم تشغيله من تحت المستخدم.
إعدادات الوكيل
مع إعداد الوكيل ، اتضح أن كل شيء بسيط. تم العثور على حل عملي بسرعة:
Function Set-Proxy {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-Proxy a.cproxy.ru 8080
.PARAMETER Server
( )
.PARAMETER Port
( )
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Server,
[PARAMETER(Mandatory=$True)][Int]$Port
)
If ((Test-NetConnection -ComputerName $Server -Port $Port).TcpTestSucceeded) {
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyServer -Value "$($Server):$($Port)"
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyEnable -Value 1
} Else {
Write-Error -Message "-- Invalid proxy server address or port: $($Server):$($Port)"
}
}
منع إنشاء الملفات على سطح المكتب
استغرق حظر إنشاء ملفات على سطح المكتب وقتًا أطول للعبث به مقارنة بالشبكة. لم يكن تعيين حقوق المجلد موجودًا كما هو الحال في أنظمة * nix. ولكن حتى هنا كانت هناك إجابات نجحت في تكييفها لنفسي:
Function Set-AccessRule {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-AccessRule -Folder $env:USERPROFILE\Desktop\ -UserName $env:USERNAME -Rules CreateFiles,AppendData -AccessControlType Deny
.PARAMETER Folder
, ( )
.PARAMETER UserName
, ( )
.PARAMETER Rules
( )
.PARAMETER AccessControlType
, : Allow Deny
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][Path]$Folder,
[PARAMETER(Mandatory=$True)][String]$UserName,
[PARAMETER(Mandatory=$True)][String]$Rules,
[PARAMETER(Mandatory=$True)][String]$AccessControlType
)
# ACL
$acl = Get-Acl $Folder
#
$fileSystemRights = [System.Security.AccessControl.FileSystemRights]"$Rules"
#C ,
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($UserName, $fileSystemRights, $AccessControlType)
# FileSystemAccessRule
$acl.SetAccessRule($AccessRule)
#
$acl | Set-Acl $Folder
}
Set-AccessRule -Folder $env:USERPROFILE\Desktop\ -UserName $env:USERNAME -Rules CreateFiles,AppendData,Delete -AccessControlType Deny
وصف FileSystemRights على الموقع الرسمي .
تخصيص لوحة تحكم المستخدم
كان هذا اختياريًا ، لكنني اعتقدت أنه سيكون من الرائع تزويد الطلاب بلوحة معلومات مخصصة مع البرامج شائعة الاستخدام. تم العثور على الجواب هنا .
تطبيق مثبت
function Set-PinnedApplication
{
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFiles\Internet Explorer\iexplore.exe"
.EXAMPLE
#Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}\Mozilla Firefox\firefox.exe"
.PARAMETER Action
, : UnpinfromTaskbar PintoTaskbar
.PARAMETER FilePath
, ( )
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)][String]$Action,
[Parameter(Mandatory=$True)][String]$FilePath
)
if(-not (test-path $FilePath)) {
throw "FilePath does not exist."
}
function InvokeVerb {
param([string]$FilePath,$verb)
$verb = $verb.Replace("&","")
$path = split-path $FilePath
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace($path)
$item = $folder.Parsename((split-path $FilePath -leaf))
$itemVerb = $item.Verbs() | ? {$_.Name.Replace("&","") -eq $verb}
if($itemVerb -eq $null){
throw "Verb $verb not found."
} else {
$itemVerb.DoIt()
}
}
function GetVerb {
param([int]$verbId)
try {
$t = [type]"CosmosKey.Util.MuiHelper"
} catch {
$def = [Text.StringBuilder]""
[void]$def.AppendLine('[DllImport("user32.dll")]')
[void]$def.AppendLine('public static extern int LoadString(IntPtr h,uint id, System.Text.StringBuilder sb,int maxBuffer);')
[void]$def.AppendLine('[DllImport("kernel32.dll")]')
[void]$def.AppendLine('public static extern IntPtr LoadLibrary(string s);')
Add-Type -MemberDefinition $def.ToString() -name MuiHelper -namespace CosmosKey.Util
}
if($global:CosmosKey_Utils_MuiHelper_Shell32 -eq $null){
$global:CosmosKey_Utils_MuiHelper_Shell32 = [CosmosKey.Util.MuiHelper]::LoadLibrary("shell32.dll")
}
$maxVerbLength=255
$verbBuilder = New-Object Text.StringBuilder "",$maxVerbLength
[void][CosmosKey.Util.MuiHelper]::LoadString($CosmosKey_Utils_MuiHelper_Shell32,$verbId,$verbBuilder,$maxVerbLength)
return $verbBuilder.ToString()
}
$verbs = @{
"PintoTaskbar"=5386
"UnpinfromTaskbar"=5387
}
if($verbs.$Action -eq $null){
Throw "Action $action not supported`nSupported actions are:`n`tPintoTaskbar`n`tUnpinfromTaskbar"
}
InvokeVerb -FilePath $FilePath -Verb $(GetVerb -VerbId $verbs.$action)
}
خاتمة
تعمل البرامج النصية ، وقد تم تقليل وقت الخدمة لكل محطة ، وتم تحقيق الهدف. بالنسبة لي ، كمستخدم لنظام التشغيل Linux ، تبين أن إعداد Windows ليس أسهل مغامرة ، ولكنه تعليمي. سوف أقوم بتطوير نص الإعداد. هناك خطط لإضافة فحص للبرامج المثبتة والتثبيت ، وإطلاق برنامج مكافحة الفيروسات.
النصوص النهائية في العمل
Function New-User {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#New-User "Student" "Student"
.PARAMETER Name
( )
.PARAMETER Password
( )
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Name,
[PARAMETER(Mandatory=$True)][String]$Password
)
$Pwd = convertto-securestring $Password -asplaintext -force
$GroupSID = "S-1-5-32-545"
New-LocalUser -User $Name -AccountNeverExpires:$true -FullName $Name -Password $Pwd -PasswordNeverExpires:$true
Add-LocalGroupMember -SID $GroupSID -Member $Name
Write-Host "-- $Name $Password" -foregroundcolor Green
}
Function Remove-Users {
<#
.SYNOPSIS
.DESCRIPTION
,
.EXAMPLE
#Remove-Users
#>
[CmdletBinding()]
$UsersProfiles = Get-WMIObject -class Win32_UserProfile -ComputerName $env:COMPUTERNAME | Where {!($_.Loaded) -and !($_.Special)}
foreach($Usr in $UsersProfiles) {
$UsrName = $Usr.LocalPath.Split("\")[2]
Write-Host "-- $UsrName ..." -foregroundcolor Green
Remove-LocalUser -Name $UsrName
Remove-WmiObject -Path $Usr.__PATH
Write-Host "-- $UsrName " -foregroundcolor Green
}
}
Function Set-AutoLogon {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-AutoLogon "Student" "Student"
.PARAMETER Name
( )
.PARAMETER Password
( )
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Name,
[PARAMETER(Mandatory=$True)][String]$Password
)
$PathToWinlogon = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
New-ItemProperty -Path $PathToWinlogon -Name AutoAdminLogon -Value 1 -PropertyType "String"
New-ItemProperty -Path $PathToWinlogon -Name DefaultUserName -Value $Name -PropertyType "String"
New-ItemProperty -Path $PathToWinlogon -Name DefaultPassword -Value $Password -PropertyType "String"
}
$Source = @'
using System;
using System.Collections.Generic;
using System.Text;
namespace MyLsaWrapper
{
using System.Runtime.InteropServices;
using System.Security;
using System.Management;
using System.Runtime.CompilerServices;
using System.ComponentModel;
using LSA_HANDLE = IntPtr;
[StructLayout(LayoutKind.Sequential)]
struct LSA_OBJECT_ATTRIBUTES
{
internal int Length;
internal IntPtr RootDirectory;
internal IntPtr ObjectName;
internal int Attributes;
internal IntPtr SecurityDescriptor;
internal IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct LSA_UNICODE_STRING
{
internal ushort Length;
internal ushort MaximumLength;
[MarshalAs(UnmanagedType.LPWStr)]
internal string Buffer;
}
sealed class Win32Sec
{
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaOpenPolicy(
LSA_UNICODE_STRING[] SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
int AccessMask,
out IntPtr PolicyHandle
);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaAddAccountRights(
LSA_HANDLE PolicyHandle,
IntPtr pSID,
LSA_UNICODE_STRING[] UserRights,
int CountOfRights
);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true),
SuppressUnmanagedCodeSecurityAttribute]
internal static extern int LsaLookupNames2(
LSA_HANDLE PolicyHandle,
uint Flags,
uint Count,
LSA_UNICODE_STRING[] Names,
ref IntPtr ReferencedDomains,
ref IntPtr Sids
);
[DllImport("advapi32")]
internal static extern int LsaNtStatusToWinError(int NTSTATUS);
[DllImport("advapi32")]
internal static extern int LsaClose(IntPtr PolicyHandle);
[DllImport("advapi32")]
internal static extern int LsaFreeMemory(IntPtr Buffer);
}
/// <summary>
/// This class is used to grant "Log on as a service", "Log on as a batchjob", "Log on localy" etc.
/// to a user.
/// </summary>
public sealed class LsaWrapper : IDisposable
{
[StructLayout(LayoutKind.Sequential)]
struct LSA_TRUST_INFORMATION
{
internal LSA_UNICODE_STRING Name;
internal IntPtr Sid;
}
[StructLayout(LayoutKind.Sequential)]
struct LSA_TRANSLATED_SID2
{
internal SidNameUse Use;
internal IntPtr Sid;
internal int DomainIndex;
uint Flags;
}
[StructLayout(LayoutKind.Sequential)]
struct LSA_REFERENCED_DOMAIN_LIST
{
internal uint Entries;
internal LSA_TRUST_INFORMATION Domains;
}
enum SidNameUse : int
{
User = 1,
Group = 2,
Domain = 3,
Alias = 4,
KnownGroup = 5,
DeletedAccount = 6,
Invalid = 7,
Unknown = 8,
Computer = 9
}
enum Access : int
{
POLICY_READ = 0x20006,
POLICY_ALL_ACCESS = 0x00F0FFF,
POLICY_EXECUTE = 0X20801,
POLICY_WRITE = 0X207F8
}
const uint STATUS_ACCESS_DENIED = 0xc0000022;
const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a;
const uint STATUS_NO_MEMORY = 0xc0000017;
IntPtr lsaHandle;
public LsaWrapper()
: this(null)
{ }
// // local system if systemName is null
public LsaWrapper(string systemName)
{
LSA_OBJECT_ATTRIBUTES lsaAttr;
lsaAttr.RootDirectory = IntPtr.Zero;
lsaAttr.ObjectName = IntPtr.Zero;
lsaAttr.Attributes = 0;
lsaAttr.SecurityDescriptor = IntPtr.Zero;
lsaAttr.SecurityQualityOfService = IntPtr.Zero;
lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
lsaHandle = IntPtr.Zero;
LSA_UNICODE_STRING[] system = null;
if (systemName != null)
{
system = new LSA_UNICODE_STRING[1];
system[0] = InitLsaString(systemName);
}
uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr,
(int)Access.POLICY_ALL_ACCESS, out lsaHandle);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
public void AddPrivileges(string account, string privilege)
{
IntPtr pSid = GetSIDInformation(account);
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
privileges[0] = InitLsaString(privilege);
uint ret = Win32Sec.LsaAddAccountRights(lsaHandle, pSid, privileges, 1);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
public void Dispose()
{
if (lsaHandle != IntPtr.Zero)
{
Win32Sec.LsaClose(lsaHandle);
lsaHandle = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
~LsaWrapper()
{
Dispose();
}
// helper functions
IntPtr GetSIDInformation(string account)
{
LSA_UNICODE_STRING[] names = new LSA_UNICODE_STRING[1];
LSA_TRANSLATED_SID2 lts;
IntPtr tsids = IntPtr.Zero;
IntPtr tdom = IntPtr.Zero;
names[0] = InitLsaString(account);
lts.Sid = IntPtr.Zero;
//Console.WriteLine("String account: {0}", names[0].Length);
int ret = Win32Sec.LsaLookupNames2(lsaHandle, 0, 1, names, ref tdom, ref tsids);
if (ret != 0)
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError(ret));
lts = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(tsids,
typeof(LSA_TRANSLATED_SID2));
Win32Sec.LsaFreeMemory(tsids);
Win32Sec.LsaFreeMemory(tdom);
return lts.Sid;
}
static LSA_UNICODE_STRING InitLsaString(string s)
{
// Unicode strings max. 32KB
if (s.Length > 0x7ffe)
throw new ArgumentException("String too long");
LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
lus.Buffer = s;
lus.Length = (ushort)(s.Length * sizeof(char));
lus.MaximumLength = (ushort)(lus.Length + sizeof(char));
return lus;
}
}
public class LsaWrapperCaller
{
public static void AddPrivileges(string account, string privilege)
{
using (LsaWrapper lsaWrapper = new LsaWrapper())
{
lsaWrapper.AddPrivileges(account, privilege);
}
}
}
}
'@
Add-Type -TypeDefinition $Source | Out-Null
# -------------------------
#
# -------------------------
$UserName = "Student"
$Password = "Student"
Remove-Users | Out-Null
New-User $UserName $Password | Out-Null
Set-AutoLogon $UserName $Password | Out-Null
[MyLsaWrapper.LsaWrapperCaller]::AddPrivileges($UserName, "SeBatchLogonRight") | Out-Null
write-host "-- $UserName" -foregroundcolor Green
schtasks /create /tn LogonUserSettings /tr "pwsh C:\Scripts\SetupUser.ps1" /sc onlogon /ru $env:USERDOMAIN\$UserName /rp $Password /f
- Student
Function Set-Proxy {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-Proxy a.cproxy.ru 8080
.PARAMETER Server
( )
.PARAMETER Port
( )
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Server,
[PARAMETER(Mandatory=$True)][Int]$Port
)
If ((Test-NetConnection -ComputerName $Server -Port $Port).TcpTestSucceeded) {
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyServer -Value "$($Server):$($Port)"
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyEnable -Value 1
} Else {
Write-Error -Message "-- Invalid proxy server address or port: $($Server):$($Port)"
}
}
Function Set-AccessRule {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-AccessRule -Folder $env:USERPROFILE\Desktop\ -UserName $env:USERNAME -Rules CreateFiles,AppendData -AccessControlType Deny
.PARAMETER Folder
, ( )
.PARAMETER UserName
, ( )
.PARAMETER Rules
( )
.PARAMETER AccessControlType
, : Allow Deny
#>
[CmdletBinding()]
param (
[PARAMETER(Mandatory=$True)][String]$Folder,
[PARAMETER(Mandatory=$True)][String]$UserName,
[PARAMETER(Mandatory=$True)][String]$Rules,
[PARAMETER(Mandatory=$True)][String]$AccessControlType
)
# ACL
$acl = Get-Acl $Folder
#
$fileSystemRights = [System.Security.AccessControl.FileSystemRights]"$Rules"
#C ,
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($UserName, $fileSystemRights, $AccessControlType)
# FileSystemAccessRule
$acl.SetAccessRule($AccessRule)
#
$acl | Set-Acl $Folder
}
function Set-PinnedApplication
{
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
#Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFiles\Internet Explorer\iexplore.exe"
.EXAMPLE
#Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}\Mozilla Firefox\firefox.exe"
.PARAMETER Action
, : UnpinfromTaskbar PintoTaskbar
.PARAMETER FilePath
, ( )
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)][String]$Action,
[Parameter(Mandatory=$True)][String]$FilePath
)
if(-not (test-path $FilePath)) {
throw "FilePath does not exist."
}
function InvokeVerb {
param([string]$FilePath,$verb)
$verb = $verb.Replace("&","")
$path = split-path $FilePath
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace($path)
$item = $folder.Parsename((split-path $FilePath -leaf))
$itemVerb = $item.Verbs() | ? {$_.Name.Replace("&","") -eq $verb}
if($itemVerb -eq $null){
throw "Verb $verb not found."
} else {
$itemVerb.DoIt()
}
}
function GetVerb {
param([int]$verbId)
try {
$t = [type]"CosmosKey.Util.MuiHelper"
} catch {
$def = [Text.StringBuilder]""
[void]$def.AppendLine('[DllImport("user32.dll")]')
[void]$def.AppendLine('public static extern int LoadString(IntPtr h,uint id, System.Text.StringBuilder sb,int maxBuffer);')
[void]$def.AppendLine('[DllImport("kernel32.dll")]')
[void]$def.AppendLine('public static extern IntPtr LoadLibrary(string s);')
Add-Type -MemberDefinition $def.ToString() -name MuiHelper -namespace CosmosKey.Util
}
if($global:CosmosKey_Utils_MuiHelper_Shell32 -eq $null){
$global:CosmosKey_Utils_MuiHelper_Shell32 = [CosmosKey.Util.MuiHelper]::LoadLibrary("shell32.dll")
}
$maxVerbLength=255
$verbBuilder = New-Object Text.StringBuilder "",$maxVerbLength
[void][CosmosKey.Util.MuiHelper]::LoadString($CosmosKey_Utils_MuiHelper_Shell32,$verbId,$verbBuilder,$maxVerbLength)
return $verbBuilder.ToString()
}
$verbs = @{
"PintoTaskbar"=5386
"UnpinfromTaskbar"=5387
}
if($verbs.$Action -eq $null){
Throw "Action $action not supported`nSupported actions are:`n`tPintoTaskbar`n`tUnpinfromTaskbar"
}
InvokeVerb -FilePath $FilePath -Verb $(GetVerb -VerbId $verbs.$action)
}
Set-Proxy cproxy.udsu.ru 8080
Set-AccessRule -Folder $env:USERPROFILE\Desktop\ -UserName $env:USERNAME -Rules "CreateFiles,AppendData,Delete" -AccessControlType Deny
Set-PinnedApplication -Action UnpinfromTaskbar -FilePath "$env:ProgramFiles\Internet Explorer\iexplore.exe"
Set-PinnedApplication -Action PintoTaskbar -FilePath "${env:ProgramFiles(x86)}\Mozilla Firefox\firefox.exe"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\Excel 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\Word 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2013\PowerPoint 2013.lnk"
Set-PinnedApplication -Action PintoTaskbar -FilePath "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\\-3D V16\-3D V16.lnk"
# ,
Unregister-ScheduledTask -TaskName UdSUSettingStudent -Confirm:$false