% Blue Nine %

Here is Conzouler's contribution to IR6. First, the textfile, then the
source code. Blue Nine is by the a poison used in the book Neuromancer,
which seem to has inspired quite a few viruswriters. Ah, just in case
you wondered - TU

A technical discussion about the Blue Nine virus
Written by: Conzouler.
(Terribly serious :-)

The Blue Nine virus was born on 19:th of November 1994.
It has about the same features as the Cybernetic Eel which I wrote this
summer but the code is much better and it doesn't disinfect files but
does instead redirect any reads from the infected areas of an infected
file, this method is, quite naturally, called redirection. It also makes
use of another infection engine, putting itself in the end of the
infected files.

This version does not have any payloads, it just reproduces and hides
itself. But we are working on a Novell password stealer to add, hence
the redirection, it will work on write protected network drives and
disks too. We have some betas with a disk/file trasher and a joke on
the 25:th of any month, but they aren't distributed.

Well, that was a brief description of it, now I will go in to
the details.

First of all, when a program is executed it performs an installation
check and checks the dos version by setting cx to 666 and issuing get dos
version (int 21/ah=30). If the virus already is resident it will change cx
to 444 and the virus will just restore the host program in memory and jump
back to the entry point. If cx not equals 444 then the virus will check if
the dos version is higher 3.30 and, if so, go resident.

If the installation checks fails the go resident routine will attempt to
allocate memory for the virus. First of all it has to deallocate some of
the memory allocated to the host program. This is done by moving the word at
cs-1:[3] to bx, subtracting the virus size from bx and issuing int21/ah=4A.
Then it uses the int 21/ah=48 to allocate memory to itself. When the
memory has been allocated the virus has to determine its entry point
(the delta offset). To do that it fetches the word at cs:[101] which is
the address of the jmp instruction that jumps to the virus entry point.
Using this offset it sets ds:si to the start of the virus and es:di to
the beginning of the newly allocated memory. Cx is set to the size of
the virus, thus preparing for a rep movsb which will put the virus in
its own allocated memory block.

The rep movsb instruction is replaced by the following code:

label:  lodsb
stosb
loop    label

This is exactly the same as rep movsb except that it destroys al and
that TB-Scan cannot find it. That means that TB-Scan does NOT emulate as
Venkmann says or possibly that the emulator is awfully bad. But that
doesn't matter, let's go on..

The virus will then jump to the int 21 hooking routine in the new
block by subtracting the segment address by 10h to compensate for the
PSP that is missing in the new block. This address and the offset of the
hooking routine are pushed and a retf will jump to the new block.

The next step is to hook int 21. This is done using the normal dos
method, not by directly change the vectors. First it calls int 21/ax=3521
to get the original vector. It then calls int 21/ax=2521 to put itself
in the vector.

And now there is only one step left. It has to restore the host
program. Since the original first 3 bytes of the host are saved right
before the entry point (at offset 103 in our new block) it moves them to
offset 100h of the host and jumps there using a retf construction
similar to the one mentioned above.

At this point the host program is running as usual, totally unaware of
the Blue Nine hiding in the dark, just waiting for an opportunity to
infect another unsuspicious program...

The virus will infect any .com file that is run after the virus has
gone resident. It will also infect .com files in a dir listing on a
random basis (25% chance).
The infection is simple and effective. The virus opens its victim,
reads the first three bytes, searches to eof, appends itself and creates
a jump construct at the beginning of the file pointing to the start of
the virus.

An infected file would look like this:

E9 xx xx   │ <-- A jump to the virus entry point

Host     │ <-- The original program except for the
program   │     first three bytes.

xx xx xx   │ <-- The first three bytes of the original program

Virus      │ <-- Guess what...
code...

Now we have only the fun left, stealth...

Size stealth:
After a successful find first/next using fcbs (ah=11/12) the fcbfind
routine will be called from the int 21 handler. First it filters out all
other files but those with extension .com. It then checks if the seconds
of the time field are set to 4, and if that is the case it will decrease
the size field with the virus size and return to dos.
If it is a .com file but the seconds don't match and the lowest 2 bits
of port 41 is zero (25% chance, 41 is the timer) then the filename will
be converted to a nul terminated ascii string, opened and sent to the
infection routine.
This will work on a dir command since Bill Gates is fucked up and
uses fcbs instead of handles as recommended since dos 2.11.
Since other programs like Norton uses handles I've added a similar
function for the calls 4E/4F (find first/next using handles) but I
haven't bothered doing an infection therein.

Redirection, the innovation in this virus...

The state of the art technique for avoiding checksummers and
self-checkers has been disinfection. Disinfection works very fine and
isn't too slow but it has one (minor) disadvantage, it doesn't work on
write protected disks and it doesn't work in networks where the file
are more likely to be write protected.

The solution that I've created to this problem is, like boot-sector
viruses, to redirect all reads from an infected area of a file.
When an infected file is opened using dos function 3D (open) or
6C00 (extended open) the virus will use the internal dos call
int 2F/ax=1220 which converts a handle to a number for an entry in
the system file tables (sft), this number is then converted to an address
to the specific sft for that file using int 2F/ax=1226. You can see
exactly how this is done in the getsft routine in the virus code.
The 14:th bit in the 5:th word from this address is set, marking
that the file's date/time should not be set on closing. The original
first three bytes of the file are read into the date/time field at
offset 0D in the sft and the last byte of the date/time field is set to
31 marking that the file is to be redirected. Then the size dword at
offset 11 in the sft is decreased by the size of the virus and the virus
returns to the caller.
Whenever this file is being read the virus
will catch the 3F (read from file) call and if the offset is within the
first 3 bytes of the file those will be replaced by those saved in the
date/time field.
The only catch with the redirection is that a file could be destroyed
if something (another virus for example) appends to the file. The simple
solution to this problem is to disinfect a file if a write is
attempted.

All interrupt, calls and data structures referred to in this article
can be found in Ralph Brown's interrupt list. The sft and the memory
control block are described under the dos call get list of lists (int
21/ah=52), a cookie. The int 2F/1220/1226 calls are described in
separate entries in the interrupt list.

Now I'm going to tell you about the TB-Fooling tricks in the Blue Nine
virus.

* The int 21/ax=2521 call will set the Memory resident flag.
Just set ax to 2125 and perform an xchg ah,al instruction.

* The rep movsb will set the Relocation flag, just do as described
above.

* Any write (int 21/40) will set the suspicious File access flag.
You can use this code:
mov   ah, 40h xor 39 (or whatever)
xor   ah, 39
int   21h

* The described 2F functions will also set the F flag.
The same code works even here:
mov   ax, 1220h xor 4321
xor   ax, 4321
int   21h

* A read at cs:[101] will set the Delta offset flag, this can be avoided
by pushing this word and pop it into a register.

* A compare with 'MZ' will cause the Z flag (exe/com determination).
Just xor both 'MZ' and the word you are checking with the same number
or xchg the word and compare it with 'ZM' instead.

* A push of 100h followed by ret or retf will set the Back to entry point
flag. Remove by moving 100 to ax and pushing ax instead.

The general method for removing a TB flag is to confuse the code a bit,
xor:ing, xchg:ing, pushing/poping all works fine, just try a few times.
If you cant guess where in the code a flag is you can use ';' to exclude
pieces of code and see if the flag disappears, just remember that a flag
can be in more than one position.

That's all for this time folks...
...until next time I may have done some multipartitite...
...or maybe I'm just too lazy...
- Cya -

-« Conzouler »-