Virus.DOS.Zhengxi

Class Virus
Platform DOS
Description

Technical Details


This is a family of very dangerous, polymorphic and stealth parasitic
viruses. These viruses are more than 7K of length, very complex, and maybe
the most complex DOS-viruses. These viruses infect EXE-, OBJ- and
LIB-files, and append COM-droppers to ZIP, ARJ, and RAR archives. The
viruses contain the internal text strings:


Abnormal program termination
The Virus/DOS 0.54 Copyright (c) 1995 Zhengxi Ltd
Warning! This program for internal use only!

Installation


The code of the virus receives the control from different points depending
on the infection way, but in all cases the destination is the polymorphic
decryption routine. In EXE files (appending) the decryption routine
receives the control immediately when an EXE file is loaded into memory
for execution, in EXE files (inserting) – from the code of loader (see
EXE infection), in the files linked with infected OBJ/LIB files – from CALL
instruction (see OBJ/LIB infection), the COM droppers have JMP instruction
at their beginnings, that JMP brings control to the decryption routine.


Being decrypted, the installation routine of the virus receives the
control. The virus hooks INT 1 (One Step Tracing), and traces INT 21h.
While tracing, the virus searches for some specific code within INT 21h
handler (that code is present in DOS 5.x and DOS 6.x). If such code is found,
the virus checks several conditions, and terminates installation in some
cases.


The virus terminates installation if:


  • MS Windows is installed
  • boot drive is A: or B:
  • INT 8, 13h, 28h points to the same segment (to exit installation if anti-virus monitor is installed?)
  • host file’s day (date and time stamp) is the same or near the current day (two highest bits of current day number XORed with file day is equal to zero)

Then the virus allocates the block of the system memory for the virus TSR
copy, stores in its body 11 bytes from the address of INT 21h handler, and
patches INT 21h code with FAR CALL instruction (2F FF 1E ?? ??) which
brings the control to INT 25h handler (Absolute Disk Read). Then the virus
stores first five bytes of INT 25h handler and writes to there five bytes
of FAR JMP to virus code. The result looks like follows:

INT 21h handler:
… …
+——- 2E FF 1F ???? CALL FAR CS:Int25
� C7 06 ???? ; magic word?
� Int25: ???? ???? ???? ???? ; far addr of INT 25h
� … …

+> INT 25h handler:
+——– EA ???? ???? JMP FAR VirusHandler
� … …

+> Virus handler:
2E 8F 06 … POP CS:Caller_IP
… …

As the result the virus has the same handler to intercept both INT 21h and
INT 25h calls. To separate these calls the virus checks the address of
caller (Caller_IP). If the call goes from INT 21h handler, the virus passes
control to Virus INT 21h handler routine, in another case the Virus INT 25h
handler receives the control.


The installation routine is complete, but the virus can move its code to
other memory blocks (see INT 21h handler analysis). So, the TSR copy of the
virus does not occupy the same blocks of the system memory, but may move
itself to other addresses, including UMB ones.


Then the virus returns the control to the host program. There are three
different variants of such return, they depend on the infection method. In
case of COM dropper the virus only displays the message:


Abnormal program termination

and returns to DOS with Terminate function (INT 21h, AH=4Ch). In case of
EXE-appending method of infection the virus restores the original file
header by using polymorphic engine (generates polymorphic decryption
routine, and executes it to restore original header, see EXE infection
below). In case of EXE-inserting way the virus just returns to the host
program because virus loader inserted into the file restores the original
code by itself. In case of OBJ/LIB file the virus also just returns to the
host program (see OBJ/LIB infection below).

INT 21h Handler


The virus intercepts 18 of INT 21h functions:

3Dh, 6Ch – Open/Create File
3Eh – Close File
3Fh – Read File
42h – Lseek
4Bh – Execute File
41h – Delete File
11h, 12h – FindFist/Next FCB
4Eh, 4Fh – FindFist/Next ASCII
00h, 4Ch – Terminate
31h – Stay TSR
67h – Set Handle Count
48h, 49h, 4Ah – memory managing functions (Allocate, Free, Resize)

The Set Handle Count, Execute File and memory managing functions are used
by the virus to hide its code into the system memory – the virus
manipulates with MCB blocks to be not visible on memory map while using
memory browsing utilities.


