Antivirus Evasion for Penetration Testing Engagements
#1
Antivirus Evasion for Penetration Testing Engagements

During a penetration testing engagement, it’s quite common to have antivirus software applications installed in a client’s computer. This makes it quite challenging for the penetration tester to run common tools while giving the clients a perception that their systems are safe but that’s not always the case. Antivirus software applications do help in protecting systems but there are still cases where these defenses can be bypassed. 

Antivirus evasion is a broad topic and this article only presents very basic methods to bypass detection when the program is resting as a file in a non-volatile storage. Evasion techniques for a run time state are quite different and challenging at the same time because of behavior monitoring done by antiviruses.

In this article, I will be discussing a few techniques that can be used to bypass antivirus software applications like string manipulation and code substitution. Before anything else however, an understanding of programming is required because I’ll assume that the detected software application has its source code available for modification. I’ll probably work out another separate article for evasion of programs that don’t have their source code available soon.

There will be two basic steps to do. First will be finding the cause of the detection while the next step goes into how the detection can be bypassed. This is because we won’t be able to fix something if we don’t know what the problem is right? 

Looking for the Origin of the Detection

For the demonstration, I will be using an object-oriented language specifically C# with the help of Visual Studio 2012. I grabbed a snippet from here specifically the functions “startup” and “USBSpread” while creating a new project to put both of these. This is what it looks like after creating a console project in C#:

[Image: anti_virus_evasion_1.png]

Please note that I have minimized the region of the code in the screenshot above to make it short. I’ll leave the credits where it is due for both those functions. After compiling the project and scanning it in VirusTotal, the result shows two antiviruses detecting it namely ESET and Sophos.  

[Image: anti_virus_evasion_2.png]

Please forgive me. If any of you are not familiar, VirusTotal actually distributes copies of a scanned file especially if a few antiviruses detect it. Chances are that if ever you are reading this right now, the scan results might have changed already when you visit the link. This endangers your tool to become detected very fast and should not be used for scanning when you are developing a penetration testing tool to be used for legal assessments.

Now here comes the fun part. How can we find out what’s causing the detection? Since we have a copy of the source code, what we can do is remove parts of the code line by line and rescan it. To start off, I have commented out the whole “USBSpread” function as seen below:

[Image: anti_virus_evasion_3.png]

Compiling this and scanning in VirusTotal will give us a result of: 

[Image: anti_virus_evasion_4.png]
 
Notice that only ESET is now detecting it and the detection previously shown by Sophos disappeared. Uncomment the function “USBSpread” and then comment out the function “startup” as seen below:

[Image: anti_virus_evasion_5.png]  

The result after rescanning in VirusTotal will be:

[Image: anti_virus_evasion_6.png]

As you have guessed, the detection found by ESET now disappeared and Sophos has reappeared. From what we did, we can conclude that having the “startup” function actually triggers detection from ESET while having the “USBSpread” function actually triggers detection from Sophos. Sounds easy to identify the detection right? 

Bypassing the Detection

After being able to identify where the detection came from, we can now try to work out how it can be bypassed. Note that the identification process shown above is in general terms. To successfully bypass the antivirus detecting it, we need to continuously do the previous step while working on a fix line by line. To add up, I’ve listed a few methods like string manipulation and code substitution that usually work but sometimes also trigger more detection so these methods are quite “experimental”.

String Manipulation

This method simply points to how a normal string can be converted into another form while being evaluated with the same meaning. To understand this better, suppose we have a registry path:

Code:
SOFTWARE\Microsoft\Windows\CurrentVersion\Run

In C#, if we declare this, it should look something like:

[Image: anti_virus_evasion_20.png]

There are numerous ways on how we can change the form of that string while maintaining the original meaning when the code executes. Here are some very basic ways to do it:

Base64

Using an encoder tool, enter the string “SOFTWARE\Microsoft\Windows\CurrentVersion\Run” and click “encode”. You should get something like this as the result: 

[Image: anti_virus_evasion_21.png]

Now we copy that string back to the source code with the following evaluator and notice that when the program runs, the string still gets evaluated to the original form:

[Image: anti_virus_evasion_22.png]

ASCII Representation

This is a pretty simple solution and it actually works sometimes too! Converting the string to its numeric ASCII form looks like this:

[Image: anti_virus_evasion_23.png]

In the image above, I have converted the “\” character into its numeric ASCII form. If we check out the ASCII table, the character “\” is equivalent to 92 in decimal. Doing some other simple calculations basically differentiate the original code from the current one.

Encryption can also take part in this like having your string encrypted and written down to a binary file. The program can then load it by browsing and decrypting the contents during execution or so. There are lots of possible methods for string manipulation and this is basically where your creativity goes. 

Code Substitution

This method on the other hand requires more in-depth knowledge of programming because it requires understanding of what a specific line of code or what a specific function does. For example, suppose we have a code that downloads the contents of a web page:

[Image: anti_virus_evasion_24.png]

With code substitution, an understanding of what the code does is essential because we will need to find a replacement of the code by commands while achieving the same logic and goal at the end. In this case, the goal of the code above tries to get the client IP address in the network where the program is running. This can also be achieved with the use of this code:

[Image: anti_virus_evasion_25.png]

Notice that the output is the same which means the code logic does the same functionality and goal but the way it is done is different. If ever the first code is detected by a few antiviruses, it can be substituted with the next one or vice-versa. There are other more ways to grab the IP address but I’ll leave that part as a research for the readers. 

Going back to the example program, let’s start with Sophos. At this point, the function “startup” is commented out to stop ESET from detecting it while we fix the first one. This antivirus was previously detecting the method “USBSpread” and after some trial and error, the detection was still popping up even after commenting out the whole function contents:

[Image: anti_virus_evasion_7.png]

[Image: anti_virus_evasion_8.png]


This simply means that Sophos gets angry when the function name is “USBSpread” so we change it to “ThisIsATest” and by scanning it again, we get:

[Image: anti_virus_evasion_9.png]

By doing the process again, we uncomment out the function contents as seen here:

[Image: anti_virus_evasion_10.png]

Once uploaded for scanning in VirusTotal, the result was 0/65!

[Image: anti_virus_evasion_11.png]

Sophos in this case was basically just finding that function name and flagged it as malicious. To proceed, we now do the same steps for the “startup” function and the specific line that started the detection by ESET was:

[Image: anti_virus_evasion_12.png]

Since there are parameters in the line and one of the parameters is a string, we will need to separate it to another line so we can confirm what is being detected by ESET. A variable “temp” was assigned to hold the string representation of the registry path for this:

[Image: anti_virus_evasion_13.png]

Scanning on the other hand still leaves us with an angry ESET here: 

[Image: anti_virus_evasion_14.png]


This confirms that the string is the one being detected by ESET. Below is a short test case that I have tried so far:

Test Cases:

  1. Reversed the string making it “nuR\\noisreVtnerruC\\swodniW\\tfosorciM\\ERAWTFOS” -  Another detection popped up
  2. Moving the variable outside the function making it a global variable:
    Code:
    static string temp = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
    - ESET still detecting
  3. Converting each characters to their decimal number equivalent in the ASCII table:
    Code:
    static string temp = ((char)83).ToString() + ((char)79).ToString() ... ;
    - ESET still detecting
  4. Removed the string contents after “SOFTWARE” leaving: string temp = “SOFTWARE”; - ESET still detecting
At this point, ESET was still detecting the program even if the registry path doesn’t really make sense anymore so this might not be the “real” thing being flagged by ESET or there is another line of code in which if combined with the current string, gets detected. Once this happens, we need to carefully go back each step and see what could probably be the issue. While leaving the code uncommented:

Code:
string temp = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";

Plus having this code commented out:

Code:
destination = System.IO.Path.Combine(destination, "nvdisp.exe");

We actually get 0/65 from VirusTotal!

[Image: anti_virus_evasion_16.png]


At this point, new test cases were applied because the string “nvdisp.exe” appears to be the real reason behind the trigger:

Test Cases:

  1. Changing the string “nvdisp.exe” to “ThisIsAnotherTest.exe” -  ESET still detecting
  2. Moving variable outside the function making it a global variable: static string dest = “nvdisp.exe” -  ESET still detecting
  3. Encoding the string to base64 deriving to the code:
    Code:
    destination = System.IO.Path.Combine(destination, System.Text.Encoding.Default.GetString(Convert.FromBase64String("Im52ZGlzcC5leGUi")));
    Another detection popped up
Now, there should be a lot of test cases here but to cut the testing short, since some basic string and variable manipulation don’t work, we can try to do some code substitution. Apparently, any programmer can understand what the “startup” function does. It simply adds the program to the Windows start up so it can execute once Windows boots. There are numerous ways to add a program in the Windows start up. This could be through copying the executable in “C:\Users\<USER>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup” or maybe by using a scheduled task. 

The “startup” function in this case was replaced by this simple code:

[Image: anti_virus_evasion_17.png]

This basically does a similar job by logic but different in terms of instructions. The final program looks similar to this:

[Image: anti_virus_evasion_18.png]

Once compiled and scanned in VirusTotal, the result gives us a rate of 0/65.

[Image: anti_virus_evasion_19.png]

While being able to achieve a fully undetected program which helps in penetration testing engagements, it is essential to understand that running this program will probably catch the attention of antiviruses that monitor its actions during run time. This is why antivirus evasion is challenging to do with automated tools because the scope is very wide.

P.S. The code presented above might have different scan results as time goes on because as mentioned, VirusTotal distributes copies of applications being scanned and other antiviruses might decide to put a flag on them.
Reply
#2
Good job man! The thread was well documented and explained.
I would like to include some things tho:
   - As you mentioned, VirusTotal distributes the software, if you want an alternative you can use https://nodistribute.com which apparently doesn't distribute to avs.
   - There are others ways of evading AVs, based on signature detection, i'm not aware of what is out there at the moment, but some time ago there were snippets of code which were able to cloak malware. 
   - Crypters can also help with this.

Once again, good job man Wink
Reply
#3
(06-05-2018, 05:49 PM)enmafia2 Wrote: Good job man! The thread was well documented and explained.
I would like to include some things tho:
   - As you mentioned, VirusTotal distributes the software, if you want an alternative you can use https://nodistribute.com which apparently doesn't distribute to avs.
   - There are others ways of evading AVs, based on signature detection, i'm not aware of what is out there at the moment, but some time ago there were snippets of code which were able to cloak malware. 
   - Crypters can also help with this.

Once again, good job man Wink

Thank you so much! I agree with nodistribute.com but a few months ago, I was somehow having trouble using their service when I was developing a tool for legal engagement. After buying off a key, it didn't quite work and support never responded. Even with the free scans, I was getting some errors during upload so it's probably under maintenance when I last used it despite making it work back about a year or two. 

Using a "crypter" is another topic that I might discuss here soon too! Maybe some kind of a part two for this thread. Very interesting to make and I even still have some chills when reviewing the process hallowing technique. Haha!
Reply
#4
Very well written. I have an interest in anything malware related so this was a fun read to me. A while ago i made a thread on the forum that went into AV evasion by checking for certain clues that could indicate the binary was being run in a sand-boxed environment. We'd count and check the rate of clicks/key presses in order to check for input simulation and check things like the time the machine had been running and such.

Since crypters were mentioned and you said you might do a thread on them i hope to see more of your content, perhaps even as a mini-series taking a closer look at various stages of malware development.

Thank you for sharing, and i am looking forward to seeing more from you!
Reply
#5
(06-06-2018, 10:57 AM)Vector Wrote: Very well written. I have an interest in anything malware related so this was a fun read to me. A while ago i made a thread on the forum that went into AV evasion by checking for certain clues that could indicate the binary was being run in a sand-boxed environment. We'd count and check the rate of clicks/key presses in order to check for input simulation and check things like the time the machine had been running and such.

I must say that this is very interesting! Am guessing it had positive results?  

(06-06-2018, 10:57 AM)Vector Wrote: Since crypters were mentioned and you said you might do a thread on them i hope to see more of your content, perhaps even as a mini-series taking a closer look at various stages of malware development.

I'd definitely push this up in the list! Thank you for the interest and again, thank you so much for the comments. Cheers!
Reply
#6
(06-06-2018, 01:58 PM)nats Wrote: I must say that this is very interesting! Am guessing it had positive results?

In the test environment i deployed it in yes. Haven't used the techniques i described in any active engagement. Mostly because security and coding is more of a passion of mine, i am currently employed in a different sector. But i hope to make the transition soon.

(06-06-2018, 01:58 PM)nats Wrote:
(06-06-2018, 10:57 AM)Vector Wrote: Since crypters were mentioned and you said you might do a thread on them i hope to see more of your content, perhaps even as a mini-series taking a closer look at various stages of malware development.

I'd definitely push this up in the list! Thank you for the interest and again, thank you so much for the comments. Cheers!

No problem, and like i said, looking forward to seeing more of your excellent content Smile
Reply
#7
You realize that the second you put that payload onto one of the websites that check if anything detects it, it is no longer a good payload right?
Reply
#8
(06-08-2018, 09:37 PM)ekultek Wrote: You realize that the second you put that payload onto one of the websites that check if anything detects it, it is no longer a good payload right?

Hi bro. Yeah. I stated it in the thread as virustotal distributes the copies.  Big Grin
Although it's convenient to use services like nodistribute.com, it's still best to do a set up of your own environment for antivirus scanning. Cheers!
Reply
#9
Really in depth stuff, bring back some good memories lol. Thanks for the write up!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Interpreting Antivirus Detection Names hworth 1 3,581 01-28-2022, 04:05 PM
Last Post: Vice
  Inner Workings of Antivirus Scanners hworth 0 2,556 01-27-2022, 04:45 AM
Last Post: hworth
  Evading AV Signatures - Derailing Antivirus Insider 2 12,004 06-06-2021, 11:15 PM
Last Post: jean_valjean
  Introduction to Sandbox Evasion with Python. Vector 5 23,762 06-09-2020, 10:25 PM
Last Post: Insider