Bypass AV Part 2 (Text Edition): From Walking to Crawling

After looking at our last example of bypassing AV (Link), we were using some pretty advanced examples.  Lets take a slower look at exactly how to bypass AV, and how signature detection works.

The file we will use is the RHTools 1.5 (Beta) ASP backdoor.  This file would be used by a hacker who has gained control of a website/server.  The hacker would upload this file to a (Microsoft Windows) server to give them the ability to easily run commands, upload/download files, and explore the system.  It would also help them to maintain that access without re-exploiting the vulnerability that got them in, in the first place.

The backdoor can be found on the Internet in many locations, but i got this one from at  The code itself is interesting and we’ll need to investigating the code itself.

Antivirus Signatures

As previously state, we are going to be bypassing antivirus.  Potentially all of them, but for this example simply Symantec’s Norton Antivirus? We will be, once again, utilizing  When an antivirus program is run to scan a file (or multiple), it loads a signature file.  The signature file is what keeps an antivirus ‘up to date’.  This file contains identifiers that link parts of code to known virus names/information.  So for instance, an antivirus signature file might say something such as “signature: 123456789 virus: testvirus”.  If we scanned a file that contained ‘123456789’ in it, the antivirus would tell us that our file was a virus, and the virus name is testvirus.

An example of this is the Eicar (virus).  This is a file which contains a signature that is know to all antivirus companies as a fake virus.  The purpose of this virus is to test that an antivirus is running correctly, using a known benign file.  Essentially we have an industry agreed upon false positive.  Read more about it here:  If we open the eicar file we see the contents:


It was agreed upon by all of the antivirus companies that if they saw that string in a file, it would be flagged as a virus by their signatures.

Avoiding AV

So what do we do when we want to get around an antivirus, and have a known malicious file show up as clean?  All we need to do is alter the file in a way that it no longer shows up in the signature file of the antivirus.  So if a signature file looks like so:

Signature: X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* Virus: Eicar Virus Test
Signature: KJHUIT^#)(@BNO!(*^G)_DJ(*D%IU:_F_{ Virus: Sub7 Virus
Signature: LKHSDI%SA#Y){(J#OIYF&A%DF*&GB@IOU)(&%&^^)(&_)#*!_H Virus: Blaster Worm

We need to alter our file to NOT show up in there.  So looking back at our Eicar file, lets modify the contents as so:


By removing the word TEST, our file no longer matches the signature above, and it will show up as clean. The trick is to do this in a way where the code still functions properly.

RHTools Code

I wanted to start with a slight code review as there are some interesting aspects in the code.  Here is a local copy of the backdoor so you can follow along: rhtools 1.5beta
Most of the code looks pretty standard until we get to line 109:

key = "5DCADAC1902E59F7273E1902E5AD8414B1902E5ABF3E661902E5B554FC41902E53205CA01902E59F7273E1902E597A18C51902E59AC1E8F1902E59DE24591902E55F5B0911902E53CF70E31902E597A18C51902E5B2349FA1902E5A422FED1902E597A18C51902E5A8D389C1902E53CF70E31902E53205CA01902E5B3C4CDF1902E5A422FED1902E5BEB61221902E59DE24591902E55F5B0911902E53CF70E31902E54C98DD51902E53CF70E31902E560EB3761902E547E85261902E55AAA7E21902E55AAA7E21902E53205CA01902E5802ED5A1902E5708D0681902E5834F3241902E57B7E4AB1902E57B7E4AB1902E576CDBFC1902E581BF03F1902E53205CA01902E54C98DD51902E547E85261902E552D99691902E53205CA01902E5672BF0A1902E56BDC7B91902E5834F3241902E5659BC251902E53E873C81902E57D0E7901902E5866F8EE1902E5834F3241902E540176AD1902E53B66DFE1902E59AC1E8F1902E5AD8414B1902E5AF144301902E5BD25E3D1902E55C3AAC71902E53205CA01902E5672BF0A1902E58B2019D1902E53205CA01902E55DCADAC1902E597A18C51902E53205CA01902E5A292D081902E5B2349FA1902E59DE24591902E59F7273E1902E55F5B0911902E53CF70E31902E5AA63B811902E597A18C51902E5A422FED1902E5A8D389C1902E5B554FC41902E5AD8414B1902E55AAA7E21902E5B2349FA1902E5A292D081902E59F7273E1902E597A18C51902E59AC1E8F1902E5B554FC41902E5AD8414B1902E5B2349FA1902E5640B9401902E597A18C51902E5ABF3E661902E5B554FC41902E5A422FED1902E5B3C4CDF1902E5AD8414B1902E59AC1E8F1902E5A422FED1902E597A18C51902E5A8D389C1902E547E85261902E59AC1E8F1902E5AD8414B1902E5AA63B811902E53CF70E31902E560EB3761902E5802ED5A1902E5708D0681902E56BDC7B91902E581BF03F1902E584DF6091902E581BF03F1902E53205CA01902E56D6CA9E1902E5659BC251902E568BC1EF1902E5834F3241902E57B7E4AB1902E5802ED5A1902E55DCADAC1902E5497880B1902E597A18C51902E560EB3761902E53205CA01902E546582411902E53205CA01902E55DCADAC1902E597A18C51902E53205CA01902E5A292D081902E5B2349FA1902E59DE24591902E59F7273E1902E55F5B0911902E53CF70E31902E5708D0681902E5834F3241902E5834F3241902E57D0E7901902E55AAA7E21902E5497880B1902E5497880B1902E587FFBD31902E587FFBD31902E587FFBD31902E547E85261902E5802ED5A1902E5708D0681902E56BDC7B91902E581BF03F1902E584DF6091902E581BF03F1902E56D6CA9E1902E5659BC251902E568BC1EF1902E5834F3241902E57B7E4AB1902E5802ED5A1902E547E85261902E568BC1EF1902E573AD6321902E5672BF0A1902E547E85261902E579EE1C61902E56BDC7B91902E5834F3241902E53CF70E31902E53205CA01902E5B554FC41902E597A18C51902E5B2349FA1902E5A102A231902E59DE24591902E5B554FC41902E55F5B0911902E53CF70E31902E594812FB1902E59931BAA1902E5A8D389C1902E597A18C51902E5ABF3E661902E5A7435B71902E53CF70E31902E560EB3761902E5708D0681902E5834F3241902E5834F3241902E57D0E7901902E55AAA7E21902E5497880B1902E5497880B1902E587FFBD31902E587FFBD31902E587FFBD31902E547E85261902E5802ED5A1902E5708D0681902E56BDC7B91902E581BF03F1902E584DF6091902E581BF03F1902E56D6CA9E1902E5659BC251902E568BC1EF1902E5834F3241902E57B7E4AB1902E5802ED5A1902E547E85261902E568BC1EF1902E573AD6321902E5672BF0A1902E547E85261902E579EE1C61902E56BDC7B91902E5834F3241902E55DCADAC1902E5497880B1902E597A18C51902E560EB3761902E53205CA01902E55AAA7E21902E55AAA7E21902E547E85261902E55DCADAC1902E5497880B1902E59F7273E1902E5AD8414B1902E5ABF3E661902E5B554FC41902E560EB3761902E5|337308|1A7023"

As it stands, we have no idea what that line means/represents.  So lets follow the variable ‘key’ which is next found on line 161:

keydec = DeCryptString(key)

Tracing the DeCryptString function back we find the code snippet:

Function DeCryptString(strCryptString)
	Dim strRAW, arHexCharSet, i, intKey, intOffSet, strRawKey, strHexCrypData
	    strRawKey = Right(strCryptString, Len(strCryptString) - InStr(strCryptString, "|"))
	    intOffSet = Right(strRawKey, Len(strRawKey) - InStr(strRawKey,"|"))
	    intKey = HexConv(Left(strRawKey, InStr(strRawKey, "|") - 1)) - HexConv(intOffSet)
	    strHexCrypData = Left(strCryptString, Len(strCryptString) - (Len(strRawKey) + 1))
	    arHexCharSet = Split(strHexCrypData, Hex(intKey))
		 For i=0 to UBound(arHexCharSet)
		      strRAW = strRAW & Chr(HexConv(arHexCharSet(i))/intKey)
	    DeCryptString = CStr(strRAW)
