VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

ACG in the Hole

Adrian Marinescu
Virus Bulletin, Jul 1999, pp.8-9
ISSN 0956-9979
July 1999

[Back to index] [Comments]
Adrian Marinescu
GeCAD srl, Romania

The MtE mutation engine was something quite new in virus programming, and led to important changes. Since then, polymorphism has been one of the ways virus writers have chosen to protect their creations from scanning engines. The development of code emulators and good cryptoanalytic algorithms resulted in anti-virus products needing slight changes and/or updates in order to detect most of the new polymorphic viruses. Furthermore, there were a few cases of polymorphic viruses that could not be detected at all for a long time; Zhengxi (see VB, April 1996, p.8) and Uruguay (December 1992, p.12) are good examples.

All polymorphic engines were based on the same idea: maintain the virus body in an encrypted form, using a variable key/algorithm, and generate a polymorphic code that decrypts the rest of the body and executes it. Some of the first viruses not based on this idea were the members of the Ply family. Ply is not encrypted, but there are no parts constant enough to extract a reliable signature.

Using a slightly modified idea, the TMC family managed to become in the wild. TMC had many small constant parts, linked with jumps. That made algorithmic detection easy to write for this virus, but the door was now open. These kinds of virus were the first ones that could not be exactly identified, raising big problems regarding their disinfection.

Then the ZCME family used the same idea, mixing the code in a 16 KB buffer. The only weakness was that algorithmic routines still worked, because there were a lot of constant small pieces that could be used for detection. Last year, a new kind of virus came up. Called Lexotran, it was able to generate different looking forms, with the same result. The idea was to keep the mixing engine in encrypted form - the mixing engine itself processed the virus body during infection before creating new and highly variable shapes of itself. The drawback was that the mixing engine was linearly encrypted with 8-bit keys. That could be used to write a detection algorithm to search for the encrypted part in the virus body.

The author of the ACG family understood this disadvantage and developed a new idea - what if the encrypted body is not stored in one piece, but in more scrambled pieces spread through the entire virus image? The ACG family is not a dangerous one, but the polymorphic engine is well written and very stable. The main problem with it is that its engine could easily be used in other viruses, far more dangerous ones. Also, the idea can be successfully applied to Windows viruses, potentially making this kind of virus a big problem in the future.

ACG - A Storm in a CPU?

In mid-April I received an archive containing several different samples. All of them had the capability to mutate in a special way, being one of the most advanced polymorphic viruses written. However, another virus known as the Yowler family had the same engine (one of them looked quite similar to a version that I received). Using a string found inside an infected file, I tried to discover the author of the virus and found the name Lucky. I took a look at several other viruses written by him.

These viruses, dated this year, betrayed a mid-range assembler programmer, incapable (in my opinion) of coding such complex viruses. After a lot of research I found out that the nature of the problem is more serious. Back in 1997, a virus writer known as Mad Daemon released a package called ACG (Amazing Code Generator). The idea is not new, several creation tools were released before, but the implementation is outstanding.

The package contained an ACG compiler, some examples (two of them in the package I received) and some documentation. ACG is a high level language adapted for polymorphic viruses. Up to now, there have been several viruses that use the ACG engine. Some of them are direct action viruses, searching for all COM files in the current directory, while the others are memory resident. All of them are simple viruses, with no payload; they seem to be written only to demonstrate the features of the engine.

Non-resident Versions of ACG

There are several of these direct action infectors in existence. When an infected file is run, the virus receives control via a jump instruction which points to the virus body. Then it resizes the used memory to 64 KB and searches for the mask `*.COM'. If a file is found, it is opened in read-write mode. If the open fails the virus assumes that the file is already infected (the infection marker is the read-only flag in the file's attributes field). After that, it reads three bytes of the original file, which will be used to restore the control to the host program.

Next, it checks the file size - only files between four and 48,640 bytes are infected. ACG's engine needs another block of 64 KB, so the virus calls DOS' memory alloc function. In order to generate a new form, the virus needs to call its engine. It joins the pieces of the engine's image together, using a marker for each block which is followed by the next chunk's address. There is also a check which tells the virus that the engine can be called - if the end of the processed image is not 0x0F. The virus writes the message `Internal compiler error!' (for the A variant) `LUCKY B.R.D 1994-99' (for the B variant) and returns control to the original file.

