Adding Get-ComputerDetails recon script
Get-ComputerDetails is a recon script which pulls a variety of useful information off a computer which might later be useful by an attacker. This includes: Logons AppLocker process start logs PowerShell logs to find scripts run RDP Client saved servers
This commit is contained in:
parent
b684da050a
commit
308042f493
|
|
@ -0,0 +1,438 @@
|
||||||
|
function Get-ComputerDetails
|
||||||
|
{
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
|
||||||
|
This script is used to get useful information from a computer.
|
||||||
|
|
||||||
|
Function: Get-ComputerDetails
|
||||||
|
Author: Joe Bialek, Twitter: @JosephBialek
|
||||||
|
Required Dependencies: None
|
||||||
|
Optional Dependencies: None
|
||||||
|
Version: 1.0
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
|
||||||
|
This script is used to get useful information from a computer. Currently, the script gets the following information:
|
||||||
|
-Explicit Credential Logons (Event ID 4648)
|
||||||
|
-Logon events (Event ID 4624)
|
||||||
|
-AppLocker logs to find what processes are created
|
||||||
|
-PowerShell logs to find PowerShell scripts which have been executed
|
||||||
|
-RDP Client Saved Servers, which indicates what servers the user typically RDP's in to
|
||||||
|
|
||||||
|
.PARAMETER ToString
|
||||||
|
|
||||||
|
Switch: Outputs the data as text instead of objects, good if you are using this script through a backdoor.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
|
||||||
|
Get-ComputerDetails
|
||||||
|
Gets information about the computer and outputs it as PowerShell objects.
|
||||||
|
|
||||||
|
Get-ComputerDetails -ToString
|
||||||
|
Gets information about the computer and outputs it as raw text.
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
This script is useful for fingerprinting a server to see who connects to this server (from where), and where users on this server connect to.
|
||||||
|
You can also use it to find Powershell scripts and executables which are typically run, and then use this to backdoor those files.
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
|
||||||
|
Blog: http://clymb3r.wordpress.com/
|
||||||
|
Github repo: https://github.com/clymb3r/PowerShell
|
||||||
|
|
||||||
|
#>
|
||||||
|
|
||||||
|
Param(
|
||||||
|
[Parameter(Position=0)]
|
||||||
|
[Switch]
|
||||||
|
$ToString
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version 2
|
||||||
|
|
||||||
|
#Retrieve the 4648 logon event. This will often find cases where a user is using remote desktop to connect to another computer. It will give the
|
||||||
|
#the account that RDP was launched with and the account name of the account being used to connect to the remote computer. This is useful
|
||||||
|
#for identifying normal authenticaiton patterns. Other actions that will trigger this include any runas action.
|
||||||
|
function Find-ExplicitLogons
|
||||||
|
{
|
||||||
|
Param(
|
||||||
|
$SecurityLog
|
||||||
|
)
|
||||||
|
|
||||||
|
$ExplicitLogons = $SecurityLog | Where {$_.InstanceID -eq 4648}
|
||||||
|
$ReturnInfo = @{}
|
||||||
|
|
||||||
|
foreach ($ExplicitLogon in $ExplicitLogons)
|
||||||
|
{
|
||||||
|
$Subject = $false
|
||||||
|
$AccountWhosCredsUsed = $false
|
||||||
|
$TargetServer = $false
|
||||||
|
$SourceAccountName = ""
|
||||||
|
$SourceAccountDomain = ""
|
||||||
|
$TargetAccountName = ""
|
||||||
|
$TargetAccountDomain = ""
|
||||||
|
$TargetServer = ""
|
||||||
|
foreach ($line in $ExplicitLogon.Message -split "\r\n")
|
||||||
|
{
|
||||||
|
if ($line -cmatch "^Subject:$")
|
||||||
|
{
|
||||||
|
$Subject = $true
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^Account\sWhose\sCredentials\sWere\sUsed:$")
|
||||||
|
{
|
||||||
|
$Subject = $false
|
||||||
|
$AccountWhosCredsUsed = $true
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^Target\sServer:")
|
||||||
|
{
|
||||||
|
$AccountWhosCredsUsed = $false
|
||||||
|
$TargetServer = $true
|
||||||
|
}
|
||||||
|
elseif ($Subject -eq $true)
|
||||||
|
{
|
||||||
|
if ($line -cmatch "\s+Account\sName:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$SourceAccountName = $Matches[1]
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "\s+Account\sDomain:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$SourceAccountDomain = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($AccountWhosCredsUsed -eq $true)
|
||||||
|
{
|
||||||
|
if ($line -cmatch "\s+Account\sName:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$TargetAccountName = $Matches[1]
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "\s+Account\sDomain:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$TargetAccountDomain = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($TargetServer -eq $true)
|
||||||
|
{
|
||||||
|
if ($line -cmatch "\s+Target\sServer\sName:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$TargetServer = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Filter out logins that don't matter
|
||||||
|
if (-not ($TargetAccountName -cmatch "^DWM-.*" -and $TargetAccountDomain -cmatch "^Window\sManager$"))
|
||||||
|
{
|
||||||
|
$Key = $SourceAccountName + $SourceAccountDomain + $TargetAccountName + $TargetAccountDomain + $TargetServer
|
||||||
|
if (-not $ReturnInfo.ContainsKey($Key))
|
||||||
|
{
|
||||||
|
$Properties = @{
|
||||||
|
LogType = 4648
|
||||||
|
LogSource = "Security"
|
||||||
|
SourceAccountName = $SourceAccountName
|
||||||
|
SourceDomainName = $SourceAccountDomain
|
||||||
|
TargetAccountName = $TargetAccountName
|
||||||
|
TargetDomainName = $TargetAccountDomain
|
||||||
|
TargetServer = $TargetServer
|
||||||
|
Count = 1
|
||||||
|
Times = @($ExplicitLogon.TimeGenerated)
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResultObj = New-Object PSObject -Property $Properties
|
||||||
|
$ReturnInfo.Add($Key, $ResultObj)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ReturnInfo[$Key].Count++
|
||||||
|
$ReturnInfo[$Key].Times += ,$ExplicitLogon.TimeGenerated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ReturnInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
#Find all Logon events to the server. This will tell you who is logging in and how. You can use this to figure out what accounts do
|
||||||
|
# network logons in to the server, what accounts RDP in, what accounts log in locally, etc...
|
||||||
|
# This is event 4624.
|
||||||
|
function Find-AllLogons
|
||||||
|
{
|
||||||
|
Param (
|
||||||
|
$SecurityLog
|
||||||
|
)
|
||||||
|
|
||||||
|
$Logons = $SecurityLog | Where {$_.InstanceID -eq 4624}
|
||||||
|
$ReturnInfo = @{}
|
||||||
|
|
||||||
|
foreach ($Logon in $Logons)
|
||||||
|
{
|
||||||
|
$SubjectSection = $false
|
||||||
|
$NewLogonSection = $false
|
||||||
|
$NetworkInformationSection = $false
|
||||||
|
$AccountName = ""
|
||||||
|
$AccountDomain = ""
|
||||||
|
$LogonType = ""
|
||||||
|
$NewLogonAccountName = ""
|
||||||
|
$NewLogonAccountDomain = ""
|
||||||
|
$WorkstationName = ""
|
||||||
|
$SourceNetworkAddress = ""
|
||||||
|
$SourcePort = ""
|
||||||
|
|
||||||
|
foreach ($line in $Logon.Message -Split "\r\n")
|
||||||
|
{
|
||||||
|
if ($line -cmatch "^Subject:$")
|
||||||
|
{
|
||||||
|
$SubjectSection = $true
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^Logon\sType:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$LogonType = $Matches[1]
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^New\sLogon:$")
|
||||||
|
{
|
||||||
|
$SubjectSection = $false
|
||||||
|
$NewLogonSection = $true
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^Network\sInformation:$")
|
||||||
|
{
|
||||||
|
$NewLogonSection = $false
|
||||||
|
$NetworkInformationSection = $true
|
||||||
|
}
|
||||||
|
elseif ($SubjectSection)
|
||||||
|
{
|
||||||
|
if ($line -cmatch "^\s+Account\sName:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$AccountName = $Matches[1]
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^\s+Account\sDomain:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$AccountDomain = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($NewLogonSection)
|
||||||
|
{
|
||||||
|
if ($line -cmatch "^\s+Account\sName:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$NewLogonAccountName = $Matches[1]
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^\s+Account\sDomain:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$NewLogonAccountDomain = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($NetworkInformationSection)
|
||||||
|
{
|
||||||
|
if ($line -cmatch "^\s+Workstation\sName:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$WorkstationName = $Matches[1]
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^\s+Source\sNetwork\sAddress:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$SourceNetworkAddress = $Matches[1]
|
||||||
|
}
|
||||||
|
elseif ($line -cmatch "^\s+Source\sPort:\s+(\S.*)")
|
||||||
|
{
|
||||||
|
$SourcePort = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Filter out logins that don't matter
|
||||||
|
if (-not ($NewLogonAccountDomain -cmatch "NT\sAUTHORITY" -or $NewLogonAccountDomain -cmatch "Window\sManager"))
|
||||||
|
{
|
||||||
|
$Key = $AccountName + $AccountDomain + $NewLogonAccountName + $NewLogonAccountDomain + $LogonType + $WorkstationName + $SourceNetworkAddress + $SourcePort
|
||||||
|
if (-not $ReturnInfo.ContainsKey($Key))
|
||||||
|
{
|
||||||
|
$Properties = @{
|
||||||
|
LogType = 4624
|
||||||
|
LogSource = "Security"
|
||||||
|
SourceAccountName = $AccountName
|
||||||
|
SourceDomainName = $AccountDomain
|
||||||
|
NewLogonAccountName = $NewLogonAccountName
|
||||||
|
NewLogonAccountDomain = $NewLogonAccountDomain
|
||||||
|
LogonType = $LogonType
|
||||||
|
WorkstationName = $WorkstationName
|
||||||
|
SourceNetworkAddress = $SourceNetworkAddress
|
||||||
|
SourcePort = $SourcePort
|
||||||
|
Count = 1
|
||||||
|
Times = @($Logon.TimeGenerated)
|
||||||
|
}
|
||||||
|
|
||||||
|
$ResultObj = New-Object PSObject -Property $Properties
|
||||||
|
$ReturnInfo.Add($Key, $ResultObj)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ReturnInfo[$Key].Count++
|
||||||
|
$ReturnInfo[$Key].Times += ,$Logon.TimeGenerated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ReturnInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
#Look through the AppLocker logs to find processes that get run on the server. You can then backdoor these exe's (or figure out what they normally run).
|
||||||
|
function Find-AppLockerLogs
|
||||||
|
{
|
||||||
|
$ReturnInfo = @{}
|
||||||
|
|
||||||
|
$AppLockerLogs = Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL" -ErrorAction SilentlyContinue | Where {$_.Id -eq 8002}
|
||||||
|
|
||||||
|
foreach ($Log in $AppLockerLogs)
|
||||||
|
{
|
||||||
|
$SID = New-Object System.Security.Principal.SecurityIdentifier($Log.Properties[7].Value)
|
||||||
|
$UserName = $SID.Translate( [System.Security.Principal.NTAccount])
|
||||||
|
|
||||||
|
$ExeName = $Log.Properties[10].Value
|
||||||
|
|
||||||
|
$Key = $UserName.ToString() + "::::" + $ExeName
|
||||||
|
|
||||||
|
if (!$ReturnInfo.ContainsKey($Key))
|
||||||
|
{
|
||||||
|
$Properties = @{
|
||||||
|
Exe = $ExeName
|
||||||
|
User = $UserName.Value
|
||||||
|
Count = 1
|
||||||
|
Times = @($Log.TimeCreated)
|
||||||
|
}
|
||||||
|
|
||||||
|
$Item = New-Object PSObject -Property $Properties
|
||||||
|
$ReturnInfo.Add($Key, $Item)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ReturnInfo[$Key].Count++
|
||||||
|
$ReturnInfo[$Key].Times += ,$Log.TimeCreated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ReturnInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
#Go through the PowerShell operational log to find scripts that run (by looking for ExecutionPipeline logs eventID 4100 in PowerShell app log).
|
||||||
|
#You can then backdoor these scripts or do other malicious things.
|
||||||
|
Function Find-PSScriptsInPSAppLog
|
||||||
|
{
|
||||||
|
$ReturnInfo = @{}
|
||||||
|
$Logs = Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -ErrorAction SilentlyContinue | Where {$_.Id -eq 4100}
|
||||||
|
|
||||||
|
foreach ($Log in $Logs)
|
||||||
|
{
|
||||||
|
$ContainsScriptName = $false
|
||||||
|
$LogDetails = $Log.Message -split "`r`n"
|
||||||
|
|
||||||
|
$FoundScriptName = $false
|
||||||
|
foreach($Line in $LogDetails)
|
||||||
|
{
|
||||||
|
if ($Line -imatch "^\s*Script\sName\s=\s(.+)")
|
||||||
|
{
|
||||||
|
$ScriptName = $Matches[1]
|
||||||
|
$FoundScriptName = $true
|
||||||
|
}
|
||||||
|
elseif ($Line -imatch "^\s*User\s=\s(.*)")
|
||||||
|
{
|
||||||
|
$User = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($FoundScriptName)
|
||||||
|
{
|
||||||
|
$Key = $ScriptName + "::::" + $User
|
||||||
|
|
||||||
|
if (!$ReturnInfo.ContainsKey($Key))
|
||||||
|
{
|
||||||
|
$Properties = @{
|
||||||
|
ScriptName = $ScriptName
|
||||||
|
UserName = $User
|
||||||
|
Count = 1
|
||||||
|
Times = @($Log.TimeCreated)
|
||||||
|
}
|
||||||
|
|
||||||
|
$Item = New-Object PSObject -Property $Properties
|
||||||
|
$ReturnInfo.Add($Key, $Item)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ReturnInfo[$Key].Count++
|
||||||
|
$ReturnInfo[$Key].Times += ,$Log.TimeCreated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ReturnInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
#Search the registry to find saved RDP client connections. This shows you what connections an RDP client has remembered, indicating what servers the user
|
||||||
|
#usually RDP's to.
|
||||||
|
Function Find-RDPClientConnections
|
||||||
|
{
|
||||||
|
$ReturnInfo = @{}
|
||||||
|
|
||||||
|
New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null
|
||||||
|
|
||||||
|
#Attempt to enumerate the servers for all users
|
||||||
|
$Users = Get-ChildItem -Path "HKU:\"
|
||||||
|
foreach ($User in $Users.PSChildName)
|
||||||
|
{
|
||||||
|
$Servers = Get-ChildItem "HKU:\$($User)\Software\Microsoft\Terminal Server Client\Servers" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
foreach ($Server in $Servers)
|
||||||
|
{
|
||||||
|
$Server = $Server.PSChildName
|
||||||
|
$UsernameHint = (Get-ItemProperty -Path "HKU:\$($User)\Software\Microsoft\Terminal Server Client\Servers\$($Server)").UsernameHint
|
||||||
|
|
||||||
|
$Key = $User + "::::" + $Server + "::::" + $UsernameHint
|
||||||
|
|
||||||
|
if (!$ReturnInfo.ContainsKey($Key))
|
||||||
|
{
|
||||||
|
$Properties = @{
|
||||||
|
CurrentUser = $User
|
||||||
|
Server = $Server
|
||||||
|
UsernameHint = $UsernameHint
|
||||||
|
}
|
||||||
|
|
||||||
|
$Item = New-Object PSObject -Property $Properties
|
||||||
|
$ReturnInfo.Add($Key, $Item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ReturnInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$SecurityLog = Get-EventLog -LogName Security
|
||||||
|
$Filtered4624 = Find-AllLogons $SecurityLog
|
||||||
|
$Filtered4648 = Find-ExplicitLogons $SecurityLog
|
||||||
|
$AppLockerLogs = Find-AppLockerLogs
|
||||||
|
$PSLogs = Find-PSScriptsInPSAppLog
|
||||||
|
$RdpClientData = Find-RDPClientConnections
|
||||||
|
|
||||||
|
if ($ToString)
|
||||||
|
{
|
||||||
|
Write-Output "Event ID 4624 (Logon):"
|
||||||
|
Write-Output $Filtered4624.Values | Format-List
|
||||||
|
Write-Output "Event ID 4648 (Explicit Credential Logon):"
|
||||||
|
Write-Output $Filtered4648.Values | Format-List
|
||||||
|
Write-Output "AppLocker Process Starts:"
|
||||||
|
Write-Output $AppLockerLogs.Values | Format-List
|
||||||
|
Write-Output "PowerShell Script Executions:"
|
||||||
|
Write-Output $PSLogs.Values | Format-List
|
||||||
|
Write-Output "RDP Client Data:"
|
||||||
|
Write-Output $RdpClientData.Values | Format-List
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$Properties = @{
|
||||||
|
LogonEvent4624 = $Filtered4624.Values
|
||||||
|
LogonEvent4648 = $Filtered4648.Values
|
||||||
|
AppLockerProcessStart = $AppLockerLogs.Values
|
||||||
|
PowerShellScriptStart = $PSLogs.Values
|
||||||
|
RdpClientData = $RdpClientData.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
$ReturnObj = New-Object PSObject -Property $Properties
|
||||||
|
return $ReturnObj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -74,7 +74,7 @@ ModuleList = @(@{ModuleName = 'Recon'; ModuleVersion = '1.0.0.0'; GUID = '7e775a
|
||||||
|
|
||||||
# List of all files packaged with this module
|
# List of all files packaged with this module
|
||||||
FileList = 'Recon.psm1', 'Recon.psd1', 'Get-HttpStatus.ps1', 'Invoke-ReverseDnsLookup.ps1',
|
FileList = 'Recon.psm1', 'Recon.psd1', 'Get-HttpStatus.ps1', 'Invoke-ReverseDnsLookup.ps1',
|
||||||
'Invoke-Portscan.ps1', 'Usage.md'
|
'Invoke-Portscan.ps1', 'Get-ComputerDetails', 'Usage.md'
|
||||||
|
|
||||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||||
# PrivateData = ''
|
# PrivateData = ''
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue