Friday, July 18, 2014

Detecting Cryptolocker/Cryptowall by encrypted files

Have you encountered the Crypto line of ransomware? Having encountered a couple variants of this with a few of my customers, I began wondering how one would detect an infection in an enterprise environment, where recent backups are available, but users *may* not advertise they caught a virus. Detecting the encrypted files before all of your backups are overwritten would be important. How would we do this?

File headers combined with write times appears to be an effective means detection, as Encrypted file headers do not match even each-other, and write-times will be VERY close to eachother when a crypto-ransomware hits, so write-times helps weed out false positives.

Turning to powershell, I borrowed from Will at http://learningpcs.blogspot.com/2012/07/powershell-v3-check-file-headers.html. I made some minor modifications to his script, limiting the file types it targets, and causing it to search recursively through the directory tree of it's target. Enable verbose messaging and you will see the headers for any mismatches, so you can add your own if needed. This script will ONLY tell you about mismatches.


<
# http://learningpcs.blogspot.com/2012/07/powershell-v3-check-file-headers.html
# http://garcol.blogspot.com/2014/07/detecting-cryptolockercryptowall-by.html
function Check-Header
{
       param(
             $path
       )
      
       # Hexidecimal signatures for expected files
       $pdf = '25504446';
       $doc = 'D0CF11E0';
       $docx = '504B0304';
       $xls = 'D0CF11E0';
       $xls2 = '093C7461';
       $xlsx = '504B0304';

       
       $targets = Get-ChildItem -file -Path $path -recurse -include ('*.pdf','*.doc','*.docx','*.xls','*.xlsx') | select fullname, lastwritetime
       foreach ($file in $targets){     
            # Get content of each file (up to 4 bytes) for analysis
            $HeaderAsHexString = $null
            [Byte[]]$fileheader = Get-Content -Path $file.fullname -TotalCount 4 -Encoding Byte
            ForEach($_ in $fileheader) {
                if(("{0:X}" -f $_).length -eq 1)
                    {
                     $HeaderAsHexString += "0{0:X}" -f $_
                    }else{
                     $HeaderAsHexString += "{0:X}" -f $_
                    }
            }
       # Validate file header
       if (@($pdf, $doc, $docx, $xls, $xls2, $xlsx) -contains $HeaderAsHexString){
            #do nothing
            }else{
            $file
            Write-Verbose -message $HeaderAsHexString
            } 
       
    }
}


Thursday, July 3, 2014

Powershell Scripting Telnet

There are some of us out there that use appliances, equipment, or software that is still stuck with the telnet protocol. Where there are options for scripting interactions with webpages, SSH, and many other resources, I did not find many options for telnet scripting, and I'm not at the point in powershell where I could whip up a telnet client in powershell. Fortunately, Grant Carthew has already done the heavy lifting here. Below you can find a modified version of his script that allows scripting interactions through the telnet protocol, retrieving the responses so that logic can be performed on them.

Credits to the Ugly Gizmo blog, this script would not be without Grant's work.
<#
.SYNOPSIS
A modified graceful telnet scripting client using PowerShell and the .NET Framework.
 
.DESCRIPTION
This script was originally made with a view of using it to have full control over the text
stream for automating Cisco router and switch configurations. Modifications have been
added for scripting automation and logic
 
.PARAMETER TelnetHost
The address of the server or router hosting the telnet service.
 
.PARAMETER Port
The TCP port number of the Telnet service running on the Telnet host.

.NOTES
Modified: http://garcol.blogspot.com/2014/07/powershell-scripting-telnet.html
Original: http://uglygizmo.blogspot.com/2013/10/a-telnet-client-written-in-powershell.html
#>


 
param
(
    [parameter(Mandatory)]
    [String]
    $TelnetHost,
    [Int]
    $TelnetPort = 23
)
 
# Initialize variables
[System.Text.ASCIIEncoding]$ASCIIEncoding = [System.Text.Encoding]::ASCII
[System.Net.Sockets.Socket]$Socket = $null
 
# Checking host address and port.
if ($TelnetHost -match ":")
{
    $hostBytes = $TelnetHost.Split(':')
    $TelnetHost = $hostBytes[0]
    $TelnetPort = $hostBytes[1]
}
if ([String]::IsNullOrEmpty($TelnetHost))
{
    Write-Host -Object "Error: Invalid host address (null or empty)." -ForegroundColor Red
    return
}
 
# Setup and connect the TCP Socket.
$Socket = New-Object -TypeName System.Net.Sockets.Socket(
    [System.Net.Sockets.AddressFamily]::InterNetwork,
    [System.Net.Sockets.SocketType]::Stream,
    [System.Net.Sockets.ProtocolType]::Tcp)
$Socket.NoDelay = $true
try
{
    $Socket.Connect($TelnetHost, $TelnetPort)
}
catch
    {
    "Unable to connect to host {0}:{1}" -f $TelnetHost,$TelnetPort
    return
}
 
# This state object is used to pass the connected Socket and the
# PowerShell parent Host reference to the child PowerShell object.
$State = [PSCustomObject]@{"Socket"=$Socket;"Host"=$Host;"Exception"=$null;"Response"=$null}
 