While intercepting of Terminate, Stay TSR and FreeMemory functions the
virus moves its code to new address in the system memory. The virus
allocates new block of the memory (that may be conventional or UMB memory
block), and copies itself into there. So, while installing the virus does
not affect UMB blocks to place its TSR copy, but then it may move itself
into UMB, and hide itself in there.


While file opening the virus performs several different calls. First, the
virus checks the opening mode, and if the file is opened for writing, the
virus disinfects the file.


Before disinfection the virus checks the file is accessed, and the program
that accesses that file (caller). The virus compares the name of accessing
program (caller) with the list of the names (see below), and does not
disinfect accessed file if the name of accessing program is from that list.
The file names are:


UUENCODE.EXE, PKLITE.EXE, LZEXE.EXE, NDD.EXE, DIET.EXE, AFD.EXE, SD.EXE,
SPEEDDSK.EXE, DEFRAG.EXE, TLINK.EXE, LINK.EXE

In case of AH=3D00h function (Open ReadOnly) the virus performs some
strange actions. It scans the code of caller, and patches it. It looks like
patching of some anti-virus scanner. Fortunately, the virus has the bug,
and that branch is never executed.


While opening the file the virus also brings the control to stealth routine
– the virus substitutes the file length with the original one.


While reading from the file the virus calls the stealth routine. In case
of reading from header of infected file the virus reads, decrypts and
copies original header into the reading buffer.


In case of Lseek function the virus brings the control to another one
stealth routine of the virus – the virus does not allow to seek out of
original file length.


While deleting of infected file the virus disinfects it.


While searching for the files with FindFirst/Next calls the virus
substitutes the file length with the original one if the file is infected.


FindFist/Next ASCII calls are also used by the virus to catch the files for
infection. The virus saves the name of any file that is accessed with
FindFirst function, and approximately each 5th file (with probability 3/16)
accessed with FindNext function. The virus has only one buffer for the file
name, so each next name overwrites previous one.


While closing of any file the virus checks and infects the file with the
name that is stored in the buffer. The virus also infects the file that is
closed, but is does it with probability 1/4 (by the result of virus’ random
generator)


Infection


Before infecting the file the virus checks several conditions:

  • the file is not “just creates” by comparing current day number with the file date and time stamp of the file (the same as while installing)
  • the file is local, and not on A: or B: drive
  • the file name is not *.?V? (*.OVL ?)
  • there is enough of free disk space (checks with INT 21h, AH=36h)

In case of all these conditions the virus reads the file header and checks
it for EXE, OBJ, LIB and archives stamps.


Infecting EXE Files


The virus infects EXE by three different methods – appending, inserting,
and infecting archives in self-extracting files.


First, the virus checks the file structure, and if it is self-extracting
EXE file (created by ZIP2EXE, for example), the virus infects attached
archive (ZIP, ARJ, RAR) by the method that is described below – creates COM
dropper, and adds it to the contents of the archive.


Then the virus checks the file length, and does not infect the files with
the length lesser than 400h (1024) bytes. If the length of the loadable
module (note: not the file length) is larger that 32K, the virus inserts
its loader into the file middle. In another case the virus infects the file
by appending method.


While infecting the files by appending method the virus reads file header,
encrypts and saves it to the end of the file. Then the virus runs its
polymorphic generator, and saves encrypted virus body and the polymorphic
loops to the file end. To finish infection the virus increases the file
length to the value that being divided by 9Dh gives the rest 25h (to detect
already infected files, it is virus “ID” stamp), and modifies EXE header
fields (registers and module length).


Note: the virus encrypts the original header of the host file with the
polymorphic encryption loop, and that loop is different with the routine
that is used while encrypting the virus body. I.e. the virus calls the
polymorphic engine twice – while encrypting original EXE header, and while
encrypting the main body.


While executing of infected EXE file the decryption loops restores the main
virus body but not original file header. To return to the host program the
virus has to decrypt the host data, but engine generates random loops with
random selected encryption functions. To solve that problem the virus
stores initial values of random generator while encrypting the host data,
and runs polymorphic generator with the same values while decrypting that
data. As the result the generator brings the same code that was used while
encrypting host data, and being executed that routine decrypts it.


Infecting EXE Files (Inserting)


