#Get-GroupHierarchy.ps1 #Alan dot Kaplan at VA dot GOV 4/9/2015 #This is based in large part on the code at http://powershell.com/cs/forums/t/9588.aspx #by Irwin Strachan 04-11-2012 #I added support of multiple domains, added logging, error handling, changed indents, #prompt for group name import-module activedirectory -NoClobber $GroupList = @{} $indent = "" Function Get-NTNameFromDN($DNPath){ #Based on #http://www.itadmintools.com/2011/09/translate-active-directory-name-formats.html #Intialize NameTranlate ComObject $oNameTrans=New-Object -ComObject NameTranslate #Initialize with Global Catalog search ADS_NAME_INITTYPE_GC=3 [System.__ComObject].InvokeMember(“init”,”InvokeMethod”,$null,$oNameTrans,(3,$null)) #Take anything as input NameType UNKNOWN = 8 [System.__ComObject].InvokeMember(“Set”,”InvokeMethod”,$null,$oNameTrans,(8,$DNPath)) #Return in format NTDNAME=3 $NTName = [System.__ComObject].InvokeMember(“Get”,”InvokeMethod”,$null,$oNameTrans,3) [System.Runtime.Interopservices.Marshal]::ReleaseComObject($oNameTrans) | Out-Null Return $NTName } Function EchoAndLog { param([string] $strText) #Echo to host and append to file Tee-Object -Append -FilePath $logfile -inputobject $strText } Function Enum-Group { param ( [Parameter(Mandatory=$true)] [String]$SearchGroup ) $a = $SearchGroup.Split("\") $SearchGroupName = $a[1].ToString().Trim() $SearchDomain = $a[0].ToString().Trim() try{ get-adgroup -identity $SearchGroupName -Server $SearchDomain -ErrorAction SilentlyContinue }Catch{ Write-Warning $Error[0].Exception.Message break } $groupMembers = get-adgroupmember -identity $SearchGroupName -Server $SearchDomain | sort-object objectClass -descending foreach ($member in $groupMembers) { [string]$FullSAMName = Get-NTNameFromDN $member.DistinguishedName #uncomment to add member DN $msg = $indent+$member.objectClass+": "+$member.name+" "+$FullSAMName #+" "+$member.distinguishedName echoandlog $msg if (!($GroupList.ContainsKey($member.name))) { if ($member.ObjectClass -eq "group") { $GroupList.add($member.name,$member.name) $indent = "`t" * ($indent.length + 1) Enum-Group $FullSAMName $indent = "`t" * ($indent.length - 1) } } Else { $msg = $indent+"Group:"+$member.name+" has already been processed, or there is loop... Please verify." EchoAndLog $msg } } } Function Get-GroupHierarchy{ if ($fullSamName.Length -eq 0){ Write-Warning "User Exit" exit } $logfile = "$env:userprofile\desktop\"+$fullSamName.replace("\","_")+"_GroupEnum.txt" if ((Test-Path $logfile) -eq $true){ri $logfile} EchoAndLog $FullSamName Enum-Group $FullSamName } $exampleGroup = "$env:USERDOMAIN\MyGroupNTName" Add-Type -assemblyname Microsoft.visualBasic $msg = "Enter the NT account name of a group to recursively enumerate." $FullSamName = [Microsoft.VisualBasic.Interaction]::InputBox($msg, "Group Account Name", $exampleGroup) Get-GroupHierarchy $FullSamName ii $logfile