Creating an Anti-AV scanner

…and blocking AVs








C:\Scanner>"Black Scanner.exe" "Anti-Bootkit Tools Signatures.bin" C:\Temp\AV-Zoo


  Black Scanner

  Engine version 1  Jan 23 2012


aswMBR.exe: Image Name infected

aswMBR.exe: Icon infected

aswMBR.exe: Icon infected

aswMBR.exe: Icon infected

aswMBR.exe: Icon infected

aswMBR.exe: Icon infected

aswMBR.exe: Icon infected

aswMBR.exe: Version Info -> Company infected

aswMBR.exe: Version Info -> Original File Name infected

TDSSKiller.exe: Image Name infected

TDSSKiller.exe: Section Name infected

TDSSKiller.exe: Icon infected

TDSSKiller.exe: Icon infected

TDSSKiller.exe: Icon infected

TDSSKiller.exe: Icon infected

TDSSKiller.exe: Icon infected

TDSSKiller.exe: Icon infected

TDSSKiller.exe: Icon infected

TDSSKiller.exe: Version Info -> Company infected

TDSSKiller.exe: Version Info -> Original File Name infected

TDSSKiller.exe: Certificate -> O infected

TDSSKiller.exe: Certificate -> CN infected

gmer Icon infected

GMER Icon infected

GMER Icon infected

Gmer.exe: Image Name infected

Gmer.exe: Icon infected

gmer2u.exe: Icon infected






























Creating an Anti-AV scanner


There is malware in the wild that blocks anti-viruses from execution. They usually use a blacklist of hard coded file or process names. While that turned out to be working quite good, a more decent solution would be making a full anti-AV scanner based on real signatures.


Prior to this article I was watching a very interesting movement: A bootkit was blocking TDSSKillers execution by patching the entry point, and they (lame Kaspersky) responded by adding a TLS callback to their executable (that gets executed before the patched entry point).


TDSSKiller as anti-rootkit tool is a very good example, as it is the most aggressive (evil) one of its kind. It is packed like a virus, uses rootkit-like features and has pseudo heuristic signatures for MBRs such as Rootkit.Win32.BackBoot.gen. By making a signature over 440 bytes false positives are confirmed by oath.


In a discussion about this (prior to this paper) a very good developer came up with the “rootkit paradox”:


         There is what we call the "rootkit paradox," namely, the more you try to hide the easier you are to find. The reason is because everything you do to hide produces artifacts by which you can be detected. So you have to hide not only the original rootkit, but also all of the hooks that you use to hide. Once you have hidden your hooks you then have to hide everything you did to hide the hooks, and so on. Eventually the rootkit collapses under its own weight.


Obviously the solution to this rootkit paradox is either not doing any hooks (and being exposed to anti-viruses), or to block the execution of AVs in advance.


For some simple solutions in the wild that rely on the file name of the AV it is easy enough to rename the AV to bypass that. But what is about a full featured anti-AV scanner?


Important: This is research here and should be considered as proof of concept.





Peter Kleissner, Software Development G.






Table of Contents


Table of Contents 3

The objective 4

Signature Database 6

Gmer 7

TDSSKiller 8

Preventing files from being executed_ 10

Parsing Certificates 12

AV Zoo 14

Behind the scenes – technical implementation_ 15

Conclusion_ 16

References 17




The objective


We need a scanner that checks every file that is executed and stops its execution in case it is detected as an anti-virus. This also includes parts of anti-virus programs like libraries or drivers. We totally want to block them, including special removers and rootkit detection tools.


The technical requirements are: We only need to scan PE files loaded in memory. The code has to be portable, working both in user-mode and kernel-mode. Since this not an AV but an anti-AV we can rely on one important fact: AV files are easily identifiable and verifiable through meta-data such as file names, descriptions and certificates.


Meta-data in PE files that can be used for AV file identification are:


-      Image name

-      Icon

-      Version Info -> Original File Name

-      Version Info -> Company

-      Section Name

-      Certificate -> Organization Name (O)

-      Certificate -> Common Name (CN)

-      Certificate -> Fingerprint

-      Debug data


Some remover tools are packed (some by UPX, some by custom ones); therefore some information could be encrypted. This is usually the case for the string table (as part of the resources) or the debug data.