Next, it calls the mixing engine. The engine generates a virus mutation at a fixed address before giving control back to the main virus body. This writes the generated mutation into the infected file, frees the allocated memory and checks for more suitable files. Infected files grow by a random amount of between 0x3000 and 0x4000.

Resident Versions of ACG

These versions are simple COM/EXE infectors, using ACG's polymorphic engine. One of them is more advanced, (in fact, it is a debug version of a more advanced virus) avoiding several known anti-virus utilities, while the others are simple infectors. Since they use ACG's features, they are polymorphic both in files and memory.

When an infected file is executed, the virus receives control, checks if it is already resident and calls the polymorphic engine. This call is made only once, so all infected files will have the same shape until a new memory installation is made. Moreover, there is a chance to generate a light version of the virus, without the compiler inside.

The Yowler family contained such cases within it (this is the same virus, despite being labelled differently by anti-virus products). This particular feature makes these versions slow polymorphics and obtaining a good sample set is harder. Infected files have the maximum memory filed in the EXE header set to 0xffff.

ACG's Polymorphic Engine

The mutation engine receives control from various points, depending on the caller's version. It is stored in packed form (7,781 bytes) using a slightly modified LZ compression scheme, similar to the variant used in old executable packers. In its unpacked form it is 11,368 bytes long.

When an ACG mutation is built, the compiler takes good care of its instructions. It generates the respective (mutated) code for them, and also generates something like a byte-code definition for the next mutation which contains informations used by the next mutation. Polymorphism is achieved using ACG language when the virus is created. ACG language contains a powerful set of instructions, which can be used to specify the nature of an operation.

Also, for bigger blocks of constant data (like the compiler itself), ACG splits them into several chunks located at random offset in the entire virus body. Moreover, these chunks are encrypted using random keys.

This reduces the possibility of detecting this virus using its constant parts (or cryptoanalysis on these parts). The polymorphic engine is not as advanced as Lexotran's, but it can generate a large range of opcodes, including 32-bit types. The main idea is that you can use several processor instructions to obtain the same result. Each original instruction or block can be generated at any position, linked by JMP or CALL statements. All the offsets involved in any instruction are relocated. Despite its complexity, on a large test-set of about 10,000 generations, the polymorphic engine generated only valid shapes. This makes ACG one of the most complex but stable polymorphic viruses ever.

Detection and Cleaning

Detection of ACG is a serious issue. There is no reliable way to add exact identification to an anti-virus product. There are two options - using dedicated algorithms or using code emulation (CE). I think a scheme based on CE is better than algorithms, for two reasons. The false alarm percent is lower and CE can also be used at disinfection.

One idea would be to make use of the fact that the virus replicates and use a detection scheme based on Int calls and all the logical parts that are constant for these viruses. Both Lexotran and ACG can be detected by hooking the emulator's Int calls and checking the parameters (there are some constants such as memory allocation, search for files, etc). This is a simple method, but it requires the CE to handle all the opcodes generated by the viruses.

Also, we could trick the CE to make the virus restore the original file's state, in order to find disinfection information (e.g. if there are no files in the current directory, ACG simply restores the host and gives control. We could make the CE report no files in the current directory, emulate until we reach a certain instruction - for COM files the jump to the initial entrypoint or intersegmental jump for EXEs). This seems more like generic disinfection, but it can be backed up by a lot of checks.


Tools like ACG could easily be used in more dangerous creations. Its features could be used by any virus creator with no outstanding qualifications in virus coding. As classic polymorphism opened a new era in computer virus history, this development could mean a new direction in virus writing. This is why such exotic viruses, despite not being in the wild, should be considered a serious matter.

ACG family
Aliases:Yowler, Kopie.
Type:COM/EXE infectors.
Infection:Direct action and resident, hooking the `execute function' 0x4b.
Self-recognition in EXE files:Maxmemory in EXE header set to 0xffff.
Self-recognition in COM files:All infected files are read-only.
Self-recognition in memory:Calling Int 21h with the edx register set to Acg! clears the carry flag.
Removal:Boot from clean floppy, delete infected files and restore from backups.
[Back to index] [Comments]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! aka