If the file length is above than 32K, the virus seeks to the beginning of
EXE main module (just after EXE header), reads 6K of the code, and looks
for C/Pascal routines in there. Usually C/Pascal routines begin from the
same “header” that saves the BP register, and moves stack pointer SP to BP.


The virus scans the code for that “headers” and if such code is found, the
virus scans the next 54h bytes of code for RET or CALL FAR instruction to
prevent overlap of next subroutine, or relocated address. If such code (RET
or CALL FAR) is found, the virus exits from infection routine.


Then the virus reads 54h bytes of that routine, overwrites it with code of
virus loader, then encrypts the main virus body with polymorphic engine,
and saves it to the file end. Then the virus encrypts with simple SUB
function the original code of subroutine and the second part of the loader,
and saves it to the end of the file. Then the virus writes to the end of
the file the random data with the same way as while “appending” method of
infection.


Not infected Infected
———— ——–
+————–+ +————–+
�Exe Header � �Exe Header �
+————–� +————–�
�Main EXE code � �Main EXE code �
�————–� �————–�
�C/Pascal subr �–+ �Virus loader � Part 1, 52h bytes, not encrypted
�————–� � �————–�
� � � �Main EXE code �
� � � �(continued) �
+————–+ � +————–�
� �Virus � Encrypted with polymorphic loops
� �————–�
� �Virus loader � Part 2, encrypted with SUB command
� �————–� 70h bytes
+->�Saved code � Original code of patched subroutine,
�————–� 52h bytes, encrypted with SUB
�Random data � file length / 9Dh , the rest is 25h
+————–+

Being executed the loader looks for the host file name by using PSP fields,
opens the files, seeks to the file end, then reads, decrypts and executes
the second part of the dropper. That part restores the patched subroutine,
allocates the system memory (conventional or UMB), reads the main virus
body, and passes the control to the decryption polymorphic loop. That loop
decrypts the virus body, and passes the control to installation routine.


That is very insidious way of infection. The code of the virus is hidden in
the file, and there is no direct entry to the virus code from the file
header. The subroutine replaced with virus loader may be “seldom-executed”
one. For example, the subroutine that displays the error message. So the
virus may “sleep” in such files for a long time, and then jump out and
infect the system under some limited conditions.


Infecting Archives


In case of archive the virus creates in memory the image of infected COM
dropper, and appends it to the archive. That COM droppers always begins
with JMP instruction followed by random data, encrypted virus code and
decryption polymorphic loop. The JMP instruction brings the control to
decryption loop.


The name of dropper is random selected and finished with .COM extension,
for example:


HAIF.COM, UCM.COM, DOO.COM, VLG.COM, and so on.

While processing the archive fields the virus does not use any external
utility, but fills by itself all necessary fields. The virus does not packs
the dropper, but uses “stored” method – the virus is stored in archive “as
is”. While infecting the virus checks the contents of archives, and does not
infect them twice.


Infecting OBJ and LIB Files


While infecting OBJ/LIB modules the virus checks the fields of the file,
creates, and inserts into there new object records containing the virus code
that is encrypted with polymorphic loops.


While scanning object file the virus checks the code of that file for
C/Pascal subroutine “header” as well as while inserting into EXE files, and
infects the files only if that code is found. But in case of OBJ or LIB
module the virus does not drops the code of loader into there, but
overwrites the C/Pascal header with CALL instruction (E8xxxx).


Being linked into executable file that CALL brings the control to the virus
polymorphic decryption loop. That loop decrypts the virus code and passes
the control to the virus installation routine.


As well as in EXE files (inserting) that CALL may never receive the
control, and virus may sleep for a long time. But under some conditions the
virus may jump out, and infect the system.


INT 25h Handler

This handler realizes stealth routine on INT 25h level. While accessing
to directory entries the virus substitutes the file length with original
ones, while reading the header of infected file the virus restores it, and
brings in original form.


The virus does not realizes 100% stealth on INT 25h level, of course. There
are the ways to bypass stealth routine. But if some anti-virus program
reads the file contents by INT 21h DOS functions, then reads directory
structure and then file contents by absolute INT 25h calls, the virus stays
not visible.


Trigger Routine


IF while processing ZIP files the virus finds some record that is packed
with “stored” method, it checks the ZIP file date and time stamp. If the
year of last modification of that file is 1996 or more, the virus search
for all files of all directories of all disks from C: till Z:, then deletes
the files and whole subdirectory tree.