The basic concept of AVs is “take the file and scan all signatures over it”. This is obviously slow (but necessary). In our case, however, we can do it reverse: Take the meta-data, hash it and look it up in a (blacklist) tree. The time to scan a file is then nearly always the same: Doing the hashes, comparing them to the list (tree).


The signatures are stored in “trees” (which are none, technically just lists but it sounds better) of the hashes calculated from the meta-data. Candidates for the hashing algorithm would be CRC32, MD5 and SHA-1, as they are widely used and easy to implement. In my solution I use CRC32 as it just uses a dword for every hash (which makes the lookup pretty fast then).


Each hash tree identifies some meta-data type:



Image Name

TDSSKiller.exe, Gmer.exe, aswMBR.exe



, , ,


Company Name

Kaspersky Lab ZAO, Kaspersky Lab


PE Section Names



Then there should be another tree for the certificate fingerprints, to explicitly blacklist them as well.



These hash trees do not equal the signature types. Rather, there are different types for the specific info that are checked:


#define BLACK_SIG_TYPE_IMAGENAME                            1

#define BLACK_SIG_TYPE_RESOURCE_ICON                        2


#define BLACK_SIG_TYPE_VERSION_INFO_COMPANY                 4

#define BLACK_SIG_TYPE_SECTION_NAME                         5

#define BLACK_SIG_TYPE_CERTIFICATE_CN                       6

#define BLACK_SIG_TYPE_CERTIFICATE_O                        7


The “image name” and the “version info -> original file name” signature types for example use the same hash tree (Image Name).



Signature Database


A scanner engine can only be as good (or in Aviras case as worse) as its signature database. The example used and shown at the first page of this article is “Anti-Bootkit Tools Signatures”. Its source looks like this:


# blacklist TDSSKiller and Kaspersky Lab

1   TDSSKiller.exe

2   CRC32   1561770547

2   CRC32   1148540081

2   CRC32   616636565

2   CRC32   1009560204

2   CRC32   649440059

2   CRC32   1449080003

2   CRC32   -1989445225

3   "Kaspersky Lab"

3   "Kaspersky Lab ZAO"

4   .pklav


# blacklist Gmer

1   Gmer.exe

2   CRC32   -1651801256


# blacklist aswMBR (uses same engine as Gmer)

1   aswMBR.exe

2   CRC32   2008367110

2   CRC32   1770432001

2   CRC32   1969924194

2   CRC32   2103422372

2   CRC32   -1560200948

2   CRC32   -1770691826

3   "AVAST Software"


This text file is compiled to a binary using a custom parser and results in a 104 bytes binary file. The (binary) file format is very simple: It has a small header followed by the 4 signature trees.


typedef struct


    DWORD SizeOfHeader;

    DWORD CountSig1;

    DWORD CountSig2;

    DWORD CountSig3;

    DWORD CountSig4;

} SigHeader;







Gmer deserves to be mentioned here in a single chapter. It has a history with malware trying to blocking it. If you want to download it, the website suggests already to use a button that generates a random file name, because some viruses used to block (hard-coded) Gmer.exe [1]:


         It's recommended to download randomly named EXE (click button above) because some malware won't let gmer.exe launch.


The developer was very good with removing meta-data and identifiable information from the image – though he missed one point, the icon. No matter what version, the icon remains always the same, therefore making every Gmer executable identifiable.


The Gmer icon is shown below, extracted using the program “Resource Hacker” [2].








While Gmer is king in having sparse identifiable information, TDSSKiller is the opposite. The Black Scanner can be used to generate signatures (or at least output that helps in generating signatures) and this is the result for TDSSKiller:


TDSSKiller.exe: Image Name CRC -984132845

TDSSKiller.exe: Section Name CRC -395631440

TDSSKiller.exe: Section Name CRC -1620306906

TDSSKiller.exe: Section Name CRC -421465104

TDSSKiller.exe: Section Name CRC 501016963

TDSSKiller.exe: Icon CRC 1561770547

TDSSKiller.exe: Icon CRC 1148540081           

TDSSKiller.exe: Icon CRC 616636565

TDSSKiller.exe: Icon CRC 1009560204

TDSSKiller.exe: Icon CRC 649440059

TDSSKiller.exe: Icon CRC 1449080003

TDSSKiller.exe: Icon CRC -1989445225

