Creating stealthy malware for Windows
(Villain C2 framework + PowerShell obfuscation + undetectable delivery)
DISCLAIMER: Using these tools and techniques against hosts for which you do not have explicit permission to test is illegal. You are responsible for any consequences that may result from using these tools and methods.
Antivirus and Windows Defender use a combination of signature and behavioral detection, as well as advanced AI solutions, to identify and block malware or attempts to connect to a C2 server. Signature-based detection is generally the easiest to bypass, but it is more difficult for attackers to overcome analysis performed on the host during script execution, such as using AMSI. I discovered an interesting tool called Villain and decided to find a way to use it to bypass modern antivirus solutions, or at least the current version of Windows Defender, which is focused on identifying threats in real time.
Villain
Villain is a C2 framework capable of working with multiple TCP sockets and HoaxShell-based reverse connections, as well as extending their functionality. This framework is extremely easy to use: just create a payload and insert it on the target system – it even automatically launches listeners! However, when Windows Defender is enabled, you will notice that the standard one is instantly flagged as malicious.
I decided to research obfuscation techniques and found the following resource from the same author: https://github.com/t3l3machus/PowerShell-Obfuscation-Bible – A collection of techniques, examples and a small amount of theoretical foundations for manual obfuscation of PowerShell scripts.
To change the signature, I first did a few things:
Inserted random comments and spaces into the script
Created variables with arbitrary names encoded in hexadecimal format
Added random quotes inside iex and pwd
None of this worked. About 9 months ago, in 2023, it was possible to simply change certain parts of the script, such as replacing iex with i''e''x, or changing standard variable names, such as $data to $3e59da34d2. But in 2024, creating stealthy malware requires some trial and error.
I then decided to try breaking down the command arguments to determine the point at which the antivirus detects them as malicious. I found that separating the first variable, which creates the TCPClient socket with the attacker's host, from the rest of the script did not trigger anything, and I ended up with a shell on Villain.
Now I needed to combine both parts of the Villain PowerShell script so that they ran separately but still ran together. I decided to use the Get-Command technique with wildcards mentioned in the above resource. The & operator runs commands as jobs. Essentially, it extracts the string itself from the specified URI (in this case our scripts) and then executes that string (command) using Invoke-Expression, which also uses a wildcard to bypass the detection. The two Get-Commands look unusual in this way to reduce the Shannon entropy, which might otherwise be too high and trigger the antivirus:
To do this on a Windows host from the command line, I needed to do a few things:
1. I created two PS scripts called stage1.ps1 and stage2.ps1, which contain the first and second parts of the Villain PS script, respectively (I added other obfuscation methods to demonstrate the concept, although this is not necessary). These scripts will be executed on the target host with IP address 10.0.2.5.
2. Host these scripts on a web server on my attack host with IP address 10.0.2.9 (via an unblocked port such as 80 or 443) to transmit them to the victim.
Wait – that's great, but I want to get a shell by forcing the user to download or open something inconspicuous. To do this, I used Invoke-PS2EXE on my Windows host to convert the two PowerShell scripts above into a Windows executable, and then used WinRAR to make it look like a regular Chrome executable (that'll be another post if you don't know how do it).
One of the things I noticed is that when a user opened an infected Chrome executable, a command prompt window would appear which the user could easily close and terminate my shell session. To get around this, I packaged a simple VBS script with a malicious executable and a clean Chrome browser (in WinRaR) that simply launched the malicious executable without a window appearing – without giving the user the option to stop our shell 🙂
Now all that remains is to use social engineering to force the user to download this seemingly harmless executable file or place it there themselves with existing access. Windows Defender is activated on the victim's machine.
When a user double-clicks our malicious chrome executable, stage1.ps1 and stage2.ps1 are downloaded and executed from our server, a session is then created on Villain, and eventually Google Chrome opens as normal for the user.
Attackers will have to work hard to get around this year's updated defenses, but it's far from impossible, even with real-time analysis. I hope you enjoyed this post!
BONUS: C2 via internet
Pagekite – fast and reliable solution for tunneling local hosting
Pagekite can be used to deliver and execute our PS scripts over the internet instead of a local network. Sign up with a valid email address for a 30-day free trial. You can also use a cheap VPS with a public IP address to receive a netcat reverse shell generated using Villain.
First, change the IP address of your attacking machine to the IP address of the public VPS so that we can connect via the Internet.
Next, create a web server that will host the stage1.ps1 and stage2.ps1 files on our PageKite FQDN, which will look like python3.pagekite.me.
Finally, modify the test.ps1 script so that it downloads files from PageKite rather than localhost. Then convert it into an executable file as before and send it to the victim.
On our VPS, open Villain and wait for a connection via the Internet (you may need to configure port forwarding).
Now we get a reverse shell using PageKite and VPS.