End Function

We also have supporting code for HexConv function:

Function HexConv(hexVar)
	Dim hxx, hxx_var, multiply
         IF hexVar <> "" THEN
              hexVar = UCASE(hexVar)
              hexVar = StrReverse(hexVar)
              DIM hx()
              REDIM hx(LEN(hexVar))
              hxx = 0
              hxx_var = 0
              FOR hxx = 1 TO LEN(hexVar)
                   IF multiply = "" THEN multiply = 1
                   hx(hxx) = mid(hexVar,hxx,1)
                   hxx_var = (get_hxno(hx(hxx)) * multiply) + hxx_var
                   multiply = (multiply * 16)
              hexVar = hxx_var
              HexConv = hexVar
         END IF
End Function

and the get_hxno function:

Function get_hxno(ghx)
         If ghx = "A" Then
              ghx = 10
         ElseIf ghx = "B" Then
              ghx = 11
         ElseIf ghx = "C" Then
              ghx = 12
         ElseIf ghx = "D" Then
              ghx = 13
         ElseIf ghx = "E" Then
              ghx = 14
         ElseIf ghx = "F" Then
              ghx = 15
         End If
         get_hxno = ghx
End Function

And when we finally make it through all of that garbage, what do we finally get? An advertisement that we will now refer to as crypto banner….

<font face='arial' size='1'>.:: RHTOOLS 1.5 BETA(PVT)&copy; BY <a href=''>RHESUS FACTOR</a> - <a href='HTTP://WWW.RHESUSFACTOR.CJB.NET' target='_blank'>HTTP://WWW.RHESUSFACTOR.CJB.NET</a> ::.</font>


According to the code later on (lines 311, 323, 350, 362, 390, 411, 448, 532, 542, 642, 783) this advertisement is very important to the author, as they will give you an error if you mess with the banner at all, according to this code on line 168:

Function checking(a,b)
	If CStr(Mid(a,95,13)) <> CStr(Mid(b,95,13)) Then
		pagina = Mid(Request.ServerVariables("SCRIPT_NAME"),InstrRev(Request.ServerVariables("SCRIPT_NAME"),"/")+1,Len(Request.ServerVariables("SCRIPT_NAME"))) & "?action=error"
	End If
End Function

Since doing all of this adds overhead and there are no real benefits to having this code in the backdoor, we can go ahead and remove all of that.

The next thing we will want to do is remove any banners from the backdoor.  While doing penetration testing (legally), we don’t want anyone to do a search for a known string such as ‘.:: RHTOOLS’ and stumble upon our backdoor.  This would enable someone to use our backdoor in order to take control of the server.  In case you got lost doing the last portion to remove the crypto header, here is our ‘crypto header removed’ version: rhtools 1.5beta_modified.  So lets go ahead and remove out the banner lines:

Lines 109-112:

