How to manage local account passwords from Active Directory without LAPS

Introduction

Active Directory provided a mechanism to set account password via GPO preferences. Unfortunately this was done with an encrypted cpassword value for which the decryption key was published and subsequently the functionality was blocked.

Later, Local Administrator Password Solution (LAPS), was adopted by Microsoft and it is well suited for the task.

The approach described in this article is an alternative method to LAPS which can be used if the schema extension requirement of LAPS cannot be done. It also allows for multiple account management.

For this solution you will need:

  • File Share
  • SQL Server
  • Group Policy
  • PasswordImporter
  • PasswordViewer

Both PasswordImport and PasswordViewer is available within the same download here

Create share

Create a folder on a server which will hold the passwords reset output files from computers that get the GPO.

It is important to only allow administrators to view files within this folder. Everyone (authenticated users) should only have create/write permission (as shown below). The reason for this is that password will be stored here in clear-text until the PasswordImporter
tool processed it.

Create GPO

Create a GPO and filter it to the computer objects for the computers you wish to manage passwords for.

 

The startup script needs to be set to save password text files to the share created in an earlier step.

Create SQL Table

Use the following SQL script to create a table within SQL to store passwords. Assign a group to this group to SQL and grant it SELECT rights on the Passwords table. Add all your administrators and support personnel into this group.

CREATE TABLE [dbo].[Passwords](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ComputerName] [varchar](255) NOT NULL,
[Password] [varchar](255) NOT NULL,
CONSTRAINT [PK_Passwords] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Below is an example of the passwords stored encrypted within SQL

Setup PasswordImporter

PasswordImporter is an application that reads password files from the share and import is, encrypted, into SQL. After a successful import, the password file is deleted.

Open Configurator and specify Location, ConnectionString and LogFile values. Note that Location and ConnectionString needs to be encrypted with encryption key wL!PIQj%EeWj%L^e$nEpdjFzL0d9%Y1#

 

Schedule this application to run every few minutes to import passwords to SQL database

Setup PasswordViewer

PasswordViewer is an application that shows the specified computers password. This application should be distributed to all administrators and support personnel.

Open Configurator and specify FQDN, NetBIOS and ConnectionString values. Note that ConnectionString needs to provide placeholder values for Domain, Username and
Password, for example:

Data source=YOURSQLSERVER;initial catalog=YOURDATABASE;Integrated Security=SSPI; User Id = [DOMAINNAME\USERNAME]; Password = [PASSWORD]

How to thread single-threaded applications

Introduction

CommandThreader is a command line tool that runs commands, line by line, but instead of it running only one at a time, it executes a batch of them so as one closes, it automatically starts a new command. The list of commands is provided via an input file
and the number of simultaneous running commands is specified as a number of allowed threads.

Implementation

Download and extract CommandThreader.zip (VirusTotal Scan Result) to a folder of your choice, on the computer that it will be scheduled to run on.

Demo Execution

In this demo, I execute a dummy application called DummyApp.exe. All this application does is delay for a random number of seconds and as a return code returns this numbers of seconds that it delays. This can
be any application that takes a long time to complete but is not resources intensive.

Input File

C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|false|true|60
...

 

Input File breakdown

C:\Temp\DummyApp\DummyApp.exe|DummyArgument|C:\Temp\DummyApp|
false|true|
60

  • Command to run
  • Arguments for the command
  • Working folder
  • Execute command hidden
  • Wait for command to exit
  • Maximum amount of time that CommandThreader should wait before killing process

CommandThreader Command

With the command below a total of 5 threads will be maintained

CommandThreader.exe DummyInput.txt 5

 

CommandThreader Output

Conclusion

With CommandThreader, the time taken to run 100s long running processes can be drastically reduced.

Non-standard success exit codes

Some software distribution tools do not allow custom success exit codes. This means that if a software package returns a non-standard success exit code that the deployment status might return a failure instead of a success.

With this script an installation package’s non-standard success exit codes can be translated to exit code 0 within the software distribution tool.

Example: CScript.exe Setup.vbs /Command:SomeSetup.exe /SuccessCodes:1;2;3
In this example exit code 1,2 and 3 for SomeSetup.exe will be changed to 0

Attachment(s): [list-attachments]

[sourcecode language=”vb”]
Option Explicit

On Error Resume Next

Dim strCommand
Dim strSuccessCodes

strCommand = WScript.Arguments.Named("Command")
strSuccessCodes = WScript.Arguments.Named("SuccessCodes")

If Len(Trim(strCommand)) = 0 Or Len(Trim(strSuccessCodes)) = 0 Then
WScript.Quit(1)
End If

Dim arrSuccessCodes
Dim intSuccessCode

arrSuccessCodes = Split(strSuccessCodes,";")

Dim objShell
Dim objExec
Dim intReturnCode

Set objShell = CreateObject("WScript.Shell")

Err.Clear
Set objExec = objShell.Exec(strCommand)
If Err.Number <> 0 Then
WScript.Echo "Problem with command"
WScript.Quit(1)
End If

Do While objExec.Status = 0
Call WScript.Sleep(100)
Loop

intReturnCode = objExec.ExitCode

For Each intSuccessCode In arrSuccessCodes
If IsNumeric(intSuccessCode) Then
If intReturnCode = CInt(intSuccessCode) Then
WScript.Echo "Success"
intReturnCode = 0
Exit For
End If
End If
Next

Set objExec = Nothing
Set objShell = Nothing