# This script block is used as the receive code for the Socket
# from within the child PowerShell object.
$Script = {
    param($state)
    [string[]]$returnLog = "Started"
    # This encoding object is used to decode the return string.
    [System.Text.ASCIIEncoding]$ASCIIEncoding = [System.Text.Encoding]::ASCII
 
    # TELNET commands
    [Byte]$GA = 249 # Go Ahead
    [Byte]$WILL = 251 # Desire to begin
    [Byte]$WONT = 252 # Refusal to perform
    [Byte]$DO = 253 # Request that the other party perform
    [Byte]$DONT = 254 # Demand that the other party stop performing
    [Byte]$IAC = 255 # Interpret as Command
 
    # TELNET options
    [Byte]$ECHO = 1 # Used to check the echo mode
    [Byte]$SUPP = 3 # Suppress go ahead
    # Used to hold the number of bytes returned from the network stream.
    [Int]$bytes = 0
    # Buffer to hold the returned Bytes.
    [Byte[]]$buffer = New-Object -TypeName Byte[]($state.Socket.ReceiveBufferSize)
    # This is the main receive loop.
    while ($state.Socket.Connected)
    {
        try
        {
        # The following statement will block the thread until data is received.
        $bytes = $state.Socket.Receive($buffer)
        }
        catch
        {
        # This exception reference is used to pass the error back to the
        # parent PowerShell process.
        $state.Exception = $Error[0]
        break
        }
 
        if ($bytes -gt 0)
        {
            $index = 0
            $responseLen = 0
            # The index is used to move through the buffer to analyze the received data
            # looking for Telnet commands and options.
            while ($index -lt $bytes)
            {
                if ($buffer[$index] -eq $IAC)
                {
                    try
                    {
                        switch ($buffer[$index + 1])
                        {
                            # If two IACs are together they represent one data byte 255 
                            $IAC
                            {
                                $buffer[$responseLen++] = $buffer[$index]
                                $index += 2
                                break
                            }
                            # Ignore the Go-Ahead command
                            $GA
                            {
                                $index += 2
                                break
                            }
                            # Respond WONT to all DOs and DONTs
                            {($_ -eq $DO) -or ($_ -eq $DONT)}
                            {
                                $buffer[$index + 1] = $WONT
                                $state.Socket.Send($buffer, $index, 3,
                                [System.Net.Sockets.SocketFlags]::None) | Out-Null
                                $index += 3
                                break
                            }
                            # Respond DONT to all WONTs
                            $WONT
                            {
                                $buffer[$index + 1] = $DONT
                                $state.Socket.Send($buffer, $index, 3,
                                [System.Net.Sockets.SocketFlags]::None) | Out-Null
                                $index += 3
                                break
                            }
                            # Respond DO to WILL ECHO and WILL SUPPRESS GO-AHEAD
                            # Respond DONT to all other WILLs
                            $WILL
                            {
                                [Byte]$action = $DONT
 
                                if ($buffer[$index + 2] -eq $ECHO)
                                {
                                    $action = $DO
                                }
                                elseif ($buffer[$index + 2] -eq $SUPP)
                                {
                                    $action = $DO
                                }
 
                                $buffer[$index + 1] = $action
                                $state.Socket.Send($buffer, $index, 3,
                                    [System.Net.Sockets.SocketFlags]::None) | Out-Null
                                $index += 3;
                                break;
                            }
                        }
                    }
                    catch
                    {
                        # If there aren't enough bytes to form a command, terminate the loop.
                        $index = $bytes
                    }
                }
                else
                {
                    if ($buffer[$index] -ne 0)
                    {
                        $buffer[$responseLen++] = $buffer[$index]
                    }
                    $index++
                }
            }
            # Displays the response with no command codes on the parent PowerShell object.
            $returnString = $ASCIIEncoding.GetString($buffer, 0, $responseLen)
            $returnLog += $returnString
            #$state.Host.UI.Write($returnString)
            $state.response += $returnString
        }
    }
} # End of the child PowerShell script definition.
 
# Create a child PowerShell object to run the background Socket receive method.
$PS = [PowerShell]::Create()
$PS.AddScript($Script).AddArgument($State) | Out-Null
[System.IAsyncResult]$AsyncJobResult = $null
try
{
    # The receive job is started asynchronously.
    $AsyncJobResult = $PS.BeginInvoke()



    #YOUR TELNET COMMANDS IN HERE

    # Sends Commands
    function sendCmd($command)
    {
        # Wait, then send data.
        start-sleep -m 500
        $Data = $ASCIIEncoding.GetBytes($command)
        $Socket.Send($Data) | Out-Null
        $Socket.Send(13) | Out-Null #sends the return keystroke after each cmd
        start-sleep -m 500
    }

    ######################################################################################
    #TELNET COMMANDS IN HERE
    # Use sendCmd("") to send text commands, use $Socket.Send() to send ascii encoded keystrokes
    #

    # List of Commands to be Sent
    [string[]]$cmdList = "username"
    $cmdlist += "password"
 
    # Login
    foreach ($cmd in $cmdlist){ sendCmd($cmd) | out-null}
    

    sendCmd("show something") | out-null
    $thisData = $state.response #Can perform logic on the response here
    $state.response = $null
    
    # Issue the Exit command, closing the session gracefully
    sendCmd("exit") | out-null


    #
    #TELNET COMMANDS IN HERE
    ######################################################################################





}
finally
{   
    # Cleanup the socket and child PowerShell process.
    if ($Socket -ne $null)
    {
        $Socket.Close()
        $Socket.Dispose()
        $Socket = $null
    }
 
    if ($PS -ne $null -and $AsyncJobResult -ne $null)
    {
        $PS.EndInvoke($AsyncJobResult)
        $PS.Dispose()
    }
    
}