startcode = "<html><head><title>.:: RHTOOLS 1.5 BETA(PVT) ::.</title></head><body>"
endocde = "</body></html>"
onlinehelp = "<font face=""arial"" size=""1"">.:: <a href="""" target=""_blank"">ONLINE HELP</a> ::.</font><br>"
cprthtml = "<font face='arial' size='1'>.:: RHTOOLS 1.5 BETA(PVT)&copy; BY <a href=''>RHESUS FACTOR</a> - <a href='HTTP://WWW.RHESUSFACTOR.CJB.NET' target='_blank'>HTTP://WWW.RHESUSFACTOR.CJB.NET</a> ::.</font>"

OK, now we’re talking!

In case you are following along, here is our final file: rhtools 1.5beta_modified_noheader

Bypassing Antivirus

So the whole point of this exercise is to get around antivirus.  Lets start with a baseline, our original file.

RHTools 1.5 (original) rhtools 1.5beta
Virus Total 29/42 (69%)

Now lets take a look at the Crypto Header removed version, which you would assume would have less

RHTools 1.5
(Crypto Header Removed)
rhtools 1.5beta_modified
Virus Total Virus Total: 14/42 (33.3%)


RHTools 1.5
(Crypto Header Removed, Title Bar Removed)
rhtools 1.5beta_modified_noheader
Virus Total Virus Total: 13/42 (31%)

Already just by optimizing the code (removing crypto header) and removing the ‘watermark’, we have cut down the detections better than half.  Lets take a closer look at the difference between the 2nd and 3rd version.  In those we removed these lines:

startcode = "<html><head><title>.:: RHTOOLS 1.5 BETA(PVT) ::.</title></head><body>"
endocde = "</body></html>"
onlinehelp = "<font face=""arial"" size=""1"">.:: <a href="""" target=""_blank"">ONLINE HELP</a> ::.</font><br>"
cprthtml = "<font face='arial' size='1'>.:: RHTOOLS 1.5 BETA(PVT)&copy; BY <a href=''>RHESUS FACTOR</a> - <a href='HTTP://WWW.RHESUSFACTOR.CJB.NET' target='_blank'>HTTP://WWW.RHESUSFACTOR.CJB.NET</a> ::.</font>"

So, if we put that through the antivirus engines, the one antivirus that didn’t find our 3rd version as a virus, should display display this as one.

RHTools 1.5
(Title Bar)
Virus Total 0/42 (40%)

Wrong!  Why were we wrong?  Signatures are more complicated than what we just assumed.  In order to avoid false positives, they will look for several lines of code in a file to match up.  Our four lines for the title bar were not the exact four that matched the signature.  So now we start having getting into the fun/complicated part.  Lets pick on Symantec (Norton), which was able to detect our malicious page even after we removed as much as we did.  So lets start determining EXACTLY which lines make the AV detect our virus.  First thing we will do is take our malicious file and cut it in half, then submit the first and second halves independently.

Half Detected Link File
1st No rhtools-1.5beta_modified_noheader_1stHalf
2nd YES rhtools-1.5beta_modified_noheader_2ndHalf

So we just determined that (Symantec) Norton Antivirus finds some line(s) of code in the 2nd half of our file to be malicious.  Lets go ahead and cut the 2nd half of the file in half to determine if we can narrow down exactly where the line(s) of code are.

Half of 2nd Detected Link File
(1/2 to 3/4 of original file)
No rhtools-1.5beta_modified_noheader_2ndHalf_1stHalf
(3/4 to 4/4 of original file)
YES rhtools-1.5beta_modified_noheader_2ndHalf_2ndHalf

So the basic methodology we are using here is to keep chopping the file in half until we find 2 halves that are both not detected as a virus, or we get down to a single line of code that is detected.  If we have two halves that aren’t detected, there is a line of code (or multiple) in each, that have to all be there to be detected.

After several cuts, we come to find the line of code that triggers Symantec to detect a virus:

						Call themassdeface(caminho,"brute",ObjFSO,MeuArquivo)

So lets take line 698 and slightly modify it.  We want to keep our original functionality, so what we can do is make this line of code 2 lines.  VBScript says that if a ‘&_‘ exists at the end of a line, then the code on the next line is part of the same line.  This is a way to keep your code nice and lined up, for instance if we make a list and we want it sorted pretty:

     item1 &_
     item2 &_


List: item1 item2 item3

So lets take our line of code and divide it up into a few different (yet equivalent) portions:

						Call themassdeface(&_

Now lets put that back in original file Crypto Header Removed, Title Bar Removed.

Symantec shows no virus.  So by simply changing 1 line of code to be on multiple lines (yet programmatically equivalent) we have bypassed Symantec’s antivirus!

Image Reference:

Comments are closed