Call WScript.Quit(intReturnCode)
[/sourcecode]

CreateFileWithCode

This utility can be used to recreate any file at runtime.

It works by reading the input file with binaryreader and creates a function that can be called to recreate the input file.

Usage: CreateFileWithCode INPUTFILE > OUTPUTFILE

Attachment(s): [list-attachments]

[sourcecode language=”vb”]
Private Sub CreateFile()
Try
Dim objBinaryWriter As System.IO.BinaryWriter

objBinaryWriter = New System.IO.BinaryWriter(System.IO.File.Open("CreateFileWithCode.exe", System.IO.FileMode.Create))

Dim intValue As Int32
Dim arrValues() As Int32 = { _
9460301, _
3, _
4, _
65535, _
184, _
0, _
64, _
0, _
0, _
0, _
0, _
0, _
0, _
0, _
0, _
128, _
247078670, _
-855002112, _
1275181089, _


0 _
}
For Each intValue In arrValues
objBinaryWriter.Write(intValue)
Next
Catch ex As Exception

End Try
End Sub
[/sourcecode]

Remotely Rename A Computer

Remotely rename a computer and its Active Directory account using PSExec and batch file (vbs dropper)

Usage: PSExec.exe \\CURRENTCOMPUTERNAME -c -d -f RenameComputer.bat NEWCOMPUTERNAME
(Account needs Admin on target computer and modify rights on computer object in AD)

RenameComputer.bat
[sourcecode language=”plain”]
@ECHO OFF
ECHO Option Explicit > RenameComputer.vbs
ECHO. >> RenameComputer.vbs
ECHO On Error Resume Next >> RenameComputer.vbs
ECHO. >> RenameComputer.vbs
ECHO Dim objWMIService >> RenameComputer.vbs
ECHO Dim colComputers >> RenameComputer.vbs
ECHO Dim objComputer >> RenameComputer.vbs
ECHO Dim varError >> RenameComputer.vbs
ECHO. >> RenameComputer.vbs
ECHO Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") >> RenameComputer.vbs
ECHO. >> RenameComputer.vbs
ECHO Set colComputers = objWMIService.ExecQuery("Select * from Win32_ComputerSystem") >> RenameComputer.vbs
ECHO. >> RenameComputer.vbs
ECHO For Each objComputer in colComputers >> RenameComputer.vbs
ECHO varError = objComputer.Rename("%1") >> RenameComputer.vbs
ECHO Next >> RenameComputer.vbs
ECHO WScript.Echo varError >> RenameComputer.vbs

CScript //NOLOGO RenameComputer.vbs
DEL RenameComputer.vbs

Shutdown -r -f -t 60
[/sourcecode]

Command Prompt with Random Color on Startup

Add REG_SZ to HKLM\SOFTWARE\Microsoft\Command Processor with name AutoRun and value of RndColor.bat

Create file RndColor.bat in %WINDIR%\System32

[sourcecode language=”plain”]
@Echo Off
Echo Loading…

SET rnd=%random%

IF %rnd% LSS 4681 GOTO 1
IF %rnd% LSS 9362 GOTO 2
IF %rnd% LSS 14043 GOTO 3
IF %rnd% LSS 18724 GOTO 4
IF %rnd% LSS 23405 GOTO 5
IF %rnd% LSS 28086 GOTO 6
IF %rnd% LSS 32767 GOTO 7

Goto END

:1
Color 1F
Goto END

:2
Color 20
Goto END

:3
Color 30
Goto END

:4
Color 4E
Goto END

:5
Color 5F
Goto END

:6
Color 80
Goto END

:7
Color 4F
Goto END

:END
CLS
[/sourcecode]

InstallWDS – Installing Windows Deployment Services (WDS) from a batch file

Installing Windows Deployment Services (WDS) from a batch file

I needed to install WDS on 300+ servers but found that the server build did not have a local copy of OS setup or service pack files. I also wanted to set the paths back to the original values.

I started by adding all files required by WDS to the DFS and I created the following batch file.

[sourcecode language=”plain”]
@ECHO OFF

REG EXPORT "HKLMSOFTWAREMicrosoftWindowsCurrentVersionSetup" %WINDIR%InstallWDS.reg /y
REG ADD "HKLMSOFTWAREMicrosoftWindowsCurrentVersionSetup" /v "SourcePath" /t REG_SZ /d "\SERVERNAMESHARE" /f
REG ADD "HKLMSOFTWAREMicrosoftWindowsCurrentVersionSetup" /v "ServicePackSourcePath" /t REG_SZ /d "\SERVERNAMESHARE" /f

VER | Find "Microsoft Windows [Version 5.2." &gt; nul
If %ERRORLEVEL% == 0 GoTo Win2003
VER | Find "Microsoft Windows [Version 6.0." &gt; nul
If %ERRORLEVEL% == 0 GoTo Win2008

GoTo CleanUp

:Win2003
ECHO [Components] &gt; %WINDIR%InstallWDS.inf
ECHO RemInst = on &gt;&gt; %WINDIR%InstallWDS.inf
Sysocmgr.exe /i:sysoc.inf /u:%WINDIR%InstallWDS.inf
GoTo CleanUp

:Win2008
ServerManagerCmd -install WDS
GoTo CleanUp

:CleanUp
REG IMPORT %WINDIR%InstallWDS.reg
DEL %WINDIR%InstallWDS.inf
DEL %WINDIR%InstallWDS.reg
[/sourcecode]

Attachment(s):
[list-attachments]