├── .gitattributes ├── .gitignore ├── Assemblies ├── ARSoft.Tools.Net.dll ├── ARSoft.Tools.Net.xml ├── IPhelper.dll ├── JHSoftware.DnsClient.dll ├── WebTools.dll └── filetimestamp.dll ├── Audit └── Audit.psm1 ├── Database ├── Database.psm1 ├── x64 │ ├── SQLite.Designer.dll │ ├── SQLite.Interop.dll │ ├── System.Data.SQLite.Linq.dll │ └── System.Data.SQLite.dll └── x86 │ ├── SQLite.Designer.dll │ ├── SQLite.Interop.dll │ ├── System.Data.SQLite.Linq.dll │ └── System.Data.SQLite.dll ├── Discovery └── Discovery.psm1 ├── LICENSE.txt ├── Parse └── Parse.psm1 ├── Posh-SecMod.psd1 ├── Posh-SecMod.psm1 ├── PostExploitation └── PostExploitation.psm1 ├── README.md ├── Registry ├── Registry.ps1 └── Registry.psm1 └── Utility └── utility.psm1 /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | -------------------------------------------------------------------------------- /Assemblies/ARSoft.Tools.Net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Assemblies/ARSoft.Tools.Net.dll -------------------------------------------------------------------------------- /Assemblies/IPhelper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Assemblies/IPhelper.dll -------------------------------------------------------------------------------- /Assemblies/JHSoftware.DnsClient.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Assemblies/JHSoftware.DnsClient.dll -------------------------------------------------------------------------------- /Assemblies/WebTools.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Assemblies/WebTools.dll -------------------------------------------------------------------------------- /Assemblies/filetimestamp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Assemblies/filetimestamp.dll -------------------------------------------------------------------------------- /Audit/Audit.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Enumerates Logged On Sessions on a give host. 4 | .DESCRIPTION 5 | Enumerates Logged On Sessions on a give host using WMI. 6 | .EXAMPLE 7 | Get-AuditLogedOnSessions | where {$_.processes.count -gt 0} 8 | 9 | Retrieves sessions that have running processes. 10 | 11 | #> 12 | function Get-AuditLogedOnSessions 13 | { 14 | [CmdletBinding()] 15 | Param 16 | ( 17 | [Parameter(Mandatory=$false)] 18 | [System.Management.Automation.PSCredential] 19 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 20 | 21 | [Parameter(Mandatory=$false)] 22 | [string]$ComputerName = "localhost" 23 | ) 24 | begin 25 | { 26 | $loggedsessions = @() 27 | $SessionType = @{ 28 | 2 = 'Interactive' 29 | 3 = 'Network' 30 | 4 = 'Batch' 31 | 5 = 'Servie' 32 | 6 = 'Proxy' 33 | 7 = 'Unlock' 34 | 8 = 'NetworkCleartext' 35 | 9 = 'NewCredentials' 36 | 10 = 'Terminal' 37 | 11 = 'CachedInteractive' 38 | 12 = 'CachedTerminal' 39 | 13 = 'CachedUnlock' 40 | } 41 | } 42 | process 43 | { 44 | $sessions = Get-WmiObject win32_logonsession -Credential $Credential -ComputerName $ComputerName | select -Unique 45 | 46 | foreach ($session in $sessions) 47 | { 48 | try{ 49 | $account = $session.getrelated('win32_useraccount') 50 | if ($account -ne $null) 51 | { 52 | $loggedsessions += [pscustomobject][ordered]@{Name=$account.Caption 53 | SID=$account.SID 54 | FullName=$account.fullname 55 | Created=[System.Management.ManagementDateTimeConverter]::todatetime($session.StartTime) 56 | AuthenticationType=$session.AuthenticationPackage 57 | LogonType=$SessionType[[int]$session.LogonType] 58 | Processes=$session.GetRelated('win32_process') 59 | } 60 | } 61 | } 62 | catch {} 63 | } 64 | } 65 | 66 | end {$loggedsessions} 67 | } 68 | 69 | 70 | <# 71 | .Synopsis 72 | Gets a list of Domain Computer accounts and their details using ADSI. 73 | .DESCRIPTION 74 | Gets a list of Domain coputer accounts and their details using ADSI. If the machine it is ran from is 75 | in the domain and no Domain Controller is specified it will run with the privelages of the user. 76 | Support the use of alternate user credentials when ran against a domain controller. The host must use 77 | the same DNS server to be able to reseolve the hostnames to the proper IPAddress. 78 | .EXAMPLE 79 | 80 | Get-AuditDSComputerAccount -DomainController 192.168.10.10 -Credential (Get-Credential) 81 | cmdlet Get-Credential at command pipeline position 1 82 | Supply values for the following parameters: 83 | 84 | 85 | HostName : DC01.acmelabs.com 86 | OperatingSystem : Windows Server 2012 Standard 87 | ServicePack : 88 | Version : 6.2 (9200) 89 | DN : CN=DC01,OU=Domain Controllers,DC=acmelabs,DC=com 90 | Created : 1/12/2013 2:08:47 AM 91 | LastModified : 9/4/2013 7:07:02 PM 92 | IPAddress : {192.168.10.10} 93 | 94 | HostName : DC02.acmelabs.com 95 | OperatingSystem : Windows Server 2008 R2 Enterprise 96 | ServicePack : Service Pack 1 97 | Version : 6.1 (7601) 98 | DN : CN=DC02,OU=Domain Controllers,DC=acmelabs,DC=com 99 | Created : 1/12/2013 2:15:02 AM 100 | LastModified : 8/27/2013 9:29:39 AM 101 | IPAddress : {192.168.10.12} 102 | 103 | HostName : WIN701.acmelabs.com 104 | OperatingSystem : Windows 7 Enterprise 105 | ServicePack : Service Pack 1 106 | Version : 6.1 (7601) 107 | DN : CN=WIN701,OU=HR,DC=acmelabs,DC=com 108 | Created : 1/12/2013 2:45:21 AM 109 | LastModified : 8/26/2013 6:45:50 PM 110 | IPAddress : {192.168.10.20} 111 | 112 | HostName : WIN702.acmelabs.com 113 | OperatingSystem : Windows 7 Ultimate 114 | ServicePack : Service Pack 1 115 | Version : 6.1 (7601) 116 | DN : CN=WIN702,OU=HR,DC=acmelabs,DC=com 117 | Created : 1/13/2013 3:27:10 PM 118 | LastModified : 8/26/2013 6:42:00 PM 119 | IPAddress : {192.168.10.21} 120 | 121 | HostName : WIN801.acmelabs.com 122 | OperatingSystem : Windows 8 Enterprise 123 | ServicePack : 124 | Version : 6.2 (9200) 125 | DN : CN=WIN801,CN=Computers,DC=acmelabs,DC=com 126 | Created : 1/13/2013 5:48:57 PM 127 | LastModified : 9/5/2013 5:09:25 AM 128 | IPAddress : {192.168.10.40} 129 | 130 | HostName : WIN2K01.acmelabs.com 131 | OperatingSystem : Windows Server 2012 Standard 132 | ServicePack : 133 | Version : 6.2 (9200) 134 | DN : CN=WIN2K01,CN=Computers,DC=acmelabs,DC=com 135 | Created : 1/14/2013 4:31:58 PM 136 | LastModified : 8/25/2013 5:28:07 PM 137 | IPAddress : {192.168.10.2} 138 | 139 | HostName : win2k301.acmelabs.com 140 | OperatingSystem : Windows Server 2003 141 | ServicePack : Service Pack 2 142 | Version : 5.2 (3790) 143 | DN : CN=WIN2K301,CN=Computers,DC=acmelabs,DC=com 144 | Created : 1/18/2013 12:51:59 PM 145 | LastModified : 8/15/2013 8:39:43 PM 146 | IPAddress : {192.168.10.50} 147 | #> 148 | function Get-AuditDSComputerAccount 149 | { 150 | [CmdletBinding()] 151 | Param( 152 | [Parameter(Mandatory=$false, 153 | HelpMessage="Credentials to use when connecting to a Domain Controller.")] 154 | [System.Management.Automation.PSCredential] 155 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 156 | 157 | [Parameter(Mandatory=$false, 158 | HelpMessage="Domain controller for Domain and Site that you want to query against.")] 159 | [string]$DomainController, 160 | 161 | [Parameter(Mandatory=$false, 162 | HelpMessage="Maximum number of Objects to pull from AD, limit is 1,000 .")] 163 | [int]$Limit = 1000, 164 | 165 | [Parameter(Mandatory=$false, 166 | HelpMessage="scope of a search as either a base, one-level, or subtree search, default is subtree.")] 167 | [ValidateSet("Subtree","OneLevel","Base")] 168 | [string]$SearchScope = "Subtree", 169 | 170 | [Parameter(Mandatory=$false, 171 | HelpMessage="Distinguished Name Path to limit search to.")] 172 | 173 | [string]$SearchDN 174 | ) 175 | Begin 176 | { 177 | if ($DomainController -and $Credential.GetNetworkCredential().Password) 178 | { 179 | $objDomain = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$($DomainController)", $Credential.UserName,$Credential.GetNetworkCredential().Password 180 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 181 | } 182 | else 183 | { 184 | $objDomain = [ADSI]"" 185 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 186 | } 187 | } 188 | 189 | Process 190 | { 191 | $CompFilter = "(&(objectCategory=Computer))" 192 | $ObjSearcher.PageSize = $Limit 193 | $ObjSearcher.Filter = $CompFilter 194 | $ObjSearcher.SearchScope = "Subtree" 195 | 196 | if ($SearchDN) 197 | { 198 | $objSearcher.SearchDN = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($SearchDN)") 199 | } 200 | 201 | $ObjSearcher.FindAll() | ForEach-Object { 202 | $CompProps = [ordered]@{} 203 | $CompProps.Add('HostName', "$($_.properties.dnshostname)") 204 | $CompProps.Add('OperatingSystem', "$($_.properties.operatingsystem)") 205 | $CompProps.Add('ServicePack', "$($_.properties.operatingsystemservicepack)") 206 | $CompProps.Add('Version', "$($_.properties.operatingsystemversion)") 207 | $CompProps.Add('DN', "$($_.properties.distinguishedname)") 208 | $CompProps.Add('Created', [datetime]"$($_.properties.whencreated)") 209 | $CompProps.Add('LastModified', [datetime]"$($_.properties.whenchanged)") 210 | $CompProps.Add('IPAddress',([System.Net.Dns]::GetHostAddresses("$($_.properties.dnshostname)"))) 211 | 212 | [pscustomobject]$CompProps 213 | } 214 | 215 | } 216 | 217 | End 218 | { 219 | 220 | } 221 | } 222 | 223 | 224 | <# 225 | .Synopsis 226 | Gets a list of Domain users and their details using ADSI. 227 | .DESCRIPTION 228 | Gets a list of Domain users and their details using ADSI. If the machine it is ran from is 229 | in the domain and no Domain Controller is specified it will run with the privelages of the user. 230 | Support the use of alternate user credentials when ran against a domain controller. 231 | .EXAMPLE 232 | Get-AuditDSUserAcount -Credential (Get-Credential) -DomainController 192.168.10.10 233 | cmdlet Get-Credential at command pipeline position 1 234 | Supply values for the following parameters: 235 | 236 | 237 | SAMAccount : Administrator 238 | Description : Built-in account for administering the computer/domain 239 | UserPrincipal : Administrator@acmelabs.com 240 | DN : CN=Administrator,CN=Users,DC=acmelabs,DC=com 241 | Created : 1/12/2013 2:06:53 AM 242 | LastModified : 9/10/2013 4:00:28 AM 243 | PasswordLastSet : 8/20/2013 2:13:07 PM 244 | AccountExpires : 245 | LastLogon : 9/14/2013 2:47:43 PM 246 | GroupMembership : CN=Organization Management,OU=Microsoft Exchange Security Groups,DC=acmelabs,DC=com CN=Group Policy Creator Owners,CN=Users,DC=acmelabs,DC=com 247 | CN=Domain Admins,CN=Users,DC=acmelabs,DC=com CN=Enterprise Admins,CN=Users,DC=acmelabs,DC=com CN=Schema Admins,CN=Users,DC=acmelabs,DC=com 248 | CN=Administrators,CN=Builtin,DC=acmelabs,DC=com 249 | SID : S-1-5-21-3435989536-2782530369-1314837659-500 250 | 251 | SAMAccount : Guest 252 | Description : Built-in account for guest access to the computer/domain 253 | UserPrincipal : 254 | DN : CN=Guest,CN=Users,DC=acmelabs,DC=com 255 | Created : 1/12/2013 2:06:53 AM 256 | LastModified : 1/12/2013 2:06:53 AM 257 | PasswordLastSet : 12/31/1600 8:00:00 PM 258 | AccountExpires : 259 | LastLogon : 12/31/1600 8:00:00 PM 260 | GroupMembership : CN=Guests,CN=Builtin,DC=acmelabs,DC=com 261 | SID : S-1-5-21-3435989536-2782530369-1314837659-501 262 | 263 | SAMAccount : krbtgt 264 | Description : Key Distribution Center Service Account 265 | UserPrincipal : 266 | DN : CN=krbtgt,CN=Users,DC=acmelabs,DC=com 267 | Created : 1/12/2013 2:08:47 AM 268 | LastModified : 3/20/2013 4:38:18 PM 269 | PasswordLastSet : 1/11/2013 10:08:47 PM 270 | AccountExpires : 271 | LastLogon : 12/31/1600 8:00:00 PM 272 | GroupMembership : CN=Denied RODC Password Replication Group,CN=Users,DC=acmelabs,DC=com 273 | SID : S-1-5-21-3435989536-2782530369-1314837659-502 274 | 275 | SAMAccount : cperez 276 | Description : 277 | UserPrincipal : cperez@acmelabs.com 278 | DN : CN=carlos Perez,CN=Users,DC=acmelabs,DC=com 279 | Created : 1/13/2013 9:32:18 PM 280 | LastModified : 7/3/2013 1:34:00 AM 281 | PasswordLastSet : 1/13/2013 5:32:18 PM 282 | AccountExpires : 283 | LastLogon : 6/26/2013 7:24:53 PM 284 | GroupMembership : 285 | SID : S-1-5-21-3435989536-2782530369-1314837659-1604 286 | #> 287 | function Get-AuditDSUserAcount 288 | { 289 | [CmdletBinding(DefaultParametersetName="Default")] 290 | Param( 291 | [Parameter(ParameterSetName='Modified')] 292 | [Parameter(ParameterSetName='Created')] 293 | [Parameter(ParameterSetName='Default')] 294 | [Parameter(Mandatory=$false, 295 | HelpMessage="Credentials to use when connecting to a Domain Controller.")] 296 | [System.Management.Automation.PSCredential] 297 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 298 | 299 | [Parameter(ParameterSetName='Modified')] 300 | [Parameter(ParameterSetName='Created')] 301 | [Parameter(ParameterSetName='Default')] 302 | [Parameter(Mandatory=$false, 303 | HelpMessage="Domain controller for Domain and Site that you want to query against.")] 304 | [string]$DomainController, 305 | 306 | [Parameter(ParameterSetName='Modified')] 307 | [Parameter(ParameterSetName='Created')] 308 | [Parameter(ParameterSetName='Default')] 309 | [Parameter(Mandatory=$false, 310 | HelpMessage="Maximum number of Objects to pull from AD, limit is 1,000 .")] 311 | [int]$Limit = 1000, 312 | 313 | [Parameter(ParameterSetName='Modified')] 314 | [Parameter(ParameterSetName='Created')] 315 | [Parameter(ParameterSetName='Default')] 316 | [Parameter(Mandatory=$false, 317 | HelpMessage="scope of a search as either a base, one-level, or subtree search, default is subtree.")] 318 | [ValidateSet("Subtree","OneLevel","Base")] 319 | [string]$SearchScope = "Subtree", 320 | 321 | [Parameter(ParameterSetName='Modified')] 322 | [Parameter(ParameterSetName='Created')] 323 | [Parameter(ParameterSetName='Default')] 324 | [Parameter(Mandatory=$false, 325 | HelpMessage="Distinguished Name Path to limit search to.")] 326 | [string]$SearchDN, 327 | 328 | [Parameter(ParameterSetName='Modified', 329 | HelpMessage="Date to search for users mofied on or after this date.")] 330 | [datetime]$ModifiedAfter, 331 | 332 | [Parameter(ParameterSetName='Modified', 333 | HelpMessage="Date to search for users mofied on or before this date.")] 334 | [datetime]$ModifiedBefore, 335 | 336 | [Parameter(ParameterSetName='Created', 337 | HelpMessage="Date to search for users created on or after this date.")] 338 | [datetime]$CreatedAfter, 339 | 340 | [Parameter(ParameterSetName='Created', 341 | HelpMessage="Date to search for users created on or after this date.")] 342 | [datetime]$CreatedBefore 343 | ) 344 | 345 | Begin 346 | { 347 | if ($DomainController -and $Credential.GetNetworkCredential().Password) 348 | { 349 | $objDomain = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$($DomainController)", $Credential.UserName,$Credential.GetNetworkCredential().Password 350 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 351 | } 352 | else 353 | { 354 | $objDomain = [ADSI]"" 355 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 356 | } 357 | } 358 | 359 | Process 360 | { 361 | $SAMAccountFilter = "(sAMAccountType=805306368)" 362 | 363 | # Filter for modification time 364 | if ($ModifiedAfter -and $ModifiedBefore) 365 | { 366 | $SAMAccountFilter = "(&$($SAMAccountFilter)(whenChanged>=$($ModifiedAfter.ToString("yyyyMMddhhmmss.sZ")))(whenChanged<=$($ModifiedBefore.ToString("yyyyMMddhhmmss.sZ"))))" 367 | } 368 | elseif ($ModifiedAfter) 369 | { 370 | $SAMAccountFilter = "(&$($SAMAccountFilter)(whenChanged>=$($ModifiedAfter.ToString("yyyyMMddhhmmss.sZ"))))" 371 | } 372 | elseif ($ModifiedBefore) 373 | { 374 | $SAMAccountFilter = "(&$($SAMAccountFilter)(whenChanged<=$($ModifiedBefore.ToString("yyyyMMddhhmmss.sZ"))))" 375 | } 376 | 377 | # Fileter for creation time 378 | if ($CreatedAfter -and $CreatedBefore) 379 | { 380 | $SAMAccountFilter = "(&$($SAMAccountFilter)(whenChanged>=$($CreatedAfter.ToString("yyyyMMddhhmmss.sZ")))(whenChanged<=$($CreatedBefore.ToString("yyyyMMddhhmmss.sZ"))))" 381 | } 382 | elseif ($CreatedAfter) 383 | { 384 | $SAMAccountFilter = "(&$($SAMAccountFilter)(whenChanged>=$($CreatedAfter.ToString("yyyyMMddhhmmss.sZ"))))" 385 | } 386 | elseif ($CreatedBefore) 387 | { 388 | $SAMAccountFilter = "(&$($SAMAccountFilter)(whenChanged<=$($CreatedBefore.ToString("yyyyMMddhhmmss.sZ"))))" 389 | } 390 | 391 | # Search parameters 392 | $ObjSearcher.PageSize = $Limit 393 | $ObjSearcher.Filter = $SAMAccountFilter 394 | $ObjSearcher.SearchScope = $SearchScope 395 | 396 | if ($SearchDN) 397 | { 398 | $objSearcher.SearchDN = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($SearchDN)") 399 | } 400 | 401 | $ObjSearcher.FindAll() | ForEach-Object { 402 | $UserProps = [ordered]@{} 403 | $UserProps.Add('SAMAccount', "$($_.properties.samaccountname)") 404 | $UserProps.Add('Description', "$($_.properties.description)") 405 | $UserProps.Add('UserPrincipal', "$($_.properties.userprincipalname)") 406 | $UserProps.Add('DN', "$($_.properties.distinguishedname)") 407 | $UserProps.Add('Created', [dateTime]"$($_.properties.whencreated)") 408 | $UserProps.Add('LastModified', [dateTime]"$($_.properties.whenchanged)") 409 | $UserProps.Add('PasswordLastSet', [dateTime]::FromFileTime("$($_.properties.pwdlastset)")) 410 | $UserProps.Add('AccountExpires',( &{$exval = "$($_.properties.accountexpires)" 411 | If (($exval -eq 0) -or ($exval -gt [DateTime]::MaxValue.Ticks)) 412 | { 413 | $AcctExpires = "" 414 | } 415 | Else 416 | { 417 | $Date = [DateTime]$exval 418 | $AcctExpires = $Date.AddYears(1600).ToLocalTime() 419 | } 420 | $AcctExpires 421 | 422 | })) 423 | $UserProps.Add('LastLogon', [dateTime]::FromFileTime("$($_.properties.lastlogon)")) 424 | $UserProps.Add('GroupMembership', "$($_.properties.memberof)") 425 | $UserProps.Add('SID', "$(&{$sidobj = [byte[]]"$($_.Properties.objectsid)".split(" ");$sid = new-object System.Security.Principal.SecurityIdentifier $sidobj, 0; $sid.Value})") 426 | $UserProps.Add('PropertyNames', "$($_.properties.PropertyNames)") 427 | 428 | [pscustomobject]$UserProps 429 | } 430 | } 431 | } 432 | 433 | 434 | 435 | <# 436 | .Synopsis 437 | Gets a list of Domain users and their details using ADSI. 438 | .DESCRIPTION 439 | Gets a list of Domain users and their details using ADSI. If the machine it is ran from is 440 | in the domain and no Domain Controller is specified it will run with the privelages of the user. 441 | Support the use of alternate user credentials when ran against a domain controller. 442 | .EXAMPLE 443 | Get-AuditDSLockedUserAcount -DomainController 192.168.10.10 -Credential (Get-Credential) 444 | cmdlet Get-Credential at command pipeline position 1 445 | Supply values for the following parameters: 446 | 447 | SAMAccount : lockeduser 448 | Description : 449 | UserPrincipal : lockeduser@acmelabs.com 450 | DN : CN=lockeduser,CN=Users,DC=acmelabs,DC=com 451 | Created : 6/27/2013 8:23:20 PM 452 | LastModified : 9/15/2013 12:40:13 AM 453 | PasswordLastSet : 6/27/2013 4:23:20 PM 454 | AccountExpires : 455 | LastLogon : 12/31/1600 8:00:00 PM 456 | GroupMembership : 457 | SID : S-1-5-21-3435989536-2782530369-1314837659-1614 458 | 459 | #> 460 | function Get-AuditDSLockedUserAcount 461 | { 462 | [CmdletBinding()] 463 | Param( 464 | [Parameter(Mandatory=$false, 465 | HelpMessage="Credentials to use when connecting to a Domain Controller.")] 466 | [System.Management.Automation.PSCredential] 467 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 468 | 469 | [Parameter(Mandatory=$false, 470 | HelpMessage="Domain controller for Domain and Site that you want to query against.")] 471 | [string]$DomainController, 472 | 473 | [Parameter(Mandatory=$false, 474 | HelpMessage="Maximum number of Objects to pull from AD, limit is 1,000 .")] 475 | [int]$Limit = 1000, 476 | 477 | [Parameter(Mandatory=$false, 478 | HelpMessage="scope of a search as either a base, one-level, or subtree search, default is subtree.")] 479 | [ValidateSet("Subtree","OneLevel","Base")] 480 | [string]$SearchScope = "Subtree", 481 | 482 | [Parameter(Mandatory=$false, 483 | HelpMessage="Distinguished Name Path to limit search to.")] 484 | [string]$SearchDN 485 | ) 486 | 487 | Begin 488 | { 489 | if ($DomainController -and $Credential.GetNetworkCredential().Password) 490 | { 491 | $objDomain = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$($DomainController)", $Credential.UserName,$Credential.GetNetworkCredential().Password 492 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 493 | } 494 | else 495 | { 496 | $objDomain = [ADSI]"" 497 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 498 | } 499 | } 500 | 501 | Process 502 | { 503 | $SAMAccountFilter = "(&(sAMAccountType=805306368)(lockoutTime>=1))" 504 | $ObjSearcher.PageSize = $Limit 505 | $ObjSearcher.Filter = $SAMAccountFilter 506 | $ObjSearcher.SearchScope = $SearchScope 507 | 508 | if ($SearchDN) 509 | { 510 | $objSearcher.SearchDN = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($SearchDN)") 511 | } 512 | 513 | $ObjSearcher.FindAll() | ForEach-Object { 514 | $UserProps = [ordered]@{} 515 | $UserProps.Add('SAMAccount', "$($_.properties.samaccountname)") 516 | $UserProps.Add('Description', "$($_.properties.description)") 517 | $UserProps.Add('UserPrincipal', "$($_.properties.userprincipalname)") 518 | $UserProps.Add('DN', "$($_.properties.distinguishedname)") 519 | $UserProps.Add('Created', [dateTime]"$($_.properties.whencreated)") 520 | $UserProps.Add('LastModified', [dateTime]"$($_.properties.whenchanged)") 521 | $UserProps.Add('PasswordLastSet', [dateTime]::FromFileTime("$($_.properties.pwdlastset)")) 522 | $UserProps.Add('AccountExpires',( &{$exval = "$($_.properties.accountexpires)" 523 | If (($exval -eq 0) -or ($exval -gt [DateTime]::MaxValue.Ticks)) 524 | { 525 | $AcctExpires = "" 526 | } 527 | Else 528 | { 529 | $Date = [DateTime]$exval 530 | $AcctExpires = $Date.AddYears(1600).ToLocalTime() 531 | } 532 | $AcctExpires 533 | 534 | })) 535 | $UserProps.Add('LastLogon', [dateTime]::FromFileTime("$($_.properties.lastlogon)")) 536 | $UserProps.Add('GroupMembership', "$($_.properties.memberof)") 537 | $UserProps.Add('SID', "$(&{$sidobj = [byte[]]"$($_.Properties.objectsid)".split(" ");$sid = new-object System.Security.Principal.SecurityIdentifier $sidobj, 0; $sid.Value})") 538 | 539 | [pscustomobject]$UserProps 540 | } 541 | } 542 | } 543 | 544 | 545 | function Get-AuditDSDisabledUserAcount 546 | { 547 | [CmdletBinding()] 548 | Param( 549 | [Parameter(Mandatory=$false, 550 | HelpMessage="Credentials to use when connecting to a Domain Controller.")] 551 | [System.Management.Automation.PSCredential] 552 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 553 | 554 | [Parameter(Mandatory=$false, 555 | HelpMessage="Domain controller for Domain and Site that you want to query against.")] 556 | [string]$DomainController, 557 | 558 | [Parameter(Mandatory=$false, 559 | HelpMessage="Maximum number of Objects to pull from AD, limit is 1,000 .")] 560 | [int]$Limit = 1000, 561 | 562 | [Parameter(Mandatory=$false, 563 | HelpMessage="scope of a search as either a base, one-level, or subtree search, default is subtree.")] 564 | [ValidateSet("Subtree","OneLevel","Base")] 565 | [string]$SearchScope = "Subtree", 566 | 567 | [Parameter(Mandatory=$false, 568 | HelpMessage="Distinguished Name Path to limit search to.")] 569 | [string]$SearchDN 570 | ) 571 | 572 | Begin 573 | { 574 | if ($DomainController -and $Credential.GetNetworkCredential().Password) 575 | { 576 | $objDomain = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$($DomainController)", $Credential.UserName,$Credential.GetNetworkCredential().Password 577 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 578 | } 579 | else 580 | { 581 | $objDomain = [ADSI]"" 582 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 583 | } 584 | } 585 | 586 | Process 587 | { 588 | $SAMAccountFilter = "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=2))" 589 | $ObjSearcher.PageSize = $Limit 590 | $ObjSearcher.Filter = $SAMAccountFilter 591 | $ObjSearcher.SearchScope = $SearchScope 592 | 593 | if ($SearchDN) 594 | { 595 | $objSearcher.SearchDN = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($SearchDN)") 596 | } 597 | 598 | $ObjSearcher.FindAll() | ForEach-Object { 599 | $UserProps = [ordered]@{} 600 | $UserProps.Add('SAMAccount', "$($_.properties.samaccountname)") 601 | $UserProps.Add('Description', "$($_.properties.description)") 602 | $UserProps.Add('UserPrincipal', "$($_.properties.userprincipalname)") 603 | $UserProps.Add('DN', "$($_.properties.distinguishedname)") 604 | $UserProps.Add('Created', [dateTime]"$($_.properties.whencreated)") 605 | $UserProps.Add('LastModified', [dateTime]"$($_.properties.whenchanged)") 606 | $UserProps.Add('PasswordLastSet', [dateTime]::FromFileTime("$($_.properties.pwdlastset)")) 607 | $UserProps.Add('AccountExpires',( &{$exval = "$($_.properties.accountexpires)" 608 | If (($exval -eq 0) -or ($exval -gt [DateTime]::MaxValue.Ticks)) 609 | { 610 | $AcctExpires = "" 611 | } 612 | Else 613 | { 614 | $Date = [DateTime]$exval 615 | $AcctExpires = $Date.AddYears(1600).ToLocalTime() 616 | } 617 | $AcctExpires 618 | 619 | })) 620 | $UserProps.Add('LastLogon', [dateTime]::FromFileTime("$($_.properties.lastlogon)")) 621 | $UserProps.Add('GroupMembership', "$($_.properties.memberof)") 622 | $UserProps.Add('SID', "$(&{$sidobj = [byte[]]"$($_.Properties.objectsid)".split(" ");$sid = new-object System.Security.Principal.SecurityIdentifier $sidobj, 0; $sid.Value})") 623 | 624 | [pscustomobject]$UserProps 625 | } 626 | } 627 | } 628 | 629 | 630 | function Get-AuditDSDeletedAccount 631 | { 632 | [CmdletBinding()] 633 | Param( 634 | [Parameter(Mandatory=$false, 635 | HelpMessage="Credentials to use when connecting to a Domain Controller.")] 636 | [System.Management.Automation.PSCredential] 637 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 638 | 639 | [Parameter(Mandatory=$false, 640 | HelpMessage="Domain controller for Domain and Site that you want to query against.")] 641 | [string]$DomainController, 642 | 643 | [Parameter(Mandatory=$false, 644 | HelpMessage="Maximum number of Objects to pull from AD, limit is 1,000 .")] 645 | [int]$Limit = 1000, 646 | 647 | [Parameter(Mandatory=$false, 648 | HelpMessage="scope of a search as either a base, one-level, or subtree search, default is subtree.")] 649 | [ValidateSet("Subtree","OneLevel","Base")] 650 | [string]$SearchScope = "Subtree", 651 | 652 | [Parameter(Mandatory=$false, 653 | HelpMessage="Distinguished Name Path to limit search to.")] 654 | [string]$SearchDN 655 | ) 656 | 657 | Begin 658 | { 659 | if ($DomainController -and $Credential.GetNetworkCredential().Password) 660 | { 661 | $objDomain = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$($DomainController)", $Credential.UserName,$Credential.GetNetworkCredential().Password 662 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 663 | } 664 | else 665 | { 666 | $objDomain = [ADSI]"" 667 | $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain 668 | } 669 | } 670 | 671 | Process 672 | { 673 | $SAMAccountFilter = "(&(objectClass=user)(isDeleted=*))" 674 | $ObjSearcher.PageSize = $Limit 675 | $ObjSearcher.Filter = $SAMAccountFilter 676 | $ObjSearcher.SearchScope = $SearchScope 677 | $objSearcher.Tombstone = $true 678 | 679 | if ($SearchDN) 680 | { 681 | $objSearcher.SearchDN = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($SearchDN)") 682 | } 683 | 684 | $ObjSearcher.FindAll() | ForEach-Object { 685 | $UserProps = [ordered]@{} 686 | $UserProps.Add('SAMAccount', "$($_.properties.samaccountname)") 687 | 688 | $UserProps.Add('DN', "$($_.properties.distinguishedname)") 689 | $UserProps.Add('Created', [dateTime]"$($_.properties.whencreated)") 690 | $UserProps.Add('LastModified', [dateTime]"$($_.properties.whenchanged)") 691 | $UserProps.Add('PasswordLastSet', [dateTime]::FromFileTime("$($_.properties.pwdlastset)")) 692 | $UserProps.Add('LastLogon', [dateTime]::FromFileTime("$($_.properties.lastlogon)")) 693 | $UserProps.Add('SID', "$(&{$sidobj = [byte[]]"$($_.Properties.objectsid)".split(" ");$sid = new-object System.Security.Principal.SecurityIdentifier $sidobj, 0; $sid.Value})") 694 | $UserProps.Add('LastKnownParent', "$($_.properties.lastknownparent)") 695 | [pscustomobject]$UserProps 696 | } 697 | } 698 | } 699 | 700 | 701 | function Get-AuditInstallSoftware 702 | { 703 | [CmdletBinding()] 704 | Param( 705 | [Parameter(Mandatory=$false)] 706 | [System.Management.Automation.PSCredential] 707 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 708 | 709 | [string]$ComputerName = $env:COMPUTERNAME 710 | ) 711 | begin 712 | { 713 | 714 | } 715 | Process 716 | { 717 | # Set initial values 718 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 719 | $x86SoftInstallKey = "Software\Microsoft\Windows\CurrentVersion\Uninstall" 720 | $x64SoftInstallkey = "Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" 721 | $data = $reg.EnumKey(2147483650,$x86SoftInstallKey) 722 | if ($data.ReturnValue -eq 0) 723 | { 724 | $x86keys = $data.snames 725 | $HKSoftKeys = $reg.EnumKey(2147483650,"SOFTWARE").snames 726 | if ($HKSoftKeys -contains "Wow6432Node") 727 | { 728 | $x64keys = $reg.EnumKey(2147483650,$x64SoftInstallkey).snames 729 | } 730 | } 731 | else 732 | { 733 | Write-Error "Failed to connect to remote server vial WMI to pull registry information" 734 | return 735 | } 736 | 737 | $x86keys | foreach { 738 | $sName = ($reg.GetStringValue(2147483650, "$x86SoftInstallKey\$($_)", 'DisplayName')).svalue 739 | if ($sName) 740 | { 741 | $sVersion = ($reg.GetStringValue(2147483650, "$x86SoftInstallKey\$($_)", 'DisplayVersion')).svalue 742 | $sInstallDate = ($reg.GetStringValue(2147483650, "$x86SoftInstallKey\$($_)", 'InstallDate')).svalue 743 | $sPublisher = ($reg.GetStringValue(2147483650, "$x86SoftInstallKey\$($_)", 'Publisher')).svalue 744 | $SoftProps = [ordered]@{Name = $sName; Version = $sVersion; Publisher = $sPublisher; InstallDate = $sInstallDate; PSComputerName = $ComputerName} 745 | [pscustomobject]$SoftProps 746 | } 747 | } 748 | 749 | if ($x64keys) 750 | { 751 | $x64keys | foreach { 752 | $sName = ($reg.GetStringValue(2147483650, "$x64SoftInstallkey\$($_)", 'DisplayName')).svalue 753 | if ($sName) 754 | { 755 | $sVersion = ($reg.GetStringValue(2147483650, "$x64SoftInstallkey\$($_)", 'DisplayVersion')).svalue 756 | $sInstallDate = ($reg.GetStringValue(2147483650, "$x64SoftInstallkey\$($_)", 'InstallDate')).svalue 757 | $sPublisher = ($reg.GetStringValue(2147483650, "$x64SoftInstallkey\$($_)", 'Publisher')).svalue 758 | $SoftProps = [ordered]@{Name = $sName; Version = $sVersion; Publisher = $sPublisher; InstallDate = $sInstallDate; PSComputerName = $ComputerName} 759 | [pscustomobject]$SoftProps 760 | } 761 | } 762 | } 763 | } 764 | End 765 | { 766 | } 767 | } 768 | 769 | 770 | function Get-AuditPrefechList 771 | { 772 | [CmdletBinding()] 773 | Param( 774 | [Parameter(Mandatory=$false)] 775 | [System.Management.Automation.PSCredential] 776 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, 777 | 778 | [string]$ComputerName = $env:COMPUTERNAME 779 | ) 780 | $winInfo = (Get-WmiObject -query "SELECT WindowsDirectory from Win32_OperatingSystem" -ComputerName $ComputerName -Credential $Credential).WindowsDirectory.split("\") 781 | if ($winInfo) 782 | { 783 | $pfquery = "SELECT Caption,CreationDate,LastAccessed,LastModified FROM CIM_DataFile WHERE Drive = '$($winInfo[0])' and Path = '\\$($winInfo[1])\\prefetch\\' AND Extension = 'pf'" 784 | if ($pfquery) 785 | { 786 | Get-WmiObject -Query $pfquery -ComputerName $ComputerName -Credential $Credential | ForEach-Object { 787 | $pfprops = [ordered]@{ 788 | Filename = $_.Caption 789 | CreationDate = $_.ConvertToDateTime($_.CreationDate) 790 | LastAccessed = $_.ConvertToDateTime($_.LastAccessed) 791 | LastModified = $_.ConvertToDateTime($_.LastModified) 792 | } 793 | [pscustomobject]$pfprops 794 | } 795 | } 796 | else 797 | { 798 | Write-Warning "Could not find pf files in the prefetch folder." 799 | } 800 | } 801 | else 802 | { 803 | Write-Warning "Could not connect to WMI on the remote system." 804 | } 805 | } 806 | 807 | 808 | <# 809 | .SYSNOPSIS 810 | Retrieves the timestamps for a given file. 811 | 812 | .DESCRIPTION 813 | Retrieves the timestamps for a given file. This not only shows the LastAccess, LastWrite and Creation timestamps, 814 | but also shows the Entrie Modified timestamp, which is not viewable just by looking at the properties of a file. 815 | 816 | .PARAMETER File 817 | Name of the file to get timestamps from. 818 | 819 | .NOTES 820 | Name: Get-AuditFileTimeStamp 821 | Author: Boe Prox 822 | DateCreated: 26 Feb 2013 823 | DateModified: 26 Feb 2013 824 | Version: 1.0 - Initial Creation 825 | 826 | .LINK 827 | http://learn-powershell.net 828 | 829 | .INPUTS 830 | System.String 831 | 832 | .OUPUTS 833 | None 834 | 835 | .EXAMPLE 836 | Get-AuditFileTimeStamp -File 'SystemError.txt' 837 | CreationDate : 2/13/2013 7:56:13 AM 838 | EntrieModifiedTime : 2/26/2013 8:49:28 AM 839 | ModifiedTime : 2/13/2013 7:56:13 AM 840 | AccessTime : 2/26/2013 8:48:00 AM 841 | FileName : C:\users\Administrator\desktop\SystemError.txt 842 | 843 | 844 | Description 845 | ----------- 846 | Displays all timestamps for the file SystemError.txt 847 | 848 | 849 | #> 850 | Function Get-AuditFileTimeStamp 851 | { 852 | [cmdletbinding()] 853 | Param ( 854 | [parameter(ValueFromPipeline = $True)] 855 | [string[]]$File 856 | ) 857 | Begin { 858 | #region Debug Information 859 | $PSBoundParameters.GetEnumerator() | ForEach { 860 | Write-Verbose ("{0}" -f $_) 861 | } 862 | Write-Verbose ("Using ParameterSetName: {0}" -f $PSCmdlet.ParameterSetName) 863 | #endregion Debug Information 864 | 865 | 866 | #region Create reference variables 867 | $creationTime = (Get-Date) 868 | $lastAccessTime = (Get-Date) 869 | $lastWriteTime = (Get-Date) 870 | $changeTime = (Get-Date) 871 | $errorMsg = $null 872 | #endregion Create reference variables 873 | } 874 | Process { 875 | #region Check file name 876 | ForEach ($item in $File) { 877 | If (-Not ([uri]$item).IsAbsoluteUri) { 878 | Write-Verbose ("{0} is not a full path, using current directory: {1}" -f $item,$pwd) 879 | $item = (Join-Path $pwd ($item -replace "\.\\","")) 880 | } 881 | #endregion Check file name 882 | 883 | #region Get file timestamps 884 | $return = [NT]::GetFourFileTimes($item, 885 | [ref]$creationTime, 886 | [ref]$lastAccessTime, 887 | [ref]$lastWriteTime, 888 | [ref]$changeTime, 889 | [ref]$errorMsg 890 | ) 891 | If ($return) { 892 | If (-Not $errorMsg) { 893 | $object = New-Object PSObject -Property @{ 894 | FileName = $item 895 | CreationDate = $creationTime 896 | ModifiedTime = $lastWriteTime 897 | AccessTime = $lastAccessTime 898 | EntrieModifiedTime = $changeTime 899 | } 900 | $object.pstypenames.insert(0,'System.File.TimeStamp') 901 | Write-Output $object 902 | } Else { 903 | Write-Warning ("{0}" -f $errorMsg) 904 | } 905 | } Else { 906 | Write-Warning ("An issue occurred querying the timestamp!") 907 | } 908 | } 909 | #endregion Get file timestamps 910 | } 911 | End {} 912 | } 913 | 914 | 915 | <# 916 | .SYNOPSIS 917 | Retrieves the last write time of the supplied registry key 918 | 919 | .DESCRIPTION 920 | The Registry data that a hive stores in containers are called cells. A cell 921 | can hold a key, a value, a security descriptor, a list of subkeys, or a 922 | list of key values. 923 | 924 | Get-RegKeyLastWriteTime retrieves the LastWriteTime through a pointer to the 925 | FILETIME structure that receives the time at which the enumerated subkey was 926 | last written. Values do not contain a LastWriteTime property, but changes to 927 | child values update the parent keys lpftLastWriteTime. 928 | 929 | The LastWriteTime is updated when a key is created, modified, accessed, or 930 | deleted. 931 | 932 | .PARAMETER ComputerName 933 | Computer name to query 934 | 935 | .PARAMETER Key 936 | Root Key to query 937 | 938 | HKCR - Symbolic link to HKEY_LOCAL_MACHINE \SOFTWARE \Classes. 939 | HKCU - Symbolic link to a key under HKEY_USERS representing a user's profile 940 | hive. 941 | HKLM - Placeholder with no corresponding physical hive. This key contains 942 | other keys that are hives. 943 | HKU - Placeholder that contains the user-profile hives of logged-on 944 | accounts. 945 | HKCC - Symbolic link to the key of the current hardware profile 946 | 947 | .PARAMETER SubKey 948 | Registry Key to query 949 | 950 | .EXAMPLE 951 | Get-AuditRegKeyLastWriteTime -ComputerName testwks -Key HKLM -SubKey Software 952 | 953 | .EXAMPLE 954 | Get-AuditRegKeyLastWriteTime -ComputerName testwks1,testwks2 -SubKey Software 955 | 956 | .EXAMPLE 957 | Get-AuditRegKeyLastWriteTime -SubKey Software\Microsoft 958 | 959 | .EXAMPLE 960 | "testwks1","testwks2" | Get-RegKeyLastWriteTime -SubKey Software\Microsoft ` 961 | \Windows\CurrentVersion 962 | 963 | .NOTES 964 | NAME: Get-RegKeyLastWriteTime 965 | AUTHOR: Shaun Hess 966 | VERSION: 1.0 967 | LASTEDIT: 01JUL2011 968 | LICENSE: Creative Commons Attribution 3.0 Unported License 969 | (http://creativecommons.org/licenses/by/3.0/) 970 | 971 | .LINK 972 | http://www.shaunhess.com 973 | #> 974 | function Get-AuditRegKeyLastWriteTime 975 | { 976 | [CmdletBinding()] 977 | 978 | param( 979 | [parameter( 980 | ValueFromPipeline=$true, 981 | ValueFromPipelineByPropertyName=$true)] 982 | [Alias("CN","__SERVER","Computer","CNAME")] 983 | [string[]]$ComputerName=$env:ComputerName, 984 | [string]$Key = "HKLM", 985 | [string]$SubKey 986 | ) 987 | 988 | BEGIN 989 | { 990 | switch ($Key) { 991 | "HKCR" { $searchKey = 0x80000000} #HK Classes Root 992 | "HKCU" { $searchKey = 0x80000001} #HK Current User 993 | "HKLM" { $searchKey = 0x80000002} #HK Local Machine 994 | "HKU" { $searchKey = 0x80000003} #HK Users 995 | "HKCC" { $searchKey = 0x80000005} #HK Current Config 996 | default { 997 | "Invalid Key. Use one of the following options: 998 | HKCR, HKCU, HKLM, HKU, HKCC"} 999 | } 1000 | 1001 | $KEYQUERYVALUE = 0x1 1002 | $KEYREAD = 0x19 1003 | $KEYALLACCESS = 0x3F 1004 | } 1005 | PROCESS 1006 | { 1007 | foreach($computer in $ComputerName) { 1008 | 1009 | $sig0 = @' 1010 | [DllImport("advapi32.dll", SetLastError = true)] 1011 | public static extern int RegConnectRegistry( 1012 | string lpMachineName, 1013 | int hkey, 1014 | ref int phkResult); 1015 | '@ 1016 | $type0 = Add-Type -MemberDefinition $sig0 -Name Win32Utils -Namespace RegConnectRegistry -Using System.Text -PassThru 1017 | 1018 | $sig1 = @' 1019 | [DllImport("advapi32.dll", CharSet = CharSet.Auto)] 1020 | public static extern int RegOpenKeyEx( 1021 | int hKey, 1022 | string subKey, 1023 | int ulOptions, 1024 | int samDesired, 1025 | out int hkResult); 1026 | '@ 1027 | $type1 = Add-Type -MemberDefinition $sig1 -Name Win32Utils -Namespace RegOpenKeyEx -Using System.Text -PassThru 1028 | 1029 | $sig2 = @' 1030 | [DllImport("advapi32.dll", EntryPoint = "RegEnumKeyEx")] 1031 | extern public static int RegEnumKeyEx( 1032 | int hkey, 1033 | int index, 1034 | StringBuilder lpName, 1035 | ref int lpcbName, 1036 | int reserved, 1037 | int lpClass, 1038 | int lpcbClass, 1039 | out long lpftLastWriteTime); 1040 | '@ 1041 | $type2 = Add-Type -MemberDefinition $sig2 -Name Win32Utils -Namespace RegEnumKeyEx -Using System.Text -PassThru 1042 | 1043 | $sig3 = @' 1044 | [DllImport("advapi32.dll", SetLastError=true)] 1045 | public static extern int RegCloseKey( 1046 | int hKey); 1047 | '@ 1048 | $type3 = Add-Type -MemberDefinition $sig3 -Name Win32Utils -Namespace RegCloseKey -Using System.Text -PassThru 1049 | 1050 | 1051 | $hKey = new-object int 1052 | $hKeyref = new-object int 1053 | $searchKeyRemote = $type0::RegConnectRegistry($computer, $searchKey, ` [ref]$hKey) 1054 | $result = $type1::RegOpenKeyEx($hKey, $SubKey, 0, $KEYREAD, ` [ref]$hKeyref) 1055 | 1056 | #initialize variables 1057 | $builder = New-Object System.Text.StringBuilder 1024 1058 | $index = 0 1059 | $length = [int] 1024 1060 | $time = New-Object Long 1061 | 1062 | #234 means more info, 0 means success. Either way, keep reading 1063 | while ( 0,234 -contains $type2::RegEnumKeyEx($hKeyref, $index++, $builder, [ref] $length, $null, $null, $null, [ref] $time) ) 1064 | { 1065 | #create output object 1066 | $o = "" | Select Key, LastWriteTime, ComputerName 1067 | $o.ComputerName = "$computer" 1068 | $o.Key = $builder.ToString() 1069 | # TODO Change to use the time api 1070 | $o.LastWriteTime = (Get-Date $time).AddYears(1600).AddHours(-4) 1071 | $o 1072 | 1073 | #reinitialize for next time through the loop 1074 | $length = [int] 1024 1075 | $builder = New-Object System.Text.StringBuilder 1024 1076 | } 1077 | 1078 | $result = $type3::RegCloseKey($hKey); 1079 | } 1080 | } 1081 | } 1082 | 1083 | -------------------------------------------------------------------------------- /Database/Database.psm1: -------------------------------------------------------------------------------- 1 | if (!(Test-Path variable:Global:SQLiteConn )) 2 | { 3 | $Global:SQLiteConn = New-Object System.Collections.ArrayList 4 | } 5 | 6 | 7 | 8 | <# 9 | .Synopsis 10 | Creates a connection to a SQLite3 Database 11 | .DESCRIPTION 12 | Creates a connection to a SQLite3 Database file and stores the connection in to $Global:sqliteconn. 13 | .EXAMPLE 14 | Opens database main.db and creates a connection object for it. 15 | 16 | PS C:\> Connect-DBSQLite3 -DataBase .\main.db 17 | 18 | Connection Database Index 19 | ---------- -------- ----- 20 | System.Data.SQLite.SQLiteConnection .\main.db 0 21 | #> 22 | function Connect-DBSQLite3 23 | { 24 | [CmdletBinding()] 25 | param ( 26 | 27 | # Databse file to open. 28 | [Parameter(Mandatory=$true, 29 | ValueFromPipelineByPropertyName=$true, 30 | Position=0)] 31 | [ValidateScript({Test-Path $_})] 32 | [string]$DataBase 33 | 34 | # Open Database ReadOnly also. 35 | #[switch]$ReadOnly, 36 | 37 | # Password for opening the database if it requieres it. 38 | #[SecureString]$Password 39 | ) 40 | 41 | Begin 42 | { 43 | $x86Assembly = "$($PSScriptRoot)\x86\System.Data.SQLite.dll" 44 | $x64Assembly = "$($PSScriptRoot)\x64\System.Data.SQLite.dll" 45 | 46 | # Load the appropiate DLL Depending on the Archiecture 47 | switch ([intptr]::size) 48 | { 49 | 4 {$sqlitedll = [System.Reflection.Assembly]::LoadFrom($x86Assembly)} 50 | 8 {$sqlitedll = [System.Reflection.Assembly]::LoadFrom($x64Assembly)} 51 | } 52 | 53 | $DataBaseFile = (Get-ItemProperty $DataBase).FullName 54 | } 55 | Process 56 | { 57 | $cn = New-Object -TypeName System.Data.SQLite.SQLiteConnection 58 | $cn.ConnectionString = "Data Source=$DataBaseFile" 59 | $cn.Open() 60 | $conn_obj = $cn 61 | if ($Global:sqliteconn -notcontains $conn_obj) 62 | { 63 | $SessionIndex = $Global:sqliteconn.Count 64 | $NewConnection = New-Object psobject -Property @{ 65 | Index = $SessionIndex.ToString() ; 66 | Connection = $conn_obj; 67 | Database = $DataBase 68 | } 69 | 70 | [void]$Global:sqliteconn.Add($NewConnection) 71 | # Return the connection object. 72 | $NewConnection 73 | } 74 | else 75 | { 76 | Write-Warning "A connection to $DataBase already exists." 77 | } 78 | } 79 | 80 | End 81 | { 82 | } 83 | 84 | } 85 | 86 | 87 | 88 | 89 | <# 90 | .Synopsis 91 | Removes a specific SQLite3 connection 92 | .DESCRIPTION 93 | Removes a specific SQLite3 connection given its Index 94 | .EXAMPLE 95 | Disconnect all SQLite3 connections 96 | 97 | PS C:\> Get-DBSQLite3Connection | Remove-SQLite3Connection 98 | 99 | Connection Database Index 100 | ---------- -------- ----- 101 | System.Data.SQLite.SQLiteConnection .\main.db 0 102 | 103 | .EXAMPLE 104 | Remove a SQLite3 connection given its index 105 | 106 | PS C:\> Remove-DBSQLite3Connection -Index 0 107 | 108 | Connection Database Index 109 | ---------- -------- ----- 110 | System.Data.SQLite.SQLiteConnection .\main.db 0 111 | 112 | #> 113 | function Remove-DBSQLite3Connection 114 | { 115 | [CmdletBinding()] 116 | param( 117 | # Index for the database connection. 118 | [Parameter(Mandatory=$true, 119 | ValueFromPipelineByPropertyName=$true)] 120 | [Int32] $Index 121 | 122 | ) 123 | Begin{ 124 | $currentConnections = @() 125 | foreach($conn in $Global:sqliteconn) {$currentConnections += $conn} 126 | } 127 | Process 128 | { 129 | if ($Index -ge 0) 130 | { 131 | Write-Verbose "Removing connection with Index $Index" 132 | foreach($i in $Index) 133 | { 134 | foreach($Connection in $currentConnections) 135 | { 136 | if ($Connection.Index -eq $i) 137 | { 138 | Write-Verbose "Connection Found" 139 | $Connection.connection.close() 140 | $Global:sqliteconn.Remove($Connection) 141 | Write-Verbose "Connection removed." 142 | } 143 | } 144 | } 145 | } 146 | } 147 | End{} 148 | 149 | } 150 | 151 | 152 | 153 | <# 154 | .Synopsis 155 | Get SQLite3 Connections 156 | .DESCRIPTION 157 | Get all or a specified existing SQLite3 Connection. 158 | .EXAMPLE 159 | Gets all SQLIte3 Connections 160 | 161 | PS C:\> Get-DBSQLite3Connection 162 | 163 | Connection Database Index 164 | ---------- -------- ----- 165 | System.Data.SQLite.SQLiteConnection .\main.db 0 166 | 167 | #> 168 | function Get-DBSQLite3Connection 169 | { 170 | [CmdletBinding()] 171 | param( 172 | [Parameter(Mandatory=$false)] 173 | [Int32] $Index 174 | ) 175 | 176 | Begin{} 177 | Process 178 | { 179 | if ($Index) 180 | { 181 | foreach($i in $Index) 182 | { 183 | foreach($Connection in $Global:sqliteconn) 184 | { 185 | if ($Connection.Index -eq $i) 186 | { 187 | $Connection 188 | } 189 | } 190 | } 191 | } 192 | else 193 | { 194 | # Return all database connections. 195 | $return_sessions = @() 196 | foreach($s in $Global:sqliteconn){$return_sessions += $s} 197 | $return_sessions 198 | } 199 | } 200 | End{} 201 | } 202 | 203 | 204 | 205 | <# 206 | .Synopsis 207 | Exsecutes SQL query against SQLite3 Connection 208 | .DESCRIPTION 209 | Exsecutes SQL query against SQLite3 Connection against an existing SQLite3 Connection 210 | .EXAMPLE 211 | Execute query to list all the tables in the database. 212 | 213 | PS C:\> Invoke-SQLite3Query -SQL "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;" -Index 0 214 | 215 | #> 216 | function Invoke-DBSQLite3Query 217 | { 218 | [CmdletBinding()] 219 | param( 220 | [Parameter(Mandatory=$true)] 221 | [string]$SQL, 222 | 223 | [Parameter(Mandatory=$true, 224 | ParameterSetName = "Index")] 225 | [int32]$Index, 226 | 227 | [Parameter(Mandatory=$true, 228 | ParameterSetName = "Connection")] 229 | [PSobject]$Connection 230 | ) 231 | if ($Index -ge 0) 232 | { 233 | Write-Verbose "Executing Query $SQL" 234 | Write-Verbose "Executing against $Index" 235 | foreach($conn in $Global:sqliteconn) 236 | { 237 | if ($conn.index -in $Index) 238 | { 239 | $cmd = new-object System.Data.SQLite.SQLiteCommand($SQL,$conn.Connection) 240 | $ds = New-Object system.Data.DataSet 241 | $da = New-Object System.Data.SQLite.SQLiteDataAdapter($cmd) 242 | $da.fill($ds) | Out-Null 243 | return $ds.tables[0] 244 | } 245 | } 246 | } 247 | elsif ($Connection -ne $null) 248 | { 249 | $cmd = new-object System.Data.SQLite.SQLiteCommand($SQL,$Connection.Connection) 250 | $ds = New-Object system.Data.DataSet 251 | $da = New-Object System.Data.SQLite.SQLiteDataAdapter($cmd) 252 | $da.fill($ds) | Out-Null 253 | return $ds.tables[0] 254 | } 255 | } 256 | 257 | 258 | function New-DBSQLConnectionString 259 | { 260 | [CmdletBinding()] 261 | Param( 262 | [string]$ServerName, 263 | [string]$DatabaseName, 264 | [string]$UserName, 265 | [string]$Password, 266 | [Switch]$IntegratedAuth 267 | ) 268 | If($IntegratedAuth) 269 | { 270 | $ConnectionString = "server=$ServerName;database=$DatabaseName;trusted_connection=true;" 271 | 272 | } 273 | Else 274 | { 275 | $ConnectionString = "server=$ServerName;database=$DatabaseName;User Id=$UserName;Password=$Password;trusted_connection=False;" 276 | } 277 | 278 | Return $ConnectionString 279 | 280 | } 281 | -------------------------------------------------------------------------------- /Database/x64/SQLite.Designer.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x64/SQLite.Designer.dll -------------------------------------------------------------------------------- /Database/x64/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x64/SQLite.Interop.dll -------------------------------------------------------------------------------- /Database/x64/System.Data.SQLite.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x64/System.Data.SQLite.Linq.dll -------------------------------------------------------------------------------- /Database/x64/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x64/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Database/x86/SQLite.Designer.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x86/SQLite.Designer.dll -------------------------------------------------------------------------------- /Database/x86/SQLite.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x86/SQLite.Interop.dll -------------------------------------------------------------------------------- /Database/x86/System.Data.SQLite.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x86/System.Data.SQLite.Linq.dll -------------------------------------------------------------------------------- /Database/x86/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Database/x86/System.Data.SQLite.dll -------------------------------------------------------------------------------- /Discovery/Discovery.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Perform Whois Query 4 | .DESCRIPTION 5 | Performs a Whois query for a given Domain. 6 | .EXAMPLE 7 | Perfrom a whois query for google.com 8 | 9 | PS C:\> Get-Whois google.com 10 | 11 | #> 12 | function Get-Whois 13 | { 14 | [CmdletBinding(DefaultParameterSetName="Domain")] 15 | 16 | Param 17 | ( 18 | # Param1 help description 19 | [Parameter(Mandatory=$true, 20 | ParameterSetName = "Domain", 21 | ValueFromPipelineByPropertyName=$true, 22 | Position=0)] 23 | [string]$Domain 24 | 25 | #[string]$IPAddress 26 | ) 27 | 28 | Begin 29 | { 30 | # Need to generate hash from http://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xml, 31 | # http://www.iana.org/assignments/ipv6-address-space 32 | # http://www.iana.org/assignments/multicast-addresses 33 | } 34 | Process 35 | { 36 | if ($Domain) 37 | { 38 | [WebTools.Whois]::lookup($Domain, [WebTools.Whois+RecordType]::domain) 39 | } 40 | } 41 | End 42 | { 43 | } 44 | } 45 | 46 | 47 | <# 48 | .Synopsis 49 | Enumerates all mDNS records in the local subnet. 50 | .DESCRIPTION 51 | Unsing mDNS the function qill query and resolve all mDNS records for 52 | devices advertising on the local subnet. 53 | .EXAMPLE 54 | Shows only the A and AAAA Records for hosts in the local subnet 55 | 56 | Get-MDNSRecords | where recordtype -like "A*" 57 | 58 | .EXAMPLE 59 | Show only HTTP servers in the local subnet 60 | 61 | Get-MDNSRecords | where name -like "*_http._tcp*" 62 | #> 63 | function Get-MDNSRecords 64 | { 65 | [CmdletBinding()] 66 | param() 67 | $mdns = new-object -typename ARSoft.Tools.Net.Dns.MulticastDnsOneShotClient -ArgumentList 4 68 | $records = $mdns.Resolve("_services._dns-sd._udp.local",[ARSoft.Tools.Net.Dns.RecordType]::Any) 69 | $doms = @(); 70 | $records| sort -Unique | foreach-object { 71 | $_.answerrecords| foreach { 72 | Write-Verbose $_.PointerDomainName 73 | $doms += $_.PointerDomainName 74 | } 75 | } 76 | $results = @() 77 | $doms | foreach-object { 78 | Write-Verbose "Resolving $($_)" 79 | $queryres = $mdns.Resolve($_,[ARSoft.Tools.Net.Dns.RecordType]::Ptr) 80 | $results += $queryres.answerrecords 81 | $results += $queryres.additionalrecords 82 | 83 | } 84 | $results | sort -Unique 85 | } 86 | 87 | 88 | 89 | <# 90 | .Synopsis 91 | Generates a IP Address Objects for IPv4 and IPv6 Ranges. 92 | .DESCRIPTION 93 | Generates a IP Address Objects for IPv4 and IPv6 Ranges given a ranges in CIDR or 94 | range - format. 95 | .EXAMPLE 96 | PS C:\> New-IPvRange -Range 192.168.1.1-192.168.1.5 97 | 98 | Generate a collection of IPv4 Object collection for the specified range. 99 | 100 | .EXAMPLE 101 | New-IPRange -Range 192.168.1.1-192.168.1.50 | select -ExpandProperty ipaddresstostring 102 | 103 | Get a list of IPv4 Addresses in a given range as a list for use in another tool. 104 | #> 105 | function New-IPRange 106 | { 107 | [CmdletBinding(DefaultParameterSetName="CIDR")] 108 | Param( 109 | [parameter(Mandatory=$true, 110 | ParameterSetName = "CIDR", 111 | Position=0)] 112 | [string]$CIDR, 113 | 114 | [parameter(Mandatory=$true, 115 | ParameterSetName = "Range", 116 | Position=0)] 117 | [string]$Range 118 | ) 119 | if($CIDR) 120 | { 121 | $IPPart,$MaskPart = $CIDR.Split("/") 122 | $AddressFamily = ([System.Net.IPAddress]::Parse($IPPart)).AddressFamily 123 | 124 | # Get the family type for the IP (IPv4 or IPv6) 125 | $subnetMaskObj = [IPHelper.IP.Subnetmask]::Parse($MaskPart, $AddressFamily) 126 | 127 | # Get the Network and Brodcast Addressed 128 | $StartIP = [IPHelper.IP.IPAddressAnalysis]::GetClasslessNetworkAddress($IPPart, $subnetMaskObj) 129 | $EndIP = [IPHelper.IP.IPAddressAnalysis]::GetClasslessBroadcastAddress($IPPart,$subnetMaskObj) 130 | 131 | # Ensure we do not list the Network and Brodcast Address 132 | $StartIP = [IPHelper.IP.IPAddressAnalysis]::Increase($StartIP) 133 | $EndIP = [IPHelper.IP.IPAddressAnalysis]::Decrease($EndIP) 134 | [IPHelper.IP.IPAddressAnalysis]::GetIPRange($StartIP, $EndIP) 135 | } 136 | elseif ($Range) 137 | { 138 | $StartIP, $EndIP = $range.split("-") 139 | [IPHelper.IP.IPAddressAnalysis]::GetIPRange($StartIP, $EndIP) 140 | } 141 | } 142 | 143 | 144 | <# 145 | .Synopsis 146 | Generates a list of IPv4 IP Addresses given a Start and End IP. 147 | .DESCRIPTION 148 | Generates a list of IPv4 IP Addresses given a Start and End IP. 149 | .EXAMPLE 150 | Generating a list of IPs from CIDR 151 | 152 | Get-IPRange 192.168.1.0/24 153 | 154 | .EXAMPLE 155 | Generating a list of IPs from Range 156 | 157 | Get-IPRange -Range 192.168.1.1-192.168.1.50 158 | #> 159 | function New-IPv4Range 160 | { 161 | param( 162 | [Parameter(Mandatory=$true, 163 | ValueFromPipelineByPropertyName=$true, 164 | Position=0)] 165 | $StartIP, 166 | 167 | [Parameter(Mandatory=$true, 168 | ValueFromPipelineByPropertyName=$true, 169 | Position=2)] 170 | $EndIP 171 | ) 172 | 173 | # created by Dr. Tobias Weltner, MVP PowerShell 174 | $ip1 = ([System.Net.IPAddress]$StartIP).GetAddressBytes() 175 | [Array]::Reverse($ip1) 176 | $ip1 = ([System.Net.IPAddress]($ip1 -join '.')).Address 177 | 178 | $ip2 = ([System.Net.IPAddress]$EndIP).GetAddressBytes() 179 | [Array]::Reverse($ip2) 180 | $ip2 = ([System.Net.IPAddress]($ip2 -join '.')).Address 181 | 182 | for ($x=$ip1; $x -le $ip2; $x++) { 183 | $ip = ([System.Net.IPAddress]$x).GetAddressBytes() 184 | [Array]::Reverse($ip) 185 | $ip -join '.' 186 | } 187 | } 188 | 189 | 190 | <# 191 | .Synopsis 192 | Generates a list of IPv4 IP Addresses given a CIDR. 193 | .DESCRIPTION 194 | Generates a list of IPv4 IP Addresses given a CIDR. 195 | .EXAMPLE 196 | Generating a list of IPs 197 | PS C:\> New-IPv4RangeFromCIDR -Network 192.168.1.0/29 198 | 192.168.1.1 199 | 192.168.1.2 200 | 192.168.1.3 201 | 192.168.1.4 202 | 192.168.1.5 203 | 192.168.1.6 204 | 192.168.1.7 205 | #> 206 | function New-IPv4RangeFromCIDR 207 | { 208 | param( 209 | [Parameter(Mandatory=$true, 210 | ValueFromPipelineByPropertyName=$true, 211 | Position=0)] 212 | $Network 213 | ) 214 | # Extract the portions of the CIDR that will be needed 215 | $StrNetworkAddress = ($Network.split("/"))[0] 216 | [int]$NetworkLength = ($Network.split("/"))[1] 217 | $NetworkIP = ([System.Net.IPAddress]$StrNetworkAddress).GetAddressBytes() 218 | $IPLength = 32-$NetworkLength 219 | [Array]::Reverse($NetworkIP) 220 | $NumberOfIPs = ([System.Math]::Pow(2, $IPLength)) -1 221 | $NetworkIP = ([System.Net.IPAddress]($NetworkIP -join ".")).Address 222 | $StartIP = $NetworkIP +1 223 | $EndIP = $NetworkIP + $NumberOfIPs 224 | # We make sure they are of type Double before conversion 225 | If ($EndIP -isnot [double]) 226 | { 227 | $EndIP = $EndIP -as [double] 228 | } 229 | If ($StartIP -isnot [double]) 230 | { 231 | $StartIP = $StartIP -as [double] 232 | } 233 | # We turn the start IP and end IP in to strings so they can be used. 234 | $StartIP = ([System.Net.IPAddress]$StartIP).IPAddressToString 235 | $EndIP = ([System.Net.IPAddress]$EndIP).IPAddressToString 236 | New-IPv4Range $StartIP $EndIP 237 | } 238 | 239 | 240 | <# 241 | .Synopsis 242 | Performs a DNS Reverse Lookup of a given IPv4 IP Range. 243 | .DESCRIPTION 244 | Performs a DNS Reverse Lookup of a given IPv4 IP Range. 245 | .EXAMPLE 246 | Perfrom a threaded reverse lookup against a given CIDR 247 | 248 | PS C:\> Invoke-ReverseDNSLookup -CIDR 192.168.1.0/24 249 | 250 | .EXAMPLE 251 | Perfrom a reverse lookup against a given range given the start and end IP Addresses 252 | 253 | PS C:\> Invoke-ReverseDNSLookup -Range 192.168.1.1-192.168.1.20 254 | #> 255 | function Invoke-ReverseDNSLookup 256 | { 257 | [CmdletBinding()] 258 | Param 259 | ( 260 | [Parameter(Mandatory=$true, 261 | ParameterSetName = "Range", 262 | ValueFromPipelineByPropertyName=$true, 263 | Position=0)] 264 | [string]$Range, 265 | 266 | [Parameter(Mandatory=$true, 267 | ParameterSetName = "CIDR", 268 | ValueFromPipelineByPropertyName=$true, 269 | Position=0)] 270 | [string]$CIDR, 271 | 272 | [Parameter(Mandatory=$false, 273 | ValueFromPipelineByPropertyName=$true, 274 | Position=0)] 275 | [string]$MaxThreads=30, 276 | [Parameter( 277 | ValueFromPipelineByPropertyName=$true, 278 | Position=2)] 279 | [int]$TimeOut = 200 280 | ) 281 | 282 | Begin 283 | { 284 | # Manage if range is given 285 | if ($Range) 286 | { 287 | $rangeips = $Range.Split("-") 288 | $targets = New-IPv4Range -StartIP $rangeips[0] -EndIP $rangeips[1] 289 | } 290 | 291 | # Manage if CIDR is given 292 | if ($CIDR) 293 | { 294 | $targets = New-IPv4RangeFromCIDR -Network $CIDR 295 | } 296 | } 297 | Process 298 | { 299 | $RvlScripBlock = { 300 | param($ip) 301 | try { 302 | [System.Net.Dns]::GetHostEntry($ip) 303 | } 304 | catch {} 305 | } 306 | 307 | #Multithreading setup 308 | 309 | # create a pool of maxThread runspaces 310 | $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads) 311 | $pool.Open() 312 | 313 | $jobs = @() 314 | $ps = @() 315 | $wait = @() 316 | 317 | $i = 0 318 | 319 | # How many servers 320 | $record_count = $targets.Length 321 | 322 | #Loop through the endpoints starting a background job for each endpoint 323 | foreach ($ip in $targets) 324 | { 325 | Write-Verbose $ip 326 | # Show Progress 327 | $record_progress = [int][Math]::Ceiling((($i / $record_count) * 100)) 328 | Write-Progress -Activity "Performing DNS Reverse Lookup Discovery" -PercentComplete $record_progress -Status "Reverse Lookup - $record_progress%" -Id 1; 329 | 330 | while ($($pool.GetAvailableRunspaces()) -le 0) 331 | { 332 | Start-Sleep -milliseconds 500 333 | } 334 | 335 | # create a "powershell pipeline runner" 336 | $ps += [powershell]::create() 337 | 338 | # assign our pool of 3 runspaces to use 339 | $ps[$i].runspacepool = $pool 340 | 341 | # command to run 342 | [void]$ps[$i].AddScript($RvlScripBlock).AddParameter('ip', $ip) 343 | #[void]$ps[$i].AddParameter('ping', $ping) 344 | 345 | # start job 346 | $jobs += $ps[$i].BeginInvoke(); 347 | 348 | # store wait handles for WaitForAll call 349 | $wait += $jobs[$i].AsyncWaitHandle 350 | 351 | $i++ 352 | } 353 | 354 | $waitTimeout = get-date 355 | 356 | while ($($jobs | ? {$_.IsCompleted -eq $false}).count -gt 0 -or $($($(get-date) - $waitTimeout).totalSeconds) -gt 60) { 357 | Start-Sleep -milliseconds 500 358 | } 359 | 360 | # end async call 361 | for ($y = 0; $y -lt $i; $y++) { 362 | 363 | try 364 | { 365 | # complete async job 366 | $ScanResults += $ps[$y].EndInvoke($jobs[$y]) 367 | 368 | } 369 | catch 370 | { 371 | 372 | # oops-ee! 373 | write-warning "error: $_" 374 | } 375 | 376 | finally 377 | { 378 | $ps[$y].Dispose() 379 | } 380 | } 381 | 382 | $pool.Dispose() 383 | } 384 | 385 | end 386 | { 387 | $ScanResults 388 | } 389 | } 390 | 391 | 392 | <# 393 | .Synopsis 394 | Performs a Ping Scan against a given range of IPv4 IP addresses. 395 | .DESCRIPTION 396 | Performs a Ping Scan against a given range of IPv4 IP addresses by sending 397 | ICMP Echo Packets. 398 | .EXAMPLE 399 | Perform Ping Scan against a given range in CIDR format 400 | 401 | PS C:\> Invoke-PingScan -CIDR 192.168.1.0/24 402 | .EXAMPLE 403 | Perform Ping Scan against a given range given the start and end IP Addresses 404 | 405 | PS C:\> Invoke-PingScan -Range 192.168.1.1-192.168.1.10 406 | #> 407 | function Invoke-PingScan 408 | { 409 | [CmdletBinding()] 410 | Param 411 | ( 412 | # IP Range to perform ping scan against. 413 | [Parameter(Mandatory=$true, 414 | ParameterSetName = "Range", 415 | ValueFromPipelineByPropertyName=$true, 416 | Position=0)] 417 | [string]$Range, 418 | 419 | # IP CIDR to perform ping scan against. 420 | [Parameter(Mandatory=$true, 421 | ParameterSetName = "CIDR", 422 | ValueFromPipelineByPropertyName=$true, 423 | Position=0)] 424 | [string]$CIDR, 425 | 426 | # Number of concurrent threads to execute 427 | [Parameter(Mandatory=$false, 428 | ValueFromPipelineByPropertyName=$true, 429 | Position=1)] 430 | [string]$MaxThreads=10, 431 | 432 | # Timeout in miliseconds for the ICMP Echo request. 433 | [Parameter(ValueFromPipelineByPropertyName=$true, 434 | Position=2)] 435 | [int]$TimeOut = 200 436 | ) 437 | 438 | Begin 439 | { 440 | # Manage if range is given 441 | if ($Range) 442 | { 443 | $rangeips = $Range.Split("-") 444 | $targets = New-IPv4Range -StartIP $rangeips[0] -EndIP $rangeips[1] 445 | } 446 | 447 | # Manage if CIDR is given 448 | if ($CIDR) 449 | { 450 | $targets = New-IPv4RangeFromCIDR -Network $CIDR 451 | } 452 | } 453 | Process 454 | { 455 | $PingScripBlock = { 456 | param($ip, $TimeOut) 457 | $ping = New-Object System.Net.NetworkInformation.Ping 458 | $result = $ping.Send($ip, $TimeOut) 459 | if ($result.Status -eq 'success') 460 | { 461 | new-object psobject -Property @{Address = $result.Address; Time = $result.RoundtripTime} 462 | } 463 | } 464 | 465 | #Multithreading setup 466 | 467 | # create a pool of maxThread runspaces 468 | $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads) 469 | $pool.Open() 470 | 471 | $jobs = @() 472 | $ps = @() 473 | $wait = @() 474 | 475 | $i = 0 476 | 477 | # How many servers 478 | $record_count = $targets.Length 479 | 480 | #Loop through the endpoints starting a background job for each endpoint 481 | foreach ($ip in $targets) 482 | { 483 | Write-Verbose $ip 484 | # Show Progress 485 | $record_progress = [int][Math]::Ceiling((($i / $record_count) * 100)) 486 | Write-Progress -Activity "Performing Ping Discovery" -PercentComplete $record_progress -Status "Pinged Host - $record_progress%" -Id 1; 487 | 488 | while ($($pool.GetAvailableRunspaces()) -le 0) { 489 | Start-Sleep -milliseconds 500 490 | } 491 | 492 | # create a "powershell pipeline runner" 493 | $ps += [powershell]::create() 494 | 495 | $ps[$i].runspacepool = $pool 496 | 497 | # command to run 498 | [void]$ps[$i].AddScript($PingScripBlock).AddParameter('ip', $ip).AddParameter('Timeout', $TimeOut) 499 | 500 | # start job 501 | $jobs += $ps[$i].BeginInvoke(); 502 | 503 | # store wait handles for WaitForAll call 504 | $wait += $jobs[$i].AsyncWaitHandle 505 | 506 | $i++ 507 | } 508 | 509 | write-verbose "Waiting for scanning threads to finish..." 510 | 511 | $waitTimeout = get-date 512 | 513 | while ($($jobs | ? {$_.IsCompleted -eq $false}).count -gt 0 -or $($($(get-date) - $waitTimeout).totalSeconds) -gt 60) { 514 | Start-Sleep -milliseconds 500 515 | } 516 | 517 | # end async call 518 | for ($y = 0; $y -lt $i; $y++) { 519 | 520 | try { 521 | # complete async job 522 | $ScanResults += $ps[$y].EndInvoke($jobs[$y]) 523 | 524 | } catch { 525 | write-warning "error: $_" 526 | } 527 | 528 | finally { 529 | $ps[$y].Dispose() 530 | } 531 | } 532 | 533 | $pool.Dispose() 534 | } 535 | 536 | end 537 | { 538 | $ScanResults 539 | } 540 | } 541 | 542 | 543 | <# 544 | .Synopsis 545 | Performs full TCP Connection and UDP port scan. 546 | .DESCRIPTION 547 | Performs full TCP Connection and UDP port scan against a given host 548 | or range of IPv4 addresses. 549 | .EXAMPLE 550 | Perform TCP Scan of known ports against a host 551 | 552 | PS C:\> Invoke-PortScan -Target 172.20.10.3 -Ports 22,135,139,445 -Type TCP 553 | 554 | Host Port State Type 555 | ---- ---- ----- ---- 556 | 172.20.10.3 135 Open TCP 557 | 172.20.10.3 139 Open TCP 558 | 172.20.10.3 445 Open TCP 559 | 560 | #> 561 | function Invoke-PortScan 562 | { 563 | [CmdletBinding()] 564 | 565 | Param 566 | ( 567 | # Param1 help description 568 | [Parameter(Mandatory=$true, 569 | ParameterSetName = "SingleIP", 570 | ValueFromPipelineByPropertyName=$true, 571 | Position=0)] 572 | [Alias("IPAddress,Host")] 573 | [string]$Target, 574 | 575 | [Parameter(Mandatory=$true, 576 | ParameterSetName = "Range", 577 | ValueFromPipelineByPropertyName=$true, 578 | Position=0)] 579 | [string]$Range, 580 | 581 | [Parameter(Mandatory=$true, 582 | ParameterSetName = "CIDR", 583 | ValueFromPipelineByPropertyName=$true, 584 | Position=0)] 585 | [string]$CIDR, 586 | 587 | [Parameter(Mandatory=$false, 588 | ValueFromPipelineByPropertyName=$false, 589 | Position=1)] 590 | [int32[]]$Ports, 591 | 592 | [Parameter(Mandatory=$true, 593 | ValueFromPipelineByPropertyName=$false, 594 | Position=2)] 595 | [ValidateSet("TCP", "UDP")] 596 | [String[]]$Type, 597 | 598 | [Parameter(Mandatory=$false, 599 | ValueFromPipelineByPropertyName=$false, 600 | Position=3)] 601 | [ValidateSet("TCP", "UDP")] 602 | [int32]$Timeout=100 603 | 604 | 605 | ) 606 | 607 | Begin 608 | { 609 | # Expand the needed address ranges 610 | if ($Range) 611 | { 612 | $rangeips = $Range.Split("-") 613 | $targets = New-IPv4Range -StartIP $rangeips[0] -EndIP $rangeips[1] 614 | } 615 | 616 | # Expnd CIDR 617 | if ($CIDR) 618 | { 619 | $targets = New-IPv4RangeFromCIDR -Network $CIDR 620 | } 621 | 622 | # Manage single target 623 | if ($Target) 624 | { 625 | $targets = @($Target) 626 | } 627 | 628 | # Set the default ports 629 | 630 | } 631 | Process 632 | { 633 | foreach ($t in $Type) 634 | { 635 | if ($t -eq "TCP") 636 | { 637 | foreach ($ip in $targets) 638 | { 639 | foreach($p in $Ports) 640 | { 641 | try 642 | { 643 | $TcpSocket = new-object System.Net.Sockets.TcpClient 644 | #$TcpSocket.client.ReceiveTimeout = $Timeout 645 | # Connect to target host and port 646 | $TcpSocket.Connect($ip, $p) 647 | $ScanPortProps = New-Object -TypeName System.Collections.Specialized.OrderedDictionary 648 | $ScanPortProps.Add("Host",$ip) 649 | $ScanPortProps.Add("Port",$p) 650 | $ScanPortProps.Add("State","Open") 651 | $ScanPortProps.Add("Type","TCP") 652 | $scanport = New-Object psobject -Property $ScanPortProps 653 | 654 | # Close Connection 655 | $tcpsocket.Close() 656 | $scanport 657 | } 658 | catch 659 | { 660 | Write-Verbose "Port $p is closed" 661 | } 662 | } 663 | } 664 | } 665 | elseif ($t -eq "UDP") 666 | { 667 | foreach ($ip in $targets) 668 | { 669 | foreach($p in $Ports) 670 | { 671 | 672 | $UDPSocket = new-object System.Net.Sockets.UdpClient 673 | $UDPSocket.client.ReceiveTimeout = $Timeout 674 | $UDPSocket.Connect($ip,$p) 675 | 676 | $data = New-Object System.Text.ASCIIEncoding 677 | $byte = $data.GetBytes("$(Get-Date)") 678 | 679 | #Send the data to the endpoint 680 | [void] $UDPSocket.Send($byte,$byte.length) 681 | 682 | #Create a listener to listen for response 683 | $Endpoint = New-Object System.Net.IPEndPoint([system.net.ipaddress]::Any,0) 684 | 685 | try 686 | { 687 | #Attempt to receive a response indicating the port was open 688 | $receivebytes = $UDPSocket.Receive([ref] $Endpoint) 689 | [string] $returndata = $data.GetString($receivebytes) 690 | $ScanPortProps = New-Object -TypeName System.Collections.Specialized.OrderedDictionary 691 | $ScanPortProps.Add("Host",$ip) 692 | $ScanPortProps.Add("Port",$p) 693 | $ScanPortProps.Add("State","Open") 694 | $ScanPortProps.Add("Type","UDP") 695 | $scanport = New-Object psobject -Property $ScanPortProps 696 | $scanport 697 | } 698 | 699 | catch 700 | { 701 | #Timeout or connection refused 702 | Write-Verbose "Port $p is closed" 703 | } 704 | 705 | finally 706 | { 707 | #Cleanup 708 | $UDPSocket.Close() 709 | } 710 | 711 | } 712 | } 713 | } 714 | } 715 | } 716 | End 717 | { 718 | } 719 | } 720 | 721 | 722 | <# 723 | .Synopsis 724 | Performs an ARP scan against a given range of IPv4 IP Addresses. 725 | .DESCRIPTION 726 | Performs an ARP scan against a given range of IPv4 IP Addresses. 727 | .EXAMPLE 728 | Invoke an ARP Scan against a range of IPs specified in CIDR Format 729 | 730 | PS C:\> Invoke-ARPScan -CIDR 172.20.10.1/24 731 | 732 | MAC Address 733 | --- ------- 734 | 14:10:9F:D5:1A:BF 172.20.10.2 735 | 00:0C:29:93:10:B5 172.20.10.3 736 | 00:0C:29:93:10:B5 172.20.10.15 737 | #> 738 | function Invoke-ARPScan { 739 | 740 | param ( 741 | [Parameter(Mandatory=$true, 742 | ParameterSetName = "Range", 743 | ValueFromPipelineByPropertyName=$true, 744 | Position=0)] 745 | [string]$Range, 746 | 747 | [Parameter(Mandatory=$true, 748 | ParameterSetName = "CIDR", 749 | ValueFromPipelineByPropertyName=$true, 750 | Position=0)] 751 | [string]$CIDR, 752 | 753 | [Parameter(Mandatory=$false, 754 | ValueFromPipelineByPropertyName=$true, 755 | Position=0)] 756 | [string]$MaxThreads=50 757 | ) 758 | 759 | 760 | Begin 761 | { 762 | $sign = @" 763 | using System; 764 | using System.Collections.Generic; 765 | using System.Text; 766 | using System.Net; 767 | using System.Net.NetworkInformation; 768 | using System.Runtime.InteropServices; 769 | 770 | public static class NetUtils 771 | { 772 | [System.Runtime.InteropServices.DllImport("iphlpapi.dll", ExactSpelling = true)] 773 | static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref int PhyAddrLen); 774 | 775 | public static string GetMacAddress(String addr) 776 | { 777 | try 778 | { 779 | IPAddress IPaddr = IPAddress.Parse(addr); 780 | 781 | byte[] mac = new byte[6]; 782 | 783 | int L = 6; 784 | 785 | SendARP(BitConverter.ToInt32(IPaddr.GetAddressBytes(), 0), 0, mac, ref L); 786 | 787 | String macAddr = BitConverter.ToString(mac, 0, L); 788 | 789 | return (macAddr.Replace('-',':')); 790 | } 791 | 792 | catch (Exception ex) 793 | { 794 | return (ex.Message); 795 | } 796 | } 797 | } 798 | "@ 799 | try 800 | { 801 | Write-Verbose "Instanciating NetUtils" 802 | $IPHlp = Add-Type -TypeDefinition $sign -Language CSharp -PassThru 803 | } 804 | catch 805 | { 806 | Write-Verbose "NetUtils already instanciated" 807 | } 808 | 809 | # Manage if range is given 810 | if ($Range) 811 | { 812 | $rangeips = $Range.Split("-") 813 | $targets = New-IPv4Range -StartIP $rangeips[0] -EndIP $rangeips[1] 814 | } 815 | 816 | # Manage if CIDR is given 817 | if ($CIDR) 818 | { 819 | $targets = New-IPv4RangeFromCIDR -Network $CIDR 820 | } 821 | } 822 | Process 823 | { 824 | 825 | 826 | $scancode = { 827 | param($IPAddress,$IPHlp) 828 | $result = $IPHlp::GetMacAddress($IPAddress) 829 | if ($result) {New-Object psobject -Property @{Address = $IPAddress; MAC = $result}} 830 | } # end ScanCode var 831 | 832 | $jobs = @() 833 | 834 | 835 | 836 | $start = get-date 837 | write-verbose "Begin Scanning at $start" 838 | 839 | #Multithreading setup 840 | 841 | # create a pool of maxThread runspaces 842 | $pool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads) 843 | $pool.Open() 844 | 845 | $jobs = @() 846 | $ps = @() 847 | $wait = @() 848 | 849 | $i = 0 850 | 851 | # How many servers 852 | $record_count = $targets.Length 853 | 854 | #Loop through the endpoints starting a background job for each endpoint 855 | foreach ($IPAddress in $targets) 856 | { 857 | # Show Progress 858 | $record_progress = [int][Math]::Ceiling((($i / $record_count) * 100)) 859 | Write-Progress -Activity "Performing ARP Scan" -PercentComplete $record_progress -Status "Addresses Queried - $record_progress%" -Id 1; 860 | 861 | while ($($pool.GetAvailableRunspaces()) -le 0) 862 | { 863 | Start-Sleep -milliseconds 500 864 | } 865 | 866 | # create a "powershell pipeline runner" 867 | $ps += [powershell]::create() 868 | 869 | # assign our pool of 3 runspaces to use 870 | $ps[$i].runspacepool = $pool 871 | 872 | # command to run 873 | [void]$ps[$i].AddScript($scancode).AddParameter('IPaddress', $IPAddress).AddParameter('IPHlp', $IPHlp) 874 | #[void]$ps[$i].AddParameter() 875 | 876 | # start job 877 | $jobs += $ps[$i].BeginInvoke(); 878 | 879 | # store wait handles for WaitForAll call 880 | $wait += $jobs[$i].AsyncWaitHandle 881 | 882 | $i++ 883 | } 884 | 885 | write-verbose "Waiting for scanning threads to finish..." 886 | 887 | $waitTimeout = get-date 888 | 889 | while ($($jobs | ? {$_.IsCompleted -eq $false}).count -gt 0 -or $($($(get-date) - $waitTimeout).totalSeconds) -gt 60) 890 | { 891 | Start-Sleep -milliseconds 500 892 | } 893 | 894 | # end async call 895 | for ($y = 0; $y -lt $i; $y++) { 896 | 897 | try 898 | { 899 | # complete async job 900 | $ScanResults += $ps[$y].EndInvoke($jobs[$y]) 901 | 902 | } 903 | catch 904 | { 905 | 906 | write-warning "error: $_" 907 | } 908 | 909 | finally 910 | { 911 | $ps[$y].Dispose() 912 | } 913 | } 914 | 915 | $pool.Dispose() 916 | } 917 | 918 | end 919 | { 920 | $ScanResults 921 | } 922 | } 923 | 924 | 925 | <# 926 | .Synopsis 927 | Enumerates the DNS Servers used by a system 928 | .DESCRIPTION 929 | Enumerates the DNS Servers used by a system returning an IP Address .Net object for each. 930 | .EXAMPLE 931 | C:\> Get-SystemDNSServer 932 | 933 | 934 | Address : 16885952 935 | AddressFamily : InterNetwork 936 | ScopeId : 937 | IsIPv6Multicast : False 938 | IsIPv6LinkLocal : False 939 | IsIPv6SiteLocal : False 940 | IsIPv6Teredo : False 941 | IsIPv4MappedToIPv6 : False 942 | IPAddressToString : 192.168.1.1 943 | #> 944 | 945 | function Get-SystemDNSServer 946 | { 947 | $DNSServerAddresses = @() 948 | $interfaces = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() 949 | foreach($interface in $interfaces) 950 | { 951 | if($interface.OperationalStatus -eq "Up") 952 | { 953 | $DNSConfig = $interface.GetIPProperties().DnsAddresses 954 | if (!$DNSConfig.IsIPv6SiteLocal) 955 | { 956 | $DNSServerAddresses += $DNSConfig 957 | } 958 | } 959 | } 960 | $DNSServerAddresses 961 | } 962 | 963 | 964 | <# 965 | .Synopsis 966 | Enumerates common DNS SRV Records for a given domain. 967 | .DESCRIPTION 968 | Enumerates common DNS SRV Records for a given domain. 969 | .EXAMPLE 970 | PS C:\> Invoke-EnumSRVRecords -Domain microsoft.com 971 | 972 | 973 | Type : SRV 974 | Name : _sip._tls.microsoft.com 975 | Port : 443 976 | Priority : 0 977 | Target : sip.microsoft.com. 978 | Address : @{Name=sip.microsoft.com; Type=A; Address=65.55.30.130} 979 | 980 | Type : SRV 981 | Name : _sipfederationtls._tcp.microsoft.com 982 | Port : 5061 983 | Priority : 0 984 | Target : sipfed.microsoft.com. 985 | Address : @{Name=sipfed.microsoft.com; Type=A; Address=65.55.30.130} 986 | 987 | Type : SRV 988 | Name : _xmpp-server._tcp.microsoft.com 989 | Port : 5269 990 | Priority : 0 991 | Target : sipdog3.microsoft.com. 992 | Address : @{Name=sipdog3.microsoft.com; Type=A; Address=131.107.1.47} 993 | #> 994 | 995 | function Invoke-EnumSRVRecords 996 | { 997 | Param( 998 | [Parameter(Mandatory = $true)] 999 | [string]$Domain, 1000 | 1001 | [Parameter(Mandatory = $false)] 1002 | [string]$NameServer, 1003 | 1004 | [Parameter(Mandatory = $false)] 1005 | [int32]$TimeOut, 1006 | 1007 | [Parameter(Mandatory = $false)] 1008 | [int32]$Retries 1009 | ) 1010 | Begin 1011 | { 1012 | 1013 | # Records to test against 1014 | $srv_rcds = @('_gc._tcp.', '_kerberos._tcp.', '_kerberos._udp.', '_ldap._tcp.', 1015 | '_test._tcp.', '_sips._tcp.', '_sip._udp.', '_sip._tcp.', '_aix._tcp.', 1016 | '_aix._tcp.', '_finger._tcp.', '_ftp._tcp.', '_http._tcp.', '_nntp._tcp.', 1017 | '_telnet._tcp.', '_whois._tcp.', '_h323cs._tcp.', '_h323cs._udp.', 1018 | '_h323be._tcp.', '_h323be._udp.', '_h323ls._tcp.', '_https._tcp.', 1019 | '_h323ls._udp.', '_sipinternal._tcp.', '_sipinternaltls._tcp.', 1020 | '_sip._tls.', '_sipfederationtls._tcp.', '_jabber._tcp.', 1021 | '_xmpp-server._tcp.', '_xmpp-client._tcp.', '_imap.tcp.', 1022 | '_certificates._tcp.', '_crls._tcp.', '_pgpkeys._tcp.', 1023 | '_pgprevokations._tcp.', '_cmp._tcp.', '_svcp._tcp.', '_crl._tcp.', 1024 | '_ocsp._tcp.', '_PKIXREP._tcp.', '_smtp._tcp.', '_hkp._tcp.', 1025 | '_hkps._tcp.', '_jabber._udp.', '_xmpp-server._udp.', '_xmpp-client._udp.', 1026 | '_jabber-client._tcp.', '_jabber-client._udp.', '_kerberos.tcp.dc._msdcs.', 1027 | '_ldap._tcp.ForestDNSZones.', '_ldap._tcp.dc._msdcs.', '_ldap._tcp.pdc._msdcs.', 1028 | '_ldap._tcp.gc._msdcs.', '_kerberos._tcp.dc._msdcs.', '_kpasswd._tcp.', '_kpasswd._udp.', 1029 | '_imap._tcp.') 1030 | 1031 | $dnsopts = new-object JHSoftware.DnsClient+RequestOptions 1032 | # Set the NS Server if one givem 1033 | if ($nameserver) 1034 | { 1035 | try 1036 | { 1037 | # Check if what we got is an IP or a FQDN 1038 | $IPObj = [Net.IPAddress]::Parse($nameserver) 1039 | $IPCheck = [System.Net.IPAddress]::TryParse($nameserver,[ref]$IPObj) 1040 | if ($IPCheck) 1041 | { 1042 | $dns = [System.Net.IPAddress]$nameserver 1043 | $dnsopts.DnsServers += $dns 1044 | } 1045 | else 1046 | { 1047 | Write-Error "$nameserver is not a valid IP Address" 1048 | } 1049 | } 1050 | 1051 | catch 1052 | { 1053 | $nsip = [Net.Dns]::GetHostAddresses($nameserver)[0] 1054 | $dns = $nsip 1055 | $dnsopts.DnsServers += $dns 1056 | } 1057 | } 1058 | # Set the timeout 1059 | if ($TimeOut) 1060 | { 1061 | $dnsopts.TimeOut = New-TimeSpan -Seconds $TimeOut 1062 | } 1063 | 1064 | # Set Retries 1065 | if ($Retries) 1066 | { 1067 | $dnsopts.RetryCount = $Retries 1068 | } 1069 | # Collection of records found 1070 | $found = @() 1071 | } 1072 | 1073 | Process 1074 | { 1075 | $i = 0 1076 | $record_count = $srv_rcds.Length 1077 | foreach($srv in $srv_rcds) 1078 | { 1079 | $record_progress = [int][Math]::Ceiling((($i / $record_count) * 100)) 1080 | Write-Progress -Activity "Enumerating Common SRV Records" -PercentComplete $record_progress -Status "Records - $record_progress%" -Id 1; 1081 | $target = $srv+$domain 1082 | 1083 | try 1084 | { 1085 | $found += [JHSoftware.DnsClient]::Lookup($target,[JHSoftware.DnsClient+RecordType]::SRV,$dnsopts).AnswerRecords 1086 | } 1087 | catch 1088 | { 1089 | } 1090 | $i++ 1091 | } 1092 | foreach($recond in $found) 1093 | { 1094 | $data_info = $recond.Data.split(' ') 1095 | New-Object psobject -Property ([ordered]@{Type=$recond.Type; 1096 | Name =$recond.name; 1097 | Port=$data_info[2];Priority=$data_info[1]; 1098 | Target=$data_info[3] 1099 | Address = & { 1100 | if ($NameServer) 1101 | { 1102 | Resolve-HostRecord -Target $data_info[3] -NameServer $NameServer} 1103 | else 1104 | { 1105 | Resolve-HostRecord -Target $data_info[3] 1106 | } 1107 | } 1108 | }) 1109 | } 1110 | } 1111 | 1112 | } 1113 | 1114 | 1115 | <# 1116 | .Synopsis 1117 | Resolve a given FQDN 1118 | .DESCRIPTION 1119 | Resolves a given FQDN to its A, AAAA and CNAME record. 1120 | .EXAMPLE 1121 | 1122 | C:\> Resolve-HostRecord ipv6.google.com 1123 | 1124 | Name Type Address 1125 | ---- ---- ------- 1126 | ipv6.google.com CNAME ipv6.l.google.com. 1127 | ipv6.l.google.com AAAA 2607:f8b0:4002:c02::93 1128 | #> 1129 | 1130 | function Resolve-HostRecord 1131 | { 1132 | param( 1133 | [Parameter(Mandatory = $true)] 1134 | [string]$Target, 1135 | 1136 | [Parameter(Mandatory = $false)] 1137 | [string]$NameServer, 1138 | 1139 | [Parameter(Mandatory = $false)] 1140 | [int32]$TimeOut, 1141 | 1142 | [Parameter(Mandatory = $false)] 1143 | [int32]$Retries 1144 | ) 1145 | 1146 | begin 1147 | { 1148 | $dnsopts = new-object JHSoftware.DnsClient+RequestOptions 1149 | # Set the NS Server if one givem 1150 | if ($nameserver) 1151 | { 1152 | try 1153 | { 1154 | # Check if what we got is an IP or a FQDN 1155 | $IPObj = [Net.IPAddress]::Parse($nameserver) 1156 | $IPCheck = [System.Net.IPAddress]::TryParse($nameserver,[ref]$IPObj) 1157 | if ($IPCheck) 1158 | { 1159 | $dns = [System.Net.IPAddress]$nameserver 1160 | $dnsopts.DnsServers += $dns 1161 | } 1162 | else 1163 | { 1164 | Write-Error "$nameserver is not a valid IP Address" 1165 | } 1166 | } 1167 | 1168 | catch 1169 | { 1170 | $nsip = [Net.Dns]::GetHostAddresses($nameserver)[0] 1171 | $dns = $nsip 1172 | $dnsopts.DnsServers += $dns 1173 | } 1174 | } 1175 | # Set the timeout 1176 | if ($TimeOut) 1177 | { 1178 | $dnsopts.TimeOut = New-TimeSpan -Seconds $TimeOut 1179 | } 1180 | 1181 | # Set Retries 1182 | if ($Retries) 1183 | { 1184 | $dnsopts.RetryCount = $Retries 1185 | } 1186 | } 1187 | process 1188 | { 1189 | $ARecs = @() 1190 | # Resolve A Record 1191 | try 1192 | { 1193 | $answer = [JHSoftware.DnsClient]::Lookup($target,[JHSoftware.DnsClient+RecordType]::A,$dnsopts).AnswerRecords 1194 | foreach ($A in $answer) 1195 | { 1196 | $ARecs += Select-Object -InputObject $A -Property Name,Type,@{Name='Address';Expression={$A.Data}} 1197 | } 1198 | } 1199 | catch {} 1200 | try 1201 | { 1202 | # Resolve AAAA Recod 1203 | $answer = [JHSoftware.DnsClient]::Lookup($target,[JHSoftware.DnsClient+RecordType]::AAAA,$dnsopts).AnswerRecords 1204 | foreach ($AAAA in $answer) 1205 | { 1206 | $ARecs += Select-Object -InputObject $AAAA -Property Name,Type,@{Name='Address';Expression={$AAAA.Data}} 1207 | } 1208 | } 1209 | catch {} 1210 | } 1211 | 1212 | end 1213 | { 1214 | $ARecs 1215 | } 1216 | } 1217 | 1218 | 1219 | <# 1220 | .Synopsis 1221 | Query for specific DNS Records against a Nameserver 1222 | .DESCRIPTION 1223 | Query for specific DNS Records against a Nameserver 1224 | .EXAMPLE 1225 | C:\> Resolve-DNSRecord -Target microsoft.com -Type MX 1226 | 1227 | Name Type TTL Data 1228 | ---- ---- --- ---- 1229 | microsoft.com MX 1001 10 microsoft-com.m... 1230 | 1231 | .EXAMPLE 1232 | 1233 | C:\> Resolve-DNSRecord -Target microsoft.com -Type NS 1234 | 1235 | Name Type TTL Data 1236 | ---- ---- --- ---- 1237 | microsoft.com NS 14893 ns1.msft.net. 1238 | microsoft.com NS 14893 ns2.msft.net. 1239 | microsoft.com NS 14893 ns3.msft.net. 1240 | microsoft.com NS 14893 ns4.msft.net. 1241 | microsoft.com NS 14893 ns5.msft.net. 1242 | #> 1243 | 1244 | function Resolve-DNSRecord 1245 | { 1246 | param( 1247 | [Parameter(Mandatory = $true)] 1248 | [string]$Target, 1249 | 1250 | [Parameter(Mandatory = $false)] 1251 | [string]$NameServer, 1252 | 1253 | [Parameter(Mandatory = $false)] 1254 | [int32]$TimeOut, 1255 | 1256 | [Parameter(Mandatory = $false)] 1257 | [int32]$Retries, 1258 | 1259 | [string] 1260 | [ValidateSet('A','A6','AAAA','AFSDB','ANY','APL','ATMA','CERT','CNAME', 1261 | 'DHCID','DLV','DNAME','DNSKEY','DS','EID','GID','GPOS','HINFO', 1262 | 'HIP','IPSECKEY','ISDN','KEY','KX','LOC','MB','MD','MF','MG', 1263 | 'MINFO','MR','MX','NAPTR','NIMLOC','NS','NSAP','NSAPPTR','NSEC', 1264 | 'NSEC3','NSEC3PARAM','NULL','NXT','OPT','PTR','PX','RP','RRSIG', 1265 | 'RT','SRV','SINK','SIG','SOA','SPF','SSHFP','TA','TXT','UID', 1266 | 'UINFO','UNSPEC','WKS','X25')] 1267 | $Type 1268 | ) 1269 | 1270 | begin 1271 | { 1272 | $dnsopts = new-object JHSoftware.DnsClient+RequestOptions 1273 | # Set the NS Server if one givem 1274 | if ($nameserver) 1275 | { 1276 | try 1277 | { 1278 | # Check if what we got is an IP or a FQDN 1279 | $IPObj = [Net.IPAddress]::Parse($nameserver) 1280 | $IPCheck = [System.Net.IPAddress]::TryParse($nameserver,[ref]$IPObj) 1281 | if ($IPCheck) 1282 | { 1283 | $dns = [System.Net.IPAddress]$nameserver 1284 | $dnsopts.DnsServers += $dns 1285 | } 1286 | else 1287 | { 1288 | Write-Error "$nameserver is not a valid IP Address" 1289 | } 1290 | } 1291 | 1292 | catch 1293 | { 1294 | $nsip = [Net.Dns]::GetHostAddresses($nameserver)[0] 1295 | $dns = $nsip 1296 | $dnsopts.DnsServers += $dns 1297 | } 1298 | } 1299 | # Set the timeout 1300 | if ($TimeOut) 1301 | { 1302 | $dnsopts.TimeOut = New-TimeSpan -Seconds $TimeOut 1303 | } 1304 | 1305 | # Set Retries 1306 | if ($Retries) 1307 | { 1308 | $dnsopts.RetryCount = $Retries 1309 | } 1310 | 1311 | } 1312 | 1313 | process 1314 | { 1315 | # Resolve A Record 1316 | $answer = [JHSoftware.DnsClient]::Lookup($target,[JHSoftware.DnsClient+RecordType]::$Type,$dnsopts).AnswerRecords 1317 | foreach ($A in $answer) 1318 | { 1319 | $A 1320 | } 1321 | } 1322 | 1323 | end 1324 | { 1325 | } 1326 | } 1327 | 1328 | 1329 | <# 1330 | .Synopsis 1331 | Convert a string representation of an IPV4 IP to In-Addr-ARPA format. 1332 | .DESCRIPTION 1333 | Convert a string representation of an IPV4 IP to In-Addr-ARPA format for performing PTR Lookups. 1334 | .EXAMPLE 1335 | ConvertTo-InAddrARPA -IPAddress 192.168.1.10 1336 | 10.1.168.192.in-addr.arpa 1337 | 1338 | #> 1339 | function ConvertTo-InAddrARPA 1340 | { 1341 | [CmdletBinding()] 1342 | [OutputType([String])] 1343 | Param 1344 | ( 1345 | # Param1 help description 1346 | [Parameter(Mandatory=$true, 1347 | ValueFromPipeline=$true, 1348 | ValueFromPipelineByPropertyName=$true, 1349 | ValueFromRemainingArguments=$false, 1350 | Position=0)] 1351 | [ValidateNotNull()] 1352 | [ValidateNotNullOrEmpty()] 1353 | [Alias("IP")] 1354 | $IPAddress 1355 | ) 1356 | 1357 | Begin 1358 | { 1359 | } 1360 | Process 1361 | { 1362 | try 1363 | { 1364 | $IPObj = [System.Net.IPAddress]::Parse($IPAddress) 1365 | $ipIpaddressSplit = $IPAddress.Split(".") 1366 | "$($ipIpaddressSplit.GetValue(3)).$($ipIpaddressSplit.GetValue(2)).$($ipIpaddressSplit.GetValue(1)).$($ipIpaddressSplit.GetValue(0)).in-addr.arpa" 1367 | } 1368 | catch 1369 | { 1370 | Write-Host "Value provided is not an IP Address" 1371 | } 1372 | } 1373 | End 1374 | { 1375 | } 1376 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | License: BSD-3-clause 2 | Redistribution and use in source and binary forms, with or without modification, 3 | are permitted provided that the following conditions are met: 4 | . 5 | * Redistributions of source code must retain the above copyright notice, 6 | this list of conditions and the following disclaimer. 7 | . 8 | * Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | . 12 | * Neither the name of the author nor the names of its contributors 13 | may be used to endorse or promote products derived from this software 14 | without specific prior written permission. 15 | . 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | 28 | License: GPL-2 29 | This program is free software; you can redistribute it 30 | and/or modify it under the terms of the GNU General Public 31 | License as published by the Free Software Foundation; either 32 | version 2 of the License, or (at your option) any later 33 | version. 34 | . 35 | This program is distributed in the hope that it will be 36 | useful, but WITHOUT ANY WARRANTY; without even the implied 37 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 38 | PURPOSE. See the GNU General Public License for more 39 | details. 40 | . 41 | You should have received a copy of the GNU General Public 42 | License along with this package; if not, write to the Free 43 | Software Foundation, Inc., 51 Franklin St, Fifth Floor, 44 | Boston, MA 02110-1301 USA 45 | . 46 | On Debian systems, the full text of the GNU General Public 47 | License version 2 can be found in the file 48 | `/usr/share/common-licenses/GPL-2'. 49 | 50 | 51 | 52 | License: Apache 53 | Version 2.0, January 2004 54 | http://www.apache.org/licenses/ 55 | . 56 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 57 | . 58 | 1. Definitions. 59 | . 60 | "License" shall mean the terms and conditions for use, reproduction, 61 | and distribution as defined by Sections 1 through 9 of this document. 62 | . 63 | "Licensor" shall mean the copyright owner or entity authorized by 64 | the copyright owner that is granting the License. 65 | . 66 | "Legal Entity" shall mean the union of the acting entity and all 67 | other entities that control, are controlled by, or are under common 68 | control with that entity. For the purposes of this definition, 69 | "control" means (i) the power, direct or indirect, to cause the 70 | direction or management of such entity, whether by contract or 71 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 72 | outstanding shares, or (iii) beneficial ownership of such entity. 73 | . 74 | "You" (or "Your") shall mean an individual or Legal Entity 75 | exercising permissions granted by this License. 76 | . 77 | "Source" form shall mean the preferred form for making modifications, 78 | including but not limited to software source code, documentation 79 | source, and configuration files. 80 | . 81 | "Object" form shall mean any form resulting from mechanical 82 | transformation or translation of a Source form, including but 83 | not limited to compiled object code, generated documentation, 84 | and conversions to other media types. 85 | . 86 | "Work" shall mean the work of authorship, whether in Source or 87 | Object form, made available under the License, as indicated by a 88 | copyright notice that is included in or attached to the work 89 | (an example is provided in the Appendix below). 90 | . 91 | "Derivative Works" shall mean any work, whether in Source or Object 92 | form, that is based on (or derived from) the Work and for which the 93 | editorial revisions, annotations, elaborations, or other modifications 94 | represent, as a whole, an original work of authorship. For the purposes 95 | of this License, Derivative Works shall not include works that remain 96 | separable from, or merely link (or bind by name) to the interfaces of, 97 | the Work and Derivative Works thereof. 98 | . 99 | "Contribution" shall mean any work of authorship, including 100 | the original version of the Work and any modifications or additions 101 | to that Work or Derivative Works thereof, that is intentionally 102 | submitted to Licensor for inclusion in the Work by the copyright owner 103 | or by an individual or Legal Entity authorized to submit on behalf of 104 | the copyright owner. For the purposes of this definition, "submitted" 105 | means any form of electronic, verbal, or written communication sent 106 | to the Licensor or its representatives, including but not limited to 107 | communication on electronic mailing lists, source code control systems, 108 | and issue tracking systems that are managed by, or on behalf of, the 109 | Licensor for the purpose of discussing and improving the Work, but 110 | excluding communication that is conspicuously marked or otherwise 111 | designated in writing by the copyright owner as "Not a Contribution." 112 | . 113 | "Contributor" shall mean Licensor and any individual or Legal Entity 114 | on behalf of whom a Contribution has been received by Licensor and 115 | subsequently incorporated within the Work. 116 | . 117 | 2. Grant of Copyright License. Subject to the terms and conditions of 118 | this License, each Contributor hereby grants to You a perpetual, 119 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 120 | copyright license to reproduce, prepare Derivative Works of, 121 | publicly display, publicly perform, sublicense, and distribute the 122 | Work and such Derivative Works in Source or Object form. 123 | . 124 | 3. Grant of Patent License. Subject to the terms and conditions of 125 | this License, each Contributor hereby grants to You a perpetual, 126 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 127 | (except as stated in this section) patent license to make, have made, 128 | use, offer to sell, sell, import, and otherwise transfer the Work, 129 | where such license applies only to those patent claims licensable 130 | by such Contributor that are necessarily infringed by their 131 | Contribution(s) alone or by combination of their Contribution(s) 132 | with the Work to which such Contribution(s) was submitted. If You 133 | institute patent litigation against any entity (including a 134 | cross-claim or counterclaim in a lawsuit) alleging that the Work 135 | or a Contribution incorporated within the Work constitutes direct 136 | or contributory patent infringement, then any patent licenses 137 | granted to You under this License for that Work shall terminate 138 | as of the date such litigation is filed. 139 | . 140 | 4. Redistribution. You may reproduce and distribute copies of the 141 | Work or Derivative Works thereof in any medium, with or without 142 | modifications, and in Source or Object form, provided that You 143 | meet the following conditions: 144 | . 145 | (a) You must give any other recipients of the Work or 146 | Derivative Works a copy of this License; and 147 | . 148 | (b) You must cause any modified files to carry prominent notices 149 | stating that You changed the files; and 150 | . 151 | (c) You must retain, in the Source form of any Derivative Works 152 | that You distribute, all copyright, patent, trademark, and 153 | attribution notices from the Source form of the Work, 154 | excluding those notices that do not pertain to any part of 155 | the Derivative Works; and 156 | . 157 | (d) If the Work includes a "NOTICE" text file as part of its 158 | distribution, then any Derivative Works that You distribute must 159 | include a readable copy of the attribution notices contained 160 | within such NOTICE file, excluding those notices that do not 161 | pertain to any part of the Derivative Works, in at least one 162 | of the following places: within a NOTICE text file distributed 163 | as part of the Derivative Works; within the Source form or 164 | documentation, if provided along with the Derivative Works; or, 165 | within a display generated by the Derivative Works, if and 166 | wherever such third-party notices normally appear. The contents 167 | of the NOTICE file are for informational purposes only and 168 | do not modify the License. You may add Your own attribution 169 | notices within Derivative Works that You distribute, alongside 170 | or as an addendum to the NOTICE text from the Work, provided 171 | that such additional attribution notices cannot be construed 172 | as modifying the License. 173 | . 174 | You may add Your own copyright statement to Your modifications and 175 | may provide additional or different license terms and conditions 176 | for use, reproduction, or distribution of Your modifications, or 177 | for any such Derivative Works as a whole, provided Your use, 178 | reproduction, and distribution of the Work otherwise complies with 179 | the conditions stated in this License. 180 | . 181 | 5. Submission of Contributions. Unless You explicitly state otherwise, 182 | any Contribution intentionally submitted for inclusion in the Work 183 | by You to the Licensor shall be under the terms and conditions of 184 | this License, without any additional terms or conditions. 185 | Notwithstanding the above, nothing herein shall supersede or modify 186 | the terms of any separate license agreement you may have executed 187 | with Licensor regarding such Contributions. 188 | . 189 | 6. Trademarks. This License does not grant permission to use the trade 190 | names, trademarks, service marks, or product names of the Licensor, 191 | except as required for reasonable and customary use in describing the 192 | origin of the Work and reproducing the content of the NOTICE file. 193 | . 194 | 7. Disclaimer of Warranty. Unless required by applicable law or 195 | agreed to in writing, Licensor provides the Work (and each 196 | Contributor provides its Contributions) on an "AS IS" BASIS, 197 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 198 | implied, including, without limitation, any warranties or conditions 199 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 200 | PARTICULAR PURPOSE. You are solely responsible for determining the 201 | appropriateness of using or redistributing the Work and assume any 202 | risks associated with Your exercise of permissions under this License. 203 | . 204 | 8. Limitation of Liability. In no event and under no legal theory, 205 | whether in tort (including negligence), contract, or otherwise, 206 | unless required by applicable law (such as deliberate and grossly 207 | negligent acts) or agreed to in writing, shall any Contributor be 208 | liable to You for damages, including any direct, indirect, special, 209 | incidental, or consequential damages of any character arising as a 210 | result of this License or out of the use or inability to use the 211 | Work (including but not limited to damages for loss of goodwill, 212 | work stoppage, computer failure or malfunction, or any and all 213 | other commercial damages or losses), even if such Contributor 214 | has been advised of the possibility of such damages. 215 | . 216 | 9. Accepting Warranty or Additional Liability. While redistributing 217 | the Work or Derivative Works thereof, You may choose to offer, 218 | and charge a fee for, acceptance of support, warranty, indemnity, 219 | or other liability obligations and/or rights consistent with this 220 | License. However, in accepting such obligations, You may act only 221 | on Your own behalf and on Your sole responsibility, not on behalf 222 | of any other Contributor, and only if You agree to indemnify, 223 | defend, and hold each Contributor harmless for any liability 224 | incurred by, or claims asserted against, such Contributor by reason 225 | of your accepting any such warranty or additional liability. 226 | . 227 | END OF TERMS AND CONDITIONS 228 | . 229 | APPENDIX: How to apply the Apache License to your work. 230 | . 231 | To apply the Apache License to your work, attach the following 232 | boilerplate notice, with the fields enclosed by brackets "[]" 233 | replaced with your own identifying information. (Don't include 234 | the brackets!) The text should be enclosed in the appropriate 235 | comment syntax for the file format. We also recommend that a 236 | file or class name and description of purpose be included on the 237 | same "printed page" as the copyright notice for easier 238 | identification within third-party archives. 239 | . 240 | Copyright [yyyy] [name of copyright owner] 241 | . 242 | Licensed under the Apache License, Version 2.0 (the "License"); 243 | you may not use this file except in compliance with the License. 244 | You may obtain a copy of the License at 245 | . 246 | http://www.apache.org/licenses/LICENSE-2.0 247 | . 248 | Unless required by applicable law or agreed to in writing, software 249 | distributed under the License is distributed on an "AS IS" BASIS, 250 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 251 | See the License for the specific language governing permissions and 252 | limitations under the License. -------------------------------------------------------------------------------- /Parse/Parse.psm1: -------------------------------------------------------------------------------- 1 |  2 | <# 3 | .Synopsis 4 | Imports an Nmap XML Scan Repot 5 | .DESCRIPTION 6 | Imports an Nmap XML report and returns a collection of objects 7 | representing the scan information in the XML report. 8 | .EXAMPLE 9 | Get Scan information 10 | 11 | PS C:\> Import-NmapXML -NmapXML $env:HOMEPATH\DEsktop\labscan.xml 12 | 13 | 14 | NmapVersion : 6.25 15 | Command : nmap -p 1-65535 -T4 -A -v -Pn 192.168.10.1-200 16 | StartTime : 4/12/2013 9:06:19 PM 17 | EndTime : 4/12/2013 9:14:14 PM 18 | RunTime : 19 | ScanType : syn 20 | ScanProtocol : tcp 21 | NumberofServices : 65535 22 | Services : 1-65535 23 | DebugLevel : 0 24 | VerboseLevel : 1 25 | Summary : 26 | ExitStatus : 27 | 28 | .EXAMPLE 29 | Show IPv4 Addresses of hosts with port 139 TCP Open 30 | 31 | PS C:\> $nmaphosts = Import-NmapXML -NmapXML $env:HOMEPATH\DEsktop\labscan.xml -InfoType Hosts 32 | PS C:\> $nmaphosts | where {$_.opentcp -contains 139} | select ipv4address 33 | 34 | IPv4Address 35 | ----------- 36 | 192.168.10.2 37 | 192.168.10.10 38 | 192.168.10.12 39 | 192.168.10.13 40 | 41 | #> 42 | function Import-NmapXML 43 | { 44 | [CmdletBinding()] 45 | Param 46 | ( 47 | # Nmap XML output file. 48 | [Parameter(Mandatory=$true, 49 | ValueFromPipelineByPropertyName=$true, 50 | Position=0, 51 | ParameterSetName = "File")] 52 | [ValidateScript({Test-Path $_})] 53 | $NmapXML, 54 | 55 | # XML Object containing Nmap XML information 56 | [Parameter(Mandatory=$true, 57 | ValueFromPipelineByPropertyName=$true, 58 | Position=0, 59 | ParameterSetName = "XMLDoc")] 60 | [xml]$InputObject, 61 | 62 | # Type of Information to return. Accepts ScanInfo and Hosts. 63 | [Parameter(Mandatory=$false, 64 | ValueFromPipelineByPropertyName=$true, 65 | Position=1)] 66 | [ValidateSet("ScanInfo","Hosts")] 67 | $InfoType = "ScanInfo" 68 | ) 69 | 70 | Begin 71 | { 72 | } 73 | Process 74 | { 75 | if ($NmapXML) 76 | { 77 | $file = Get-ChildItem $NmapXML 78 | [xml]$nmap = [System.IO.File]::ReadAllText($file.FullName) 79 | } 80 | else 81 | { 82 | [xml]$nmap = $InputObject 83 | } 84 | 85 | if ($InfoType -eq "ScanInfo") 86 | { 87 | # Format string for date 88 | $datefrmtstr = "ddd MMM dd HH:mm:ss yyyy" 89 | $scanstart = $nmap.nmaprun.startstr 90 | $scanend = $nmap.nmaprun.runstats.finished.timestr 91 | 92 | 93 | $ScanInfoProperties = [ordered]@{ 94 | NmapVersion = $nmap.nmaprun.version 95 | Command = $nmap.nmaprun.args 96 | StartTime = [datetime]::ParseExact($scanstart,$datefrmtstr,$null) 97 | EndTime = [datetime]::ParseExact($scanend,$datefrmtstr,$null) 98 | RunTime = $nmap.nmaprun.runstats.finished.elapsed 99 | ScanType = $nmap.nmaprun.scaninfo.type 100 | ScanProtocol = $nmap.nmaprun.scaninfo.protocol 101 | NumberofServices = $nmap.nmaprun.scaninfo.numservices 102 | Services = $nmap.nmaprun.scaninfo.services 103 | DebugLevel = $nmap.nmaprun.debugging.level 104 | VerboseLevel = $nmap.nmaprun.verbose.level 105 | Summary = $nmap.nmaprun.runstats.finished.summary 106 | ExitStatus = $nmap.nmaprun.runstats.finished.exit 107 | } 108 | [pscustomobject]$ScanInfoProperties 109 | 110 | } 111 | elseif ($InfoType -eq "Hosts") 112 | { 113 | # Returns epoch time so we need to tranform it 114 | $origin = New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0 115 | 116 | $discoveredhosts = $nmap.nmaprun.host | Where-Object {$_.status.state -eq "up"} 117 | foreach($dischost in $discoveredhosts) 118 | { 119 | # Set host addresses 120 | $macaddr = $dischost.address | ForEach-Object {if($_.addrtype -eq "mac"){$_.addr}} 121 | $ipv4addr = $dischost.address | ForEach-Object {if($_.addrtype -eq "ipv4"){$_.addr}} 122 | $ipv6addr = $dischost.address | ForEach-Object {if($_.addrtype -eq "ipv6"){$_.addr}} 123 | 124 | # Hostsnames detected and type 125 | $hostnames = @() 126 | foreach($hostname in $dischost.hostnames.childnodes) 127 | { 128 | $hostnmae_props = [ordered]@{ 129 | Name = $hostname.name 130 | Type = $hostname.type 131 | } 132 | $hostnameobj = [pscustomobject]$hostnmae_props 133 | $hostnameobj.pstypenames.insert(0,'Nmap.Host.Hostname') 134 | $hostnames += $hostnameobj 135 | } 136 | 137 | # Traceroute information for the specific host 138 | $hops = @() 139 | foreach($hop in $dischost.trace.hop) 140 | { 141 | $hopobj = [pscustomobject][ordered]@{ 142 | rtt = $hop.rtt 143 | ttl = $hop.ttl 144 | Host = $hop.host 145 | IPAddress = $hop.ipaddr 146 | } 147 | $hopobj.pstypenames.insert(0,'Nmap.Host.Trace.Hop') 148 | $hops += $hopobj 149 | } 150 | 151 | $traceprop = [ordered]@{ 152 | Port = $dischost.trace.port 153 | Protocol = $dischost.trace.proto 154 | Hops = $hops 155 | } 156 | $traceobj = [pscustomobject]$traceprop 157 | $traceobj.pstypenames.insert(0,'Nmap.Host.Trace') 158 | 159 | # OS information on host 160 | $OSName = $dischost.os.osmatch.name 161 | $Accuracy = $dischost.os.osmatch.accuracy 162 | $OSDBLine = $dischost.os.osmatch.line 163 | $osclass = @() 164 | foreach($class in $dischost.os.osmatch.osclass){ 165 | $osclassobj = [pscustomobject][ordered]@{ 166 | Type = $class.type 167 | Vendor = $class.vendor 168 | OSFamily = $class.osfamily 169 | OSGeneration = $class.osgen 170 | Accuracy = $class.accuracy 171 | } 172 | $osclassobj.pstypenames.insert(0,'Nmap.Host.OS.OSMatch.Class') 173 | $osclass += $osclassobj 174 | } 175 | 176 | $portsused = @() 177 | foreach($portuse in $dischost.os.portused) 178 | { 179 | $portusedobj = [pscustomobject]@{ 180 | State = $portuse.state 181 | PortNumber = $portuse.portid 182 | Protocol = $portuse.proto 183 | } 184 | } 185 | 186 | # Port information for hosts 187 | $ports = @() 188 | $OpenTCP = @() 189 | $OpenUDP = @() 190 | foreach($port in $dischost.ports.port) 191 | { 192 | # Port Scripts if any ran 193 | $scripts = @() 194 | if ($port.script) 195 | { 196 | foreach($script in $port.script) 197 | { 198 | $scripts += [pscustomobject][ordered]@{ 199 | ScriptName = $script.id 200 | ScriptOutput = $script.output 201 | } 202 | } 203 | } 204 | 205 | # port details 206 | 207 | # Collect simple lists of open ports for easier parsing 208 | if (($port.protocol -eq "tcp") -and ($port.state.state -eq "open")) 209 | { 210 | $OpenTCP += $port.portid 211 | } 212 | 213 | if (($port.protocol -eq "udp") -and ($port.state.state -eq "open")) 214 | { 215 | $OpenUDP += $port.portid 216 | } 217 | 218 | $portobj = [pscustomobject][ordered]@{ 219 | PortNumber = $port.portid 220 | Protocol = $port.protocol 221 | PortState = $port.state.state 222 | Reason = $port.state.reason 223 | Scripts = if ($scripts.count -gt 0){$scripts}else{$null} 224 | Service = [pscustomobject][ordered]@{ 225 | ServiceName = $port.service.name 226 | Product = $port.service.product 227 | OSType = $port.service.ostype 228 | Conf = $port.service.conf 229 | Extrainfo = $port.service.extrainfo 230 | Method = $port.service.method 231 | CPE = $port.service.cpe 232 | Tunnel = $port.service.tunnel 233 | RPCNumber = $port.service.rpcnum 234 | LowVersion = $port.service.lowver 235 | HighVersion = $port.service.highver 236 | Hostname = $port.service.hostname 237 | ServiceFP = $port.service.servicefp 238 | DeviceType = $port.service.devicetype 239 | } 240 | } 241 | $portobj.pstypenames.insert(0,'Nmap.Host.Port') 242 | $ports += $portobj 243 | } 244 | 245 | # Hosts scripts 246 | $hostscripts = @() 247 | $prescripts = @() 248 | $postscripts = @() 249 | 250 | if ($dischost.hostscript) 251 | { 252 | foreach($hostscript in $dischost.hostscript.script) 253 | { 254 | $hostscripts += [pscustomobject]@{ 255 | ScriptName = $hostscript.id 256 | ScriptOutput = $hostscript.output 257 | } 258 | } 259 | } 260 | 261 | if ($dischost.prescript) 262 | { 263 | foreach($prescript in $dischost.prescript.script) 264 | { 265 | $prescripts += [pscustomobject]@{ 266 | ScriptName = $prescript.id 267 | ScriptOutput = $prescript.output 268 | } 269 | } 270 | } 271 | 272 | if ($dischost.postscript) 273 | { 274 | foreach($postscript in $dischost.postscript.script) 275 | { 276 | $postscripts += [pscustomobject]@{ 277 | ScriptName = $postscript.id 278 | ScriptOutput = $postscript.output 279 | } 280 | } 281 | } 282 | 283 | $hostprops = [ordered]@{ 284 | ScanStartTime = $origin.AddSeconds($dischost.starttime).ToLocalTime() 285 | ScanEndTime = $origin.AddSeconds($dischost.endtime).ToLocalTime() 286 | Status = $dischost.status 287 | MacAddress = $macaddr 288 | IPv4Address = $ipv4addr 289 | IPv6Address = $ipv6addr 290 | HostNames = $hostnames 291 | Smurf = $dischost.smurf.responses 292 | Distance = $dischost.distance.value 293 | Trace = $traceobj 294 | Ports = $ports 295 | OpenTCP = $OpenTCP 296 | OpenUDP = $OpenUDP 297 | HostScript = $hostscripts 298 | PreScript = $prescripts 299 | PostScript = $postscripts 300 | OSFingerprint = $osclass 301 | } 302 | [pscustomobject]$hostprops 303 | } 304 | } 305 | } 306 | End 307 | { 308 | } 309 | } 310 | 311 | <# 312 | .Synopsis 313 | Converts object properties in a DNSRecon XML output file in to objects. 314 | 315 | .DESCRIPTION 316 | The Import-DNSReconXML cmdlet creates objects from XML files that are generated by DNSRecon DNS Enumeration tool. 317 | 318 | .EXAMPLE 319 | Returns all records in the XML file 320 | 321 | .EXAMPLE 322 | Returns the objects for Service Records 323 | 324 | Import-DNSReconXML .\output.xml -Filter SRV 325 | 326 | .EXAMPLE 327 | Returns the objects for A, AAAA and PTR Records 328 | 329 | Import-DNSReconXML .\output.xml -Filter A,AAAA,PTR 330 | #> 331 | function Import-DNSReconXML 332 | { 333 | [CmdletBinding()] 334 | Param 335 | ( 336 | # XML File generated by DNSRecon 337 | [Parameter(Mandatory=$true, 338 | ValueFromPipelineByPropertyName=$true, 339 | Position=0)] 340 | [ValidateScript({Test-Path $_})] 341 | $XMLFile, 342 | 343 | # DNS RR Records to query for. Accpets A, AAAA, NS, TXT, SPF, MX, SOA, SRV and PTR 344 | [Parameter(Mandatory=$false, 345 | ValueFromPipelineByPropertyName=$true, 346 | Position=1)] 347 | [ValidateSet("A","AAAA","NS","TXT","SPF","MX","SOA","SRV","PTR")] 348 | $Filter 349 | ) 350 | 351 | Begin 352 | { 353 | [Array]$dnsrecords = @() 354 | if ($Filter -eq $null) 355 | { 356 | $Filter = "A","AAAA","NS","TXT","SPF","MX","SOA","SRV","PTR" 357 | } 358 | 359 | $file = Get-ChildItem $XMLFile 360 | [xml]$dnsr = [System.IO.File]::ReadAllText($file.FullName) 361 | } 362 | Process 363 | { 364 | # How many servers 365 | $record_count = $dnsr.records.record.Length 366 | # processed server count 367 | $i = 0; 368 | # Parse each record 369 | foreach ($record in $dnsr.records.record) { 370 | $record_progress = [int][Math]::Ceiling((($i / $record_count) * 100)) 371 | Write-Progress -Activity "Processing XML" -PercentComplete $record_progress -Status "Processing records - $record_progress%" -Id 1; 372 | 373 | if ($Filter -contains $record.type) { 374 | 375 | # Check each of the record types 376 | switch -Regex ($record.type) 377 | { 378 | # Parse SRV records 379 | "SRV" 380 | { 381 | $DNSRObject = New-Object PSObject -Property @{ 382 | Type = $record.type 383 | Name = $record.name 384 | Target = $record.target 385 | Address = $record.address 386 | Port = $record.port 387 | ZoneTransfer = $record.zone_server 388 | Text = $null 389 | } 390 | 391 | $dnsrecords += $DNSRObject 392 | } 393 | 394 | # Parse NS records 395 | "NS" 396 | { 397 | $DNSRObject = New-Object PSObject -Property @{ 398 | Type = $record.type 399 | Name = $record.target 400 | Target = $null 401 | Address = $record.address 402 | Port = $null 403 | ZoneTransfer = $record.zone_server 404 | Text = $null 405 | } 406 | 407 | $dnsrecords += $DNSRObject 408 | } 409 | 410 | # Parse AAAA, A and PTR records 411 | "AAAA|A|PTR" 412 | { 413 | $DNSRObject = New-Object PSObject -Property @{ 414 | Type = $record.type 415 | Name = $record.name 416 | Target = $record.target 417 | Address = $record.address 418 | Port = $record.port 419 | ZoneTransfer = $record.zone_server 420 | Text = $null 421 | } 422 | 423 | $dnsrecords += $DNSRObject 424 | } 425 | 426 | # Parse MX records 427 | "MX" 428 | { 429 | $DNSRObject = New-Object PSObject -Property @{ 430 | Type = $record.type 431 | Name = $record.exchange 432 | Target = $null 433 | Address = $record.address 434 | Port = $record.port 435 | ZoneTransfer = $record.zone_server 436 | Text = $null 437 | } 438 | 439 | $dnsrecords += $DNSRObject 440 | } 441 | 442 | # Parse SOA records 443 | "SOA" 444 | { 445 | $DNSRObject = New-Object PSObject -Property @{ 446 | Type = $record.type 447 | Name = $record.mname 448 | Target = $null 449 | Address = $record.address 450 | Port = $record.port 451 | ZoneTransfer = $record.zone_server 452 | Text = $null 453 | } 454 | 455 | $dnsrecords += $DNSRObject 456 | } 457 | 458 | "TXT|SPF" 459 | { 460 | $DNSRObject = New-Object PSObject -Property @{ 461 | Type = $record.type 462 | Name = $record.mname 463 | Target = $record.target 464 | Address = $null 465 | Port = $null 466 | ZoneTransfer = $record.zone_server 467 | Text = $record.text 468 | } 469 | 470 | $dnsrecords += $DNSRObject 471 | } 472 | } 473 | } 474 | $i++ 475 | } 476 | } 477 | End 478 | { 479 | $dnsrecords 480 | } 481 | } 482 | -------------------------------------------------------------------------------- /Posh-SecMod.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darkoperator/Posh-SecMod/a4b7f5039c98ed270e5d20c1081d44b5a387e3c2/Posh-SecMod.psd1 -------------------------------------------------------------------------------- /Posh-SecMod.psm1: -------------------------------------------------------------------------------- 1 |  2 | function Get-LogDateString 3 | { 4 | (get-date).toString(‘yyyyMMddhhmm’) 5 | } 6 | 7 | function Confirm-IsAdmin 8 | { 9 | <# 10 | .Synopsis 11 | Checks if current PowerShell Session is running with administrative privelages. 12 | .DESCRIPTION 13 | Checks if current PowerShell Session is running with administrative privelages 14 | .EXAMPLE 15 | Return True or False if curremt PowerShell session is running with adminitratibe privelages. 16 | PS c:\> Confirm-IsAdmin 17 | True 18 | #> 19 | $sign = @" 20 | using System; 21 | using System.Runtime.InteropServices; 22 | public static class priv 23 | { 24 | [DllImport("shell32.dll")] 25 | public static extern bool IsUserAnAdmin(); 26 | } 27 | 28 | "@ 29 | 30 | $adminasembly = Add-Type -TypeDefinition $sign -Language CSharp -PassThru 31 | 32 | return [priv]::IsUserAnAdmin() 33 | } 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Posh-SecModule 2 | 3 | This module is a PowerShell v3 only module at the moment. The module is a collection of functions that I have found usefull in my day to day work as a security professional. The functions are broken in to functionality: 4 | 5 | - Discovery: Perform network discovery. 6 | - Parse: Parsers for Nmap, DNSRecon and other type of output files from security tools. 7 | - PostExploitation: Functions to help in performing post exploitation tasks. 8 | - Registry: Collection of functions for manipulating the registry in remote hosts using WMI. 9 | - Utilities: General purpose functions. 10 | - Audit: Functions that may be usful when performing audits of systems. 11 | - Database: Functions that are useful when interacting with databases. 12 | 13 | ## ChangeLog 14 | 15 | ### Version 1.3 16 | 17 | Moved Nessus, Shodan, VirusTotal and Metasploit modules to individual ones for easier maintenance and update. 18 | 19 | ### Version 1.2 20 | 21 | - Added Shodan submodule 22 | - Added VirusTotal submodule 23 | - Added Metasploit submodule 24 | - BugFixes 25 | - Added new fuctions in audit that work in WinPE for performing incident response and auditing (Disk MSFT Time, ADSI functions) 26 | 27 | 28 | ## Licensing 29 | 30 | The functions I have written are BSD 3-Clause Licensed. The other files I used for the project are licensed as follows: 31 | 32 | - NessusSharp and Metasploit-Sharp libraries from Brandon Perry from: https://github.com/brandonprry are BSD 3-Clause Licensed. 33 | 34 | - SQlite Libraries provided by the SQLite Projects these libraries are GPL2 licensed libraries. 35 | 36 | - ARSoft.Tools.Net that is licensed ad Apache License 2.0 (Apache) http://arsofttoolsnet.codeplex.com/ 37 | 38 | - Whois Library from http://coderbuddy.wordpress.com/ under the GPL2 License 39 | 40 | ## Installation Instrcutions 41 | 42 | To install the module from a PowerShell v3 session run: 43 |
44 | iex (New-Object Net.WebClient).DownloadString("https://gist.github.com/darkoperator/6404266/raw/982cae410fc41f6c64e69d91fc3dda777554f241/gistfile1.ps1")
45 | 
46 | -------------------------------------------------------------------------------- /Registry/Registry.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Enumerates the keys that are under a given Registry Key. 4 | .DESCRIPTION 5 | Enumerates the keys that are under a given Registry Key. 6 | .EXAMPLE 7 | Listing all of the keys under HKCU\Software key 8 | PS C:\> Get-RegKeys -Hive HKCU -Key software 9 | 10 | Key FullPath 11 | --- -------- 12 | 7-Zip HKCU\software\7-Zip 13 | AppDataLow HKCU\software\AppDataLow 14 | Macromedia HKCU\software\Macromedia 15 | Microsoft HKCU\software\Microsoft 16 | Microsoft Corporation HKCU\software\Microsoft Corporation 17 | Mine HKCU\software\Mine 18 | Policies HKCU\software\Policies 19 | RegisteredApplications HKCU\software\RegisteredApplications 20 | ThinPrint HKCU\software\ThinPrint 21 | VMware, Inc. HKCU\software\VMware, Inc. 22 | Wow6432Node HKCU\software\Wow6432Node 23 | Classes HKCU\software\Classes 24 | #> 25 | function Get-RegKeys 26 | { 27 | [CmdletBinding()] 28 | Param 29 | ( 30 | [parameter(Mandatory=$true)] 31 | [string] 32 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 33 | $Hive, 34 | 35 | [parameter(Mandatory=$true)] 36 | [AllowEmptyString()] 37 | [string]$Key, 38 | 39 | [parameter(ValueFromPipeline=$true, 40 | ValueFromPipelineByPropertyName=$true)] 41 | [string]$Computername="$env:COMPUTERNAME", 42 | 43 | [Parameter(Mandatory=$false)] 44 | [System.Management.Automation.PSCredential] 45 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 46 | ) 47 | 48 | Begin 49 | { 50 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 51 | } 52 | Process 53 | { 54 | # We get the correct value associated with the key. 55 | switch ($hive) 56 | { 57 | "HKCR" {$reg_hive = 2147483648} 58 | "HKCU" {$reg_hive = 2147483649} 59 | "HKLM" {$reg_hive = 2147483650} 60 | "HKUS" {$reg_hive = 2147483651} 61 | "HKCC" {$reg_hive = 2147483653} 62 | } 63 | 64 | $data = $reg.EnumKey($reg_hive, $key) 65 | if ($data.ReturnValue -eq 0) 66 | { 67 | $keynum = ($data.snames).Length 68 | if ($keynum -gt 0) 69 | { 70 | foreach($keyname in $data.snames) 71 | { 72 | New-Object PSObject -Property @{Key=$keyname;FullPath = "$hive\$key\$keyname"} 73 | } 74 | } 75 | else 76 | { 77 | Write-Verbose "Key $key does not have any keys to enumerate" 78 | } 79 | } 80 | elseif ($data.ReturnValue -eq 2) 81 | { 82 | Write-Error "Key $key does not exist" 83 | } 84 | else 85 | { 86 | Write-Error "Error when enumerating keys: $($data.ReturnValue)" 87 | } 88 | } 89 | End 90 | { 91 | } 92 | } 93 | 94 | 95 | <# 96 | .Synopsis 97 | Creates a registry key under a given Registry Key. 98 | .DESCRIPTION 99 | Creates a registry key under a given Registry Key. 100 | .EXAMPLE 101 | Create a key named _deleteme under the registry HKCU key. 102 | PS C:\> New-RegKey -Hive HKCU -Key _deleteme -Verbose 103 | VERBOSE: Key HKCU\_deleteme was created. 104 | #> 105 | function New-RegKey 106 | { 107 | [CmdletBinding()] 108 | Param 109 | ( 110 | [parameter(Mandatory=$true)] 111 | [string] 112 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 113 | $Hive, 114 | 115 | [parameter(Mandatory=$true)] 116 | [string]$Key, 117 | 118 | [parameter(ValueFromPipeline=$true, 119 | ValueFromPipelineByPropertyName=$true)] 120 | [string]$Computername="$env:COMPUTERNAME", 121 | 122 | [Parameter(Mandatory=$false)] 123 | [System.Management.Automation.PSCredential] 124 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 125 | ) 126 | 127 | Begin 128 | { 129 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 130 | } 131 | Process 132 | { 133 | # We get the correct value associated with the key. 134 | switch ($hive) 135 | { 136 | "HKCR" {$reg_hive = 2147483648} 137 | "HKCU" {$reg_hive = 2147483649} 138 | "HKLM" {$reg_hive = 2147483650} 139 | "HKUS" {$reg_hive = 2147483651} 140 | "HKCC" {$reg_hive = 2147483653} 141 | } 142 | 143 | $data = $reg.CreateKey($reg_hive, $key) 144 | if ($data.ReturnValue -eq 0) 145 | { 146 | Write-Verbose "Key $hive\$key was created." 147 | } 148 | elseif ($data.ReturnValue -eq 2) 149 | { 150 | Write-Error "Key $key does not exist" 151 | } 152 | else 153 | { 154 | Write-Error "Error when creating key: $($data.ReturnValue)" 155 | } 156 | } 157 | End 158 | { 159 | } 160 | } 161 | 162 | 163 | <# 164 | .Synopsis 165 | Removes a registry key under a given Registry Key. 166 | .DESCRIPTION 167 | Removes a registry key under a given Registry Key. 168 | .EXAMPLE 169 | Remove a key named _deleteme under the registry HKCU key. 170 | PS C:\> Remove-RegKey -Hive HKCU -Key _deleteme -Verbose 171 | VERBOSE: Key HKCU\_deleteme was removed. 172 | #> 173 | function Remove-RegKey 174 | { 175 | [CmdletBinding()] 176 | Param 177 | ( 178 | [parameter(Mandatory=$true)] 179 | [string] 180 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 181 | $Hive, 182 | 183 | [parameter(Mandatory=$true)] 184 | [string]$Key, 185 | 186 | [parameter(ValueFromPipeline=$true, 187 | ValueFromPipelineByPropertyName=$true)] 188 | [string]$Computername="$env:COMPUTERNAME", 189 | 190 | [Parameter(Mandatory=$false)] 191 | [System.Management.Automation.PSCredential] 192 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 193 | ) 194 | 195 | Begin 196 | { 197 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 198 | } 199 | Process 200 | { 201 | # We get the correct value associated with the key. 202 | switch ($hive) 203 | { 204 | "HKCR" {$reg_hive = 2147483648} 205 | "HKCU" {$reg_hive = 2147483649} 206 | "HKLM" {$reg_hive = 2147483650} 207 | "HKUS" {$reg_hive = 2147483651} 208 | "HKCC" {$reg_hive = 2147483653} 209 | } 210 | 211 | $data = $reg.DeleteKey($reg_hive, $key) 212 | if ($data.ReturnValue -eq 0) 213 | { 214 | Write-Verbose "Key $hive\$key was removed." 215 | } 216 | elseif ($data.ReturnValue -eq 2) 217 | { 218 | Write-Error "Key $key does not exist" 219 | } 220 | else 221 | { 222 | Write-Error "Error when removing key: $($data.ReturnValue)" 223 | } 224 | } 225 | End 226 | { 227 | } 228 | } 229 | 230 | 231 | <# 232 | .Synopsis 233 | Enumerates the values and their type of a given Registry Key. 234 | .DESCRIPTION 235 | Enumerates the values and their type of a given Registry Key. 236 | .EXAMPLE 237 | Listing all of the console settings in the HKCU\Console key 238 | Get-RegValues -Hive HKCU -Key console 239 | #> 240 | function Get-RegValues 241 | { 242 | [CmdletBinding()] 243 | Param 244 | ( 245 | [parameter(Mandatory=$true)] 246 | [string] 247 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 248 | $Hive, 249 | 250 | [parameter(Mandatory=$true)] 251 | [string]$Key, 252 | 253 | [parameter(ValueFromPipeline=$true, 254 | ValueFromPipelineByPropertyName=$true)] 255 | [string]$Computername="$env:COMPUTERNAME", 256 | 257 | [Parameter(Mandatory=$false)] 258 | [System.Management.Automation.PSCredential] 259 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 260 | ) 261 | 262 | Begin 263 | { 264 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 265 | } 266 | Process 267 | { 268 | # We get the correct value associated with the key. 269 | switch ($hive) 270 | { 271 | "HKCR" {$reg_hive = 2147483648} 272 | "HKCU" {$reg_hive = 2147483649} 273 | "HKLM" {$reg_hive = 2147483650} 274 | "HKUS" {$reg_hive = 2147483651} 275 | "HKCC" {$reg_hive = 2147483653} 276 | } 277 | 278 | # Registry value types 279 | $reg_types = @{ 280 | "1" = "REG_SZ" 281 | "2" = "REG_EXPAND_SZ" 282 | "3" = "REG_BINARY" 283 | "4" = "REG_DWORD" 284 | "7" = "REG_MULTI_SZ" 285 | "11" = "REG_QWORD" 286 | } 287 | 288 | $data = $reg.EnumValues($reg_hive, $key) 289 | if ($data.ReturnValue -eq 0) 290 | { 291 | $keynum = ($data.snames).Length 292 | if ($keynum -gt 0) 293 | { 294 | for ($i=0; $i -le $keynum; $i++) 295 | { 296 | New-Object PSObject -Property @{ValueName="$($data.snames[$i])";Type = $reg_types["$($data.types[$i])"]} 297 | } 298 | } 299 | else 300 | { 301 | Write-Verbose "Key $key does not have any values to enumerate" 302 | } 303 | } 304 | elseif ($data.ReturnValue -eq 2) 305 | { 306 | Write-Error "Key $key does not exist" 307 | } 308 | else 309 | { 310 | Write-Error "Error when enumerating values: $($data.ReturnValue)" 311 | } 312 | } 313 | End 314 | { 315 | } 316 | } 317 | 318 | 319 | <# 320 | .Synopsis 321 | Checks for specific access type on a given registry key. 322 | .DESCRIPTION 323 | Checks for specific access type on a given registry key. Returns a Boolean value. 324 | .PARAMETER AccessType 325 | Access Type to test against a given Registry Key 326 | 327 | - KEY_QUERY_VALUE Required to query the values of a registry key. 328 | - KEY_SET_VALUE Required to create, delete, or set a registry value. 329 | - KEY_CREATE_SUB_KEY Required to create a subkey of a registry key. 330 | - KEY_ENUMERATE_SUB_KEYS Required to enumerate the subkeys of a registry key. 331 | - KEY_NOTIFY Required to request change notifications for a registry key or for subkeys of a registry key. 332 | - KEY_CREATE_SUB_KEY Required to create a registry key. 333 | - DELETE Required to delete a registry key. 334 | - READ_CONTROL Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. 335 | - WRITE_DAC Required to modify the DACL in the object's security descriptor. 336 | - WRITE_OWNER Required to change the owner in the object's security descriptor. 337 | .EXAMPLE 338 | PS C:\> Test-RegKeyAccess -Hive hkcu -Key software -AccessType DELETE 339 | True 340 | #> 341 | function Test-RegKeyAccess 342 | { 343 | [CmdletBinding()] 344 | 345 | Param 346 | ( 347 | [parameter(Mandatory=$true)] 348 | [string] 349 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 350 | $Hive, 351 | 352 | [parameter(Mandatory=$true)] 353 | [string] 354 | [Validateset(“KEY_QUERY_VALUE”, "KEY_CREATE_SUB_KEY", "KEY_ENUMERATE_SUB_KEYS", 355 | "KEY_NOTIFY", "KEY_CREATE", "DELETE", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER")] 356 | $AccessType, 357 | 358 | [parameter(Mandatory=$true)] 359 | [string]$Key, 360 | 361 | [parameter(ValueFromPipeline=$true, 362 | ValueFromPipelineByPropertyName=$true)] 363 | [string]$Computername="$env:COMPUTERNAME", 364 | 365 | [Parameter(Mandatory=$false)] 366 | [System.Management.Automation.PSCredential] 367 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 368 | ) 369 | 370 | Begin 371 | { 372 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 373 | } 374 | Process 375 | { 376 | # We get the correct value associated with the key. 377 | switch ($hive) 378 | { 379 | "HKCR" {$reg_hive = 2147483648} 380 | "HKCU" {$reg_hive = 2147483649} 381 | "HKLM" {$reg_hive = 2147483650} 382 | "HKUS" {$reg_hive = 2147483651} 383 | "HKCC" {$reg_hive = 2147483653} 384 | } 385 | 386 | switch ($AccessType) 387 | { 388 | “KEY_QUERY_VALUE” {$type2check = 1} 389 | "KEY_SET_VALUE" {$type2check = 2} 390 | "KEY_CREATE_SUB_KEY" {$type2check = 4} 391 | "KEY_ENUMERATE_SUB_KEYS" {$type2check = 8} 392 | "KEY_NOTIFY" {$type2check = 16} 393 | "KEY_CREATE" {$type2check = 32} 394 | "DELETE" {$type2check = 65536} 395 | "READ_CONTROL" {$type2check = 131072} 396 | "WRITE_DAC" {$type2check = 262144} 397 | "WRITE_OWNER" {$type2check = 524288} 398 | } 399 | 400 | $data = $reg.CheckAccess($reg_hive, $key, $type2check) 401 | if ($data.ReturnValue -eq 0) 402 | { 403 | $data.bGranted 404 | } 405 | elseif ($data.ReturnValue -eq 2) 406 | { 407 | Write-Error "Key $key does not exist" 408 | } 409 | else 410 | { 411 | Write-Error "Error when Checking Access Type on key: $($data.ReturnValue)" 412 | } 413 | } 414 | End 415 | { 416 | } 417 | } 418 | 419 | 420 | <# 421 | .Synopsis 422 | Set a value on a given key. 423 | .DESCRIPTION 424 | Set a value on a given key using WMI. 425 | .EXAMPLE 426 | set a SZ value. 427 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name stringval -Type SZ -Data "data" -Verbose 428 | VERBOSE: Value set on HKCU\_deletme\stringval of type SZ 429 | .EXAMPLE 430 | Set a MULTISZ value. 431 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name multistring -Type MULTISZ -Data "str1","str2","str3" -Verbose 432 | VERBOSE: Value set on HKCU\_deletme\multistring of type MULTISZ 433 | .EXAMPLE 434 | Set a QWORD value. 435 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name qval -Type QWORD -Data 4060 -Verbose 436 | VERBOSE: Value set on HKCU\_deletme\qval of type QWORD 437 | .EXAMPLE 438 | Set a EXPANDSZ value. 439 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name expanval -Type EXPANDSZ -Data "%envvar%" -Verbose 440 | VERBOSE: Value set on HKCU\_deletme\expanval of type EXPANDSZ 441 | .EXAMPLE 442 | Set a DWORD value. 443 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name dworval -Type DWORD -Data 10 -Verbose 444 | VERBOSE: Value set on HKCU\_deletme\dworval of type DWORD 445 | .EXAMPLE 446 | Set a Binary value. 447 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name binval -Type BINARY -Data @([char[]]'PowerShell') -Verbose 448 | VERBOSE: Value set on HKCU\_deletme\binval of type BINARY 449 | #> 450 | function Set-RegValue 451 | { 452 | [CmdletBinding()] 453 | 454 | Param 455 | ( 456 | [parameter(Mandatory=$true)] 457 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 458 | [string]$Hive, 459 | 460 | [parameter(Mandatory=$true)] 461 | [Validateset(“DWORD”, “EXPANDSZ”, “MULTISZ”, "QWORD", "SZ", "BINARY")] 462 | [string]$Type, 463 | 464 | [parameter(Mandatory=$true)] 465 | [string]$Key, 466 | 467 | [parameter(Mandatory=$true)] 468 | [string]$Name, 469 | 470 | [parameter(Mandatory=$true)] 471 | $Data, 472 | 473 | [parameter(ValueFromPipeline=$true, 474 | ValueFromPipelineByPropertyName=$true)] 475 | [string]$Computername="$env:COMPUTERNAME", 476 | 477 | [Parameter(Mandatory=$false)] 478 | [System.Management.Automation.PSCredential] 479 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 480 | ) 481 | 482 | Begin 483 | { 484 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 485 | 486 | } 487 | Process 488 | { 489 | # We get the correct value associated with the key. 490 | switch ($hive) 491 | { 492 | "HKCR" {$reg_hive = 2147483648} 493 | "HKCU" {$reg_hive = 2147483649} 494 | "HKLM" {$reg_hive = 2147483650} 495 | "HKUS" {$reg_hive = 2147483651} 496 | "HKCC" {$reg_hive = 2147483653} 497 | } 498 | 499 | # Set according to type 500 | switch ($type) 501 | { 502 | “DWORD” {$data = ($reg.SetDwordValue($reg_hive, $key, $Name, $Data))} 503 | “EXPANDSZ” {$data = ($reg.SetExpandedStringValue($reg_hive, $key, $Name, $Data))} 504 | “MULTISZ” {$data = ($reg.SetMultiStringValue($reg_hive, $key, $Name, $Data))} 505 | "QWORD" {$data = ($reg.SetQwordValue($reg_hive, $key, $Name, $Data))} 506 | "SZ" {$data = ($reg.SetStringValue($reg_hive, $key, $Name, $Data))} 507 | "BINARY" {$data = ($reg.SetBinaryValue($reg_hive, $key, $Name, $Data))} 508 | } 509 | 510 | # process return value 511 | if ($data.ReturnValue -eq 0) 512 | { 513 | Write-Verbose "Value set on $hive\$key\$name of type $type" 514 | } 515 | elseif ($data.ReturnValue -eq 2) 516 | { 517 | Write-Error "Key $key does not exist" 518 | } 519 | else 520 | { 521 | Write-Error "Error when setting value on key: $($data.ReturnValue)" 522 | } 523 | } 524 | End 525 | { 526 | } 527 | } 528 | 529 | 530 | <# 531 | .Synopsis 532 | Retrives a the content of a specified value in a given key. 533 | .DESCRIPTION 534 | Retrives a the content of a specified value in a given key. 535 | .EXAMPLE 536 | Getting the Windows Version fromt the registry 537 | PS C:\> Get-RegValue -Hive HKLM -key "SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ProductName 538 | Windows 8 Enterprise 539 | .EXAMPLE 540 | Read registry binary data and turn it in to ASCII String 541 | PS C:\> $bindata = Get-RegValue -Hive HKCU -Key _deleteme -Name binval 542 | PS C:\> ([System.Text.Encoding]::ASCII).GetString($bindata) 543 | PowerShell 544 | #> 545 | function Get-RegValue 546 | { 547 | [CmdletBinding()] 548 | [OutputType([int])] 549 | Param 550 | ( 551 | [parameter(Mandatory=$true)] 552 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 553 | [string]$Hive, 554 | 555 | [parameter(Mandatory=$true)] 556 | [string]$Key, 557 | 558 | [parameter(Mandatory=$true)] 559 | [string]$Name, 560 | 561 | [parameter(ValueFromPipeline=$true, 562 | ValueFromPipelineByPropertyName=$true)] 563 | [string]$Computername="$env:COMPUTERNAME", 564 | 565 | [Parameter(Mandatory=$false)] 566 | [System.Management.Automation.PSCredential] 567 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 568 | ) 569 | 570 | Begin 571 | { 572 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 573 | } 574 | Process 575 | { 576 | # We get the correct value associated with the key. 577 | switch ($hive) 578 | { 579 | "HKCR" {$reg_hive = 2147483648} 580 | "HKCU" {$reg_hive = 2147483649} 581 | "HKLM" {$reg_hive = 2147483650} 582 | "HKUS" {$reg_hive = 2147483651} 583 | "HKCC" {$reg_hive = 2147483653} 584 | } 585 | 586 | $valdata = $reg.EnumValues($reg_hive, $key) 587 | if ($valdata.returnvalue -eq 0) 588 | { 589 | # check that the value actualy exists 590 | if ($valdata.snames -contains $Name) 591 | { 592 | # Get value index in the array 593 | $index = (0..($valdata.snames.Count - 1) | Where { $valdata.snames[$_] -eq $Name }) 594 | $type = $valdata.types[$index] 595 | # Get according to type 596 | switch ($type) 597 | { 598 | “4” {$data = ($reg.GetDwordValue($reg_hive, $key, $Name)).uvalue} 599 | “2” {$data = ($reg.GetExpandedStringValue($reg_hive, $key, $Name)).svalue} 600 | “7” {$data = ($reg.GetMultiStringValue($reg_hive, $key, $Name)).svalue} 601 | "11" {$data = ($reg.GetQwordValue($reg_hive, $key, $Name)).uvalue} 602 | "1" {$data = ($reg.GetStringValue($reg_hive, $key, $Name)).svalue} 603 | "3" {$data = ($reg.GetBinaryValue($reg_hive, $key, $Name)).uvalue} 604 | } 605 | $data 606 | } 607 | else 608 | { 609 | Write-Error "Value $name does not exist in key specified." 610 | } 611 | } 612 | elseif ($valdata.returnvalue -eq 2) 613 | { 614 | Write-Error "Key $key does not exist" 615 | } 616 | else 617 | { 618 | Write-Error "Error when retreaving value on key: $($data.ReturnValue)" 619 | } 620 | } 621 | End 622 | { 623 | } 624 | } 625 | 626 | 627 | <# 628 | .Synopsis 629 | Removes a specified value in a given key. 630 | .DESCRIPTION 631 | Removes a specified value in a given key. 632 | .EXAMPLE 633 | Removing a value from the registry 634 | PS C:\> Remove-RegValue -Hive HKCU -Key _deleteme -Name dworval -Verbose 635 | VERBOSE: Value dworval has been removed. 636 | #> 637 | function Remove-RegValue 638 | { 639 | [CmdletBinding()] 640 | [OutputType([int])] 641 | Param 642 | ( 643 | [parameter(Mandatory=$true)] 644 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 645 | [string]$Hive, 646 | 647 | [parameter(Mandatory=$true)] 648 | [string]$Key, 649 | 650 | [parameter(Mandatory=$true)] 651 | [string]$Name, 652 | 653 | [parameter(ValueFromPipeline=$true, 654 | ValueFromPipelineByPropertyName=$true)] 655 | [string]$Computername="$env:COMPUTERNAME", 656 | 657 | [Parameter(Mandatory=$false)] 658 | [System.Management.Automation.PSCredential] 659 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 660 | ) 661 | 662 | Begin 663 | { 664 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 665 | } 666 | Process 667 | { 668 | # We get the correct value associated with the key. 669 | switch ($hive) 670 | { 671 | "HKCR" {$reg_hive = 2147483648} 672 | "HKCU" {$reg_hive = 2147483649} 673 | "HKLM" {$reg_hive = 2147483650} 674 | "HKUS" {$reg_hive = 2147483651} 675 | "HKCC" {$reg_hive = 2147483653} 676 | } 677 | 678 | $valdata = $reg.EnumValues($reg_hive, $key) 679 | if ($valdata.returnvalue -eq 0) 680 | { 681 | # check that the value actualy exists 682 | if ($valdata.snames -contains $Name) 683 | { 684 | $data = $reg.DeleteValue($reg_hive, $Key, $Name) 685 | switch ($data.returnvalue) 686 | { 687 | "0" {Write-Verbose "Value $name has been removed."} 688 | default {Write-Error "Error while removing value $name $($data.retunvalue)"} 689 | } 690 | } 691 | else 692 | { 693 | Write-Error "Value $name does not exist in key specified." 694 | } 695 | } 696 | elseif ($valdata.returnvalue -eq 2) 697 | { 698 | Write-Error "Key $key does not exist" 699 | } 700 | else 701 | { 702 | Write-Error "Error when removing value on key: $($data.ReturnValue)" 703 | } 704 | } 705 | End 706 | { 707 | } 708 | } 709 | 710 | 711 | <# 712 | .Synopsis 713 | Gets the Security DACL and Owner of a given Registry Key. 714 | .DESCRIPTION 715 | Gets the Security DACL and Owner of a given Registry Key. 716 | .EXAMPLE 717 | Get the DACL for the SAM key in HKLM 718 | PS C:\> Get-RegKeySecurityDescriptor -Hive HKlm -Key sam 719 | 720 | Trustee Permission 721 | ------- ---------- 722 | BUILTIN\Administrators Owner 723 | BUILTIN\Users Read Access 724 | BUILTIN\Administrators All Access 725 | NT AUTHORITY\SYSTEM All Access 726 | \CREATOR OWNER All Access 727 | APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Read Access 728 | 729 | #> 730 | function Get-RegKeySecurityDescriptor 731 | { 732 | [CmdletBinding()] 733 | Param 734 | ( 735 | [parameter(Mandatory=$true)] 736 | [string] 737 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 738 | $Hive, 739 | 740 | [parameter(Mandatory=$true)] 741 | [string]$Key, 742 | 743 | [parameter(ValueFromPipeline=$true, 744 | ValueFromPipelineByPropertyName=$true)] 745 | [string]$Computername="$env:COMPUTERNAME", 746 | 747 | [Parameter(Mandatory=$false)] 748 | [System.Management.Automation.PSCredential] 749 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 750 | ) 751 | 752 | Begin 753 | { 754 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 755 | $accessmask = @{ 756 | "1" = "Query Value" 757 | "2" = "Set Value." 758 | "4" = "Create Subkey" 759 | "8" = "Enumerate Subkeys" 760 | "16" = "Notify" 761 | "32" = "Create Key" 762 | "65536" = "Delete Key" 763 | "131072" = "Read Control" 764 | "262144" = "Write DAC" 765 | "524288" = "Write Owner" 766 | "983103" = "All Access" 767 | "131097" = "Read Access" 768 | } 769 | } 770 | Process 771 | { 772 | # We get the correct value associated with the key. 773 | switch ($hive) 774 | { 775 | "HKCR" {$reg_hive = 2147483648} 776 | "HKCU" {$reg_hive = 2147483649} 777 | "HKLM" {$reg_hive = 2147483650} 778 | "HKUS" {$reg_hive = 2147483651} 779 | "HKCC" {$reg_hive = 2147483653} 780 | } 781 | 782 | $data = $reg.GetSecurityDescriptor($reg_hive, $key) 783 | if ($data.ReturnValue -eq 0) 784 | { 785 | $owner = New-Object psobject 786 | Add-Member -InputObject $owner -MemberType NoteProperty -Name Trustee -Value "$($Data.Descriptor.Owner.Domain)\$($Data.Descriptor.Owner.Name)" 787 | Add-Member -InputObject $owner -MemberType NoteProperty -Name Permission -Value "Owner" 788 | $owner 789 | $data.Descriptor.DACL| ForEach-Object { 790 | $dacl = New-Object psobject 791 | Add-Member -InputObject $dacl -MemberType NoteProperty -Name Trustee -Value "$($_.Trustee.Domain)\$($_.Trustee.Name)" 792 | Write-Verbose "Access mask for $($_.Trustee.Domain)\$($_.Trustee.Name) is $($_.accessmask)" 793 | Add-Member -InputObject $dacl -MemberType NoteProperty -Name Permission -Value "$($accessmask[[string]$_.accessmask])" 794 | $dacl 795 | } 796 | } 797 | elseif ($data.ReturnValue -eq 2) 798 | { 799 | Write-Error "Key $key does not exist" 800 | } 801 | else 802 | { 803 | Write-Error "Error when creating key: $($data.ReturnValue)" 804 | } 805 | } 806 | End 807 | { 808 | } 809 | } 810 | -------------------------------------------------------------------------------- /Registry/Registry.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Enumerates the keys that are under a given Registry Key. 4 | .DESCRIPTION 5 | Enumerates the keys that are under a given Registry Key. 6 | .EXAMPLE 7 | Listing all of the keys under HKCU\Software key 8 | PS C:\> Get-RegKeys -Hive HKCU -Key software 9 | 10 | Key FullPath 11 | --- -------- 12 | 7-Zip HKCU\software\7-Zip 13 | AppDataLow HKCU\software\AppDataLow 14 | Macromedia HKCU\software\Macromedia 15 | Microsoft HKCU\software\Microsoft 16 | Microsoft Corporation HKCU\software\Microsoft Corporation 17 | Mine HKCU\software\Mine 18 | Policies HKCU\software\Policies 19 | RegisteredApplications HKCU\software\RegisteredApplications 20 | ThinPrint HKCU\software\ThinPrint 21 | VMware, Inc. HKCU\software\VMware, Inc. 22 | Wow6432Node HKCU\software\Wow6432Node 23 | Classes HKCU\software\Classes 24 | #> 25 | function Get-RegKeys 26 | { 27 | [CmdletBinding()] 28 | Param 29 | ( 30 | [parameter(Mandatory=$true)] 31 | [string] 32 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 33 | $Hive, 34 | 35 | [parameter(Mandatory=$true)] 36 | [AllowEmptyString()] 37 | [string]$Key, 38 | 39 | [parameter(ValueFromPipeline=$true, 40 | ValueFromPipelineByPropertyName=$true)] 41 | [string]$Computername="$env:COMPUTERNAME", 42 | 43 | [Parameter(Mandatory=$false)] 44 | [System.Management.Automation.PSCredential] 45 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 46 | ) 47 | 48 | Begin 49 | { 50 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 51 | } 52 | Process 53 | { 54 | # We get the correct value associated with the key. 55 | switch ($hive) 56 | { 57 | "HKCR" {$reg_hive = 2147483648} 58 | "HKCU" {$reg_hive = 2147483649} 59 | "HKLM" {$reg_hive = 2147483650} 60 | "HKUS" {$reg_hive = 2147483651} 61 | "HKCC" {$reg_hive = 2147483653} 62 | } 63 | 64 | $data = $reg.EnumKey($reg_hive, $key) 65 | if ($data.ReturnValue -eq 0) 66 | { 67 | $keynum = ($data.snames).Length 68 | if ($keynum -gt 0) 69 | { 70 | foreach($keyname in $data.snames) 71 | { 72 | New-Object PSObject -Property @{Key=$keyname;FullPath = "$hive\$key\$keyname"} 73 | } 74 | } 75 | else 76 | { 77 | Write-Verbose "Key $key does not have any keys to enumerate" 78 | } 79 | } 80 | elseif ($data.ReturnValue -eq 2) 81 | { 82 | Write-Error "Key $key does not exist" 83 | } 84 | else 85 | { 86 | Write-Error "Error when enumerating keys: $($data.ReturnValue)" 87 | } 88 | } 89 | End 90 | { 91 | } 92 | } 93 | 94 | 95 | <# 96 | .Synopsis 97 | Creates a registry key under a given Registry Key. 98 | .DESCRIPTION 99 | Creates a registry key under a given Registry Key. 100 | .EXAMPLE 101 | Create a key named _deleteme under the registry HKCU key. 102 | PS C:\> New-RegKey -Hive HKCU -Key _deleteme -Verbose 103 | VERBOSE: Key HKCU\_deleteme was created. 104 | #> 105 | function New-RegKey 106 | { 107 | [CmdletBinding()] 108 | Param 109 | ( 110 | [parameter(Mandatory=$true)] 111 | [string] 112 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 113 | $Hive, 114 | 115 | [parameter(Mandatory=$true)] 116 | [string]$Key, 117 | 118 | [parameter(ValueFromPipeline=$true, 119 | ValueFromPipelineByPropertyName=$true)] 120 | [string]$Computername="$env:COMPUTERNAME", 121 | 122 | [Parameter(Mandatory=$false)] 123 | [System.Management.Automation.PSCredential] 124 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 125 | ) 126 | 127 | Begin 128 | { 129 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 130 | } 131 | Process 132 | { 133 | # We get the correct value associated with the key. 134 | switch ($hive) 135 | { 136 | "HKCR" {$reg_hive = 2147483648} 137 | "HKCU" {$reg_hive = 2147483649} 138 | "HKLM" {$reg_hive = 2147483650} 139 | "HKUS" {$reg_hive = 2147483651} 140 | "HKCC" {$reg_hive = 2147483653} 141 | } 142 | 143 | $data = $reg.CreateKey($reg_hive, $key) 144 | if ($data.ReturnValue -eq 0) 145 | { 146 | Write-Verbose "Key $hive\$key was created." 147 | } 148 | elseif ($data.ReturnValue -eq 2) 149 | { 150 | Write-Error "Key $key does not exist" 151 | } 152 | else 153 | { 154 | Write-Error "Error when creating key: $($data.ReturnValue)" 155 | } 156 | } 157 | End 158 | { 159 | } 160 | } 161 | 162 | 163 | <# 164 | .Synopsis 165 | Removes a registry key under a given Registry Key. 166 | .DESCRIPTION 167 | Removes a registry key under a given Registry Key. 168 | .EXAMPLE 169 | Remove a key named _deleteme under the registry HKCU key. 170 | PS C:\> Remove-RegKey -Hive HKCU -Key _deleteme -Verbose 171 | VERBOSE: Key HKCU\_deleteme was removed. 172 | #> 173 | function Remove-RegKey 174 | { 175 | [CmdletBinding()] 176 | Param 177 | ( 178 | [parameter(Mandatory=$true)] 179 | [string] 180 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 181 | $Hive, 182 | 183 | [parameter(Mandatory=$true)] 184 | [string]$Key, 185 | 186 | [parameter(ValueFromPipeline=$true, 187 | ValueFromPipelineByPropertyName=$true)] 188 | [string]$Computername="$env:COMPUTERNAME", 189 | 190 | [Parameter(Mandatory=$false)] 191 | [System.Management.Automation.PSCredential] 192 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 193 | ) 194 | 195 | Begin 196 | { 197 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 198 | } 199 | Process 200 | { 201 | # We get the correct value associated with the key. 202 | switch ($hive) 203 | { 204 | "HKCR" {$reg_hive = 2147483648} 205 | "HKCU" {$reg_hive = 2147483649} 206 | "HKLM" {$reg_hive = 2147483650} 207 | "HKUS" {$reg_hive = 2147483651} 208 | "HKCC" {$reg_hive = 2147483653} 209 | } 210 | 211 | $data = $reg.DeleteKey($reg_hive, $key) 212 | if ($data.ReturnValue -eq 0) 213 | { 214 | Write-Verbose "Key $hive\$key was removed." 215 | } 216 | elseif ($data.ReturnValue -eq 2) 217 | { 218 | Write-Error "Key $key does not exist" 219 | } 220 | else 221 | { 222 | Write-Error "Error when removing key: $($data.ReturnValue)" 223 | } 224 | } 225 | End 226 | { 227 | } 228 | } 229 | 230 | 231 | <# 232 | .Synopsis 233 | Enumerates the values and their type of a given Registry Key. 234 | .DESCRIPTION 235 | Enumerates the values and their type of a given Registry Key. 236 | .EXAMPLE 237 | Listing all of the console settings in the HKCU\Console key 238 | Get-RegValues -Hive HKCU -Key console 239 | #> 240 | function Get-RegValues 241 | { 242 | [CmdletBinding()] 243 | Param 244 | ( 245 | [parameter(Mandatory=$true)] 246 | [string] 247 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 248 | $Hive, 249 | 250 | [parameter(Mandatory=$true)] 251 | [string]$Key, 252 | 253 | [parameter(ValueFromPipeline=$true, 254 | ValueFromPipelineByPropertyName=$true)] 255 | [string]$Computername="$env:COMPUTERNAME", 256 | 257 | [Parameter(Mandatory=$false)] 258 | [System.Management.Automation.PSCredential] 259 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 260 | ) 261 | 262 | Begin 263 | { 264 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 265 | } 266 | Process 267 | { 268 | # We get the correct value associated with the key. 269 | switch ($hive) 270 | { 271 | "HKCR" {$reg_hive = 2147483648} 272 | "HKCU" {$reg_hive = 2147483649} 273 | "HKLM" {$reg_hive = 2147483650} 274 | "HKUS" {$reg_hive = 2147483651} 275 | "HKCC" {$reg_hive = 2147483653} 276 | } 277 | 278 | # Registry value types 279 | $reg_types = @{ 280 | "1" = "REG_SZ" 281 | "2" = "REG_EXPAND_SZ" 282 | "3" = "REG_BINARY" 283 | "4" = "REG_DWORD" 284 | "7" = "REG_MULTI_SZ" 285 | "11" = "REG_QWORD" 286 | } 287 | 288 | $data = $reg.EnumValues($reg_hive, $key) 289 | if ($data.ReturnValue -eq 0) 290 | { 291 | $keynum = ($data.snames).Length 292 | if ($keynum -gt 0) 293 | { 294 | for ($i=0; $i -le $keynum; $i++) 295 | { 296 | New-Object PSObject -Property @{ValueName="$($data.snames[$i])";Type = $reg_types["$($data.types[$i])"]} 297 | } 298 | } 299 | else 300 | { 301 | Write-Verbose "Key $key does not have any values to enumerate" 302 | } 303 | } 304 | elseif ($data.ReturnValue -eq 2) 305 | { 306 | Write-Error "Key $key does not exist" 307 | } 308 | else 309 | { 310 | Write-Error "Error when enumerating values: $($data.ReturnValue)" 311 | } 312 | } 313 | End 314 | { 315 | } 316 | } 317 | 318 | 319 | <# 320 | .Synopsis 321 | Checks for specific access type on a given registry key. 322 | .DESCRIPTION 323 | Checks for specific access type on a given registry key. Returns a Boolean value. 324 | .PARAMETER AccessType 325 | Access Type to test against a given Registry Key 326 | 327 | - KEY_QUERY_VALUE Required to query the values of a registry key. 328 | - KEY_SET_VALUE Required to create, delete, or set a registry value. 329 | - KEY_CREATE_SUB_KEY Required to create a subkey of a registry key. 330 | - KEY_ENUMERATE_SUB_KEYS Required to enumerate the subkeys of a registry key. 331 | - KEY_NOTIFY Required to request change notifications for a registry key or for subkeys of a registry key. 332 | - KEY_CREATE_SUB_KEY Required to create a registry key. 333 | - DELETE Required to delete a registry key. 334 | - READ_CONTROL Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. 335 | - WRITE_DAC Required to modify the DACL in the object's security descriptor. 336 | - WRITE_OWNER Required to change the owner in the object's security descriptor. 337 | .EXAMPLE 338 | PS C:\> Test-RegKeyAccess -Hive hkcu -Key software -AccessType DELETE 339 | True 340 | #> 341 | function Test-RegKeyAccess 342 | { 343 | [CmdletBinding()] 344 | 345 | Param 346 | ( 347 | [parameter(Mandatory=$true)] 348 | [string] 349 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 350 | $Hive, 351 | 352 | [parameter(Mandatory=$true)] 353 | [string] 354 | [Validateset(“KEY_QUERY_VALUE”, "KEY_CREATE_SUB_KEY", "KEY_ENUMERATE_SUB_KEYS", 355 | "KEY_NOTIFY", "KEY_CREATE", "DELETE", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER")] 356 | $AccessType, 357 | 358 | [parameter(Mandatory=$true)] 359 | [string]$Key, 360 | 361 | [parameter(ValueFromPipeline=$true, 362 | ValueFromPipelineByPropertyName=$true)] 363 | [string]$Computername="$env:COMPUTERNAME", 364 | 365 | [Parameter(Mandatory=$false)] 366 | [System.Management.Automation.PSCredential] 367 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 368 | ) 369 | 370 | Begin 371 | { 372 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 373 | } 374 | Process 375 | { 376 | # We get the correct value associated with the key. 377 | switch ($hive) 378 | { 379 | "HKCR" {$reg_hive = 2147483648} 380 | "HKCU" {$reg_hive = 2147483649} 381 | "HKLM" {$reg_hive = 2147483650} 382 | "HKUS" {$reg_hive = 2147483651} 383 | "HKCC" {$reg_hive = 2147483653} 384 | } 385 | 386 | switch ($AccessType) 387 | { 388 | “KEY_QUERY_VALUE” {$type2check = 1} 389 | "KEY_SET_VALUE" {$type2check = 2} 390 | "KEY_CREATE_SUB_KEY" {$type2check = 4} 391 | "KEY_ENUMERATE_SUB_KEYS" {$type2check = 8} 392 | "KEY_NOTIFY" {$type2check = 16} 393 | "KEY_CREATE" {$type2check = 32} 394 | "DELETE" {$type2check = 65536} 395 | "READ_CONTROL" {$type2check = 131072} 396 | "WRITE_DAC" {$type2check = 262144} 397 | "WRITE_OWNER" {$type2check = 524288} 398 | } 399 | 400 | $data = $reg.CheckAccess($reg_hive, $key, $type2check) 401 | if ($data.ReturnValue -eq 0) 402 | { 403 | $data.bGranted 404 | } 405 | elseif ($data.ReturnValue -eq 2) 406 | { 407 | Write-Error "Key $key does not exist" 408 | } 409 | else 410 | { 411 | Write-Error "Error when Checking Access Type on key: $($data.ReturnValue)" 412 | } 413 | } 414 | End 415 | { 416 | } 417 | } 418 | 419 | 420 | <# 421 | .Synopsis 422 | Set a value on a given key. 423 | .DESCRIPTION 424 | Set a value on a given key using WMI. 425 | .EXAMPLE 426 | set a SZ value. 427 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name stringval -Type SZ -Data "data" -Verbose 428 | VERBOSE: Value set on HKCU\_deletme\stringval of type SZ 429 | .EXAMPLE 430 | Set a MULTISZ value. 431 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name multistring -Type MULTISZ -Data "str1","str2","str3" -Verbose 432 | VERBOSE: Value set on HKCU\_deletme\multistring of type MULTISZ 433 | .EXAMPLE 434 | Set a QWORD value. 435 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name qval -Type QWORD -Data 4060 -Verbose 436 | VERBOSE: Value set on HKCU\_deletme\qval of type QWORD 437 | .EXAMPLE 438 | Set a EXPANDSZ value. 439 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name expanval -Type EXPANDSZ -Data "%envvar%" -Verbose 440 | VERBOSE: Value set on HKCU\_deletme\expanval of type EXPANDSZ 441 | .EXAMPLE 442 | Set a DWORD value. 443 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name dworval -Type DWORD -Data 10 -Verbose 444 | VERBOSE: Value set on HKCU\_deletme\dworval of type DWORD 445 | .EXAMPLE 446 | Set a Binary value. 447 | PS C:\> Set-RegValue -Hive HKCU -Key _deleteme -Name binval -Type BINARY -Data @([char[]]'PowerShell') -Verbose 448 | VERBOSE: Value set on HKCU\_deletme\binval of type BINARY 449 | #> 450 | function Set-RegValue 451 | { 452 | [CmdletBinding()] 453 | 454 | Param 455 | ( 456 | [parameter(Mandatory=$true)] 457 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 458 | [string]$Hive, 459 | 460 | [parameter(Mandatory=$true)] 461 | [Validateset(“DWORD”, “EXPANDSZ”, “MULTISZ”, "QWORD", "SZ", "BINARY")] 462 | [string]$Type, 463 | 464 | [parameter(Mandatory=$true)] 465 | [string]$Key, 466 | 467 | [parameter(Mandatory=$true)] 468 | [string]$Name, 469 | 470 | [parameter(Mandatory=$true)] 471 | $Data, 472 | 473 | [parameter(ValueFromPipeline=$true, 474 | ValueFromPipelineByPropertyName=$true)] 475 | [string]$Computername="$env:COMPUTERNAME", 476 | 477 | [Parameter(Mandatory=$false)] 478 | [System.Management.Automation.PSCredential] 479 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 480 | ) 481 | 482 | Begin 483 | { 484 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 485 | 486 | } 487 | Process 488 | { 489 | # We get the correct value associated with the key. 490 | switch ($hive) 491 | { 492 | "HKCR" {$reg_hive = 2147483648} 493 | "HKCU" {$reg_hive = 2147483649} 494 | "HKLM" {$reg_hive = 2147483650} 495 | "HKUS" {$reg_hive = 2147483651} 496 | "HKCC" {$reg_hive = 2147483653} 497 | } 498 | 499 | # Set according to type 500 | switch ($type) 501 | { 502 | “DWORD” {$data = ($reg.SetDwordValue($reg_hive, $key, $Name, $Data))} 503 | “EXPANDSZ” {$data = ($reg.SetExpandedStringValue($reg_hive, $key, $Name, $Data))} 504 | “MULTISZ” {$data = ($reg.SetMultiStringValue($reg_hive, $key, $Name, $Data))} 505 | "QWORD" {$data = ($reg.SetQwordValue($reg_hive, $key, $Name, $Data))} 506 | "SZ" {$data = ($reg.SetStringValue($reg_hive, $key, $Name, $Data))} 507 | "BINARY" {$data = ($reg.SetBinaryValue($reg_hive, $key, $Name, $Data))} 508 | } 509 | 510 | # process return value 511 | if ($data.ReturnValue -eq 0) 512 | { 513 | Write-Verbose "Value set on $hive\$key\$name of type $type" 514 | } 515 | elseif ($data.ReturnValue -eq 2) 516 | { 517 | Write-Error "Key $key does not exist" 518 | } 519 | else 520 | { 521 | Write-Error "Error when setting value on key: $($data.ReturnValue)" 522 | } 523 | } 524 | End 525 | { 526 | } 527 | } 528 | 529 | 530 | <# 531 | .Synopsis 532 | Retrives a the content of a specified value in a given key. 533 | .DESCRIPTION 534 | Retrives a the content of a specified value in a given key. 535 | .EXAMPLE 536 | Getting the Windows Version fromt the registry 537 | PS C:\> Get-RegValue -Hive HKLM -key "SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ProductName 538 | Windows 8 Enterprise 539 | .EXAMPLE 540 | Read registry binary data and turn it in to ASCII String 541 | PS C:\> $bindata = Get-RegValue -Hive HKCU -Key _deleteme -Name binval 542 | PS C:\> ([System.Text.Encoding]::ASCII).GetString($bindata) 543 | PowerShell 544 | 545 | PS C:\Wind 546 | #> 547 | function Get-RegValue 548 | { 549 | [CmdletBinding()] 550 | [OutputType([int])] 551 | Param 552 | ( 553 | [parameter(Mandatory=$true)] 554 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 555 | [string]$Hive, 556 | 557 | [parameter(Mandatory=$true)] 558 | [string]$Key, 559 | 560 | [parameter(Mandatory=$true)] 561 | [string]$Name, 562 | 563 | [parameter(ValueFromPipeline=$true, 564 | ValueFromPipelineByPropertyName=$true)] 565 | [string]$Computername="$env:COMPUTERNAME", 566 | 567 | [Parameter(Mandatory=$false)] 568 | [System.Management.Automation.PSCredential] 569 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 570 | ) 571 | 572 | Begin 573 | { 574 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 575 | } 576 | Process 577 | { 578 | # We get the correct value associated with the key. 579 | switch ($hive) 580 | { 581 | "HKCR" {$reg_hive = 2147483648} 582 | "HKCU" {$reg_hive = 2147483649} 583 | "HKLM" {$reg_hive = 2147483650} 584 | "HKUS" {$reg_hive = 2147483651} 585 | "HKCC" {$reg_hive = 2147483653} 586 | } 587 | 588 | $valdata = $reg.EnumValues($reg_hive, $key) 589 | if ($valdata.returnvalue -eq 0) 590 | { 591 | # check that the value actualy exists 592 | if ($valdata.snames -contains $Name) 593 | { 594 | # Get value index in the array 595 | $index = (0..($valdata.snames.Count - 1) | Where { $valdata.snames[$_] -eq $Name }) 596 | $type = $valdata.types[$index] 597 | # Get according to type 598 | switch ($type) 599 | { 600 | “4” {$data = ($reg.GetDwordValue($reg_hive, $key, $Name)).uvalue} 601 | “2” {$data = ($reg.GetExpandedStringValue($reg_hive, $key, $Name)).svalue} 602 | “7” {$data = ($reg.GetMultiStringValue($reg_hive, $key, $Name)).svalue} 603 | "11" {$data = ($reg.GetQwordValue($reg_hive, $key, $Name)).uvalue} 604 | "1" {$data = ($reg.GetStringValue($reg_hive, $key, $Name)).svalue} 605 | "3" {$data = ($reg.GetBinaryValue($reg_hive, $key, $Name)).uvalue} 606 | } 607 | $data 608 | } 609 | else 610 | { 611 | Write-Error "Value $name does not exist in key specified." 612 | } 613 | } 614 | elseif ($valdata.returnvalue -eq 2) 615 | { 616 | Write-Error "Key $key does not exist" 617 | } 618 | else 619 | { 620 | Write-Error "Error when retreaving value on key: $($data.ReturnValue)" 621 | } 622 | } 623 | End 624 | { 625 | } 626 | } 627 | 628 | 629 | <# 630 | .Synopsis 631 | Removes a specified value in a given key. 632 | .DESCRIPTION 633 | Removes a specified value in a given key. 634 | .EXAMPLE 635 | Removing a value from the registry 636 | PS C:\> Remove-RegValue -Hive HKCU -Key _deleteme -Name dworval -Verbose 637 | VERBOSE: Value dworval has been removed. 638 | #> 639 | function Remove-RegValue 640 | { 641 | [CmdletBinding()] 642 | [OutputType([int])] 643 | Param 644 | ( 645 | [parameter(Mandatory=$true)] 646 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 647 | [string]$Hive, 648 | 649 | [parameter(Mandatory=$true)] 650 | [string]$Key, 651 | 652 | [parameter(Mandatory=$true)] 653 | [string]$Name, 654 | 655 | [parameter(ValueFromPipeline=$true, 656 | ValueFromPipelineByPropertyName=$true)] 657 | [string]$Computername="$env:COMPUTERNAME", 658 | 659 | [Parameter(Mandatory=$false)] 660 | [System.Management.Automation.PSCredential] 661 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 662 | ) 663 | 664 | Begin 665 | { 666 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 667 | } 668 | Process 669 | { 670 | # We get the correct value associated with the key. 671 | switch ($hive) 672 | { 673 | "HKCR" {$reg_hive = 2147483648} 674 | "HKCU" {$reg_hive = 2147483649} 675 | "HKLM" {$reg_hive = 2147483650} 676 | "HKUS" {$reg_hive = 2147483651} 677 | "HKCC" {$reg_hive = 2147483653} 678 | } 679 | 680 | $valdata = $reg.EnumValues($reg_hive, $key) 681 | if ($valdata.returnvalue -eq 0) 682 | { 683 | # check that the value actualy exists 684 | if ($valdata.snames -contains $Name) 685 | { 686 | $data = $reg.DeleteValue($reg_hive, $Key, $Name) 687 | switch ($data.returnvalue) 688 | { 689 | "0" {Write-Verbose "Value $name has been removed."} 690 | default {Write-Error "Error while removing value $name $($data.retunvalue)"} 691 | } 692 | } 693 | else 694 | { 695 | Write-Error "Value $name does not exist in key specified." 696 | } 697 | } 698 | elseif ($valdata.returnvalue -eq 2) 699 | { 700 | Write-Error "Key $key does not exist" 701 | } 702 | else 703 | { 704 | Write-Error "Error when removing value on key: $($data.ReturnValue)" 705 | } 706 | } 707 | End 708 | { 709 | } 710 | } 711 | 712 | 713 | <# 714 | .Synopsis 715 | Gets the Security DACL and Owner of a given Registry Key. 716 | .DESCRIPTION 717 | Gets the Security DACL and Owner of a given Registry Key. 718 | .EXAMPLE 719 | Get the DACL for the SAM key in HKLM 720 | PS C:\> Get-RegKeySecurityDescriptor -Hive HKlm -Key sam 721 | 722 | Trustee Permission 723 | ------- ---------- 724 | BUILTIN\Administrators Owner 725 | BUILTIN\Users Read Access 726 | BUILTIN\Administrators All Access 727 | NT AUTHORITY\SYSTEM All Access 728 | \CREATOR OWNER All Access 729 | APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Read Access 730 | 731 | #> 732 | function Get-RegKeySecurityDescriptor 733 | { 734 | [CmdletBinding()] 735 | Param 736 | ( 737 | [parameter(Mandatory=$true)] 738 | [string] 739 | [Validateset(“HKCR”, “HKCU”, “HKLM”, "HKUS", "HKCC")] 740 | $Hive, 741 | 742 | [parameter(Mandatory=$true)] 743 | [string]$Key, 744 | 745 | [parameter(ValueFromPipeline=$true, 746 | ValueFromPipelineByPropertyName=$true)] 747 | [string]$Computername="$env:COMPUTERNAME", 748 | 749 | [Parameter(Mandatory=$false)] 750 | [System.Management.Automation.PSCredential] 751 | [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty 752 | ) 753 | 754 | Begin 755 | { 756 | $reg = Get-WmiObject -List "StdRegprov" -ComputerName $computername -Credential $Credential 757 | $accessmask = @{ 758 | "1" = "Query Value" 759 | "2" = "Set Value." 760 | "4" = "Create Subkey" 761 | "8" = "Enumerate Subkeys" 762 | "16" = "Notify" 763 | "32" = "Create Key" 764 | "65536" = "Delete Key" 765 | "131072" = "Read Control" 766 | "262144" = "Write DAC" 767 | "524288" = "Write Owner" 768 | "983103" = "All Access" 769 | "131097" = "Read Access" 770 | } 771 | } 772 | Process 773 | { 774 | # We get the correct value associated with the key. 775 | switch ($hive) 776 | { 777 | "HKCR" {$reg_hive = 2147483648} 778 | "HKCU" {$reg_hive = 2147483649} 779 | "HKLM" {$reg_hive = 2147483650} 780 | "HKUS" {$reg_hive = 2147483651} 781 | "HKCC" {$reg_hive = 2147483653} 782 | } 783 | 784 | $data = $reg.GetSecurityDescriptor($reg_hive, $key) 785 | if ($data.ReturnValue -eq 0) 786 | { 787 | $owner = New-Object psobject 788 | Add-Member -InputObject $owner -MemberType NoteProperty -Name Trustee -Value "$($Data.Descriptor.Owner.Domain)\$($Data.Descriptor.Owner.Name)" 789 | Add-Member -InputObject $owner -MemberType NoteProperty -Name Permission -Value "Owner" 790 | $owner 791 | $data.Descriptor.DACL| ForEach-Object { 792 | $dacl = New-Object psobject 793 | Add-Member -InputObject $dacl -MemberType NoteProperty -Name Trustee -Value "$($_.Trustee.Domain)\$($_.Trustee.Name)" 794 | Write-Verbose "Access mask for $($_.Trustee.Domain)\$($_.Trustee.Name) is $($_.accessmask)" 795 | Add-Member -InputObject $dacl -MemberType NoteProperty -Name Permission -Value "$($accessmask[[string]$_.accessmask])" 796 | $dacl 797 | } 798 | } 799 | elseif ($data.ReturnValue -eq 2) 800 | { 801 | Write-Error "Key $key does not exist" 802 | } 803 | else 804 | { 805 | Write-Error "Error when creating key: $($data.ReturnValue)" 806 | } 807 | } 808 | End 809 | { 810 | } 811 | } -------------------------------------------------------------------------------- /Utility/utility.psm1: -------------------------------------------------------------------------------- 1 |  2 | <# 3 | .Synopsis 4 | Downloads a file from a specified URL on the Internet. 5 | .DESCRIPTION 6 | Function will download a single file from the Internet. This cmdlet requires that an explicit URI is entered and that the destination file name and location is specified as well 7 | .PARAMETER URL 8 | Target location to download a specified file from a remote location. 9 | .PARAMETER LocalFile 10 | Local destination to store targeted file. 11 | .EXAMPLE 12 | Get-WebFile -URL http://www.contoso.com/targetfile.txt -LocalFile .\destinationfile.txt 13 | 14 | Downloads targetfile.txt and saves it to the current working directory as destinationfile.txt 15 | .EXAMPLE 16 | Get-WebFile http://www.contoso.com/install.exe C:\Downloads\install.exe 17 | 18 | Downloads install.exe from contoso.com and save it with an absolute path of C:\Downloads 19 | .LINK 20 | https://www.github.com/darkoperator/Posh-SecMod/ 21 | #> 22 | Function Get-WebFile 23 | { 24 | Param( 25 | [Parameter(Mandatory = $true)] 26 | [uri]$URL, 27 | 28 | [Parameter(Mandatory = $true)] 29 | $LocalFile 30 | ) 31 | 32 | Begin 33 | { 34 | $WebClient = New-Object System.Net.WebClient 35 | } 36 | 37 | Process 38 | { 39 | try 40 | { 41 | Register-ObjectEvent $WebClient DownloadProgressChanged -action { 42 | 43 | Write-Progress -Activity "Downloading" -Status ` 44 | ("{0} of {1}" -f $eventargs.BytesReceived, $eventargs.TotalBytesToReceive) ` 45 | -PercentComplete $eventargs.ProgressPercentage 46 | } 47 | 48 | Register-ObjectEvent $client DownloadFileCompleted -SourceIdentifier Finished 49 | $WebClient.DownloadFileAsync($URL, $LocalFile) 50 | 51 | # optionally wait, but you can break out and it will still write progress 52 | Wait-Event -SourceIdentifier Finished 53 | 54 | } 55 | finally 56 | { 57 | $WebClient.dispose() 58 | } 59 | } 60 | End{} 61 | } 62 | 63 | 64 | 65 | function New-Zip 66 | { 67 | [CmdletBinding()] 68 | Param 69 | ( 70 | [Parameter(Mandatory=$true, 71 | ValueFromPipelineByPropertyName=$true, 72 | Position=0)] 73 | $ZipFile 74 | ) 75 | set-content $ZipFile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 76 | (dir $ZipFile).IsReadOnly = $false 77 | } 78 | 79 | 80 | function Add-Zip 81 | { 82 | [CmdletBinding()] 83 | Param 84 | ( 85 | [Parameter(Mandatory=$true)] 86 | $ZipFile, 87 | 88 | [Parameter(Mandatory=$true, 89 | ValueFromPipelineByPropertyName=$true, 90 | Position=1)] 91 | [ValidateScript({Test-Path $_})] 92 | [Alias("Name", "FullName")] 93 | $File 94 | 95 | ) 96 | 97 | Begin 98 | { 99 | if(-not (test-path($ZipFile))) 100 | { 101 | set-content $ZipFile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 102 | (dir $ZipFile).IsReadOnly = $false 103 | } 104 | } 105 | Process 106 | { 107 | Write-Verbose $File 108 | $shellApplication = new-object -com shell.application 109 | $zipPackage = (new-object -com shell.application).NameSpace(((get-item $ZipFile).fullname)) 110 | $zipPackage.CopyHere((get-item $File).FullName) 111 | } 112 | } 113 | 114 | 115 | function Get-ZipChildItems_Recurse 116 | { 117 | [CmdletBinding()] 118 | param( 119 | [Parameter(Mandatory=$true, 120 | ValueFromPipelineByPropertyName=$true, 121 | Position=0)] 122 | [object]$items 123 | ) 124 | 125 | foreach($si in $items) 126 | { 127 | if($si.getfolder -ne $null) 128 | { 129 | Get-ZipChildItems_Recurse $si.getfolder.items() 130 | } 131 | $si | select path 132 | } 133 | } 134 | 135 | 136 | function Get-Zip 137 | { 138 | [CmdletBinding()] 139 | Param 140 | ( 141 | [Parameter(Mandatory=$true, 142 | ValueFromPipelineByPropertyName=$true, 143 | Position=0)] 144 | [ValidateScript({Test-Path $_})] 145 | $ZipFile, 146 | $Recurse = $true 147 | ) 148 | 149 | $shellApplication = new-object -com shell.application 150 | $zipPackage = $shellApplication.NameSpace(((get-item $ZipFile).fullname)) 151 | if ($Recurse -eq $false) 152 | { 153 | $zipPackage.Items() | select path 154 | } 155 | else 156 | { 157 | Get-ZipChildItems_Recurse $zipPackage.Items() 158 | } 159 | } 160 | 161 | 162 | function Expand-Zip 163 | { 164 | [CmdletBinding()] 165 | Param 166 | ( 167 | [Parameter(Mandatory=$true, 168 | ValueFromPipelineByPropertyName=$true, 169 | Position=0)] 170 | [ValidateScript({Test-Path $_})] 171 | $ZipFile, 172 | 173 | [Parameter(Mandatory=$true, 174 | ValueFromPipelineByPropertyName=$true, 175 | Position=1)] 176 | $Destination 177 | ) 178 | 179 | if (Test-Path -PathType Container $Destination) 180 | { 181 | $destinationFolder = $shellApplication.NameSpace(((get-item $Destination).fullname)) 182 | } 183 | else 184 | { 185 | New-Item -ItemType container -Path $Destination | Out-Null 186 | $destinationFolder = $shellApplication.NameSpace(((get-item $Destination).fullname)) 187 | } 188 | 189 | $shellApplication = new-object -com shell.application 190 | $zipPackage = $shellApplication.NameSpace(((get-item $ZipFile).fullname)) 191 | $destinationFolder = $shellApplication.NameSpace(((get-item $Destination).fullname)) 192 | $destinationFolder.CopyHere($zipPackage.Items()) 193 | } 194 | 195 | 196 | <# 197 | .SYNOPSIS 198 | cmdlet for calculatingt the hash of a given file. 199 | 200 | .DESCRIPTION 201 | Calculates either the MD5, SHA1, SHA256, SHA384 or SHA512 checksum of a given file. 202 | 203 | .PARAMETER File 204 | File to hash. 205 | 206 | .PARAMETER HashAlgorithm 207 | Algorithum to use for hashing. MD5, SHA1, SHA256, SHA384 or SHA512 208 | 209 | .EXAMPLE 210 | Get-ChildItem *.dll | Get-FileHash 211 | 212 | 213 | #> 214 | function Get-FileHash 215 | { 216 | [CmdletBinding()] 217 | [OutputType([string])] 218 | param( 219 | [Parameter(Mandatory=$true, 220 | ValueFromPipelineByPropertyName=$true, 221 | Position=0)] 222 | [Alias("Name","FileName","FullName")] 223 | [ValidateScript({Test-Path $_})] 224 | $File, 225 | 226 | [ValidateSet("MD5", "SHA1", "SHA256", "SHA384", "SHA512")] 227 | $HashAlgorithm = "MD5" 228 | ) 229 | Begin 230 | { 231 | 232 | } 233 | 234 | Process 235 | { 236 | 237 | if (Test-Path (resolve-path $File).Path -PathType Leaf) 238 | { 239 | Write-Verbose "Hashing $((resolve-path $File).Path)" 240 | $hashType = [Type] "System.Security.Cryptography.$HashAlgorithm" 241 | $hasher = $hashType::Create() 242 | $inputStream = New-Object IO.StreamReader ((resolve-path $File).Path) 243 | $hashBytes = $hasher.ComputeHash($inputStream.BaseStream) 244 | $inputStream.Close() 245 | 246 | # Convert the result to hexadecimal 247 | $builder = New-Object System.Text.StringBuilder 248 | $hashBytes | Foreach-Object -Process { [void] $builder.Append($_.ToString("X2")) } 249 | # Create Object 250 | $output = New-Object PsObject -Property @{ 251 | Path = (resolve-path $file).path; 252 | HashAlgorithm = $hashAlgorithm; 253 | HashValue = $builder.ToString() 254 | } 255 | $output 256 | } 257 | } 258 | End 259 | { 260 | 261 | } 262 | } 263 | 264 | 265 | <# 266 | .Synopsis 267 | Updateds to the latest version the Sysinternals Tool Suite 268 | .DESCRIPTION 269 | Updates to the latest version the Sysinternals Tool Suite the files 270 | located in a given path using WebDav to connect to the Microsoft Servers. 271 | If the Path does not exists it will create the folder and download 272 | the tools if the force parameter is used. 273 | .EXAMPLE 274 | PS C:\> Update-SysinternalsTools -Path C:\SysinternalsSuite -Verbose 275 | 276 | Updates the to the latest version the tools in a given path 277 | 278 | .EXAMPLE 279 | PS C:\> Update-SysinternalsTools -Path C:\SysinternalsSuite -Verbose -Force 280 | 281 | Updates the to the latest version the tools in a given path and if the path 282 | does not exists it will create it. 283 | #> 284 | function Update-SysinternalsTools 285 | { 286 | [CmdletBinding()] 287 | [OutputType([int])] 288 | Param 289 | ( 290 | # Path to where update the tools 291 | [Parameter(Mandatory=$true, 292 | ValueFromPipelineByPropertyName=$true, 293 | Position=0)] 294 | [string]$Path, 295 | 296 | # Creates the directory for the tools if it does not exist. 297 | [Parameter(Mandatory=$false)] 298 | [switch]$Force 299 | 300 | ) 301 | 302 | Begin 303 | { 304 | $WebPath = "\\live.sysinternals.com\Tools" 305 | # Check if the folder exists and if we should create it before starting. 306 | if ((Test-Path $Path) -eq $false) 307 | { 308 | if ($Force -eq $true) 309 | { 310 | Write-Verbose "Creating folder $($Path)" 311 | New-Item $Path -type directory | out-null 312 | } 313 | else 314 | { 315 | Write-Error "Path $($Path) does not exist." 316 | return 317 | } 318 | } 319 | $files = Get-ChildItem -Path $WebPath -File 320 | } 321 | Process 322 | { 323 | if (Test-Path $Path) 324 | { 325 | Write-Verbose "Folder exists, collecting information of files on host." 326 | $filesonhost = @{} 327 | foreach ($tool in (Get-ChildItem -Path $Path -File)) 328 | { 329 | $filesonhost += @{$tool.name = $tool.CreationTime} 330 | } 331 | 332 | foreach ($file in $files) 333 | { 334 | if ($file.CreationTime -gt $filesonhost[$file.Name]) 335 | { 336 | Write-Verbose "$($file.Name) is newer." 337 | Write-Verbose "Downloading $($file.Name)" 338 | Copy-Item -Path $file.FullName -Destination "$($Path)\$($file.Name)" 339 | } 340 | else 341 | { 342 | write-verbose "$($file.name) is up to date." 343 | } 344 | } 345 | } 346 | else 347 | { 348 | 349 | foreach ($file in $files) 350 | { 351 | Write-Verbose "Downloading $($file.Name)" 352 | Copy-Item -Path $file.FullName -Destination "$($Path)\$($file.Name)" 353 | } 354 | 355 | } 356 | } 357 | End 358 | { 359 | } 360 | } 361 | 362 | 363 | <# 364 | .Synopsis 365 | Gets a list of the COM Objects Available on the local system. 366 | .DESCRIPTION 367 | Gets a list of the COM Objects Available on the local system. 368 | .NOTES 369 | http://www.powershellmagazine.com/2013/06/27/pstip-get-a-list-of-all-com-objects-available/ 370 | #> 371 | 372 | function Get-ComObject { 373 | 374 | param( 375 | [Parameter(Position=0)] 376 | [string]$Filter = "*" 377 | ) 378 | 379 | $ListofObjects = Get-ChildItem HKLM:\Software\Classes -ErrorAction SilentlyContinue | Where-Object { 380 | $_.PSChildName -match '^\w+\.\w+$' -and (Test-Path -Path "$($_.PSPath)\CLSID") 381 | } | Select-Object -ExpandProperty PSChildName 382 | 383 | $ListofObjects | Where-Object {$_ -like $Filter} 384 | } 385 | 386 | <# 387 | .Synopsis 388 | Gets the current installed version and the latest version of Posh-SecMod. 389 | .DESCRIPTION 390 | Gets the current installed version and the latest version of Posh-SecMod. 391 | .EXAMPLE 392 | Get-PoshSecModVersion 393 | 394 | InstalledVersion CurrentVersion 395 | ---------------- -------------- 396 | 1.1 1.1 397 | 398 | #> 399 | function Get-PoshSecModVersion 400 | { 401 | [CmdletBinding()] 402 | [OutputType([pscustomobject])] 403 | Param 404 | () 405 | 406 | Begin 407 | { 408 | $currentversion = "" 409 | $installed = Get-Module -Name "posh-secmod" -ListAvailable 410 | } 411 | Process 412 | { 413 | $webClient = New-Object System.Net.WebClient 414 | Try 415 | { 416 | $current = Invoke-Expression $webClient.DownloadString('https://raw.github.com/darkoperator/Posh-SecMod/master/Posh-SecMod.psd1') 417 | $currentversion = $current.moduleversion 418 | } 419 | Catch 420 | { 421 | Write-Warning "Could not retrieve the current version." 422 | } 423 | $majorver,$minorver = $currentversion.split(".") 424 | 425 | if ($majorver -gt $installed.Version.Major) 426 | { 427 | Write-Warning "You are running an outdated version of the module." 428 | } 429 | elseif ($minorver -gt $installed.Version.Minor) 430 | { 431 | Write-Warning "You are running an outdated version of the module." 432 | } 433 | 434 | $props = @{ 435 | InstalledVersion = $installed.Version.ToString() 436 | CurrentVersion = $currentversion 437 | } 438 | New-Object -TypeName psobject -Property $props 439 | } 440 | End 441 | { 442 | 443 | } 444 | } --------------------------------------------------------------------------------