My antivirus evasion journey

Hi!
Several people asked me in my previous post if I could share the knowladge that I acquired during my attempts to bypass antiviruses. At the beginning, I would like to inform that it won’t be a step by step guide how to write crypter, but more likely a hint to people that are struggling with same problem. And please do not use this knowladge in any evil purposes. Don’t be an asshole and don’t hack anyone please, it’s more satisfying to open FUD reverse shell on a good CTF :smile:

Antivirus bypass concept.
So the concept is not really hard to understand. You have a detectable payload (for example reverse shell) and to make it undetectable you have to execute it directly in memory. To make that, you have to write something called “Stub”. Stub is a program that holds encrypted payload inside it and when it gets executed, it decrypts payload bytes and loads them directly to memory using something called Process Hollowing. This technique bypasses antivirus scans. Sounds easy in theory but it’s much harder to actually write it FUD. It’s not really a big deal to write method that will have copy-pasted RunPE from github, encrypted payload bytes which are attached to the Stub. It would work a few years ago but now antiviruses are armed with advanced scantime and runtime protection + often they have sandboxes supported by AI.

Making your stub actually FUD
I couldn’t really find any tutorial/guide how to keep my stub undetectable, so I decided to write a few different stubs and just test which of them are least detectable and then make different versions of these least detectable and check which are least detectable of them. Some sort of machine learning :grinning_face_with_smiling_eyes:
And this are my results:

  • Do not attach not encrypted payload to your stub.
  • Do not attempt any internet connection with your stub
  • If you are writing stub in C# try not to use Assembly.Load, Assembly.GetTypes etc.
  • Try executing RunPE at runtime, don’t copy-paste it into your main Stub, it will give you a lot of detections
  • Write Stub as small as possible and as simple as you can and it will drastically reduce scantime detections. There are many functions that can be used to execute RunPE at runtime, just think creatively and test it.
  • You need to write it completly by yourself, you can’t use someones techinques because they will be probably already detectable
  • Changing icon and assembly information of your binary helps A LOT.
  • Write your own obfuscator.
  • Write your own junk code generator
  • Write your own antisandbox
  • Antisandbox has to be really simple, do not overengineer it. Try not looking through processes and files. ESET might be triggered by this.
  • Your payload quality also matters. If you want to open reverse shell I recommend you writing it by yourself, because shells such as meterpreter can be detected when you try to execute some of their functions for instance open remote powershell/cmd. (It depends on the AV)
  • If you want to stall, do it using winapi. Don’t use Sleep(time) or Thread.Sleep(time) because AVs can skip it
  • It’s like a cat and mouse game, it will take you a time to make it completly FUD, because some functions that can bypass 1 AV can trigger 5 different AVs
  • AMSI Bypass doesn’t work with all AVs, it even triggers some. For example Defender can be bypassed, ESET doesn’t care and Avast will kill your process but won’t do anything despite this.
  • Don’t do tests on Virustotal. Only on sites which are not distributing samples: antiscan.me or kleenscan.com

If you have any questions or I made a mistake in my post just write them down in the comments below.

13 Likes

Nice , You kept it short and sweet , thanks for the post.

3 Likes

This is a pretty good thread

3 Likes

A very basic overview of some of these things that you are talking about:

One part that it touches on and you did as well, is “stalling” or “delaying” execution. Using something like NtDelayExecution to just hold off executing for a moderate amount of time seems to be the best way to counter AV detection, and even sandboxing because of the time it is expected to provide analysis. Is this technique just trivial or worth leveraging more if time isn’t of the essence?

Reference: NtDelayExecution

3 Likes

Hi thanks for this thread.
Do you have any alternative for Assembly.Load() in C# ? I’m pretty new to this language and to “learn” it i’ve written my own builder and stub, that was not hard (using ofc Assembly.Load), but the detection rate is pretty scary as expected. I’ve seen this repo https://github.com/gigajew/WinXRunPE but to be honest i don’t want to just copy/paste someone else work, i’d like to write something i understand not only something that just works. If you have any hints, i’ll be glad to do my research and post an update if it’s successful.

2 Likes

Pretty neat threat. Thanks.

1 Like