TDSSKiller.exe: Version Info -> Company CRC 1627962736

TDSSKiller.exe: Version Info -> Original File Name CRC -984132845

TDSSKiller.exe: Certificate -> O CRC 1231392781

TDSSKiller.exe: Certificate -> CN CRC 1231392781


This output shows the CRCs (in decimal notation) of the info. You can directly compare the CRCs of the icons with the sample signature database in the chapter “Signature Database”. Prior to this generation functionality of the scanner I had to manually extract the icon, and then generate the CRC32 using 3rd party tools:




This acquired CRC32 can be added to the signature database by adding a single line. The 2 means a CRC32 signature of a RT_ICON resource:


2 CRC32 1561770547





Preventing files from being executed


PE image files can be scanned in the PsSetLoadImageNotifyRoutine driver callback function. That is, after the image is loaded into memory, but before it is being executed. Previous blocking solutions in-the-wild have been implemented as:


1.   Injecting an APC that calls ExitProcess() – done by ZeroAccess [3]


When a typical security scanner tries to analyze the rootkit-created svchost.exe file, the rootkit queues an initialized APC into the scanner’s own process, then calls the ExitProcess() function — essentially forcing the scanner to kill itself.


2.   Patching the entry point with a ret instruction – done by BlackEnergy [4]


Instead of defence, this malware attacks AV by preventing AV processes from loading. It registers notification callbacks using functions such as PsSetLoadImageNotifyRoutine.


When a process is loading, the malware gets a callback by the OS where it first checks if the loading process is on its blacklist of known AV processes. If it isn’t, then the malware allows the process to load normally. But if it is an AV process, the malware writes a return instruction (0xc3) at the entry point in the memory of the process and then allows it to load. The AV process typically terminates immediately due to this patch by the malware. This technique was first reported to be used in the wild by Nuwar back in 2007.



The simplest (and most practical) solution is to overwrite the entry point with a return code. Below the entry point is patched to return the infamous STATUS_TOO_MANY_SECRETS error code, from a bootkit (which hashes the image name and compares it to a blacklist):



This error code is also used by ZeroAccess [3]:



And also by TDL4 [5]:


         When a program or driver attempts to open one of the  \Device\HarddiskVolumeX  devices, the rootkit will return error code 0xC0000156 (STATUS_TOO_MANY_SECRETS - the author had a sense of humor) to block opening.  Because most antirootkits try to open this (for raw-disk scanning), most of them will have issues.


Obviously also the TLS callbacks have to be patched, as they are executed before the entry point.


A more “funny” solution would be to wipe the entire hard disk (and maybe flash the boot firmware), to force the vendor to withdraw the tool. Of course I am not supporting that, but installing Kaspersky on your machine makes it to a brick already anyway.



Parsing Certificates


Even though there are Windows (user-mode) functions to handle certificates (and extract information) they cannot be used here, because one requirement of the scanner is to run within kernel mode.


Unfortunately, to make things even more complicated, the certificate table has to be loaded explicitly into memory by the scanner. The PE documentation (pecoff_v8.docx) says:


         These certificates are not loaded into memory as part of the image. As such, the first field of this entry, which is normally an RVA, is a file pointer instead.


For the execution of user mode programs this makes perfectly sense, because the certificate is not checked there. I verified that the pointer remains a file pointer of the loaded image in memory (no cheating by Microsofts PE loader). Also scanning the memory for the certificate was without luck. In kernel mode, digital signatures of images are verified by ImgpValidateImageHash, an important function for bootkits (explained in “The Art of Bootkit Development”).


In fact the certificate is stored immediately after the Certificate Table in PCKS7 DER encoded format. Microsoft calls it “Authenticode”. OpenSSL supports that format, you can launch following command on the dumped raw certificate:


openssl.exe pkcs7 -inform DER -text -print_certs -in rawcert.pkcs7




        Version: 3 (0x2)

        Serial Number:


        Signature Algorithm: sha1WithRSAEncryption

        Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at (c)10, CN=VeriSign Class 3 Code Signing 2010 CA


            Not Before: Feb 21 00:00:00 2011 GMT

            Not After : Mar  7 23:59:59 2012 GMT

        Subject: C=RU, ST=Moscow, L=Moscow, O=Kaspersky Lab, OU=Digital ID Class 3 - Microsoft Software Validation v2, OU=Technical dept, CN=Kaspersky Lab

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

            RSA Public Key: (2048 bit)

                Modulus (2048 bit):






One interesting thing about Authenticode is that Microsoft still allows the use of MD5 hashes, whereof collisions can be easily generated. SHA-1 is used by Microsofts code signing tool by default though. [6] [7]


The OpenSSL library, however, turns out to be unusable in the scanner. It is bloated up, (the official distribution) requires MinGW/Gnu LibGwC on Windows, contains as good as no comments in its source (badly documented, the spare html website does not help there either) is unreadable and the PKCS7 code is not abstracted from things like the data input at all. I would not call this interoperability.


However, there is a very good lightweight ASN.1 dumping code available from Peter Gutmann. PKCS7 uses ASN.1 representation. The interesting fields there are the ones with the object identifier “2 5 4 10” = Organization Name (O) and “2 5 4 3” = Common Name (CN).





AV Zoo


Opening an AV zoo is important for the signature generation to stay up to date. Like AVs download the virus samples directly from the source (from the bad guys C&Cs), the AVs (or remover tools) can be downloaded automatically.


TDSSKiller is a good example here, on every run it checks if there is an updated version on the Kaspersky server. For that reason it downloads an xml file:


4     0.064434     HTTP  GET /downloads/utils/tdsskiller.xml HTTP/1.1


That file can be downloaded directly from










This simple xml format is ideal for automating the download process, and automatically adding the latest TDSSKiller version to the zoo.


Ideally, an automated system checks every half hour for a new version and automatically generates a new signature in case it is not detected. For a botnet, this means the bad guys could always stay ahead of anti-viruses. The process:


1.   Dowload anti-virus executable

2.   Check if it is a new file (SHA-1 hash), if not -> exit

3.   Add it to the AV database (zoo)

4.   Check if it is detected by current signatures, if so -> exit

5.   Generate a new signature and alarm the developer

a.    Compare the signature over legitimate files

b.    Generate a new signature database

6.   Deploy the new signature database to the botnet



Behind the scenes – technical implementation


The project is split into the scanner and the actual scanner engine. The engine is coded in C/C++ and uses a structure to save its internal state:


struct Scanner


    // Input File (all parameters are required)

    char * ImageName;

    wchar_t * FullFilePath;

    void * ImageBase;


    // Scanning Options

    BOOL StopOnFirstFound;

    BOOL SignatureGenerationMode;

    void (* Callback)(const Scanner * Instance);


    // Results

    unsigned SignaturesFound;

    unsigned LastSigType;

    DWORD LastBadCRC;


    // Internal Data


    DWORD ImageSize;



The callback is called on every found infection. The scanner engine was developed to check files that are loaded into memory (on the image notification callback). To check files on hard disk, the scanner uses LoadLibraryEx with the DONT_RESOLVE_DLL_REFERENCES flag (that prevents the entry point of being called).


The most complicated code part was the resource parsing. Someone at Microsoft should be fired for making these unwell defined “flying around” structures.


The core function is ScanCRCInDatabase which looks up a generated CRC in the tree corresponding to the specific signature type. If it finds it, it will invoke the callback.


The source is published under the European Union Public Licence.







What I have shown here is the reverse operation of an anti-virus, relying on meta-data and the fact that AV files are easy identifiable. Obviously this is only of advantage if the virus is already installed. What I have described is a way to protect from anti-viruses, not how to bypass them.


At the end of the day virus developers always have a small advantage though. They can use services like scan4you or KIMS to check if they are being detected and doing appropriate changes. AV vendors, however, cannot simply change their file name, product name etc.


Conficker is a famous example of a virus that was blocking AVs as hell. With the result however, that is was simple enough visiting a website to check if someone’s infected (Conficker blocks AV websites so embedded pictures linked to them would not show up).



Peter Kleissner











[1]     Gmer


[2]     Resource Hacker


[3]     Webroot: ZeroAccess Rootkit Guards Itself with a Tripwire


[4]     McAfee: Predicting the future of stealth attacks


[5]     Forum entry at Sysinternals “Interesting new malware”


[6]     Playing With Authenticode and MD5 Collisions


[7]     MD5 Collision Demo


[8]     Format of a Signed File and ASN.1 dumping code